@agent-native/core 0.84.35 → 0.84.36
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/README.md +15 -51
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/docs/content/actions.mdx +17 -24
- package/corpus/core/docs/content/agent-surfaces.mdx +59 -56
- package/corpus/core/docs/content/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/faq.mdx +4 -4
- package/corpus/core/docs/content/getting-started.mdx +246 -204
- package/corpus/core/docs/content/key-concepts.mdx +9 -9
- package/corpus/core/docs/content/locales/ar-SA/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/ar-SA/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/ar-SA/getting-started.mdx +148 -214
- package/corpus/core/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/ar-SA/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/de-DE/getting-started.mdx +145 -211
- package/corpus/core/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/de-DE/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/de-DE/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/es-ES/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/es-ES/getting-started.mdx +148 -214
- package/corpus/core/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/es-ES/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/cloneable-saas.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/fr-FR/getting-started.mdx +146 -212
- package/corpus/core/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/fr-FR/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/hi-IN/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/hi-IN/getting-started.mdx +149 -215
- package/corpus/core/docs/content/locales/hi-IN/pure-agent-apps.mdx +8 -13
- package/corpus/core/docs/content/locales/hi-IN/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/hi-IN/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/cloneable-saas.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/ja-JP/getting-started.mdx +144 -210
- package/corpus/core/docs/content/locales/ja-JP/pure-agent-apps.mdx +8 -13
- package/corpus/core/docs/content/locales/ja-JP/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/ko-KR/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/ko-KR/getting-started.mdx +146 -212
- package/corpus/core/docs/content/locales/ko-KR/pure-agent-apps.mdx +8 -13
- package/corpus/core/docs/content/locales/ko-KR/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/pt-BR/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/pt-BR/getting-started.mdx +145 -211
- package/corpus/core/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/pt-BR/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-CN/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/zh-CN/getting-started.mdx +158 -209
- package/corpus/core/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/zh-CN/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/cloneable-saas.mdx +3 -3
- package/corpus/core/docs/content/locales/zh-TW/faq.mdx +4 -4
- package/corpus/core/docs/content/locales/zh-TW/getting-started.mdx +158 -212
- package/corpus/core/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -9
- package/corpus/core/docs/content/locales/zh-TW/template-chat.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/native-chat-ui.mdx +17 -32
- package/corpus/core/docs/content/pure-agent-apps.mdx +46 -26
- package/corpus/core/docs/content/template-chat.mdx +8 -8
- package/corpus/core/docs/content/using-your-agent.mdx +2 -2
- package/corpus/core/docs/content/what-is-agent-native.mdx +6 -6
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/cli/skills.ts +7 -9
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +2 -0
- package/corpus/core/src/client/RunStuckBanner.tsx +172 -18
- package/corpus/core/src/client/blocks/library/wireframe-kit.tsx +57 -9
- package/corpus/core/src/client/blocks/library/wireframe.tsx +3 -18
- package/corpus/core/src/client/chat/widgets/builtin-tool-renderers.tsx +28 -32
- package/corpus/core/src/db/schema.ts +5 -0
- package/corpus/core/src/styles/blocks.css +27 -6
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +1 -4
- package/corpus/templates/content/actions/list-trashed-content-databases.ts +1 -1
- package/corpus/templates/plan/.agents/skills/visual-plan/references/wireframe.md +7 -9
- package/corpus/templates/plan/.agents/skills/visual-recap/references/wireframe.md +7 -9
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +7 -9
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +1 -1
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/RunStuckBanner.d.ts +13 -1
- package/dist/client/RunStuckBanner.d.ts.map +1 -1
- package/dist/client/RunStuckBanner.js +123 -16
- package/dist/client/RunStuckBanner.js.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.d.ts +6 -6
- package/dist/client/blocks/library/wireframe-kit.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe-kit.js +52 -5
- package/dist/client/blocks/library/wireframe-kit.js.map +1 -1
- package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
- package/dist/client/blocks/library/wireframe.js +1 -11
- package/dist/client/blocks/library/wireframe.js.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.d.ts.map +1 -1
- package/dist/client/chat/widgets/builtin-tool-renderers.js +27 -31
- package/dist/client/chat/widgets/builtin-tool-renderers.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/schema.d.ts +2 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +3 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/styles/blocks.css +27 -6
- package/docs/content/actions.mdx +17 -24
- package/docs/content/agent-surfaces.mdx +59 -56
- package/docs/content/cloneable-saas.mdx +3 -3
- package/docs/content/faq.mdx +4 -4
- package/docs/content/getting-started.mdx +246 -204
- package/docs/content/key-concepts.mdx +9 -9
- package/docs/content/locales/ar-SA/cloneable-saas.mdx +3 -3
- package/docs/content/locales/ar-SA/faq.mdx +4 -4
- package/docs/content/locales/ar-SA/getting-started.mdx +148 -214
- package/docs/content/locales/ar-SA/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/ar-SA/template-chat.mdx +2 -2
- package/docs/content/locales/ar-SA/using-your-agent.mdx +2 -2
- package/docs/content/locales/de-DE/cloneable-saas.mdx +3 -3
- package/docs/content/locales/de-DE/faq.mdx +4 -4
- package/docs/content/locales/de-DE/getting-started.mdx +145 -211
- package/docs/content/locales/de-DE/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/de-DE/template-chat.mdx +2 -2
- package/docs/content/locales/de-DE/using-your-agent.mdx +2 -2
- package/docs/content/locales/es-ES/cloneable-saas.mdx +3 -3
- package/docs/content/locales/es-ES/faq.mdx +4 -4
- package/docs/content/locales/es-ES/getting-started.mdx +148 -214
- package/docs/content/locales/es-ES/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/es-ES/template-chat.mdx +2 -2
- package/docs/content/locales/es-ES/using-your-agent.mdx +2 -2
- package/docs/content/locales/fr-FR/cloneable-saas.mdx +2 -2
- package/docs/content/locales/fr-FR/faq.mdx +4 -4
- package/docs/content/locales/fr-FR/getting-started.mdx +146 -212
- package/docs/content/locales/fr-FR/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/fr-FR/template-chat.mdx +2 -2
- package/docs/content/locales/fr-FR/using-your-agent.mdx +2 -2
- package/docs/content/locales/hi-IN/cloneable-saas.mdx +3 -3
- package/docs/content/locales/hi-IN/faq.mdx +4 -4
- package/docs/content/locales/hi-IN/getting-started.mdx +149 -215
- package/docs/content/locales/hi-IN/pure-agent-apps.mdx +8 -13
- package/docs/content/locales/hi-IN/template-chat.mdx +2 -2
- package/docs/content/locales/hi-IN/using-your-agent.mdx +2 -2
- package/docs/content/locales/ja-JP/cloneable-saas.mdx +2 -2
- package/docs/content/locales/ja-JP/faq.mdx +4 -4
- package/docs/content/locales/ja-JP/getting-started.mdx +144 -210
- package/docs/content/locales/ja-JP/pure-agent-apps.mdx +8 -13
- package/docs/content/locales/ja-JP/template-chat.mdx +2 -2
- package/docs/content/locales/ja-JP/using-your-agent.mdx +2 -2
- package/docs/content/locales/ko-KR/cloneable-saas.mdx +3 -3
- package/docs/content/locales/ko-KR/faq.mdx +4 -4
- package/docs/content/locales/ko-KR/getting-started.mdx +146 -212
- package/docs/content/locales/ko-KR/pure-agent-apps.mdx +8 -13
- package/docs/content/locales/ko-KR/template-chat.mdx +2 -2
- package/docs/content/locales/ko-KR/using-your-agent.mdx +2 -2
- package/docs/content/locales/pt-BR/cloneable-saas.mdx +3 -3
- package/docs/content/locales/pt-BR/faq.mdx +4 -4
- package/docs/content/locales/pt-BR/getting-started.mdx +145 -211
- package/docs/content/locales/pt-BR/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/pt-BR/template-chat.mdx +2 -2
- package/docs/content/locales/pt-BR/using-your-agent.mdx +2 -2
- package/docs/content/locales/zh-CN/cloneable-saas.mdx +3 -3
- package/docs/content/locales/zh-CN/faq.mdx +4 -4
- package/docs/content/locales/zh-CN/getting-started.mdx +158 -209
- package/docs/content/locales/zh-CN/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/zh-CN/template-chat.mdx +2 -2
- package/docs/content/locales/zh-CN/using-your-agent.mdx +2 -2
- package/docs/content/locales/zh-TW/cloneable-saas.mdx +3 -3
- package/docs/content/locales/zh-TW/faq.mdx +4 -4
- package/docs/content/locales/zh-TW/getting-started.mdx +158 -212
- package/docs/content/locales/zh-TW/pure-agent-apps.mdx +4 -9
- package/docs/content/locales/zh-TW/template-chat.mdx +2 -2
- package/docs/content/locales/zh-TW/using-your-agent.mdx +2 -2
- package/docs/content/native-chat-ui.mdx +17 -32
- package/docs/content/pure-agent-apps.mdx +46 -26
- package/docs/content/template-chat.mdx +8 -8
- package/docs/content/using-your-agent.mdx +2 -2
- package/docs/content/what-is-agent-native.mdx +6 -6
- package/package.json +1 -1
|
@@ -28,8 +28,20 @@ export interface RunStuckBannerProps {
|
|
|
28
28
|
* observability events (Sentry, PostHog) at the call site.
|
|
29
29
|
*/
|
|
30
30
|
onStuckStateChange?: (state: RunStuckState) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Automatically abort and retry once when the server reports a run is
|
|
33
|
+
* alive but has stopped making real progress. Manual controls remain visible
|
|
34
|
+
* as the fallback if the automatic recovery cannot clear the run.
|
|
35
|
+
*/
|
|
36
|
+
autoRetry?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Stable browser-tab/window id used to coordinate automatic retries across
|
|
39
|
+
* multiple mounted chat views for the same thread. A local id is generated
|
|
40
|
+
* when omitted.
|
|
41
|
+
*/
|
|
42
|
+
autoRetryOwnerId?: string;
|
|
31
43
|
/** Extra class on the outer container. */
|
|
32
44
|
className?: string;
|
|
33
45
|
}
|
|
34
|
-
export declare function RunStuckBanner({ threadId, apiUrl, stuckThresholdMs, onRetry, onStuckStateChange, className, }: RunStuckBannerProps): import("react").JSX.Element | null;
|
|
46
|
+
export declare function RunStuckBanner({ threadId, apiUrl, stuckThresholdMs, onRetry, onStuckStateChange, autoRetry, autoRetryOwnerId, className, }: RunStuckBannerProps): import("react").JSX.Element | null;
|
|
35
47
|
//# sourceMappingURL=RunStuckBanner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunStuckBanner.d.ts","sourceRoot":"","sources":["../../src/client/RunStuckBanner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACpD,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"RunStuckBanner.d.ts","sourceRoot":"","sources":["../../src/client/RunStuckBanner.tsx"],"names":[],"mappings":"AAIA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAGtC;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACpC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACpD;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAgFD,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,MAAM,EACN,gBAAgB,EAChB,OAAO,EACP,kBAAkB,EAClB,SAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,EAAE,mBAAmB,sCAwLrB"}
|
|
@@ -4,10 +4,65 @@ import { useEffect, useRef, useState } from "react";
|
|
|
4
4
|
import { trackEvent } from "./analytics.js";
|
|
5
5
|
import { useRunStuckDetection, useAbortRun, } from "./use-run-stuck-detection.js";
|
|
6
6
|
import { cn } from "./utils.js";
|
|
7
|
-
|
|
7
|
+
const AUTO_RETRY_CLAIM_TTL_MS = 5 * 60 * 1000;
|
|
8
|
+
function createAutoRetryOwnerId() {
|
|
9
|
+
const cryptoApi = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
10
|
+
? crypto
|
|
11
|
+
: null;
|
|
12
|
+
return cryptoApi?.randomUUID() ?? `owner-${Math.random().toString(36)}`;
|
|
13
|
+
}
|
|
14
|
+
function autoRetryClaimKey(threadId, runId) {
|
|
15
|
+
return `agent-native:stuck-auto-retry:${threadId}:${runId}`;
|
|
16
|
+
}
|
|
17
|
+
function markAutoRetryClaim(key, ownerId) {
|
|
18
|
+
if (typeof window === "undefined")
|
|
19
|
+
return true;
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
try {
|
|
22
|
+
const raw = window.localStorage.getItem(key);
|
|
23
|
+
if (raw) {
|
|
24
|
+
const existing = JSON.parse(raw);
|
|
25
|
+
const expiresAt = typeof existing.expiresAt === "number" ? existing.expiresAt : 0;
|
|
26
|
+
if (expiresAt > now && existing.ownerId !== ownerId)
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
window.localStorage.setItem(key, JSON.stringify({ ownerId, expiresAt: now + AUTO_RETRY_CLAIM_TTL_MS }));
|
|
30
|
+
const confirmed = JSON.parse(window.localStorage.getItem(key) ?? "{}");
|
|
31
|
+
return confirmed.ownerId === ownerId;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Private browsing or disabled storage: fall back to in-tab retry. The
|
|
35
|
+
// server abort is idempotent, and manual controls remain available.
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function claimAutoRetryAttempt(threadId, runId, ownerId) {
|
|
40
|
+
if (!threadId)
|
|
41
|
+
return true;
|
|
42
|
+
const key = autoRetryClaimKey(threadId, runId);
|
|
43
|
+
const locks = typeof navigator !== "undefined"
|
|
44
|
+
? navigator.locks
|
|
45
|
+
: undefined;
|
|
46
|
+
if (locks?.request) {
|
|
47
|
+
try {
|
|
48
|
+
return await locks.request(key, { mode: "exclusive", ifAvailable: true }, (lock) => (lock ? markAutoRetryClaim(key, ownerId) : false));
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return markAutoRetryClaim(key, ownerId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return markAutoRetryClaim(key, ownerId);
|
|
55
|
+
}
|
|
56
|
+
export function RunStuckBanner({ threadId, apiUrl, stuckThresholdMs, onRetry, onStuckStateChange, autoRetry = false, autoRetryOwnerId, className, }) {
|
|
8
57
|
const state = useRunStuckDetection({ threadId, stuckThresholdMs, apiUrl });
|
|
9
58
|
const abortRun = useAbortRun(apiUrl);
|
|
10
|
-
const [busy, setBusy] = useState("none");
|
|
59
|
+
const [busy, setBusy] = useState({ type: "none" });
|
|
60
|
+
const autoRetriedRunIdsRef = useRef(new Set());
|
|
61
|
+
const generatedOwnerIdRef = useRef(null);
|
|
62
|
+
if (!generatedOwnerIdRef.current) {
|
|
63
|
+
generatedOwnerIdRef.current = createAutoRetryOwnerId();
|
|
64
|
+
}
|
|
65
|
+
const ownerId = autoRetryOwnerId ?? generatedOwnerIdRef.current;
|
|
11
66
|
const lastReportedRef = useRef({ isStuck: false, runId: null });
|
|
12
67
|
useEffect(() => {
|
|
13
68
|
const last = lastReportedRef.current;
|
|
@@ -27,40 +82,92 @@ export function RunStuckBanner({ threadId, apiUrl, stuckThresholdMs, onRetry, on
|
|
|
27
82
|
});
|
|
28
83
|
}
|
|
29
84
|
}, [state, onStuckStateChange, threadId]);
|
|
30
|
-
// Reset the busy spinner once the underlying run
|
|
31
|
-
//
|
|
85
|
+
// Reset the busy spinner once the underlying run is no longer the one we
|
|
86
|
+
// acted on. A recovery continuation can start quickly enough that polling
|
|
87
|
+
// never observes an idle state between run ids.
|
|
32
88
|
useEffect(() => {
|
|
33
|
-
|
|
34
|
-
|
|
89
|
+
setBusy((current) => {
|
|
90
|
+
if (current.type === "none")
|
|
91
|
+
return current;
|
|
92
|
+
if (state.status !== "running")
|
|
93
|
+
return { type: "none" };
|
|
94
|
+
if (state.runId && state.runId !== current.runId)
|
|
95
|
+
return { type: "none" };
|
|
96
|
+
return current;
|
|
97
|
+
});
|
|
98
|
+
}, [state.runId, state.status]);
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!autoRetry ||
|
|
101
|
+
!state.isStuck ||
|
|
102
|
+
!state.runId ||
|
|
103
|
+
busy.type !== "none" ||
|
|
104
|
+
autoRetriedRunIdsRef.current.has(state.runId)) {
|
|
105
|
+
return;
|
|
35
106
|
}
|
|
36
|
-
|
|
107
|
+
const runId = state.runId;
|
|
108
|
+
void claimAutoRetryAttempt(threadId, runId, ownerId).then((claimed) => {
|
|
109
|
+
autoRetriedRunIdsRef.current.add(runId);
|
|
110
|
+
if (!claimed)
|
|
111
|
+
return;
|
|
112
|
+
setBusy({ type: "retry", runId });
|
|
113
|
+
trackEvent("agent_chat_stuck_auto_retry", {
|
|
114
|
+
runId,
|
|
115
|
+
threadId: threadId ?? null,
|
|
116
|
+
stuckSinceMs: state.stuckSinceMs ?? null,
|
|
117
|
+
});
|
|
118
|
+
void abortRun(runId, "auto_stuck_retry").then((aborted) => {
|
|
119
|
+
if (aborted) {
|
|
120
|
+
onRetry?.(aborted);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
setBusy((current) => current.type !== "none" && current.runId === runId
|
|
124
|
+
? { type: "none" }
|
|
125
|
+
: current);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}, [
|
|
129
|
+
abortRun,
|
|
130
|
+
autoRetry,
|
|
131
|
+
busy,
|
|
132
|
+
onRetry,
|
|
133
|
+
ownerId,
|
|
134
|
+
state.isStuck,
|
|
135
|
+
state.runId,
|
|
136
|
+
state.stuckSinceMs,
|
|
137
|
+
threadId,
|
|
138
|
+
]);
|
|
37
139
|
if (!state.isStuck || !state.runId)
|
|
38
140
|
return null;
|
|
39
141
|
const handleCancel = async () => {
|
|
40
|
-
if (!state.runId || busy !== "none")
|
|
142
|
+
if (!state.runId || busy.type !== "none")
|
|
41
143
|
return;
|
|
42
|
-
|
|
144
|
+
const runId = state.runId;
|
|
145
|
+
setBusy({ type: "cancel", runId });
|
|
43
146
|
trackEvent("agent_chat_stuck_cancel", {
|
|
44
|
-
runId
|
|
147
|
+
runId,
|
|
45
148
|
threadId: threadId ?? null,
|
|
46
149
|
stuckSinceMs: state.stuckSinceMs ?? null,
|
|
47
150
|
});
|
|
48
|
-
await abortRun(
|
|
151
|
+
await abortRun(runId, "user_stuck_cancel");
|
|
49
152
|
};
|
|
50
153
|
const handleRetry = async () => {
|
|
51
|
-
if (!state.runId || busy !== "none")
|
|
154
|
+
if (!state.runId || busy.type !== "none")
|
|
52
155
|
return;
|
|
53
|
-
|
|
156
|
+
const runId = state.runId;
|
|
157
|
+
setBusy({ type: "retry", runId });
|
|
54
158
|
trackEvent("agent_chat_stuck_retry", {
|
|
55
|
-
runId
|
|
159
|
+
runId,
|
|
56
160
|
threadId: threadId ?? null,
|
|
57
161
|
stuckSinceMs: state.stuckSinceMs ?? null,
|
|
58
162
|
});
|
|
59
|
-
const aborted = await abortRun(
|
|
163
|
+
const aborted = await abortRun(runId, "user_stuck_retry");
|
|
60
164
|
if (aborted)
|
|
61
165
|
onRetry?.(aborted);
|
|
62
166
|
};
|
|
167
|
+
const busyType = busy.type;
|
|
63
168
|
const stuckSeconds = state.stuckSinceMs != null ? Math.floor(state.stuckSinceMs / 1000) : null;
|
|
64
|
-
return (_jsxs("div", { role: "status", "aria-live": "polite", className: cn("mx-3 mt-2 flex items-start gap-2.5 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2.5 text-xs text-foreground", className), children: [_jsx(IconAlertTriangle, { size: 16, className: "mt-0.5 shrink-0 text-amber-500", "aria-hidden": "true" }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [_jsxs("div", { className: "leading-snug", children: [_jsx("span", { className: "font-medium", children: "This chat looks stuck." }), " ", _jsxs("span", { className: "text-muted-foreground", children: ["No progress", stuckSeconds != null ? ` for ${stuckSeconds}s` : "", ". The agent may have hit a server timeout or lost its connection."
|
|
169
|
+
return (_jsxs("div", { role: "status", "aria-live": "polite", className: cn("mx-3 mt-2 flex items-start gap-2.5 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2.5 text-xs text-foreground", className), children: [_jsx(IconAlertTriangle, { size: 16, className: "mt-0.5 shrink-0 text-amber-500", "aria-hidden": "true" }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [_jsxs("div", { className: "leading-snug", children: [_jsx("span", { className: "font-medium", children: "This chat looks stuck." }), " ", _jsxs("span", { className: "text-muted-foreground", children: ["No progress", stuckSeconds != null ? ` for ${stuckSeconds}s` : "", ". The agent may have hit a server timeout or lost its connection.", autoRetry && busyType === "retry"
|
|
170
|
+
? " Retrying automatically now."
|
|
171
|
+
: ""] })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("button", { type: "button", onClick: handleRetry, disabled: busyType !== "none", className: "inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md bg-foreground px-2.5 text-[11px] font-medium text-background transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60", children: [busyType === "retry" ? (_jsx(IconLoader2, { size: 12, className: "animate-spin", "aria-hidden": "true" })) : null, "Retry"] }), _jsxs("button", { type: "button", onClick: handleCancel, disabled: busyType !== "none", className: "inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60", children: [busyType === "cancel" ? (_jsx(IconLoader2, { size: 12, className: "animate-spin", "aria-hidden": "true" })) : null, "Cancel"] })] })] })] }));
|
|
65
172
|
}
|
|
66
173
|
//# sourceMappingURL=RunStuckBanner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RunStuckBanner.js","sourceRoot":"","sources":["../../src/client/RunStuckBanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconAlertTriangle, IconLoader2 } from \"@tabler/icons-react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { trackEvent } from \"./analytics.js\";\nimport {\n useRunStuckDetection,\n useAbortRun,\n type RunStuckState,\n} from \"./use-run-stuck-detection.js\";\nimport { cn } from \"./utils.js\";\n\n/**\n * Surface a user-visible affordance when a chat run hasn't emitted any\n * events for an unusually long time. The adapter's silent reconnect logic\n * keeps trying in the background; this banner is the fallback when those\n * attempts haven't restored progress and the user is staring at a frozen\n * spinner.\n */\nexport interface RunStuckBannerProps {\n /** The thread to monitor. Pass null/undefined to disable. */\n threadId: string | null | undefined;\n /** API base path. Default `/_agent-native/agent-chat`. */\n apiUrl?: string;\n /**\n * Threshold above which an in-flight run is considered stuck.\n * Defaults to 90s (after the adapter's 75s no-progress reconnect\n * has had a chance to recover).\n */\n stuckThresholdMs?: number;\n /**\n * Called when the user clicks Retry. Implementations should re-prompt\n * the agent (typically via `chatHandle.sendMessage(...)`) — the banner\n * itself only handles aborting the prior run.\n */\n onRetry?: (runId: string) => void;\n /**\n * Called whenever the stuck state transitions. Useful for surfacing\n * observability events (Sentry, PostHog) at the call site.\n */\n onStuckStateChange?: (state: RunStuckState) => void;\n /** Extra class on the outer container. */\n className?: string;\n}\n\nexport function RunStuckBanner({\n threadId,\n apiUrl,\n stuckThresholdMs,\n onRetry,\n onStuckStateChange,\n className,\n}: RunStuckBannerProps) {\n const state = useRunStuckDetection({ threadId, stuckThresholdMs, apiUrl });\n const abortRun = useAbortRun(apiUrl);\n const [busy, setBusy] = useState<\"none\" | \"cancel\" | \"retry\">(\"none\");\n\n const lastReportedRef = useRef<{\n isStuck: boolean;\n runId: string | null;\n }>({ isStuck: false, runId: null });\n useEffect(() => {\n const last = lastReportedRef.current;\n if (last.isStuck === state.isStuck && last.runId === state.runId) return;\n lastReportedRef.current = { isStuck: state.isStuck, runId: state.runId };\n onStuckStateChange?.(state);\n if (state.isStuck && state.runId) {\n trackEvent(\"agent_chat_stuck_detected\", {\n runId: state.runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n stuckSinceSec:\n state.stuckSinceMs != null\n ? Math.floor(state.stuckSinceMs / 1000)\n : null,\n runStatus: state.status,\n });\n }\n }, [state, onStuckStateChange, threadId]);\n\n // Reset the busy spinner once the underlying run has flipped away from\n // running — no need to keep showing a stale \"Retrying…\" indicator.\n useEffect(() => {\n if (state.status !== \"running\") {\n setBusy(\"none\");\n }\n }, [state.status]);\n\n if (!state.isStuck || !state.runId) return null;\n\n const handleCancel = async () => {\n if (!state.runId || busy !== \"none\") return;\n setBusy(\"cancel\");\n trackEvent(\"agent_chat_stuck_cancel\", {\n runId: state.runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n });\n await abortRun(state.runId, \"user_stuck_cancel\");\n };\n\n const handleRetry = async () => {\n if (!state.runId || busy !== \"none\") return;\n setBusy(\"retry\");\n trackEvent(\"agent_chat_stuck_retry\", {\n runId: state.runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n });\n const aborted = await abortRun(state.runId, \"user_stuck_retry\");\n if (aborted) onRetry?.(aborted);\n };\n\n const stuckSeconds =\n state.stuckSinceMs != null ? Math.floor(state.stuckSinceMs / 1000) : null;\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"mx-3 mt-2 flex items-start gap-2.5 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2.5 text-xs text-foreground\",\n className,\n )}\n >\n <IconAlertTriangle\n size={16}\n className=\"mt-0.5 shrink-0 text-amber-500\"\n aria-hidden=\"true\"\n />\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <div className=\"leading-snug\">\n <span className=\"font-medium\">This chat looks stuck.</span>{\" \"}\n <span className=\"text-muted-foreground\">\n No progress\n {stuckSeconds != null ? ` for ${stuckSeconds}s` : \"\"}. The agent may\n have hit a server timeout or lost its connection.\n </span>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleRetry}\n disabled={busy !== \"none\"}\n className=\"inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md bg-foreground px-2.5 text-[11px] font-medium text-background transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {busy === \"retry\" ? (\n <IconLoader2\n size={12}\n className=\"animate-spin\"\n aria-hidden=\"true\"\n />\n ) : null}\n Retry\n </button>\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={busy !== \"none\"}\n className=\"inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {busy === \"cancel\" ? (\n <IconLoader2\n size={12}\n className=\"animate-spin\"\n aria-hidden=\"true\"\n />\n ) : null}\n Cancel\n </button>\n </div>\n </div>\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"RunStuckBanner.js","sourceRoot":"","sources":["../../src/client/RunStuckBanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import { IconAlertTriangle, IconLoader2 } from \"@tabler/icons-react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { trackEvent } from \"./analytics.js\";\nimport {\n useRunStuckDetection,\n useAbortRun,\n type RunStuckState,\n} from \"./use-run-stuck-detection.js\";\nimport { cn } from \"./utils.js\";\n\n/**\n * Surface a user-visible affordance when a chat run hasn't emitted any\n * events for an unusually long time. The adapter's silent reconnect logic\n * keeps trying in the background; this banner is the fallback when those\n * attempts haven't restored progress and the user is staring at a frozen\n * spinner.\n */\nexport interface RunStuckBannerProps {\n /** The thread to monitor. Pass null/undefined to disable. */\n threadId: string | null | undefined;\n /** API base path. Default `/_agent-native/agent-chat`. */\n apiUrl?: string;\n /**\n * Threshold above which an in-flight run is considered stuck.\n * Defaults to 90s (after the adapter's 75s no-progress reconnect\n * has had a chance to recover).\n */\n stuckThresholdMs?: number;\n /**\n * Called when the user clicks Retry. Implementations should re-prompt\n * the agent (typically via `chatHandle.sendMessage(...)`) — the banner\n * itself only handles aborting the prior run.\n */\n onRetry?: (runId: string) => void;\n /**\n * Called whenever the stuck state transitions. Useful for surfacing\n * observability events (Sentry, PostHog) at the call site.\n */\n onStuckStateChange?: (state: RunStuckState) => void;\n /**\n * Automatically abort and retry once when the server reports a run is\n * alive but has stopped making real progress. Manual controls remain visible\n * as the fallback if the automatic recovery cannot clear the run.\n */\n autoRetry?: boolean;\n /**\n * Stable browser-tab/window id used to coordinate automatic retries across\n * multiple mounted chat views for the same thread. A local id is generated\n * when omitted.\n */\n autoRetryOwnerId?: string;\n /** Extra class on the outer container. */\n className?: string;\n}\n\nconst AUTO_RETRY_CLAIM_TTL_MS = 5 * 60 * 1000;\n\ntype BusyState = { type: \"none\" } | { type: \"cancel\" | \"retry\"; runId: string };\n\ntype MaybeLockManager = {\n request<T>(\n name: string,\n options: { mode?: \"exclusive\" | \"shared\"; ifAvailable?: boolean },\n callback: (lock: unknown) => T | Promise<T>,\n ): Promise<T>;\n};\n\nfunction createAutoRetryOwnerId() {\n const cryptoApi =\n typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\"\n ? crypto\n : null;\n return cryptoApi?.randomUUID() ?? `owner-${Math.random().toString(36)}`;\n}\n\nfunction autoRetryClaimKey(threadId: string, runId: string) {\n return `agent-native:stuck-auto-retry:${threadId}:${runId}`;\n}\n\nfunction markAutoRetryClaim(key: string, ownerId: string) {\n if (typeof window === \"undefined\") return true;\n const now = Date.now();\n try {\n const raw = window.localStorage.getItem(key);\n if (raw) {\n const existing = JSON.parse(raw) as {\n ownerId?: unknown;\n expiresAt?: unknown;\n };\n const expiresAt =\n typeof existing.expiresAt === \"number\" ? existing.expiresAt : 0;\n if (expiresAt > now && existing.ownerId !== ownerId) return false;\n }\n window.localStorage.setItem(\n key,\n JSON.stringify({ ownerId, expiresAt: now + AUTO_RETRY_CLAIM_TTL_MS }),\n );\n const confirmed = JSON.parse(window.localStorage.getItem(key) ?? \"{}\") as {\n ownerId?: unknown;\n };\n return confirmed.ownerId === ownerId;\n } catch {\n // Private browsing or disabled storage: fall back to in-tab retry. The\n // server abort is idempotent, and manual controls remain available.\n return true;\n }\n}\n\nasync function claimAutoRetryAttempt(\n threadId: string | null | undefined,\n runId: string,\n ownerId: string,\n) {\n if (!threadId) return true;\n const key = autoRetryClaimKey(threadId, runId);\n const locks =\n typeof navigator !== \"undefined\"\n ? (navigator as Navigator & { locks?: MaybeLockManager }).locks\n : undefined;\n if (locks?.request) {\n try {\n return await locks.request(\n key,\n { mode: \"exclusive\", ifAvailable: true },\n (lock) => (lock ? markAutoRetryClaim(key, ownerId) : false),\n );\n } catch {\n return markAutoRetryClaim(key, ownerId);\n }\n }\n return markAutoRetryClaim(key, ownerId);\n}\n\nexport function RunStuckBanner({\n threadId,\n apiUrl,\n stuckThresholdMs,\n onRetry,\n onStuckStateChange,\n autoRetry = false,\n autoRetryOwnerId,\n className,\n}: RunStuckBannerProps) {\n const state = useRunStuckDetection({ threadId, stuckThresholdMs, apiUrl });\n const abortRun = useAbortRun(apiUrl);\n const [busy, setBusy] = useState<BusyState>({ type: \"none\" });\n const autoRetriedRunIdsRef = useRef<Set<string>>(new Set());\n const generatedOwnerIdRef = useRef<string | null>(null);\n if (!generatedOwnerIdRef.current) {\n generatedOwnerIdRef.current = createAutoRetryOwnerId();\n }\n const ownerId = autoRetryOwnerId ?? generatedOwnerIdRef.current;\n\n const lastReportedRef = useRef<{\n isStuck: boolean;\n runId: string | null;\n }>({ isStuck: false, runId: null });\n useEffect(() => {\n const last = lastReportedRef.current;\n if (last.isStuck === state.isStuck && last.runId === state.runId) return;\n lastReportedRef.current = { isStuck: state.isStuck, runId: state.runId };\n onStuckStateChange?.(state);\n if (state.isStuck && state.runId) {\n trackEvent(\"agent_chat_stuck_detected\", {\n runId: state.runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n stuckSinceSec:\n state.stuckSinceMs != null\n ? Math.floor(state.stuckSinceMs / 1000)\n : null,\n runStatus: state.status,\n });\n }\n }, [state, onStuckStateChange, threadId]);\n\n // Reset the busy spinner once the underlying run is no longer the one we\n // acted on. A recovery continuation can start quickly enough that polling\n // never observes an idle state between run ids.\n useEffect(() => {\n setBusy((current) => {\n if (current.type === \"none\") return current;\n if (state.status !== \"running\") return { type: \"none\" };\n if (state.runId && state.runId !== current.runId) return { type: \"none\" };\n return current;\n });\n }, [state.runId, state.status]);\n\n useEffect(() => {\n if (\n !autoRetry ||\n !state.isStuck ||\n !state.runId ||\n busy.type !== \"none\" ||\n autoRetriedRunIdsRef.current.has(state.runId)\n ) {\n return;\n }\n\n const runId = state.runId;\n void claimAutoRetryAttempt(threadId, runId, ownerId).then((claimed) => {\n autoRetriedRunIdsRef.current.add(runId);\n if (!claimed) return;\n setBusy({ type: \"retry\", runId });\n trackEvent(\"agent_chat_stuck_auto_retry\", {\n runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n });\n void abortRun(runId, \"auto_stuck_retry\").then((aborted) => {\n if (aborted) {\n onRetry?.(aborted);\n return;\n }\n setBusy((current) =>\n current.type !== \"none\" && current.runId === runId\n ? { type: \"none\" }\n : current,\n );\n });\n });\n }, [\n abortRun,\n autoRetry,\n busy,\n onRetry,\n ownerId,\n state.isStuck,\n state.runId,\n state.stuckSinceMs,\n threadId,\n ]);\n\n if (!state.isStuck || !state.runId) return null;\n\n const handleCancel = async () => {\n if (!state.runId || busy.type !== \"none\") return;\n const runId = state.runId;\n setBusy({ type: \"cancel\", runId });\n trackEvent(\"agent_chat_stuck_cancel\", {\n runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n });\n await abortRun(runId, \"user_stuck_cancel\");\n };\n\n const handleRetry = async () => {\n if (!state.runId || busy.type !== \"none\") return;\n const runId = state.runId;\n setBusy({ type: \"retry\", runId });\n trackEvent(\"agent_chat_stuck_retry\", {\n runId,\n threadId: threadId ?? null,\n stuckSinceMs: state.stuckSinceMs ?? null,\n });\n const aborted = await abortRun(runId, \"user_stuck_retry\");\n if (aborted) onRetry?.(aborted);\n };\n\n const busyType = busy.type;\n\n const stuckSeconds =\n state.stuckSinceMs != null ? Math.floor(state.stuckSinceMs / 1000) : null;\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={cn(\n \"mx-3 mt-2 flex items-start gap-2.5 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2.5 text-xs text-foreground\",\n className,\n )}\n >\n <IconAlertTriangle\n size={16}\n className=\"mt-0.5 shrink-0 text-amber-500\"\n aria-hidden=\"true\"\n />\n <div className=\"flex min-w-0 flex-1 flex-col gap-1.5\">\n <div className=\"leading-snug\">\n <span className=\"font-medium\">This chat looks stuck.</span>{\" \"}\n <span className=\"text-muted-foreground\">\n No progress\n {stuckSeconds != null ? ` for ${stuckSeconds}s` : \"\"}. The agent may\n have hit a server timeout or lost its connection.\n {autoRetry && busyType === \"retry\"\n ? \" Retrying automatically now.\"\n : \"\"}\n </span>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleRetry}\n disabled={busyType !== \"none\"}\n className=\"inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md bg-foreground px-2.5 text-[11px] font-medium text-background transition-colors hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {busyType === \"retry\" ? (\n <IconLoader2\n size={12}\n className=\"animate-spin\"\n aria-hidden=\"true\"\n />\n ) : null}\n Retry\n </button>\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={busyType !== \"none\"}\n className=\"inline-flex h-7 cursor-pointer items-center gap-1.5 rounded-md border border-border bg-background px-2.5 text-[11px] font-medium text-foreground transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {busyType === \"cancel\" ? (\n <IconLoader2\n size={12}\n className=\"animate-spin\"\n aria-hidden=\"true\"\n />\n ) : null}\n Cancel\n </button>\n </div>\n </div>\n </div>\n );\n}\n"]}
|
|
@@ -9,10 +9,10 @@ import type { WireframeElName, WireframeNode, WireframeTone } from "./wireframe.
|
|
|
9
9
|
* DECOUPLING: the only behavioral change from the plan copy is theme detection —
|
|
10
10
|
* core blocks read `document.documentElement.classList.contains("dark")` (the
|
|
11
11
|
* MermaidBlock precedent) instead of importing `next-themes`. Everything else
|
|
12
|
-
* (the `.plan-wf` / `[data-rough]` class contract the rough overlay
|
|
13
|
-
* the `--wf-*` / `--ink` / `--paper` token names every primitive
|
|
14
|
-
* preserved exactly, so the kit looks identical in plan and renders
|
|
15
|
-
* any app once the matching tokens exist in `core/styles/blocks.css`.
|
|
12
|
+
* (the `.plan-wf` / `.wf-*` / `[data-rough]` class contract the rough overlay
|
|
13
|
+
* measures, the `--wf-*` / `--ink` / `--paper` token names every primitive
|
|
14
|
+
* reads) is preserved exactly, so the kit looks identical in plan and renders
|
|
15
|
+
* correctly in any app once the matching tokens exist in `core/styles/blocks.css`.
|
|
16
16
|
*/
|
|
17
17
|
export type WireframeStyle = "sketchy" | "clean";
|
|
18
18
|
export declare function setWireframeStyle(style: WireframeStyle): void;
|
|
@@ -240,8 +240,8 @@ export declare function renderNodes(nodes: WireframeNode[]): ReactNode;
|
|
|
240
240
|
/** Whether an `el` name has a registered renderer. */
|
|
241
241
|
export declare function hasRenderer(el: string): el is WireframeElName;
|
|
242
242
|
export { REGISTRY as NODE_REGISTRY, V as WFV, toneColors, toneInk, fontWeight };
|
|
243
|
-
/** The default selector used for HTML mockups:
|
|
244
|
-
export declare const HTML_ROUGH_SELECTOR = "[data-rough],button,input,textarea,select,hr";
|
|
243
|
+
/** The default selector used for HTML mockups: standard wireframe primitives plus explicit opt-ins. */
|
|
244
|
+
export declare const HTML_ROUGH_SELECTOR = "[data-rough],button,input,textarea,select,hr,.wf-btn,.wf-card,.wf-box,.wf-pill,.wf-chip,.wf-icon-fallback,[style*='border:'],[style*='border-top:'],[style*='border-right:'],[style*='border-bottom:'],[style*='border-left:']";
|
|
245
245
|
/** Map the 0–100 sketch slider to a rough.js roughness (calm + legible). */
|
|
246
246
|
export declare function sketchRoughness(sketch: number): number;
|
|
247
247
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wireframe-kit.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/wireframe-kit.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"wireframe-kit.d.ts","sourceRoot":"","sources":["../../../../src/client/blocks/library/wireframe-kit.tsx"],"names":[],"mappings":"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"}
|
|
@@ -134,7 +134,7 @@ export function Screen({ children, pad = 0, sketch, density, theme, skeleton = f
|
|
|
134
134
|
// clipping. The frame shell (`ArtboardFrame`) owns the height policy; a
|
|
135
135
|
// caller can still override via `style.height` for a fixed canvas.
|
|
136
136
|
minHeight: "100%",
|
|
137
|
-
background:
|
|
137
|
+
background: "transparent",
|
|
138
138
|
color: V.ink,
|
|
139
139
|
fontFamily: V.hand,
|
|
140
140
|
fontSize: V.fs,
|
|
@@ -658,8 +658,8 @@ export { REGISTRY as NODE_REGISTRY, V as WFV, toneColors, toneInk, fontWeight };
|
|
|
658
658
|
/* Rough overlay (ported from kit/rough.tsx) */
|
|
659
659
|
/* ========================================================================== */
|
|
660
660
|
const gen = rough.generator();
|
|
661
|
-
/** The default selector used for HTML mockups:
|
|
662
|
-
export const HTML_ROUGH_SELECTOR = "[data-rough],button,input,textarea,select,hr";
|
|
661
|
+
/** The default selector used for HTML mockups: standard wireframe primitives plus explicit opt-ins. */
|
|
662
|
+
export const HTML_ROUGH_SELECTOR = "[data-rough],button,input,textarea,select,hr,.wf-btn,.wf-card,.wf-box,.wf-pill,.wf-chip,.wf-icon-fallback,[style*='border:'],[style*='border-top:'],[style*='border-right:'],[style*='border-bottom:'],[style*='border-left:']";
|
|
663
663
|
/** Stable per-element seed so a frame doesn't re-wobble on every measure. */
|
|
664
664
|
function seedFrom(...parts) {
|
|
665
665
|
const value = parts.join(":");
|
|
@@ -744,6 +744,47 @@ function elementStroke(node, fallback) {
|
|
|
744
744
|
}
|
|
745
745
|
return fallback;
|
|
746
746
|
}
|
|
747
|
+
function visibleBorderSides(node) {
|
|
748
|
+
const cs = getComputedStyle(node);
|
|
749
|
+
const sides = [];
|
|
750
|
+
for (const [side, widthProp, colorProp] of [
|
|
751
|
+
["top", "borderTopWidth", "borderTopColor"],
|
|
752
|
+
["right", "borderRightWidth", "borderRightColor"],
|
|
753
|
+
["bottom", "borderBottomWidth", "borderBottomColor"],
|
|
754
|
+
["left", "borderLeftWidth", "borderLeftColor"],
|
|
755
|
+
]) {
|
|
756
|
+
const width = parseFloat(cs[widthProp]);
|
|
757
|
+
const color = cs[colorProp];
|
|
758
|
+
if (width > 0 &&
|
|
759
|
+
color &&
|
|
760
|
+
color !== "rgba(0, 0, 0, 0)" &&
|
|
761
|
+
color !== "transparent") {
|
|
762
|
+
sides.push(side);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
return sides;
|
|
766
|
+
}
|
|
767
|
+
function inferRoughKind(node) {
|
|
768
|
+
const explicit = node.getAttribute("data-rough");
|
|
769
|
+
if (explicit)
|
|
770
|
+
return explicit;
|
|
771
|
+
if (node.tagName === "HR")
|
|
772
|
+
return "line:middle";
|
|
773
|
+
const sides = visibleBorderSides(node);
|
|
774
|
+
if (sides.length !== 1)
|
|
775
|
+
return "rect";
|
|
776
|
+
switch (sides[0]) {
|
|
777
|
+
case "top":
|
|
778
|
+
return "line:top";
|
|
779
|
+
case "right":
|
|
780
|
+
return "line:right";
|
|
781
|
+
case "bottom":
|
|
782
|
+
return "line:bottom";
|
|
783
|
+
case "left":
|
|
784
|
+
return "line:left";
|
|
785
|
+
}
|
|
786
|
+
return "rect";
|
|
787
|
+
}
|
|
747
788
|
function build(scope, opts) {
|
|
748
789
|
const base = scope.getBoundingClientRect();
|
|
749
790
|
const layoutW = scope.offsetWidth;
|
|
@@ -796,7 +837,7 @@ function build(scope, opts) {
|
|
|
796
837
|
const h = r.height / zoom;
|
|
797
838
|
if (w < 2 || h < 2)
|
|
798
839
|
return;
|
|
799
|
-
const kind = node
|
|
840
|
+
const kind = inferRoughKind(node);
|
|
800
841
|
const rawStroke = elementStroke(node, sketch);
|
|
801
842
|
const stroke = sameColor(rawStroke, ink) || (line !== "" && sameColor(rawStroke, line))
|
|
802
843
|
? sketch
|
|
@@ -808,13 +849,19 @@ function build(scope, opts) {
|
|
|
808
849
|
if (kind === "ellipse") {
|
|
809
850
|
drawable = gen.ellipse(x + w / 2, y + h / 2, w, h, o);
|
|
810
851
|
}
|
|
852
|
+
else if (kind === "line:left") {
|
|
853
|
+
drawable = gen.line(x, y, x, y + h, o);
|
|
854
|
+
}
|
|
811
855
|
else if (kind === "line:right") {
|
|
812
856
|
drawable = gen.line(x + w, y, x + w, y + h, o);
|
|
813
857
|
}
|
|
814
858
|
else if (kind === "line:bottom") {
|
|
815
859
|
drawable = gen.line(x, y + h, x + w, y + h, o);
|
|
816
860
|
}
|
|
817
|
-
else if (kind === "line:top"
|
|
861
|
+
else if (kind === "line:top") {
|
|
862
|
+
drawable = gen.line(x, y, x + w, y, o);
|
|
863
|
+
}
|
|
864
|
+
else if (kind === "line:middle") {
|
|
818
865
|
drawable = gen.line(x, y + h / 2, x + w, y + h / 2, o);
|
|
819
866
|
}
|
|
820
867
|
else {
|