@agent-native/core 0.157.8 → 0.157.10
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +26 -8
- package/corpus/templates/analytics/scripts/first-party-analytics-postgres-retention-dry-run.sql +261 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +3 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +75 -31
- package/corpus/templates/analytics/server/lib/workspace-feature-flags.ts +4 -1
- package/corpus/templates/analytics/server/plugins/db.ts +139 -0
- package/corpus/templates/slides/AGENTS.md +14 -10
- package/corpus/templates/slides/actions/export-pptx.ts +1311 -121
- package/corpus/templates/slides/actions/import-file.ts +28 -1
- package/corpus/templates/slides/actions/import-pptx.ts +69 -42
- package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +222 -29
- package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +71 -0
- package/corpus/templates/slides/app/global.css +19 -1
- package/corpus/templates/slides/app/lib/export-google-slides-client.ts +44 -5
- package/corpus/templates/slides/app/lib/export-pdf-client.ts +13 -6
- package/corpus/templates/slides/app/lib/export-pptx-client.ts +601 -30
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +18 -1
- package/corpus/templates/slides/server/handlers/import/html-converter.ts +1240 -22
- package/corpus/templates/slides/server/handlers/import/pdf-fidelity-parser.ts +329 -64
- package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +24 -0
- package/corpus/templates/slides/server/lib/source-import.ts +10 -1
- package/corpus/templates/slides/shared/aspect-ratios.ts +13 -1
- package/dist/agent/harness/migrations.d.ts +4 -0
- package/dist/agent/harness/migrations.js +60 -0
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.js +15 -0
- package/dist/agent/run-loop-with-resume.d.ts +1 -0
- package/dist/agent/run-loop-with-resume.js +44 -12
- package/dist/agent/run-migrations.d.ts +8 -0
- package/dist/agent/run-migrations.js +61 -0
- package/dist/automations/service.d.ts +6 -0
- package/dist/automations/service.js +35 -0
- package/dist/chat-threads/migrations.d.ts +1 -0
- package/dist/chat-threads/migrations.js +1 -0
- package/dist/chat-threads/schema-migrations.d.ts +8 -0
- package/dist/chat-threads/schema-migrations.js +60 -0
- package/dist/cli/code-agent-connector.d.ts +4 -1
- package/dist/cli/code-agent-connector.js +154 -23
- package/dist/cli/code-agent-executor.js +255 -13
- package/dist/cli/code-agent-runs.d.ts +1 -0
- package/dist/cli/code-agent-runs.js +2 -1
- package/dist/cli/portal-workspace.d.ts +49 -0
- package/dist/cli/portal-workspace.js +320 -0
- package/dist/client/AssistantChat.d.ts +1 -1
- package/dist/client/AssistantChat.js +43 -61
- package/dist/client/ConnectBuilderCard.js +33 -5
- package/dist/client/agent-chat-adapter.js +4 -0
- package/dist/client/analytics-platform.d.ts +2 -0
- package/dist/client/analytics-platform.js +12 -0
- package/dist/client/analytics.d.ts +3 -0
- package/dist/client/analytics.js +10 -1
- package/dist/client/chat/index.d.ts +1 -0
- package/dist/client/chat/index.js +1 -0
- package/dist/client/chat/message-components.d.ts +2 -0
- package/dist/client/chat/message-components.js +11 -1
- package/dist/client/chat/run-recovery.d.ts +2 -1
- package/dist/client/chat/run-recovery.js +2 -2
- package/dist/client/chat-first/apps-rail.d.ts +1 -1
- package/dist/client/chat-first/apps-rail.js +11 -11
- package/dist/client/chat-first/surface-tabs.d.ts +1 -1
- package/dist/client/chat-first/surface-tabs.js +38 -36
- package/dist/client/chat-first/types.d.ts +5 -0
- package/dist/client/chat-first.d.ts +1 -1
- package/dist/client/chat-first.js +4 -4
- package/dist/client/desktop-local-code-change.d.ts +10 -0
- package/dist/client/desktop-local-code-change.js +16 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +1 -0
- package/dist/client/observability/ThumbsFeedback.js +53 -26
- package/dist/client/observability/useObservability.d.ts +1 -1
- package/dist/client/observability/useObservability.js +6 -3
- package/dist/client/terminal/AgentTerminal.d.ts +9 -1
- package/dist/client/terminal/AgentTerminal.js +38 -3
- package/dist/client/terminal/index.d.ts +1 -1
- package/dist/client/terminal/index.js +1 -1
- package/dist/client/track.js +9 -1
- package/dist/client/use-action.js +3 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/deploy/build.js +1 -1
- package/dist/feature-flags/a2a-action-route.js +4 -2
- package/dist/feature-flags/permissions.d.ts +2 -0
- package/dist/feature-flags/permissions.js +6 -1
- package/dist/ingestion/pptx.d.ts +92 -1
- package/dist/ingestion/pptx.js +1180 -115
- package/dist/integrations/index.d.ts +3 -3
- package/dist/integrations/index.js +2 -2
- package/dist/integrations/plugin.js +95 -6
- package/dist/integrations/remote-commands-store.d.ts +5 -0
- package/dist/integrations/remote-commands-store.js +63 -22
- package/dist/integrations/remote-devices-store.d.ts +2 -1
- package/dist/integrations/remote-devices-store.js +46 -0
- package/dist/integrations/remote-types.d.ts +20 -0
- package/dist/jobs/actions/list-recurring-jobs.d.ts +3 -0
- package/dist/jobs/actions/list-recurring-jobs.js +5 -1
- package/dist/jobs/frontmatter.d.ts +16 -0
- package/dist/jobs/frontmatter.js +53 -0
- package/dist/jobs/remote-execution.d.ts +42 -0
- package/dist/jobs/remote-execution.js +287 -0
- package/dist/jobs/scheduler.js +102 -3
- package/dist/jobs/tools.js +50 -3
- package/dist/localization/core-messages/ar-SA.js +4 -0
- package/dist/localization/core-messages/de-DE.js +4 -0
- package/dist/localization/core-messages/en-US.d.ts +4 -0
- package/dist/localization/core-messages/en-US.js +4 -0
- package/dist/localization/core-messages/es-ES.js +4 -0
- package/dist/localization/core-messages/fr-FR.js +4 -0
- package/dist/localization/core-messages/hi-IN.js +4 -0
- package/dist/localization/core-messages/ja-JP.js +4 -0
- package/dist/localization/core-messages/ko-KR.js +4 -0
- package/dist/localization/core-messages/pt-BR.js +4 -0
- package/dist/localization/core-messages/zh-CN.js +4 -0
- package/dist/localization/core-messages/zh-TW.js +4 -0
- package/dist/localization/core-messages.d.ts +4 -0
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/feedback.js +40 -16
- package/dist/observability/routes.d.ts +6 -6
- package/dist/observability/routes.js +15 -3
- package/dist/observability/store.js +2 -0
- package/dist/observability/traces.js +5 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/action-routes.d.ts +7 -5
- package/dist/server/action-routes.js +13 -6
- package/dist/server/agent-chat-plugin.js +6 -0
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +1 -0
- package/dist/server/agent-run-context.js +9 -0
- package/dist/server/better-auth-instance.js +4 -0
- package/dist/server/core-routes-plugin.js +8 -1
- package/dist/server/realtime-voice.js +2 -1
- package/dist/server/release-migrations.js +16 -0
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/shared/analytics-platform.d.ts +6 -0
- package/dist/shared/analytics-platform.js +14 -0
- package/dist/shared/mcp-embed-headers.d.ts +1 -1
- package/dist/shared/mcp-embed-headers.js +1 -1
- package/dist/styles/agent-native.css +83 -103
- package/dist/terminal/cli-registry.js +5 -0
- package/dist/tracking/registry.js +9 -1
- package/dist/triggers/actions/list-automations.d.ts +3 -0
- package/dist/triggers/actions/list-automations.js +3 -0
- package/dist/triggers/actions/manage-automation.d.ts +9 -0
- package/dist/triggers/actions/manage-automation.js +14 -2
- package/dist/triggers/actions.js +82 -7
- package/dist/usage/migrations.d.ts +4 -0
- package/dist/usage/migrations.js +45 -0
- package/docs/content/template-content-developers.mdx +48 -0
- package/docs/content/toolkit-ui.mdx +57 -0
- package/package.json +3 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const DESKTOP_LOCAL_CODE_CHANGE_EVENT = "agent-native:desktop-local-code-change";
|
|
2
|
+
/**
|
|
3
|
+
* Ask an embedding desktop shell to prepare a local code-change workspace.
|
|
4
|
+
* The optional target keeps bubbling events scoped to the shell that owns the
|
|
5
|
+
* chat card while preserving a window fallback for standalone consumers.
|
|
6
|
+
*/
|
|
7
|
+
export function requestDesktopLocalCodeChange(prompt, target = typeof window === "undefined" ? null : window) {
|
|
8
|
+
const trimmed = prompt.trim();
|
|
9
|
+
if (!trimmed || !target)
|
|
10
|
+
return false;
|
|
11
|
+
target.dispatchEvent(new CustomEvent(DESKTOP_LOCAL_CODE_CHANGE_EVENT, {
|
|
12
|
+
bubbles: true,
|
|
13
|
+
detail: { prompt: trimmed },
|
|
14
|
+
}));
|
|
15
|
+
return true;
|
|
16
|
+
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Compatibility aggregation only; new code must not import this barrel.
|
|
4
4
|
*/
|
|
5
5
|
export * from "./agent-chat/index.js";
|
|
6
|
+
export * from "./desktop-local-code-change.js";
|
|
6
7
|
export * from "./hooks/index.js";
|
|
7
8
|
export * from "./navigation/index.js";
|
|
8
9
|
export * from "./host/index.js";
|
package/dist/client/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Compatibility aggregation only; new code must not import this barrel.
|
|
4
4
|
*/
|
|
5
5
|
export * from "./agent-chat/index.js";
|
|
6
|
+
export * from "./desktop-local-code-change.js";
|
|
6
7
|
export * from "./hooks/index.js";
|
|
7
8
|
export * from "./navigation/index.js";
|
|
8
9
|
export * from "./host/index.js";
|
|
@@ -1,24 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "@agent-native/toolkit/ui/button";
|
|
3
|
+
import { Textarea } from "@agent-native/toolkit/ui/textarea";
|
|
2
4
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
3
5
|
import { IconThumbUp, IconThumbDown } from "@tabler/icons-react";
|
|
4
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useId, useRef } from "react";
|
|
5
7
|
import { agentNativePath } from "../api-path.js";
|
|
6
8
|
import { useT } from "../i18n.js";
|
|
7
9
|
import { cn } from "../utils.js";
|
|
8
|
-
const THUMBS_DOWN_CATEGORIES = [
|
|
9
|
-
{ value: "Inaccurate", key: "agentChat.feedback.inaccurate" },
|
|
10
|
-
{ value: "Not helpful", key: "agentChat.feedback.notHelpful" },
|
|
11
|
-
{ value: "Wrong tool", key: "agentChat.feedback.wrongTool" },
|
|
12
|
-
{ value: "Too slow", key: "agentChat.feedback.tooSlow" },
|
|
13
|
-
];
|
|
14
10
|
export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
15
11
|
const t = useT();
|
|
16
12
|
const [selection, setSelection] = useState(null);
|
|
17
|
-
const [
|
|
18
|
-
const [
|
|
13
|
+
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
14
|
+
const [textFeedback, setTextFeedback] = useState("");
|
|
15
|
+
const feedbackInputId = useId();
|
|
16
|
+
const feedbackInputRef = useRef(null);
|
|
19
17
|
const sendFeedback = useCallback(async (feedbackType, value) => {
|
|
20
18
|
try {
|
|
21
|
-
await fetch(agentNativePath("/_agent-native/observability/feedback"), {
|
|
19
|
+
const response = await fetch(agentNativePath("/_agent-native/observability/feedback"), {
|
|
22
20
|
method: "POST",
|
|
23
21
|
headers: { "Content-Type": "application/json" },
|
|
24
22
|
body: JSON.stringify({
|
|
@@ -29,38 +27,67 @@ export function ThumbsFeedback({ threadId, runId, messageSeq, className, }) {
|
|
|
29
27
|
value: value ?? "",
|
|
30
28
|
}),
|
|
31
29
|
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
throw new Error(`Feedback submission failed (${response.status})`);
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
32
34
|
}
|
|
33
35
|
catch {
|
|
34
|
-
//
|
|
36
|
+
// coercion-ok: callers receive false and restore the retryable UI state.
|
|
37
|
+
return false;
|
|
35
38
|
}
|
|
36
39
|
}, [threadId, runId, messageSeq]);
|
|
37
40
|
const handleThumbsUp = useCallback(() => {
|
|
38
41
|
if (selection === "up")
|
|
39
42
|
return;
|
|
40
43
|
setSelection("up");
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
setPopoverOpen(false);
|
|
45
|
+
void sendFeedback("thumbs_up").then((submitted) => {
|
|
46
|
+
if (!submitted)
|
|
47
|
+
setSelection(null);
|
|
48
|
+
});
|
|
44
49
|
}, [selection, sendFeedback]);
|
|
45
50
|
const handleThumbsDown = useCallback(() => {
|
|
46
51
|
if (selection === "down") {
|
|
47
|
-
|
|
52
|
+
setPopoverOpen((prev) => !prev);
|
|
48
53
|
return;
|
|
49
54
|
}
|
|
50
55
|
setSelection("down");
|
|
51
|
-
|
|
52
|
-
sendFeedback("thumbs_down")
|
|
56
|
+
setPopoverOpen(true);
|
|
57
|
+
void sendFeedback("thumbs_down").then((submitted) => {
|
|
58
|
+
if (!submitted)
|
|
59
|
+
setSelection(null);
|
|
60
|
+
});
|
|
53
61
|
}, [selection, sendFeedback]);
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
const handleTextFeedback = useCallback(() => {
|
|
63
|
+
const value = textFeedback.trim();
|
|
64
|
+
if (!value)
|
|
65
|
+
return;
|
|
66
|
+
void sendFeedback("text", value).then((submitted) => {
|
|
67
|
+
if (!submitted)
|
|
68
|
+
return;
|
|
69
|
+
setTextFeedback("");
|
|
70
|
+
setPopoverOpen(false);
|
|
71
|
+
});
|
|
72
|
+
}, [sendFeedback, textFeedback]);
|
|
59
73
|
return (_jsxs("div", { className: cn("inline-flex items-center gap-0.5", className), children: [_jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsUp"), onClick: handleThumbsUp, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "up"
|
|
60
74
|
? "text-foreground"
|
|
61
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open:
|
|
75
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbUp, { size: 16, stroke: selection === "up" ? 2.5 : 1.5, fill: selection === "up" ? "currentColor" : "none" }) }), _jsxs(PopoverPrimitive.Root, { open: popoverOpen, onOpenChange: setPopoverOpen, children: [_jsx(PopoverPrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": t("agentChat.feedback.thumbsDown"), onClick: handleThumbsDown, className: cn("flex h-6 w-6 items-center justify-center rounded", selection === "down"
|
|
62
76
|
? "text-foreground"
|
|
63
|
-
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8,
|
|
64
|
-
|
|
65
|
-
|
|
77
|
+
: "text-muted-foreground/70 hover:text-muted-foreground hover:bg-accent/50"), children: _jsx(IconThumbDown, { size: 16, stroke: selection === "down" ? 2.5 : 1.5, fill: selection === "down" ? "currentColor" : "none" }) }) }), _jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { side: "bottom", align: "start", sideOffset: 4, collisionPadding: 8, onOpenAutoFocus: (event) => {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
feedbackInputRef.current?.focus();
|
|
80
|
+
}, className: "z-[300] w-[min(320px,calc(100vw-24px))] overflow-hidden rounded-lg border border-border bg-popover p-3 text-popover-foreground shadow-lg outline-none origin-[var(--radix-popover-content-transform-origin)]", children: _jsxs("form", { className: "flex flex-col gap-2.5", onSubmit: (event) => {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
handleTextFeedback();
|
|
83
|
+
}, children: [_jsx("label", { htmlFor: feedbackInputId, className: "text-xs font-medium text-foreground", children: t("agentChat.feedback.whatWentWrong") }), _jsx(Textarea, { id: feedbackInputId, ref: feedbackInputRef, autoFocus: true, value: textFeedback, onChange: (event) => setTextFeedback(event.target.value), onKeyDown: (event) => {
|
|
84
|
+
if ((event.metaKey || event.ctrlKey) &&
|
|
85
|
+
event.key === "Enter") {
|
|
86
|
+
event.preventDefault();
|
|
87
|
+
handleTextFeedback();
|
|
88
|
+
}
|
|
89
|
+
}, placeholder: t("agentChat.feedback.placeholder"), rows: 3, maxLength: 2000, className: "min-h-20 resize-none px-2.5 py-2 text-xs" }), _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx("span", { className: "text-[11px] text-muted-foreground/75", children: t("agentChat.feedback.keyboardHint").replace("{{shortcut}}", typeof navigator !== "undefined" &&
|
|
90
|
+
/Mac|iPhone|iPad/.test(navigator.userAgent)
|
|
91
|
+
? "⌘"
|
|
92
|
+
: "Ctrl") }), _jsx(Button, { type: "submit", size: "sm", disabled: !textFeedback.trim(), className: "h-7 px-2.5 text-xs", children: t("agentChat.feedback.submit") })] })] }) }) })] })] }));
|
|
66
93
|
}
|
|
@@ -57,7 +57,7 @@ export interface FeedbackEntry {
|
|
|
57
57
|
userId: string | null;
|
|
58
58
|
createdAt: number;
|
|
59
59
|
}
|
|
60
|
-
export declare function useFeedbackList(sinceDays?: number, limit?: number): import("@tanstack/react-query").UseQueryResult<NoInfer<FeedbackEntry[]>, Error>;
|
|
60
|
+
export declare function useFeedbackList(sinceDays?: number, limit?: number, feedbackType?: FeedbackEntry["feedbackType"]): import("@tanstack/react-query").UseQueryResult<NoInfer<FeedbackEntry[]>, Error>;
|
|
61
61
|
export interface FeedbackStats {
|
|
62
62
|
total: number;
|
|
63
63
|
thumbsUp: number;
|
|
@@ -31,11 +31,14 @@ export function useTraceDetail(runId) {
|
|
|
31
31
|
enabled: !!runId,
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
export function useFeedbackList(sinceDays = 7, limit = 100) {
|
|
34
|
+
export function useFeedbackList(sinceDays = 7, limit = 100, feedbackType) {
|
|
35
35
|
const sinceMs = Date.now() - sinceDays * 86_400_000;
|
|
36
|
+
const typeQuery = feedbackType
|
|
37
|
+
? `&feedbackType=${encodeURIComponent(feedbackType)}`
|
|
38
|
+
: "";
|
|
36
39
|
return useQuery({
|
|
37
|
-
queryKey: ["observability", "feedback", sinceDays, limit],
|
|
38
|
-
queryFn: () => fetchJson(`${BASE}/feedback?since=${sinceMs}&limit=${limit}`),
|
|
40
|
+
queryKey: ["observability", "feedback", sinceDays, limit, feedbackType],
|
|
41
|
+
queryFn: () => fetchJson(`${BASE}/feedback?since=${sinceMs}&limit=${limit}${typeQuery}`),
|
|
39
42
|
refetchInterval: 30_000,
|
|
40
43
|
});
|
|
41
44
|
}
|
|
@@ -30,6 +30,14 @@ export interface AgentTerminalProps {
|
|
|
30
30
|
onConnectionChange?: (connected: boolean) => void;
|
|
31
31
|
/** Callback when agent running state changes */
|
|
32
32
|
onAgentRunningChange?: (running: boolean) => void;
|
|
33
|
+
/** Queue a prompt for the CLI once the PTY WebSocket is ready. */
|
|
34
|
+
submitRequest?: AgentTerminalSubmitRequest;
|
|
35
|
+
/** Called after a queued prompt is written to the PTY. */
|
|
36
|
+
onPromptSubmitted?: (request: AgentTerminalSubmitRequest) => void;
|
|
37
|
+
}
|
|
38
|
+
export interface AgentTerminalSubmitRequest {
|
|
39
|
+
id: string | number;
|
|
40
|
+
text: string;
|
|
33
41
|
}
|
|
34
42
|
export declare function formatWebSocketHostname(hostname: string): string;
|
|
35
|
-
export declare function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame, theme, fontSize, className, style, onConnectionChange, onAgentRunningChange, }: AgentTerminalProps): import("react").JSX.Element | null;
|
|
43
|
+
export declare function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame, theme, fontSize, className, style, onConnectionChange, onAgentRunningChange, submitRequest, onPromptSubmitted, }: AgentTerminalProps): import("react").JSX.Element | null;
|
|
@@ -33,7 +33,7 @@ function injectXtermCss() {
|
|
|
33
33
|
.xterm .composition-view { display: none; position: absolute; white-space: nowrap; z-index: 1; }
|
|
34
34
|
.xterm .composition-view.active { display: block; }
|
|
35
35
|
.xterm .xterm-viewport {
|
|
36
|
-
background-color:
|
|
36
|
+
background-color: var(--agent-terminal-background); overflow-y: scroll;
|
|
37
37
|
cursor: default; position: absolute; right: 0; left: 0; top: 0; bottom: 0;
|
|
38
38
|
}
|
|
39
39
|
.xterm .xterm-screen { position: relative; }
|
|
@@ -85,8 +85,12 @@ export function formatWebSocketHostname(hostname) {
|
|
|
85
85
|
? `[${hostname}]`
|
|
86
86
|
: hostname;
|
|
87
87
|
}
|
|
88
|
-
export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame = true, theme, fontSize = 12, className, style, onConnectionChange, onAgentRunningChange, }) {
|
|
88
|
+
export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame = true, theme, fontSize = 12, className, style, onConnectionChange, onAgentRunningChange, submitRequest, onPromptSubmitted, }) {
|
|
89
89
|
const termRef = useRef(null);
|
|
90
|
+
const submitPromptRef = useRef(null);
|
|
91
|
+
const pendingSubmitRequestRef = useRef(null);
|
|
92
|
+
const onPromptSubmittedRef = useRef(onPromptSubmitted);
|
|
93
|
+
onPromptSubmittedRef.current = onPromptSubmitted;
|
|
90
94
|
const [connected, setConnected] = useState(false);
|
|
91
95
|
const [error, setError] = useState(null);
|
|
92
96
|
const [inFrame, setInFrame] = useState(false);
|
|
@@ -226,6 +230,22 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
226
230
|
let agentRunning = false;
|
|
227
231
|
let idleTimer = null;
|
|
228
232
|
let connectionId = 0;
|
|
233
|
+
function submitPrompt(request) {
|
|
234
|
+
const text = request.text.trim();
|
|
235
|
+
if (!text)
|
|
236
|
+
return;
|
|
237
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
238
|
+
pendingSubmitRequestRef.current = request;
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
ws.send(text + "\r");
|
|
242
|
+
agentRunning = true;
|
|
243
|
+
notifyAgentRunning(true);
|
|
244
|
+
if (pendingSubmitRequestRef.current?.id === request.id) {
|
|
245
|
+
pendingSubmitRequestRef.current = null;
|
|
246
|
+
}
|
|
247
|
+
onPromptSubmittedRef.current?.(request);
|
|
248
|
+
}
|
|
229
249
|
function sendResize() {
|
|
230
250
|
if (ws && ws.readyState === WebSocket.OPEN && term) {
|
|
231
251
|
ws.send(JSON.stringify({
|
|
@@ -258,6 +278,9 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
258
278
|
cols: term.cols,
|
|
259
279
|
rows: term.rows,
|
|
260
280
|
}));
|
|
281
|
+
const pendingRequest = pendingSubmitRequestRef.current;
|
|
282
|
+
if (pendingRequest)
|
|
283
|
+
submitPrompt(pendingRequest);
|
|
261
284
|
};
|
|
262
285
|
socket.onmessage = (event) => {
|
|
263
286
|
const data = event.data instanceof ArrayBuffer
|
|
@@ -328,6 +351,10 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
328
351
|
};
|
|
329
352
|
window.addEventListener("message", messageHandler);
|
|
330
353
|
cleanupMessageHandler = () => window.removeEventListener("message", messageHandler);
|
|
354
|
+
submitPromptRef.current = submitPrompt;
|
|
355
|
+
const initialRequest = pendingSubmitRequestRef.current;
|
|
356
|
+
if (initialRequest)
|
|
357
|
+
submitPrompt(initialRequest);
|
|
331
358
|
connect(fullWsUrl);
|
|
332
359
|
// Store cleanup references
|
|
333
360
|
return () => {
|
|
@@ -340,6 +367,7 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
340
367
|
ws.close();
|
|
341
368
|
ws = null;
|
|
342
369
|
}
|
|
370
|
+
submitPromptRef.current = null;
|
|
343
371
|
};
|
|
344
372
|
}
|
|
345
373
|
let cleanup;
|
|
@@ -353,6 +381,12 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
353
381
|
};
|
|
354
382
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
355
383
|
}, [hideInFrame, inFrame, command, flags, wsUrlProp]);
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (!submitRequest)
|
|
386
|
+
return;
|
|
387
|
+
pendingSubmitRequestRef.current = submitRequest;
|
|
388
|
+
submitPromptRef.current?.(submitRequest);
|
|
389
|
+
}, [submitRequest?.id, submitRequest?.text]);
|
|
356
390
|
if (hideInFrame && inFrame) {
|
|
357
391
|
return null;
|
|
358
392
|
}
|
|
@@ -361,6 +395,7 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
361
395
|
...style,
|
|
362
396
|
background: terminalBackground,
|
|
363
397
|
backgroundColor: terminalBackground,
|
|
398
|
+
"--agent-terminal-background": terminalBackground,
|
|
364
399
|
};
|
|
365
400
|
return (_jsx("div", { ref: termRef, className: className, style: {
|
|
366
401
|
width: "100%",
|
|
@@ -374,7 +409,7 @@ export function AgentTerminal({ command, flags, wsUrl: wsUrlProp, hideInFrame =
|
|
|
374
409
|
display: "flex",
|
|
375
410
|
alignItems: "center",
|
|
376
411
|
justifyContent: "center",
|
|
377
|
-
backgroundColor:
|
|
412
|
+
backgroundColor: terminalBackground,
|
|
378
413
|
color: "#ff7b72",
|
|
379
414
|
fontSize: "13px",
|
|
380
415
|
fontFamily: "monospace",
|
package/dist/client/track.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ANALYTICS_CLIENT_PLATFORM_HEADER, ANALYTICS_CLIENT_PLATFORM_PROPERTY, } from "../shared/analytics-platform.js";
|
|
2
|
+
import { getAnalyticsClientPlatform } from "./analytics-platform.js";
|
|
1
3
|
import { getOrCreateAnalyticsSessionId } from "./analytics-session.js";
|
|
2
4
|
import { agentNativePath } from "./api-path.js";
|
|
3
5
|
/**
|
|
@@ -28,9 +30,14 @@ export function track(name, properties) {
|
|
|
28
30
|
return Promise.resolve();
|
|
29
31
|
if (typeof name !== "string" || !name.trim())
|
|
30
32
|
return Promise.resolve();
|
|
33
|
+
const clientPlatform = getAnalyticsClientPlatform();
|
|
34
|
+
const trackedProperties = {
|
|
35
|
+
...(properties ?? {}),
|
|
36
|
+
[ANALYTICS_CLIENT_PLATFORM_PROPERTY]: clientPlatform,
|
|
37
|
+
};
|
|
31
38
|
let body;
|
|
32
39
|
try {
|
|
33
|
-
body = JSON.stringify(
|
|
40
|
+
body = JSON.stringify({ name, properties: trackedProperties });
|
|
34
41
|
}
|
|
35
42
|
catch {
|
|
36
43
|
// Non-serializable properties — drop rather than throw into the caller.
|
|
@@ -45,6 +52,7 @@ export function track(name, properties) {
|
|
|
45
52
|
// middleware trusts it as a first-party marker. Matches the convention
|
|
46
53
|
// used by other client writes (application-state, guided-questions).
|
|
47
54
|
"X-Agent-Native-CSRF": "1",
|
|
55
|
+
[ANALYTICS_CLIENT_PLATFORM_HEADER]: clientPlatform,
|
|
48
56
|
// Same session the action client and agent chat send, so a client event
|
|
49
57
|
// and the server events from the same visit share one session.
|
|
50
58
|
...(browserSessionId
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
* compatibility.
|
|
23
23
|
*/
|
|
24
24
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
25
|
+
import { ANALYTICS_CLIENT_PLATFORM_HEADER } from "../shared/analytics-platform.js";
|
|
26
|
+
import { getAnalyticsClientPlatform } from "./analytics-platform.js";
|
|
25
27
|
import { getOrCreateAnalyticsSessionId } from "./analytics-session.js";
|
|
26
28
|
import { trackEvent } from "./analytics.js";
|
|
27
29
|
import { agentNativePath } from "./api-path.js";
|
|
@@ -203,6 +205,7 @@ async function performActionFetch(name, method, params, options) {
|
|
|
203
205
|
if (browserSessionId) {
|
|
204
206
|
headers["X-Agent-Native-Session-Id"] = browserSessionId;
|
|
205
207
|
}
|
|
208
|
+
headers[ANALYTICS_CLIENT_PLATFORM_HEADER] = getAnalyticsClientPlatform();
|
|
206
209
|
const init = {
|
|
207
210
|
method,
|
|
208
211
|
headers,
|
|
@@ -62,11 +62,11 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
62
62
|
error: string;
|
|
63
63
|
states?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
states: {
|
|
66
67
|
clientId: number;
|
|
67
68
|
state: string;
|
|
68
69
|
}[];
|
|
69
|
-
error?: undefined;
|
|
70
70
|
}>>;
|
|
71
71
|
/**
|
|
72
72
|
* GET /_agent-native/collab/:docId/users
|
|
@@ -77,9 +77,9 @@ export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("
|
|
|
77
77
|
error: string;
|
|
78
78
|
users?: undefined;
|
|
79
79
|
} | {
|
|
80
|
+
error?: undefined;
|
|
80
81
|
users: {
|
|
81
82
|
clientId: number;
|
|
82
83
|
lastSeen: number;
|
|
83
84
|
}[];
|
|
84
|
-
error?: undefined;
|
|
85
85
|
}>>;
|
package/dist/deploy/build.js
CHANGED
|
@@ -1245,7 +1245,7 @@ async function getHandler() {
|
|
|
1245
1245
|
headers: {
|
|
1246
1246
|
"Access-Control-Allow-Origin": "*",
|
|
1247
1247
|
"Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS",
|
|
1248
|
-
"Access-Control-Allow-Headers": "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-Agent-Native-Embed-Target",
|
|
1248
|
+
"Access-Control-Allow-Headers": "Content-Type,Authorization,X-Requested-With,X-Request-Source,X-Agent-Native-CSRF,X-User-Timezone,X-Agent-Native-Session-Id,X-Agent-Native-Client-Platform,X-Agent-Native-Tool-Bridge,X-Agent-Native-Tool-Id,X-Agent-Native-Frontend,X-Agent-Native-Client-Compatibility,X-Agent-Native-Build-Id,X-Agent-Native-Embed-Target",
|
|
1249
1249
|
},
|
|
1250
1250
|
});
|
|
1251
1251
|
}
|
|
@@ -3,6 +3,7 @@ import * as jose from "jose";
|
|
|
3
3
|
import { verifyA2ATokenWithClaims } from "../a2a-claims.js";
|
|
4
4
|
import { resolveOrgByDomain } from "../org/context.js";
|
|
5
5
|
import { consumeOneTimeJti } from "../server/identity-sso-store.js";
|
|
6
|
+
import { isFeatureFlagAdminEmail } from "./permissions.js";
|
|
6
7
|
const FLAG_ACTION_SCOPES = {
|
|
7
8
|
"list-feature-flags": "flags:read",
|
|
8
9
|
"set-feature-flag": "flags:write",
|
|
@@ -40,15 +41,16 @@ export function createFeatureFlagA2AActionRouteAuth(actionName) {
|
|
|
40
41
|
throw new Error("Invalid feature flag delegation");
|
|
41
42
|
}
|
|
42
43
|
const localOrg = await resolveOrgByDomain(claims.orgDomain);
|
|
43
|
-
if (!localOrg)
|
|
44
|
+
if (!localOrg && !isFeatureFlagAdminEmail(claims.email)) {
|
|
44
45
|
throw new Error("Invalid feature flag delegation");
|
|
46
|
+
}
|
|
45
47
|
if (actionName === "set-feature-flag" &&
|
|
46
48
|
(await consumeOneTimeJti(claims.jti))) {
|
|
47
49
|
throw new Error("Invalid feature flag delegation");
|
|
48
50
|
}
|
|
49
51
|
return {
|
|
50
52
|
owner: claims.email,
|
|
51
|
-
orgId: localOrg
|
|
53
|
+
orgId: localOrg?.orgId ?? null,
|
|
52
54
|
anonymous: false,
|
|
53
55
|
delegationJti: claims.jti,
|
|
54
56
|
delegationIssuer: claims.issuer,
|
|
@@ -2,6 +2,8 @@ export declare class FeatureFlagPermissionError extends Error {
|
|
|
2
2
|
statusCode: number;
|
|
3
3
|
constructor(message: string, statusCode: number);
|
|
4
4
|
}
|
|
5
|
+
/** Return whether an email is explicitly allowed to manage no-org flags. */
|
|
6
|
+
export declare function isFeatureFlagAdminEmail(email: string | undefined): boolean;
|
|
5
7
|
/** Require an org admin/owner, or an explicit production no-org allowlist entry. */
|
|
6
8
|
export declare function requireFeatureFlagManager(scope: {
|
|
7
9
|
userEmail?: string;
|
|
@@ -13,6 +13,11 @@ function productionAdminAllowlist() {
|
|
|
13
13
|
.map((email) => email.trim().toLowerCase())
|
|
14
14
|
.filter(Boolean));
|
|
15
15
|
}
|
|
16
|
+
/** Return whether an email is explicitly allowed to manage no-org flags. */
|
|
17
|
+
export function isFeatureFlagAdminEmail(email) {
|
|
18
|
+
const normalized = email?.trim().toLowerCase();
|
|
19
|
+
return Boolean(normalized && productionAdminAllowlist().has(normalized));
|
|
20
|
+
}
|
|
16
21
|
/** Require an org admin/owner, or an explicit production no-org allowlist entry. */
|
|
17
22
|
export async function requireFeatureFlagManager(scope) {
|
|
18
23
|
const email = scope.userEmail?.trim().toLowerCase();
|
|
@@ -29,7 +34,7 @@ export async function requireFeatureFlagManager(scope) {
|
|
|
29
34
|
}
|
|
30
35
|
if (process.env.NODE_ENV !== "production")
|
|
31
36
|
return { email, orgId: null };
|
|
32
|
-
if (!
|
|
37
|
+
if (!isFeatureFlagAdminEmail(email)) {
|
|
33
38
|
throw new FeatureFlagPermissionError("Feature flag management without an organization requires an explicit admin allowlist entry.", 403);
|
|
34
39
|
}
|
|
35
40
|
return { email, orgId: null };
|
package/dist/ingestion/pptx.d.ts
CHANGED
|
@@ -21,21 +21,35 @@ export interface ParsedPptxParagraph {
|
|
|
21
21
|
lineSpacing?: number;
|
|
22
22
|
spaceBeforePt?: number;
|
|
23
23
|
spaceAfterPt?: number;
|
|
24
|
+
/** `a:pPr/@_rtl` — the paragraph's base writing direction is right-to-left. Only set when the source states it; absent means inherit (LTR). */
|
|
25
|
+
rtl?: boolean;
|
|
24
26
|
}
|
|
25
27
|
export interface ParsedPptxElement {
|
|
26
28
|
id: string;
|
|
27
29
|
name?: string;
|
|
28
30
|
placeholderType?: string;
|
|
29
|
-
kind: "text" | "image" | "shape";
|
|
31
|
+
kind: "text" | "image" | "shape" | "table";
|
|
30
32
|
x: number;
|
|
31
33
|
y: number;
|
|
32
34
|
width: number;
|
|
33
35
|
height: number;
|
|
34
36
|
rotation?: number;
|
|
37
|
+
/** `a:xfrm/@_flipH` — the shape's geometry is mirrored across its own vertical axis before rotation. */
|
|
38
|
+
flipH?: boolean;
|
|
39
|
+
/** `a:xfrm/@_flipV` — the shape's geometry is mirrored across its own horizontal axis before rotation. */
|
|
40
|
+
flipV?: boolean;
|
|
35
41
|
shapeType?: string;
|
|
42
|
+
/** `a:prstGeom/a:avLst` adjustment values keyed by guide name (`adj`, `adj1`, ...), in the preset's own units. Absent when the deck accepts the preset's defaults. */
|
|
43
|
+
shapeAdjustments?: Record<string, number>;
|
|
44
|
+
/** `a:custGeom`'s authored outline, when the shape declares one instead of a preset. */
|
|
45
|
+
geometry?: ParsedPptxGeometry;
|
|
36
46
|
fill?: string;
|
|
37
47
|
lineColor?: string;
|
|
38
48
|
lineWidth?: number;
|
|
49
|
+
/** `a:ln/a:headEnd` — the decoration drawn where the line starts. */
|
|
50
|
+
lineHeadEnd?: ParsedPptxLineEnd;
|
|
51
|
+
/** `a:ln/a:tailEnd` — the decoration drawn where the line ends. */
|
|
52
|
+
lineTailEnd?: ParsedPptxLineEnd;
|
|
39
53
|
padding?: {
|
|
40
54
|
left: number;
|
|
41
55
|
right: number;
|
|
@@ -45,6 +59,79 @@ export interface ParsedPptxElement {
|
|
|
45
59
|
verticalAlign?: "top" | "middle" | "bottom";
|
|
46
60
|
paragraphs?: ParsedPptxParagraph[];
|
|
47
61
|
image?: ParsedPptxImage;
|
|
62
|
+
table?: ParsedPptxTable;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* One end of a line or connector — the round dots a chevron timeline's
|
|
66
|
+
* connectors terminate in (`<a:headEnd type="oval"/>`), an arrowhead, a
|
|
67
|
+
* diamond. Recorded whatever the type, including the ones a consumer cannot
|
|
68
|
+
* draw, so an end a renderer skips stays distinguishable from a line the
|
|
69
|
+
* source drew bare and an export can still round-trip it.
|
|
70
|
+
*/
|
|
71
|
+
export interface ParsedPptxLineEnd {
|
|
72
|
+
/** `@_type`: `none`, `triangle`, `stealth`, `diamond`, `oval`, or `arrow`. */
|
|
73
|
+
type: string;
|
|
74
|
+
/** `@_w`/`@_len` — the end's size across and along the line, as `sm`/`med`/`lg` multiples of the line's own width, not absolute units. Absent means the OOXML default (`med`). */
|
|
75
|
+
w?: string;
|
|
76
|
+
len?: string;
|
|
77
|
+
}
|
|
78
|
+
/** A single `a:path` command, in the path's own `w`/`h` coordinate space. `arcTo` keeps OOXML's radii-and-angles form because converting it needs the current point, which only a consumer walking the whole command list knows. */
|
|
79
|
+
export type ParsedPptxPathCommand = {
|
|
80
|
+
kind: "moveTo" | "lnTo" | "quadBezTo" | "cubicBezTo";
|
|
81
|
+
points: {
|
|
82
|
+
x: number;
|
|
83
|
+
y: number;
|
|
84
|
+
}[];
|
|
85
|
+
} | {
|
|
86
|
+
kind: "arcTo";
|
|
87
|
+
/** Ellipse radii in path units. */
|
|
88
|
+
wR: number;
|
|
89
|
+
hR: number;
|
|
90
|
+
/** Start angle and swing, in 60000ths of a degree, clockwise from the +x axis. */
|
|
91
|
+
stAng: number;
|
|
92
|
+
swAng: number;
|
|
93
|
+
} | {
|
|
94
|
+
kind: "close";
|
|
95
|
+
};
|
|
96
|
+
/** One `a:custGeom/a:pathLst/a:path`. `w`/`h` define the coordinate space its points are expressed in; the shape's own box is what they scale onto. */
|
|
97
|
+
export interface ParsedPptxPath {
|
|
98
|
+
w: number;
|
|
99
|
+
h: number;
|
|
100
|
+
commands: ParsedPptxPathCommand[];
|
|
101
|
+
}
|
|
102
|
+
export interface ParsedPptxGeometry {
|
|
103
|
+
kind: "custom";
|
|
104
|
+
paths: ParsedPptxPath[];
|
|
105
|
+
}
|
|
106
|
+
/** A `p:graphicFrame`'s `a:tbl` flattened into a simple row/cell grid. `hMerge`/`vMerge` continuation cells are omitted — their content is already represented once, by the spanning cell's `colSpan`/`rowSpan`. */
|
|
107
|
+
export interface ParsedPptxTable {
|
|
108
|
+
rows: ParsedPptxTableCell[][];
|
|
109
|
+
/** Authored `a:tblGrid/a:gridCol/@_w` values, in EMUs, when present. */
|
|
110
|
+
columnWidthsEmu?: number[];
|
|
111
|
+
/** Authored `a:tr/@_h` values, in EMUs, when present. */
|
|
112
|
+
rowHeightsEmu?: number[];
|
|
113
|
+
}
|
|
114
|
+
export interface ParsedPptxTableCell {
|
|
115
|
+
paragraphs: ParsedPptxParagraph[];
|
|
116
|
+
colSpan?: number;
|
|
117
|
+
rowSpan?: number;
|
|
118
|
+
fill?: string;
|
|
119
|
+
/** Resolved cell edges. A side is present only when the cell's own `a:tcPr/a:lnL|R|T|B` or the deck table style's `a:tcBdr` draws a line there — a cell the source leaves borderless stays borderless. */
|
|
120
|
+
borders?: ParsedPptxTableCellBorders;
|
|
121
|
+
}
|
|
122
|
+
export interface ParsedPptxTableCellBorders {
|
|
123
|
+
left?: ParsedPptxTableBorder;
|
|
124
|
+
right?: ParsedPptxTableBorder;
|
|
125
|
+
top?: ParsedPptxTableBorder;
|
|
126
|
+
bottom?: ParsedPptxTableBorder;
|
|
127
|
+
}
|
|
128
|
+
/** One resolved table cell edge, from an `a:ln`. */
|
|
129
|
+
export interface ParsedPptxTableBorder {
|
|
130
|
+
color: string;
|
|
131
|
+
/** `a:ln/@_w`, in EMU. Absent when the line declares no width. */
|
|
132
|
+
widthEmu?: number;
|
|
133
|
+
/** `a:prstDash/@_val`, collapsed onto the CSS border styles that can draw it. Absent for a solid line. */
|
|
134
|
+
dash?: "dashed" | "dotted";
|
|
48
135
|
}
|
|
49
136
|
export type ParsedPptxTransition = "instant" | "none" | "fade" | "slide" | "zoom";
|
|
50
137
|
export interface ParsedPptxImage {
|
|
@@ -75,6 +162,8 @@ export interface ParsedPptxSlide {
|
|
|
75
162
|
layoutHint?: string;
|
|
76
163
|
transition?: ParsedPptxTransition;
|
|
77
164
|
splitByParagraph?: boolean;
|
|
165
|
+
/** Count of this slide's `graphicFrame` shapes that could not be converted into a `"table"` element (charts, SmartArt, embedded OLE objects, or a malformed/empty `a:tbl`) — a fidelity signal for `buildSourceImportMetadata`, the same way `imagesSkipped` already works. */
|
|
166
|
+
tablesDegraded?: number;
|
|
78
167
|
}
|
|
79
168
|
export interface ParsedPptxGrid {
|
|
80
169
|
color: string;
|
|
@@ -95,6 +184,8 @@ export interface ParsedPptxPresentation {
|
|
|
95
184
|
colors: string[];
|
|
96
185
|
fonts: string[];
|
|
97
186
|
};
|
|
187
|
+
/** Slides the source deck marked `show="0"` and this import deliberately left out — the only legitimate reason `slides.length` is short of the deck's `p:sldId` count, so callers can say so instead of reporting a silently shorter deck. */
|
|
188
|
+
hiddenSlideCount?: number;
|
|
98
189
|
}
|
|
99
190
|
export declare function parsePptxPresentation(fileBuffer: Uint8Array): Promise<ParsedPptxPresentation>;
|
|
100
191
|
export declare function parsePptxSlideMetadata(value: unknown): ParsedPptxSlideMetadata;
|