@flanksource/clicky-ui 0.3.5 → 0.3.7
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 +42 -0
- package/dist/ai.cjs +15 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +15 -0
- package/dist/ai.js.map +1 -1
- package/dist/components/DateField.d.ts +1 -1
- package/dist/components/DatePicker.d.ts +1 -1
- package/dist/components/DateTimePicker.d.ts +1 -1
- package/dist/components/FormLookupProvider.cjs +12 -0
- package/dist/components/FormLookupProvider.cjs.map +1 -0
- package/dist/components/FormLookupProvider.d.ts +7 -0
- package/dist/components/FormLookupProvider.d.ts.map +1 -0
- package/dist/components/FormLookupProvider.js +12 -0
- package/dist/components/FormLookupProvider.js.map +1 -0
- package/dist/components/JsonSchemaForm.cjs +2 -2
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.js +1 -1
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/ListMenu.cjs +145 -0
- package/dist/components/ListMenu.cjs.map +1 -0
- package/dist/components/ListMenu.d.ts +54 -0
- package/dist/components/ListMenu.d.ts.map +1 -0
- package/dist/components/ListMenu.js +145 -0
- package/dist/components/ListMenu.js.map +1 -0
- package/dist/components/MdxEditorField.cjs +128 -0
- package/dist/components/MdxEditorField.cjs.map +1 -0
- package/dist/components/MdxEditorField.d.ts +4 -0
- package/dist/components/MdxEditorField.d.ts.map +1 -0
- package/dist/components/MdxEditorField.js +106 -0
- package/dist/components/MdxEditorField.js.map +1 -0
- package/dist/components/MdxEditorToolbar.cjs +76 -0
- package/dist/components/MdxEditorToolbar.cjs.map +1 -0
- package/dist/components/MdxEditorToolbar.d.ts +8 -0
- package/dist/components/MdxEditorToolbar.d.ts.map +1 -0
- package/dist/components/MdxEditorToolbar.js +76 -0
- package/dist/components/MdxEditorToolbar.js.map +1 -0
- package/dist/components/button-variants.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/form-lookup-context.cjs +1 -8
- package/dist/components/form-lookup-context.cjs.map +1 -1
- package/dist/components/form-lookup-context.d.ts +1 -5
- package/dist/components/form-lookup-context.d.ts.map +1 -1
- package/dist/components/form-lookup-context.js +1 -8
- package/dist/components/form-lookup-context.js.map +1 -1
- package/dist/components/jotai-bindings-core.cjs +197 -0
- package/dist/components/jotai-bindings-core.cjs.map +1 -0
- package/dist/components/jotai-bindings-core.d.ts +45 -0
- package/dist/components/jotai-bindings-core.d.ts.map +1 -0
- package/dist/components/jotai-bindings-core.js +197 -0
- package/dist/components/jotai-bindings-core.js.map +1 -0
- package/dist/components/jotai-bindings.cjs +17 -0
- package/dist/components/jotai-bindings.cjs.map +1 -0
- package/dist/components/jotai-bindings.d.ts +4 -0
- package/dist/components/jotai-bindings.d.ts.map +1 -0
- package/dist/components/jotai-bindings.js +17 -0
- package/dist/components/jotai-bindings.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +37 -0
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts +6 -0
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +38 -1
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +3 -1
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +4 -2
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +9 -0
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +9 -0
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +4 -1
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/mdx-editor-field-plugins.cjs +124 -0
- package/dist/components/mdx-editor-field-plugins.cjs.map +1 -0
- package/dist/components/mdx-editor-field-plugins.d.ts +6 -0
- package/dist/components/mdx-editor-field-plugins.d.ts.map +1 -0
- package/dist/components/mdx-editor-field-plugins.js +124 -0
- package/dist/components/mdx-editor-field-plugins.js.map +1 -0
- package/dist/components/mdx-editor-options.d.ts +77 -0
- package/dist/components/mdx-editor-options.d.ts.map +1 -0
- package/dist/components/use-list-menu-selection.cjs +77 -0
- package/dist/components/use-list-menu-selection.cjs.map +1 -0
- package/dist/components/use-list-menu-selection.d.ts +40 -0
- package/dist/components/use-list-menu-selection.d.ts.map +1 -0
- package/dist/components/use-list-menu-selection.js +77 -0
- package/dist/components/use-list-menu-selection.js.map +1 -0
- package/dist/components.cjs +10 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +4 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +10 -1
- package/dist/components.js.map +1 -1
- package/dist/data/MarkdownEditor.model.d.ts +1 -1
- package/dist/data/ProgressBars.cjs +194 -0
- package/dist/data/ProgressBars.cjs.map +1 -0
- package/dist/data/ProgressBars.d.ts +85 -0
- package/dist/data/ProgressBars.d.ts.map +1 -0
- package/dist/data/ProgressBars.js +194 -0
- package/dist/data/ProgressBars.js.map +1 -0
- package/dist/data/ProgressBars.model.cjs +27 -0
- package/dist/data/ProgressBars.model.cjs.map +1 -0
- package/dist/data/ProgressBars.model.d.ts +20 -0
- package/dist/data/ProgressBars.model.d.ts.map +1 -0
- package/dist/data/ProgressBars.model.js +27 -0
- package/dist/data/ProgressBars.model.js.map +1 -0
- package/dist/data/PromptBanner.cjs +199 -0
- package/dist/data/PromptBanner.cjs.map +1 -0
- package/dist/data/PromptBanner.d.ts +17 -0
- package/dist/data/PromptBanner.d.ts.map +1 -0
- package/dist/data/PromptBanner.js +199 -0
- package/dist/data/PromptBanner.js.map +1 -0
- package/dist/data/PromptBanner.model.cjs +132 -0
- package/dist/data/PromptBanner.model.cjs.map +1 -0
- package/dist/data/PromptBanner.model.d.ts +23 -0
- package/dist/data/PromptBanner.model.d.ts.map +1 -0
- package/dist/data/PromptBanner.model.js +132 -0
- package/dist/data/PromptBanner.model.js.map +1 -0
- package/dist/data/PromptDialog.cjs +43 -0
- package/dist/data/PromptDialog.cjs.map +1 -0
- package/dist/data/PromptDialog.d.ts +14 -0
- package/dist/data/PromptDialog.d.ts.map +1 -0
- package/dist/data/PromptDialog.js +43 -0
- package/dist/data/PromptDialog.js.map +1 -0
- package/dist/data/TaskManager.cjs +8 -1
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +8 -1
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskProgress.cjs +15 -2
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +0 -10
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +15 -2
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.cjs +19 -173
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +9 -26
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +20 -174
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/WorkloadCard.model.cjs.map +1 -1
- package/dist/data/WorkloadCard.model.d.ts +2 -2
- package/dist/data/WorkloadCard.model.d.ts.map +1 -1
- package/dist/data/WorkloadCard.model.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +53 -9
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +53 -9
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +275 -0
- package/dist/data/ai/SessionViewer.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.d.ts +33 -0
- package/dist/data/ai/SessionViewer.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts +4 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.js +275 -0
- package/dist/data/ai/SessionViewer.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +275 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts +87 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.model.js +275 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -0
- package/dist/data/ai/SessionViewerMenu.cjs +190 -0
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -0
- package/dist/data/ai/SessionViewerMenu.d.ts +24 -0
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -0
- package/dist/data/ai/SessionViewerMenu.js +190 -0
- package/dist/data/ai/SessionViewerMenu.js.map +1 -0
- package/dist/data/ai/ToolPreferences.cjs +232 -39
- package/dist/data/ai/ToolPreferences.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.d.ts +4 -7
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.js +234 -41
- package/dist/data/ai/ToolPreferences.js.map +1 -1
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/session-categories.cjs +219 -0
- package/dist/data/ai/session-categories.cjs.map +1 -0
- package/dist/data/ai/session-categories.d.ts +36 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -0
- package/dist/data/ai/session-categories.js +219 -0
- package/dist/data/ai/session-categories.js.map +1 -0
- package/dist/data/chat/clickyOperationsToTools.cjs +89 -3
- package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.d.ts +1 -1
- package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.js +89 -3
- package/dist/data/chat/clickyOperationsToTools.js.map +1 -1
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +7 -1
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/task-status.cjs +19 -12
- package/dist/data/task-status.cjs.map +1 -1
- package/dist/data/task-status.d.ts +2 -1
- package/dist/data/task-status.d.ts.map +1 -1
- package/dist/data/task-status.js +19 -12
- package/dist/data/task-status.js.map +1 -1
- package/dist/data/test-runner/TestRunner.fixtures.d.ts +11 -4
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +11 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +6 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +11 -2
- package/dist/data.js.map +1 -1
- package/dist/hooks/use-prompts.cjs +83 -0
- package/dist/hooks/use-prompts.cjs.map +1 -0
- package/dist/hooks/use-prompts.d.ts +43 -0
- package/dist/hooks/use-prompts.d.ts.map +1 -0
- package/dist/hooks/use-prompts.js +83 -0
- package/dist/hooks/use-prompts.js.map +1 -0
- package/dist/hooks.cjs +3 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +3 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +21 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/jotai.cjs +9 -0
- package/dist/jotai.cjs.map +1 -0
- package/dist/jotai.d.ts +4 -0
- package/dist/jotai.d.ts.map +1 -0
- package/dist/jotai.js +9 -0
- package/dist/jotai.js.map +1 -0
- package/dist/lib/utils.cjs +18 -1
- package/dist/lib/utils.cjs.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +18 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/mdx-editor.cjs +5 -0
- package/dist/mdx-editor.cjs.map +1 -0
- package/dist/mdx-editor.css +2 -0
- package/dist/mdx-editor.d.ts +2 -0
- package/dist/mdx-editor.d.ts.map +1 -0
- package/dist/mdx-editor.js +5 -0
- package/dist/mdx-editor.js.map +1 -0
- package/dist/rpc/apiClient.cjs +1 -1
- package/dist/rpc/apiClient.cjs.map +1 -1
- package/dist/rpc/apiClient.js +1 -1
- package/dist/rpc/apiClient.js.map +1 -1
- package/dist/rpc/surfaceIconMap.cjs +12 -1
- package/dist/rpc/surfaceIconMap.cjs.map +1 -1
- package/dist/rpc/surfaceIconMap.d.ts.map +1 -1
- package/dist/rpc/surfaceIconMap.js +12 -1
- package/dist/rpc/surfaceIconMap.js.map +1 -1
- package/dist/rpc/types.cjs.map +1 -1
- package/dist/rpc/types.d.ts +1 -0
- package/dist/rpc/types.d.ts.map +1 -1
- package/dist/rpc/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/oxlint-plugins/README.md +148 -0
- package/oxlint-plugins/clicky-ui-no-adhoc-overlay.js +88 -0
- package/oxlint-plugins/clicky-ui-prefer-components.js +46 -0
- package/oxlint-plugins/clicky-ui-prefer-icons.js +121 -0
- package/oxlint-plugins/clicky-ui-prefer-tailwind.js +98 -0
- package/oxlint-plugins/clicky-ui-prefer-theme.js +134 -0
- package/oxlint-plugins/clicky-ui-shared.js +132 -0
- package/oxlint-plugins/clicky-ui.js +34 -0
- package/oxlint-plugins/no-iconify-names.js +37 -0
- package/package.json +21 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +0 -27
- package/dist/data/TimeseriesCoreBars.model.cjs.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.d.ts +0 -20
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.js +0 -27
- package/dist/data/TimeseriesCoreBars.model.js.map +0 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useMemo, useEffect } from "react";
|
|
3
|
+
import { Button } from "../components/button.js";
|
|
4
|
+
import { Icon } from "./Icon.js";
|
|
5
|
+
import { cn } from "../lib/utils.js";
|
|
6
|
+
import { usePrompts, answerPrompt } from "../hooks/use-prompts.js";
|
|
7
|
+
import { PromptDialog } from "./PromptDialog.js";
|
|
8
|
+
import { analyzePromptInlineActions, summarizePrompts, initialPromptComment, buildPromptInlineValues, summarizePromptAnswer } from "./PromptBanner.model.js";
|
|
9
|
+
import { UiQuestion } from "../icons/components/UiQuestion.js";
|
|
10
|
+
import { UiRobotAi } from "../icons/components/UiRobotAi.js";
|
|
11
|
+
import { UiClose } from "../icons/components/UiClose.js";
|
|
12
|
+
import { UiCheck } from "../icons/components/UiCheck.js";
|
|
13
|
+
import { UiHourglass } from "../icons/components/UiHourglass.js";
|
|
14
|
+
import { UiComment } from "../icons/components/UiComment.js";
|
|
15
|
+
function PromptBanner({
|
|
16
|
+
basePath = "/api/todos",
|
|
17
|
+
enabled,
|
|
18
|
+
title,
|
|
19
|
+
className,
|
|
20
|
+
inlineActions = "auto",
|
|
21
|
+
showSummary = true,
|
|
22
|
+
historyLimit = 5,
|
|
23
|
+
state: _ignoredState,
|
|
24
|
+
...filter
|
|
25
|
+
}) {
|
|
26
|
+
const { prompts, pending } = usePrompts({
|
|
27
|
+
...filter,
|
|
28
|
+
basePath,
|
|
29
|
+
...enabled !== void 0 ? { enabled } : {},
|
|
30
|
+
...showSummary ? {} : { state: "pending" }
|
|
31
|
+
});
|
|
32
|
+
const [active, setActive] = useState(null);
|
|
33
|
+
const [comment, setComment] = useState("");
|
|
34
|
+
const [resolving, setResolving] = useState(null);
|
|
35
|
+
const [error, setError] = useState(null);
|
|
36
|
+
const next = pending[0];
|
|
37
|
+
const activePrompt = active ?? next;
|
|
38
|
+
const inlineSpec = useMemo(
|
|
39
|
+
() => inlineActions === "auto" && activePrompt ? analyzePromptInlineActions(activePrompt) : null,
|
|
40
|
+
[activePrompt, inlineActions]
|
|
41
|
+
);
|
|
42
|
+
const summary = useMemo(() => summarizePrompts(prompts), [prompts]);
|
|
43
|
+
const recent = prompts.slice(0, Math.max(0, historyLimit));
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setComment(activePrompt ? initialPromptComment(activePrompt, inlineSpec) : "");
|
|
46
|
+
setError(null);
|
|
47
|
+
setResolving(null);
|
|
48
|
+
}, [activePrompt == null ? void 0 : activePrompt.id, inlineSpec]);
|
|
49
|
+
if (showSummary ? prompts.length === 0 : !next) return null;
|
|
50
|
+
const headline = title ?? (pending.length > 1 ? `${pending.length} questions need your input` : (next == null ? void 0 : next.title) ?? "No pending prompts");
|
|
51
|
+
const resolveInline = async (decision) => {
|
|
52
|
+
if (!activePrompt || !inlineSpec) return;
|
|
53
|
+
setResolving(decision);
|
|
54
|
+
setError(null);
|
|
55
|
+
try {
|
|
56
|
+
await answerPrompt(basePath, activePrompt.id, {
|
|
57
|
+
values: buildPromptInlineValues(activePrompt, inlineSpec, decision, comment)
|
|
58
|
+
});
|
|
59
|
+
setActive(null);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
62
|
+
} finally {
|
|
63
|
+
setResolving(null);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const commentRequiredButEmpty = Boolean((inlineSpec == null ? void 0 : inlineSpec.commentRequired) && comment.trim().length === 0);
|
|
67
|
+
return /* @__PURE__ */ jsxs(
|
|
68
|
+
"section",
|
|
69
|
+
{
|
|
70
|
+
"aria-label": "Prompt requests",
|
|
71
|
+
className: cn(
|
|
72
|
+
"rounded-md border border-border bg-card px-3 py-2 text-card-foreground",
|
|
73
|
+
className
|
|
74
|
+
),
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
77
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
78
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-2", children: [
|
|
79
|
+
/* @__PURE__ */ jsx(Icon, { icon: next ? UiQuestion : UiRobotAi, className: "mt-0.5 size-4 shrink-0" }),
|
|
80
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
81
|
+
/* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium", children: headline }),
|
|
82
|
+
(next == null ? void 0 : next.description) ? /* @__PURE__ */ jsx("div", { className: "mt-0.5 line-clamp-2 text-xs opacity-80", children: next.description }) : null
|
|
83
|
+
] })
|
|
84
|
+
] }),
|
|
85
|
+
showSummary ? /* @__PURE__ */ jsx(PromptSummaryCounts, { summary }) : null
|
|
86
|
+
] }),
|
|
87
|
+
next ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: inlineSpec ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
88
|
+
inlineSpec.commentField ? /* @__PURE__ */ jsxs("label", { className: "flex min-w-0 flex-col gap-1 text-xs", children: [
|
|
89
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: inlineSpec.commentLabel ?? "Comment" }),
|
|
90
|
+
/* @__PURE__ */ jsx(
|
|
91
|
+
"textarea",
|
|
92
|
+
{
|
|
93
|
+
className: "min-h-16 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
94
|
+
placeholder: "Add a short note",
|
|
95
|
+
value: comment,
|
|
96
|
+
onChange: (event) => setComment(event.target.value)
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
] }) : null,
|
|
100
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [
|
|
101
|
+
error ? /* @__PURE__ */ jsx("span", { className: "mr-auto text-xs text-red-600 dark:text-red-300", children: error }) : null,
|
|
102
|
+
/* @__PURE__ */ jsxs(
|
|
103
|
+
Button,
|
|
104
|
+
{
|
|
105
|
+
size: "sm",
|
|
106
|
+
variant: "outline",
|
|
107
|
+
type: "button",
|
|
108
|
+
loading: resolving === "reject",
|
|
109
|
+
disabled: resolving !== null || commentRequiredButEmpty,
|
|
110
|
+
onClick: () => void resolveInline("reject"),
|
|
111
|
+
className: "gap-1.5",
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiClose, className: "size-3.5" }),
|
|
114
|
+
"Reject"
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
/* @__PURE__ */ jsxs(
|
|
119
|
+
Button,
|
|
120
|
+
{
|
|
121
|
+
size: "sm",
|
|
122
|
+
type: "button",
|
|
123
|
+
loading: resolving === "approve",
|
|
124
|
+
disabled: resolving !== null || commentRequiredButEmpty,
|
|
125
|
+
onClick: () => void resolveInline("approve"),
|
|
126
|
+
className: "gap-1.5",
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiCheck, className: "size-3.5" }),
|
|
129
|
+
"Approve"
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
),
|
|
133
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "ghost", type: "button", onClick: () => setActive(next), children: "More" })
|
|
134
|
+
] })
|
|
135
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ jsx(Button, { size: "sm", type: "button", onClick: () => setActive(next), children: "Answer" }) }) }) : null,
|
|
136
|
+
showSummary && recent.length > 0 ? /* @__PURE__ */ jsx(PromptHistory, { prompts: recent, activeId: next == null ? void 0 : next.id }) : null
|
|
137
|
+
] }),
|
|
138
|
+
active ? /* @__PURE__ */ jsx(
|
|
139
|
+
PromptDialog,
|
|
140
|
+
{
|
|
141
|
+
prompt: active,
|
|
142
|
+
basePath,
|
|
143
|
+
open: true,
|
|
144
|
+
onClose: () => setActive(null),
|
|
145
|
+
onResolved: () => setActive(null)
|
|
146
|
+
}
|
|
147
|
+
) : null
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
function PromptSummaryCounts({ summary }) {
|
|
153
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs opacity-85", children: [
|
|
154
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 font-medium", children: [
|
|
155
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiHourglass, className: "size-3.5" }),
|
|
156
|
+
summary.pending,
|
|
157
|
+
" pending"
|
|
158
|
+
] }),
|
|
159
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
160
|
+
summary.answered,
|
|
161
|
+
" answered"
|
|
162
|
+
] }),
|
|
163
|
+
(summary.cancelled > 0 || summary.expired > 0) && /* @__PURE__ */ jsxs("span", { children: [
|
|
164
|
+
summary.cancelled + summary.expired,
|
|
165
|
+
" closed"
|
|
166
|
+
] })
|
|
167
|
+
] });
|
|
168
|
+
}
|
|
169
|
+
function PromptHistory({ prompts, activeId }) {
|
|
170
|
+
return /* @__PURE__ */ jsx("ol", { className: "divide-y divide-border overflow-hidden rounded-md border border-border bg-background text-xs", children: prompts.map((prompt) => /* @__PURE__ */ jsxs(
|
|
171
|
+
"li",
|
|
172
|
+
{
|
|
173
|
+
className: cn("flex min-w-0 items-start gap-2 px-2 py-1.5", prompt.id === activeId && "bg-muted/60"),
|
|
174
|
+
children: [
|
|
175
|
+
/* @__PURE__ */ jsx(PromptStateIcon, { prompt }),
|
|
176
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
177
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
178
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium text-foreground", children: prompt.title }),
|
|
179
|
+
prompt.kind ? /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", children: prompt.kind }) : null
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 truncate text-muted-foreground", children: summarizePromptAnswer(prompt) })
|
|
182
|
+
] })
|
|
183
|
+
]
|
|
184
|
+
},
|
|
185
|
+
prompt.id
|
|
186
|
+
)) });
|
|
187
|
+
}
|
|
188
|
+
function PromptStateIcon({ prompt }) {
|
|
189
|
+
if (prompt.state === "answered") return /* @__PURE__ */ jsx(Icon, { icon: UiCheck, className: "mt-0.5 size-3.5 shrink-0 text-emerald-600" });
|
|
190
|
+
if (prompt.state === "cancelled" || prompt.state === "expired") {
|
|
191
|
+
return /* @__PURE__ */ jsx(Icon, { icon: UiClose, className: "mt-0.5 size-3.5 shrink-0 text-rose-600" });
|
|
192
|
+
}
|
|
193
|
+
if (prompt.kind === "comment") return /* @__PURE__ */ jsx(Icon, { icon: UiComment, className: "mt-0.5 size-3.5 shrink-0" });
|
|
194
|
+
return /* @__PURE__ */ jsx(Icon, { icon: UiHourglass, className: "mt-0.5 size-3.5 shrink-0" });
|
|
195
|
+
}
|
|
196
|
+
export {
|
|
197
|
+
PromptBanner
|
|
198
|
+
};
|
|
199
|
+
//# sourceMappingURL=PromptBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptBanner.js","sources":["../../src/data/PromptBanner.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Icon } from \"./Icon\";\nimport { UiCheck, UiClose, UiComment, UiHourglass, UiQuestion, UiRobotAi } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { answerPrompt, usePrompts, type PromptFilter, type PromptSnapshot } from \"../hooks/use-prompts\";\nimport { PromptDialog } from \"./PromptDialog\";\nimport {\n analyzePromptInlineActions,\n buildPromptInlineValues,\n initialPromptComment,\n summarizePromptAnswer,\n summarizePrompts,\n type PromptInlineDecision,\n} from \"./PromptBanner.model\";\n\nexport interface PromptBannerProps extends PromptFilter {\n /** Base path the prompt API is mounted under, e.g. \"/api/todos\". */\n basePath?: string | undefined;\n enabled?: boolean | undefined;\n /** Override the headline; defaults to a count-aware message. */\n title?: string | undefined;\n className?: string | undefined;\n /** Render approve/reject quick actions when the prompt schema supports them. */\n inlineActions?: \"auto\" | false | undefined;\n /** Show compact counts and recent prompt outcomes, not only the current pending prompt. */\n showSummary?: boolean | undefined;\n /** Maximum recent prompts shown in the summary list. */\n historyLimit?: number | undefined;\n}\n\n// PromptBanner subscribes to pending prompts for a scope (owner / session label)\n// and surfaces them as an inline affordance, opening a PromptDialog to answer.\n// Mount it scoped to a todo (owner) at the top of a detail page, or to a session\n// (labels.session) inside a session view using the same component and filters.\nexport function PromptBanner({\n basePath = \"/api/todos\",\n enabled,\n title,\n className,\n inlineActions = \"auto\",\n showSummary = true,\n historyLimit = 5,\n state: _ignoredState,\n ...filter\n}: PromptBannerProps) {\n const { prompts, pending } = usePrompts({\n ...filter,\n basePath,\n ...(enabled !== undefined ? { enabled } : {}),\n ...(showSummary ? {} : { state: \"pending\" }),\n });\n const [active, setActive] = useState<PromptSnapshot | null>(null);\n const [comment, setComment] = useState(\"\");\n const [resolving, setResolving] = useState<PromptInlineDecision | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const next = pending[0];\n const activePrompt = active ?? next;\n const inlineSpec = useMemo(\n () => (inlineActions === \"auto\" && activePrompt ? analyzePromptInlineActions(activePrompt) : null),\n [activePrompt, inlineActions],\n );\n const summary = useMemo(() => summarizePrompts(prompts), [prompts]);\n const recent = prompts.slice(0, Math.max(0, historyLimit));\n\n useEffect(() => {\n setComment(activePrompt ? initialPromptComment(activePrompt, inlineSpec) : \"\");\n setError(null);\n setResolving(null);\n }, [activePrompt?.id, inlineSpec]);\n\n if (showSummary ? prompts.length === 0 : !next) return null;\n const headline =\n title ??\n (pending.length > 1\n ? `${pending.length} questions need your input`\n : next?.title ?? \"No pending prompts\");\n\n const resolveInline = async (decision: PromptInlineDecision) => {\n if (!activePrompt || !inlineSpec) return;\n setResolving(decision);\n setError(null);\n try {\n await answerPrompt(basePath, activePrompt.id, {\n values: buildPromptInlineValues(activePrompt, inlineSpec, decision, comment),\n });\n setActive(null);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setResolving(null);\n }\n };\n\n const commentRequiredButEmpty = Boolean(inlineSpec?.commentRequired && comment.trim().length === 0);\n\n return (\n <section\n aria-label=\"Prompt requests\"\n className={cn(\n \"rounded-md border border-border bg-card px-3 py-2 text-card-foreground\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"flex min-w-0 flex-1 items-start gap-2\">\n <Icon icon={next ? UiQuestion : UiRobotAi} className=\"mt-0.5 size-4 shrink-0\" />\n <div className=\"min-w-0\">\n <div className=\"truncate text-sm font-medium\">{headline}</div>\n {next?.description ? (\n <div className=\"mt-0.5 line-clamp-2 text-xs opacity-80\">{next.description}</div>\n ) : null}\n </div>\n </div>\n {showSummary ? <PromptSummaryCounts summary={summary} /> : null}\n </div>\n\n {next ? (\n <div className=\"flex flex-col gap-2\">\n {inlineSpec ? (\n <div className=\"flex flex-col gap-2\">\n {inlineSpec.commentField ? (\n <label className=\"flex min-w-0 flex-col gap-1 text-xs\">\n <span className=\"font-medium\">{inlineSpec.commentLabel ?? \"Comment\"}</span>\n <textarea\n className=\"min-h-16 w-full resize-y rounded-md border border-input bg-background px-2 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n placeholder=\"Add a short note\"\n value={comment}\n onChange={(event) => setComment(event.target.value)}\n />\n </label>\n ) : null}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {error ? <span className=\"mr-auto text-xs text-red-600 dark:text-red-300\">{error}</span> : null}\n <Button\n size=\"sm\"\n variant=\"outline\"\n type=\"button\"\n loading={resolving === \"reject\"}\n disabled={resolving !== null || commentRequiredButEmpty}\n onClick={() => void resolveInline(\"reject\")}\n className=\"gap-1.5\"\n >\n <Icon icon={UiClose} className=\"size-3.5\" />\n Reject\n </Button>\n <Button\n size=\"sm\"\n type=\"button\"\n loading={resolving === \"approve\"}\n disabled={resolving !== null || commentRequiredButEmpty}\n onClick={() => void resolveInline(\"approve\")}\n className=\"gap-1.5\"\n >\n <Icon icon={UiCheck} className=\"size-3.5\" />\n Approve\n </Button>\n <Button size=\"sm\" variant=\"ghost\" type=\"button\" onClick={() => setActive(next)}>\n More\n </Button>\n </div>\n </div>\n ) : (\n <div className=\"flex items-center justify-end\">\n <Button size=\"sm\" type=\"button\" onClick={() => setActive(next)}>\n Answer\n </Button>\n </div>\n )}\n </div>\n ) : null}\n\n {showSummary && recent.length > 0 ? <PromptHistory prompts={recent} activeId={next?.id} /> : null}\n </div>\n {active ? (\n <PromptDialog\n prompt={active}\n basePath={basePath}\n open={true}\n onClose={() => setActive(null)}\n onResolved={() => setActive(null)}\n />\n ) : null}\n </section>\n );\n}\n\nfunction PromptSummaryCounts({ summary }: { summary: ReturnType<typeof summarizePrompts> }) {\n return (\n <div className=\"flex shrink-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs opacity-85\">\n <span className=\"inline-flex items-center gap-1 font-medium\">\n <Icon icon={UiHourglass} className=\"size-3.5\" />\n {summary.pending} pending\n </span>\n <span>{summary.answered} answered</span>\n {(summary.cancelled > 0 || summary.expired > 0) && (\n <span>{summary.cancelled + summary.expired} closed</span>\n )}\n </div>\n );\n}\n\nfunction PromptHistory({ prompts, activeId }: { prompts: PromptSnapshot[]; activeId?: string | undefined }) {\n return (\n <ol className=\"divide-y divide-border overflow-hidden rounded-md border border-border bg-background text-xs\">\n {prompts.map((prompt) => (\n <li\n key={prompt.id}\n className={cn(\"flex min-w-0 items-start gap-2 px-2 py-1.5\", prompt.id === activeId && \"bg-muted/60\")}\n >\n <PromptStateIcon prompt={prompt} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"truncate font-medium text-foreground\">{prompt.title}</span>\n {prompt.kind ? <span className=\"shrink-0 text-muted-foreground\">{prompt.kind}</span> : null}\n </div>\n <div className=\"mt-0.5 truncate text-muted-foreground\">{summarizePromptAnswer(prompt)}</div>\n </div>\n </li>\n ))}\n </ol>\n );\n}\n\nfunction PromptStateIcon({ prompt }: { prompt: PromptSnapshot }) {\n if (prompt.state === \"answered\") return <Icon icon={UiCheck} className=\"mt-0.5 size-3.5 shrink-0 text-emerald-600\" />;\n if (prompt.state === \"cancelled\" || prompt.state === \"expired\") {\n return <Icon icon={UiClose} className=\"mt-0.5 size-3.5 shrink-0 text-rose-600\" />;\n }\n if (prompt.kind === \"comment\") return <Icon icon={UiComment} className=\"mt-0.5 size-3.5 shrink-0\" />;\n return <Icon icon={UiHourglass} className=\"mt-0.5 size-3.5 shrink-0\" />;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const ACTION_FIELD_PRIORITY = ["decision", "choice", "action", "value", "approve", "approved"];
|
|
4
|
+
const COMMENT_FIELD_PRIORITY = ["comment", "reason", "message", "note"];
|
|
5
|
+
const APPROVE_RE = /\b(approve|approved|allow|allowed|continue|yes|accept|accepted|proceed|run)\b/i;
|
|
6
|
+
const REJECT_RE = /\b(reject|rejected|deny|denied|cancel|cancelled|canceled|no|block|stop|decline|declined)\b/i;
|
|
7
|
+
function hasType(schema, type) {
|
|
8
|
+
if (!(schema == null ? void 0 : schema.type)) return false;
|
|
9
|
+
return Array.isArray(schema.type) ? schema.type.includes(type) : schema.type === type;
|
|
10
|
+
}
|
|
11
|
+
function sortedPropertyEntries(schema) {
|
|
12
|
+
const entries = Object.entries(schema.properties ?? {});
|
|
13
|
+
return entries.sort(([a], [b]) => {
|
|
14
|
+
const ia = ACTION_FIELD_PRIORITY.indexOf(a);
|
|
15
|
+
const ib = ACTION_FIELD_PRIORITY.indexOf(b);
|
|
16
|
+
if (ia === -1 && ib === -1) return 0;
|
|
17
|
+
if (ia === -1) return 1;
|
|
18
|
+
if (ib === -1) return -1;
|
|
19
|
+
return ia - ib;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function optionText(schema, value) {
|
|
23
|
+
var _a;
|
|
24
|
+
const key = String(value);
|
|
25
|
+
const label = (_a = schema["x-enum-labels"]) == null ? void 0 : _a[key];
|
|
26
|
+
return [key, label].filter(Boolean).join(" ");
|
|
27
|
+
}
|
|
28
|
+
function findCommentField(schema) {
|
|
29
|
+
const properties = schema.properties ?? {};
|
|
30
|
+
const required = new Set(schema.required ?? []);
|
|
31
|
+
for (const key of COMMENT_FIELD_PRIORITY) {
|
|
32
|
+
const property = properties[key];
|
|
33
|
+
if (!property || !hasType(property, "string") || property.enum) continue;
|
|
34
|
+
return {
|
|
35
|
+
commentField: key,
|
|
36
|
+
commentRequired: required.has(key),
|
|
37
|
+
commentLabel: property.title ?? "Comment"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return { commentRequired: false };
|
|
41
|
+
}
|
|
42
|
+
function findEnumAction(schema) {
|
|
43
|
+
for (const [field, property] of sortedPropertyEntries(schema)) {
|
|
44
|
+
const values = property.enum ?? [];
|
|
45
|
+
if (values.length === 0) continue;
|
|
46
|
+
const approve = values.find((value) => APPROVE_RE.test(optionText(property, value)));
|
|
47
|
+
const reject = values.find((value) => REJECT_RE.test(optionText(property, value)));
|
|
48
|
+
if (approve === void 0 || reject === void 0) continue;
|
|
49
|
+
return {
|
|
50
|
+
field,
|
|
51
|
+
approveValue: approve,
|
|
52
|
+
rejectValue: reject,
|
|
53
|
+
...findCommentField(schema)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function findBooleanAction(schema) {
|
|
59
|
+
var _a;
|
|
60
|
+
const properties = schema.properties ?? {};
|
|
61
|
+
const preferred = ["value", "approve", "approved", "confirm", "confirmed", "allowed"];
|
|
62
|
+
const field = preferred.find((key) => hasType(properties[key], "boolean")) ?? ((_a = Object.entries(properties).find(([, property]) => hasType(property, "boolean"))) == null ? void 0 : _a[0]);
|
|
63
|
+
if (!field) return null;
|
|
64
|
+
return {
|
|
65
|
+
field,
|
|
66
|
+
approveValue: true,
|
|
67
|
+
rejectValue: false,
|
|
68
|
+
...findCommentField(schema)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function analyzePromptInlineActions(prompt) {
|
|
72
|
+
const schema = prompt.schema;
|
|
73
|
+
if (!(schema == null ? void 0 : schema.properties)) return null;
|
|
74
|
+
return findEnumAction(schema) ?? findBooleanAction(schema);
|
|
75
|
+
}
|
|
76
|
+
function initialPromptComment(prompt, spec) {
|
|
77
|
+
var _a;
|
|
78
|
+
if (!(spec == null ? void 0 : spec.commentField)) return "";
|
|
79
|
+
const value = (_a = prompt.value) == null ? void 0 : _a[spec.commentField];
|
|
80
|
+
return typeof value === "string" ? value : "";
|
|
81
|
+
}
|
|
82
|
+
function buildPromptInlineValues(prompt, spec, decision, comment) {
|
|
83
|
+
const values = { ...prompt.value };
|
|
84
|
+
values[spec.field] = decision === "approve" ? spec.approveValue : spec.rejectValue;
|
|
85
|
+
if (spec.commentField) {
|
|
86
|
+
const trimmed = comment.trim();
|
|
87
|
+
if (trimmed || spec.commentRequired) {
|
|
88
|
+
values[spec.commentField] = trimmed;
|
|
89
|
+
} else {
|
|
90
|
+
delete values[spec.commentField];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return values;
|
|
94
|
+
}
|
|
95
|
+
function summarizePrompts(prompts) {
|
|
96
|
+
return prompts.reduce(
|
|
97
|
+
(acc, prompt) => {
|
|
98
|
+
acc.total += 1;
|
|
99
|
+
if (prompt.state === "pending") acc.pending += 1;
|
|
100
|
+
else if (prompt.state === "answered") acc.answered += 1;
|
|
101
|
+
else if (prompt.state === "cancelled") acc.cancelled += 1;
|
|
102
|
+
else if (prompt.state === "expired") acc.expired += 1;
|
|
103
|
+
return acc;
|
|
104
|
+
},
|
|
105
|
+
{ total: 0, pending: 0, answered: 0, cancelled: 0, expired: 0 }
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function summarizePromptAnswer(prompt) {
|
|
109
|
+
if (prompt.cancelled || prompt.state === "cancelled") return "Cancelled";
|
|
110
|
+
if (prompt.state === "expired") return "Expired";
|
|
111
|
+
if (prompt.state === "pending") return prompt.kind ? `Pending ${prompt.kind}` : "Pending";
|
|
112
|
+
const values = prompt.value ?? {};
|
|
113
|
+
const spec = analyzePromptInlineActions(prompt);
|
|
114
|
+
const parts = [];
|
|
115
|
+
if (spec && spec.field in values) {
|
|
116
|
+
if (Object.is(values[spec.field], spec.approveValue)) parts.push("Approved");
|
|
117
|
+
else if (Object.is(values[spec.field], spec.rejectValue)) parts.push("Rejected");
|
|
118
|
+
}
|
|
119
|
+
if (spec == null ? void 0 : spec.commentField) {
|
|
120
|
+
const comment = values[spec.commentField];
|
|
121
|
+
if (typeof comment === "string" && comment) parts.push(comment);
|
|
122
|
+
}
|
|
123
|
+
if (parts.length > 0) return parts.join(" - ");
|
|
124
|
+
const primitive = Object.entries(values).filter(([, value]) => ["string", "number", "boolean"].includes(typeof value)).slice(0, 2).map(([key, value]) => `${key}: ${String(value)}`);
|
|
125
|
+
return primitive.join(" - ") || prompt.state;
|
|
126
|
+
}
|
|
127
|
+
exports.analyzePromptInlineActions = analyzePromptInlineActions;
|
|
128
|
+
exports.buildPromptInlineValues = buildPromptInlineValues;
|
|
129
|
+
exports.initialPromptComment = initialPromptComment;
|
|
130
|
+
exports.summarizePromptAnswer = summarizePromptAnswer;
|
|
131
|
+
exports.summarizePrompts = summarizePrompts;
|
|
132
|
+
//# sourceMappingURL=PromptBanner.model.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptBanner.model.cjs","sources":["../../src/data/PromptBanner.model.ts"],"sourcesContent":["import type { JsonSchemaObject, JsonSchemaProperty } from \"../components/json-schema-form-types\";\nimport type { PromptSnapshot } from \"../hooks/use-prompts\";\n\nexport type PromptInlineDecision = \"approve\" | \"reject\";\n\nexport interface PromptInlineActionSpec {\n field: string;\n approveValue: unknown;\n rejectValue: unknown;\n commentField?: string;\n commentRequired: boolean;\n commentLabel?: string;\n}\n\nexport interface PromptSummary {\n total: number;\n pending: number;\n answered: number;\n cancelled: number;\n expired: number;\n}\n\nconst ACTION_FIELD_PRIORITY = [\"decision\", \"choice\", \"action\", \"value\", \"approve\", \"approved\"];\nconst COMMENT_FIELD_PRIORITY = [\"comment\", \"reason\", \"message\", \"note\"];\n\nconst APPROVE_RE = /\\b(approve|approved|allow|allowed|continue|yes|accept|accepted|proceed|run)\\b/i;\nconst REJECT_RE = /\\b(reject|rejected|deny|denied|cancel|cancelled|canceled|no|block|stop|decline|declined)\\b/i;\n\nfunction hasType(schema: JsonSchemaProperty | undefined, type: string): boolean {\n if (!schema?.type) return false;\n return Array.isArray(schema.type) ? schema.type.includes(type as never) : schema.type === type;\n}\n\nfunction sortedPropertyEntries(schema: JsonSchemaObject): [string, JsonSchemaProperty][] {\n const entries = Object.entries(schema.properties ?? {});\n return entries.sort(([a], [b]) => {\n const ia = ACTION_FIELD_PRIORITY.indexOf(a);\n const ib = ACTION_FIELD_PRIORITY.indexOf(b);\n if (ia === -1 && ib === -1) return 0;\n if (ia === -1) return 1;\n if (ib === -1) return -1;\n return ia - ib;\n });\n}\n\nfunction optionText(schema: JsonSchemaProperty, value: unknown): string {\n const key = String(value);\n const label = schema[\"x-enum-labels\"]?.[key];\n return [key, label].filter(Boolean).join(\" \");\n}\n\nfunction findCommentField(schema: JsonSchemaObject): Pick<\n PromptInlineActionSpec,\n \"commentField\" | \"commentRequired\" | \"commentLabel\"\n> {\n const properties = schema.properties ?? {};\n const required = new Set(schema.required ?? []);\n for (const key of COMMENT_FIELD_PRIORITY) {\n const property = properties[key];\n if (!property || !hasType(property, \"string\") || property.enum) continue;\n return {\n commentField: key,\n commentRequired: required.has(key),\n commentLabel: property.title ?? \"Comment\",\n };\n }\n return { commentRequired: false };\n}\n\nfunction findEnumAction(schema: JsonSchemaObject): PromptInlineActionSpec | null {\n for (const [field, property] of sortedPropertyEntries(schema)) {\n const values = property.enum ?? [];\n if (values.length === 0) continue;\n\n const approve = values.find((value) => APPROVE_RE.test(optionText(property, value)));\n const reject = values.find((value) => REJECT_RE.test(optionText(property, value)));\n if (approve === undefined || reject === undefined) continue;\n\n return {\n field,\n approveValue: approve,\n rejectValue: reject,\n ...findCommentField(schema),\n };\n }\n return null;\n}\n\nfunction findBooleanAction(schema: JsonSchemaObject): PromptInlineActionSpec | null {\n const properties = schema.properties ?? {};\n const preferred = [\"value\", \"approve\", \"approved\", \"confirm\", \"confirmed\", \"allowed\"];\n const field =\n preferred.find((key) => hasType(properties[key], \"boolean\")) ??\n Object.entries(properties).find(([, property]) => hasType(property, \"boolean\"))?.[0];\n\n if (!field) return null;\n return {\n field,\n approveValue: true,\n rejectValue: false,\n ...findCommentField(schema),\n };\n}\n\nexport function analyzePromptInlineActions(prompt: PromptSnapshot): PromptInlineActionSpec | null {\n const schema = prompt.schema;\n if (!schema?.properties) return null;\n return findEnumAction(schema) ?? findBooleanAction(schema);\n}\n\nexport function initialPromptComment(prompt: PromptSnapshot, spec: PromptInlineActionSpec | null): string {\n if (!spec?.commentField) return \"\";\n const value = prompt.value?.[spec.commentField];\n return typeof value === \"string\" ? value : \"\";\n}\n\nexport function buildPromptInlineValues(\n prompt: PromptSnapshot,\n spec: PromptInlineActionSpec,\n decision: PromptInlineDecision,\n comment: string,\n): Record<string, unknown> {\n const values: Record<string, unknown> = { ...prompt.value };\n values[spec.field] = decision === \"approve\" ? spec.approveValue : spec.rejectValue;\n\n if (spec.commentField) {\n const trimmed = comment.trim();\n if (trimmed || spec.commentRequired) {\n values[spec.commentField] = trimmed;\n } else {\n delete values[spec.commentField];\n }\n }\n\n return values;\n}\n\nexport function summarizePrompts(prompts: PromptSnapshot[]): PromptSummary {\n return prompts.reduce<PromptSummary>(\n (acc, prompt) => {\n acc.total += 1;\n if (prompt.state === \"pending\") acc.pending += 1;\n else if (prompt.state === \"answered\") acc.answered += 1;\n else if (prompt.state === \"cancelled\") acc.cancelled += 1;\n else if (prompt.state === \"expired\") acc.expired += 1;\n return acc;\n },\n { total: 0, pending: 0, answered: 0, cancelled: 0, expired: 0 },\n );\n}\n\nexport function summarizePromptAnswer(prompt: PromptSnapshot): string {\n if (prompt.cancelled || prompt.state === \"cancelled\") return \"Cancelled\";\n if (prompt.state === \"expired\") return \"Expired\";\n if (prompt.state === \"pending\") return prompt.kind ? `Pending ${prompt.kind}` : \"Pending\";\n\n const values = prompt.value ?? {};\n const spec = analyzePromptInlineActions(prompt);\n const parts: string[] = [];\n if (spec && spec.field in values) {\n if (Object.is(values[spec.field], spec.approveValue)) parts.push(\"Approved\");\n else if (Object.is(values[spec.field], spec.rejectValue)) parts.push(\"Rejected\");\n }\n if (spec?.commentField) {\n const comment = values[spec.commentField];\n if (typeof comment === \"string\" && comment) parts.push(comment);\n }\n if (parts.length > 0) return parts.join(\" - \");\n\n const primitive = Object.entries(values)\n .filter(([, value]) => [\"string\", \"number\", \"boolean\"].includes(typeof value))\n .slice(0, 2)\n .map(([key, value]) => `${key}: ${String(value)}`);\n return primitive.join(\" - \") || prompt.state;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { PromptSnapshot } from '../hooks/use-prompts';
|
|
2
|
+
export type PromptInlineDecision = "approve" | "reject";
|
|
3
|
+
export interface PromptInlineActionSpec {
|
|
4
|
+
field: string;
|
|
5
|
+
approveValue: unknown;
|
|
6
|
+
rejectValue: unknown;
|
|
7
|
+
commentField?: string;
|
|
8
|
+
commentRequired: boolean;
|
|
9
|
+
commentLabel?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface PromptSummary {
|
|
12
|
+
total: number;
|
|
13
|
+
pending: number;
|
|
14
|
+
answered: number;
|
|
15
|
+
cancelled: number;
|
|
16
|
+
expired: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function analyzePromptInlineActions(prompt: PromptSnapshot): PromptInlineActionSpec | null;
|
|
19
|
+
export declare function initialPromptComment(prompt: PromptSnapshot, spec: PromptInlineActionSpec | null): string;
|
|
20
|
+
export declare function buildPromptInlineValues(prompt: PromptSnapshot, spec: PromptInlineActionSpec, decision: PromptInlineDecision, comment: string): Record<string, unknown>;
|
|
21
|
+
export declare function summarizePrompts(prompts: PromptSnapshot[]): PromptSummary;
|
|
22
|
+
export declare function summarizePromptAnswer(prompt: PromptSnapshot): string;
|
|
23
|
+
//# sourceMappingURL=PromptBanner.model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptBanner.model.d.ts","sourceRoot":"","sources":["../../src/data/PromptBanner.model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAoFD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,cAAc,GAAG,sBAAsB,GAAG,IAAI,CAIhG;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,sBAAsB,GAAG,IAAI,GAAG,MAAM,CAIxG;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,sBAAsB,EAC5B,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,aAAa,CAYzE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAuBpE"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const ACTION_FIELD_PRIORITY = ["decision", "choice", "action", "value", "approve", "approved"];
|
|
2
|
+
const COMMENT_FIELD_PRIORITY = ["comment", "reason", "message", "note"];
|
|
3
|
+
const APPROVE_RE = /\b(approve|approved|allow|allowed|continue|yes|accept|accepted|proceed|run)\b/i;
|
|
4
|
+
const REJECT_RE = /\b(reject|rejected|deny|denied|cancel|cancelled|canceled|no|block|stop|decline|declined)\b/i;
|
|
5
|
+
function hasType(schema, type) {
|
|
6
|
+
if (!(schema == null ? void 0 : schema.type)) return false;
|
|
7
|
+
return Array.isArray(schema.type) ? schema.type.includes(type) : schema.type === type;
|
|
8
|
+
}
|
|
9
|
+
function sortedPropertyEntries(schema) {
|
|
10
|
+
const entries = Object.entries(schema.properties ?? {});
|
|
11
|
+
return entries.sort(([a], [b]) => {
|
|
12
|
+
const ia = ACTION_FIELD_PRIORITY.indexOf(a);
|
|
13
|
+
const ib = ACTION_FIELD_PRIORITY.indexOf(b);
|
|
14
|
+
if (ia === -1 && ib === -1) return 0;
|
|
15
|
+
if (ia === -1) return 1;
|
|
16
|
+
if (ib === -1) return -1;
|
|
17
|
+
return ia - ib;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function optionText(schema, value) {
|
|
21
|
+
var _a;
|
|
22
|
+
const key = String(value);
|
|
23
|
+
const label = (_a = schema["x-enum-labels"]) == null ? void 0 : _a[key];
|
|
24
|
+
return [key, label].filter(Boolean).join(" ");
|
|
25
|
+
}
|
|
26
|
+
function findCommentField(schema) {
|
|
27
|
+
const properties = schema.properties ?? {};
|
|
28
|
+
const required = new Set(schema.required ?? []);
|
|
29
|
+
for (const key of COMMENT_FIELD_PRIORITY) {
|
|
30
|
+
const property = properties[key];
|
|
31
|
+
if (!property || !hasType(property, "string") || property.enum) continue;
|
|
32
|
+
return {
|
|
33
|
+
commentField: key,
|
|
34
|
+
commentRequired: required.has(key),
|
|
35
|
+
commentLabel: property.title ?? "Comment"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return { commentRequired: false };
|
|
39
|
+
}
|
|
40
|
+
function findEnumAction(schema) {
|
|
41
|
+
for (const [field, property] of sortedPropertyEntries(schema)) {
|
|
42
|
+
const values = property.enum ?? [];
|
|
43
|
+
if (values.length === 0) continue;
|
|
44
|
+
const approve = values.find((value) => APPROVE_RE.test(optionText(property, value)));
|
|
45
|
+
const reject = values.find((value) => REJECT_RE.test(optionText(property, value)));
|
|
46
|
+
if (approve === void 0 || reject === void 0) continue;
|
|
47
|
+
return {
|
|
48
|
+
field,
|
|
49
|
+
approveValue: approve,
|
|
50
|
+
rejectValue: reject,
|
|
51
|
+
...findCommentField(schema)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
function findBooleanAction(schema) {
|
|
57
|
+
var _a;
|
|
58
|
+
const properties = schema.properties ?? {};
|
|
59
|
+
const preferred = ["value", "approve", "approved", "confirm", "confirmed", "allowed"];
|
|
60
|
+
const field = preferred.find((key) => hasType(properties[key], "boolean")) ?? ((_a = Object.entries(properties).find(([, property]) => hasType(property, "boolean"))) == null ? void 0 : _a[0]);
|
|
61
|
+
if (!field) return null;
|
|
62
|
+
return {
|
|
63
|
+
field,
|
|
64
|
+
approveValue: true,
|
|
65
|
+
rejectValue: false,
|
|
66
|
+
...findCommentField(schema)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function analyzePromptInlineActions(prompt) {
|
|
70
|
+
const schema = prompt.schema;
|
|
71
|
+
if (!(schema == null ? void 0 : schema.properties)) return null;
|
|
72
|
+
return findEnumAction(schema) ?? findBooleanAction(schema);
|
|
73
|
+
}
|
|
74
|
+
function initialPromptComment(prompt, spec) {
|
|
75
|
+
var _a;
|
|
76
|
+
if (!(spec == null ? void 0 : spec.commentField)) return "";
|
|
77
|
+
const value = (_a = prompt.value) == null ? void 0 : _a[spec.commentField];
|
|
78
|
+
return typeof value === "string" ? value : "";
|
|
79
|
+
}
|
|
80
|
+
function buildPromptInlineValues(prompt, spec, decision, comment) {
|
|
81
|
+
const values = { ...prompt.value };
|
|
82
|
+
values[spec.field] = decision === "approve" ? spec.approveValue : spec.rejectValue;
|
|
83
|
+
if (spec.commentField) {
|
|
84
|
+
const trimmed = comment.trim();
|
|
85
|
+
if (trimmed || spec.commentRequired) {
|
|
86
|
+
values[spec.commentField] = trimmed;
|
|
87
|
+
} else {
|
|
88
|
+
delete values[spec.commentField];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return values;
|
|
92
|
+
}
|
|
93
|
+
function summarizePrompts(prompts) {
|
|
94
|
+
return prompts.reduce(
|
|
95
|
+
(acc, prompt) => {
|
|
96
|
+
acc.total += 1;
|
|
97
|
+
if (prompt.state === "pending") acc.pending += 1;
|
|
98
|
+
else if (prompt.state === "answered") acc.answered += 1;
|
|
99
|
+
else if (prompt.state === "cancelled") acc.cancelled += 1;
|
|
100
|
+
else if (prompt.state === "expired") acc.expired += 1;
|
|
101
|
+
return acc;
|
|
102
|
+
},
|
|
103
|
+
{ total: 0, pending: 0, answered: 0, cancelled: 0, expired: 0 }
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
function summarizePromptAnswer(prompt) {
|
|
107
|
+
if (prompt.cancelled || prompt.state === "cancelled") return "Cancelled";
|
|
108
|
+
if (prompt.state === "expired") return "Expired";
|
|
109
|
+
if (prompt.state === "pending") return prompt.kind ? `Pending ${prompt.kind}` : "Pending";
|
|
110
|
+
const values = prompt.value ?? {};
|
|
111
|
+
const spec = analyzePromptInlineActions(prompt);
|
|
112
|
+
const parts = [];
|
|
113
|
+
if (spec && spec.field in values) {
|
|
114
|
+
if (Object.is(values[spec.field], spec.approveValue)) parts.push("Approved");
|
|
115
|
+
else if (Object.is(values[spec.field], spec.rejectValue)) parts.push("Rejected");
|
|
116
|
+
}
|
|
117
|
+
if (spec == null ? void 0 : spec.commentField) {
|
|
118
|
+
const comment = values[spec.commentField];
|
|
119
|
+
if (typeof comment === "string" && comment) parts.push(comment);
|
|
120
|
+
}
|
|
121
|
+
if (parts.length > 0) return parts.join(" - ");
|
|
122
|
+
const primitive = Object.entries(values).filter(([, value]) => ["string", "number", "boolean"].includes(typeof value)).slice(0, 2).map(([key, value]) => `${key}: ${String(value)}`);
|
|
123
|
+
return primitive.join(" - ") || prompt.state;
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
analyzePromptInlineActions,
|
|
127
|
+
buildPromptInlineValues,
|
|
128
|
+
initialPromptComment,
|
|
129
|
+
summarizePromptAnswer,
|
|
130
|
+
summarizePrompts
|
|
131
|
+
};
|
|
132
|
+
//# sourceMappingURL=PromptBanner.model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptBanner.model.js","sources":["../../src/data/PromptBanner.model.ts"],"sourcesContent":["import type { JsonSchemaObject, JsonSchemaProperty } from \"../components/json-schema-form-types\";\nimport type { PromptSnapshot } from \"../hooks/use-prompts\";\n\nexport type PromptInlineDecision = \"approve\" | \"reject\";\n\nexport interface PromptInlineActionSpec {\n field: string;\n approveValue: unknown;\n rejectValue: unknown;\n commentField?: string;\n commentRequired: boolean;\n commentLabel?: string;\n}\n\nexport interface PromptSummary {\n total: number;\n pending: number;\n answered: number;\n cancelled: number;\n expired: number;\n}\n\nconst ACTION_FIELD_PRIORITY = [\"decision\", \"choice\", \"action\", \"value\", \"approve\", \"approved\"];\nconst COMMENT_FIELD_PRIORITY = [\"comment\", \"reason\", \"message\", \"note\"];\n\nconst APPROVE_RE = /\\b(approve|approved|allow|allowed|continue|yes|accept|accepted|proceed|run)\\b/i;\nconst REJECT_RE = /\\b(reject|rejected|deny|denied|cancel|cancelled|canceled|no|block|stop|decline|declined)\\b/i;\n\nfunction hasType(schema: JsonSchemaProperty | undefined, type: string): boolean {\n if (!schema?.type) return false;\n return Array.isArray(schema.type) ? schema.type.includes(type as never) : schema.type === type;\n}\n\nfunction sortedPropertyEntries(schema: JsonSchemaObject): [string, JsonSchemaProperty][] {\n const entries = Object.entries(schema.properties ?? {});\n return entries.sort(([a], [b]) => {\n const ia = ACTION_FIELD_PRIORITY.indexOf(a);\n const ib = ACTION_FIELD_PRIORITY.indexOf(b);\n if (ia === -1 && ib === -1) return 0;\n if (ia === -1) return 1;\n if (ib === -1) return -1;\n return ia - ib;\n });\n}\n\nfunction optionText(schema: JsonSchemaProperty, value: unknown): string {\n const key = String(value);\n const label = schema[\"x-enum-labels\"]?.[key];\n return [key, label].filter(Boolean).join(\" \");\n}\n\nfunction findCommentField(schema: JsonSchemaObject): Pick<\n PromptInlineActionSpec,\n \"commentField\" | \"commentRequired\" | \"commentLabel\"\n> {\n const properties = schema.properties ?? {};\n const required = new Set(schema.required ?? []);\n for (const key of COMMENT_FIELD_PRIORITY) {\n const property = properties[key];\n if (!property || !hasType(property, \"string\") || property.enum) continue;\n return {\n commentField: key,\n commentRequired: required.has(key),\n commentLabel: property.title ?? \"Comment\",\n };\n }\n return { commentRequired: false };\n}\n\nfunction findEnumAction(schema: JsonSchemaObject): PromptInlineActionSpec | null {\n for (const [field, property] of sortedPropertyEntries(schema)) {\n const values = property.enum ?? [];\n if (values.length === 0) continue;\n\n const approve = values.find((value) => APPROVE_RE.test(optionText(property, value)));\n const reject = values.find((value) => REJECT_RE.test(optionText(property, value)));\n if (approve === undefined || reject === undefined) continue;\n\n return {\n field,\n approveValue: approve,\n rejectValue: reject,\n ...findCommentField(schema),\n };\n }\n return null;\n}\n\nfunction findBooleanAction(schema: JsonSchemaObject): PromptInlineActionSpec | null {\n const properties = schema.properties ?? {};\n const preferred = [\"value\", \"approve\", \"approved\", \"confirm\", \"confirmed\", \"allowed\"];\n const field =\n preferred.find((key) => hasType(properties[key], \"boolean\")) ??\n Object.entries(properties).find(([, property]) => hasType(property, \"boolean\"))?.[0];\n\n if (!field) return null;\n return {\n field,\n approveValue: true,\n rejectValue: false,\n ...findCommentField(schema),\n };\n}\n\nexport function analyzePromptInlineActions(prompt: PromptSnapshot): PromptInlineActionSpec | null {\n const schema = prompt.schema;\n if (!schema?.properties) return null;\n return findEnumAction(schema) ?? findBooleanAction(schema);\n}\n\nexport function initialPromptComment(prompt: PromptSnapshot, spec: PromptInlineActionSpec | null): string {\n if (!spec?.commentField) return \"\";\n const value = prompt.value?.[spec.commentField];\n return typeof value === \"string\" ? value : \"\";\n}\n\nexport function buildPromptInlineValues(\n prompt: PromptSnapshot,\n spec: PromptInlineActionSpec,\n decision: PromptInlineDecision,\n comment: string,\n): Record<string, unknown> {\n const values: Record<string, unknown> = { ...prompt.value };\n values[spec.field] = decision === \"approve\" ? spec.approveValue : spec.rejectValue;\n\n if (spec.commentField) {\n const trimmed = comment.trim();\n if (trimmed || spec.commentRequired) {\n values[spec.commentField] = trimmed;\n } else {\n delete values[spec.commentField];\n }\n }\n\n return values;\n}\n\nexport function summarizePrompts(prompts: PromptSnapshot[]): PromptSummary {\n return prompts.reduce<PromptSummary>(\n (acc, prompt) => {\n acc.total += 1;\n if (prompt.state === \"pending\") acc.pending += 1;\n else if (prompt.state === \"answered\") acc.answered += 1;\n else if (prompt.state === \"cancelled\") acc.cancelled += 1;\n else if (prompt.state === \"expired\") acc.expired += 1;\n return acc;\n },\n { total: 0, pending: 0, answered: 0, cancelled: 0, expired: 0 },\n );\n}\n\nexport function summarizePromptAnswer(prompt: PromptSnapshot): string {\n if (prompt.cancelled || prompt.state === \"cancelled\") return \"Cancelled\";\n if (prompt.state === \"expired\") return \"Expired\";\n if (prompt.state === \"pending\") return prompt.kind ? `Pending ${prompt.kind}` : \"Pending\";\n\n const values = prompt.value ?? {};\n const spec = analyzePromptInlineActions(prompt);\n const parts: string[] = [];\n if (spec && spec.field in values) {\n if (Object.is(values[spec.field], spec.approveValue)) parts.push(\"Approved\");\n else if (Object.is(values[spec.field], spec.rejectValue)) parts.push(\"Rejected\");\n }\n if (spec?.commentField) {\n const comment = values[spec.commentField];\n if (typeof comment === \"string\" && comment) parts.push(comment);\n }\n if (parts.length > 0) return parts.join(\" - \");\n\n const primitive = Object.entries(values)\n .filter(([, value]) => [\"string\", \"number\", \"boolean\"].includes(typeof value))\n .slice(0, 2)\n .map(([key, value]) => `${key}: ${String(value)}`);\n return primitive.join(\" - \") || prompt.state;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const react = require("react");
|
|
5
|
+
const button = require("../components/button.cjs");
|
|
6
|
+
const JsonSchemaForm = require("../components/JsonSchemaForm.cjs");
|
|
7
|
+
const Modal = require("../overlay/Modal.cjs");
|
|
8
|
+
const usePrompts = require("../hooks/use-prompts.cjs");
|
|
9
|
+
function PromptDialog({ prompt, basePath, open, onClose, onResolved }) {
|
|
10
|
+
const [value, setValue] = react.useState(() => ({ ...prompt.value }));
|
|
11
|
+
const [busy, setBusy] = react.useState(false);
|
|
12
|
+
const [error, setError] = react.useState(null);
|
|
13
|
+
const resolve = async (answer) => {
|
|
14
|
+
setBusy(true);
|
|
15
|
+
setError(null);
|
|
16
|
+
try {
|
|
17
|
+
await usePrompts.answerPrompt(basePath, prompt.id, answer);
|
|
18
|
+
onResolved == null ? void 0 : onResolved();
|
|
19
|
+
onClose();
|
|
20
|
+
} catch (e) {
|
|
21
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
22
|
+
} finally {
|
|
23
|
+
setBusy(false);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27
|
+
Modal.Modal,
|
|
28
|
+
{
|
|
29
|
+
open,
|
|
30
|
+
onClose,
|
|
31
|
+
title: prompt.title,
|
|
32
|
+
subtitle: prompt.description,
|
|
33
|
+
footer: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
34
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-auto text-sm text-red-600", children: error }) : null,
|
|
35
|
+
/* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "ghost", disabled: busy, onClick: () => void resolve({ cancelled: true }), children: "Cancel" }),
|
|
36
|
+
/* @__PURE__ */ jsxRuntime.jsx(button.Button, { disabled: busy, onClick: () => void resolve({ values: value }), children: "Submit" })
|
|
37
|
+
] }),
|
|
38
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(JsonSchemaForm.JsonSchemaForm, { schema: prompt.schema, value, onChange: setValue, idPrefix: `prompt-${prompt.id}` })
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
exports.PromptDialog = PromptDialog;
|
|
43
|
+
//# sourceMappingURL=PromptDialog.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PromptDialog.cjs","sources":["../../src/data/PromptDialog.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { JsonSchemaForm } from \"../components/JsonSchemaForm\";\nimport { Modal } from \"../overlay/Modal\";\nimport { answerPrompt, type PromptSnapshot } from \"../hooks/use-prompts\";\n\nexport interface PromptDialogProps {\n /** The pending prompt to answer. Its `schema` drives the rendered form. */\n prompt: PromptSnapshot;\n /** Base path the prompt API is mounted under, e.g. \"/api/todos\". */\n basePath: string;\n open: boolean;\n /** Closes the modal without answering (the prompt stays pending). */\n onClose: () => void;\n /** Called after the prompt is successfully answered or cancelled. */\n onResolved?: (() => void) | undefined;\n}\n\n// PromptDialog renders a pending prompt's JSON Schema via the generic\n// JsonSchemaForm inside a Modal and POSTs the answer back to the prompt manager.\n// It is the human side of the same mechanism an AI model elicits through.\nexport function PromptDialog({ prompt, basePath, open, onClose, onResolved }: PromptDialogProps) {\n const [value, setValue] = useState<Record<string, unknown>>(() => ({ ...prompt.value }));\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const resolve = async (answer: { values?: Record<string, unknown>; cancelled?: boolean }) => {\n setBusy(true);\n setError(null);\n try {\n await answerPrompt(basePath, prompt.id, answer);\n onResolved?.();\n onClose();\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n title={prompt.title}\n subtitle={prompt.description}\n footer={\n <div className=\"flex items-center justify-end gap-2\">\n {error ? <span className=\"mr-auto text-sm text-red-600\">{error}</span> : null}\n <Button variant=\"ghost\" disabled={busy} onClick={() => void resolve({ cancelled: true })}>\n Cancel\n </Button>\n <Button disabled={busy} onClick={() => void resolve({ values: value })}>\n Submit\n </Button>\n </div>\n }\n >\n <JsonSchemaForm schema={prompt.schema} value={value} onChange={setValue} idPrefix={`prompt-${prompt.id}`} />\n </Modal>\n );\n}\n"],"names":["useState","answerPrompt","jsx","Modal","jsxs","Button","JsonSchemaForm"],"mappings":";;;;;;;;AAqBO,SAAS,aAAa,EAAE,QAAQ,UAAU,MAAM,SAAS,cAAiC;AAC/F,QAAM,CAAC,OAAO,QAAQ,IAAIA,MAAAA,SAAkC,OAAO,EAAE,GAAG,OAAO,MAAA,EAAQ;AACvF,QAAM,CAAC,MAAM,OAAO,IAAIA,MAAAA,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAIA,MAAAA,SAAwB,IAAI;AAEtD,QAAM,UAAU,OAAO,WAAsE;AAC3F,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,YAAMC,WAAAA,aAAa,UAAU,OAAO,IAAI,MAAM;AAC9C;AACA,cAAA;AAAA,IACF,SAAS,GAAG;AACV,eAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,IACrD,UAAA;AACE,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AAEA,SACEC,2BAAAA;AAAAA,IAACC,MAAAA;AAAAA,IAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,OAAO,OAAO;AAAA,MACd,UAAU,OAAO;AAAA,MACjB,QACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,uCACZ,UAAA;AAAA,QAAA,QAAQF,2BAAAA,IAAC,QAAA,EAAK,WAAU,gCAAgC,iBAAM,IAAU;AAAA,QACzEA,2BAAAA,IAACG,OAAAA,QAAA,EAAO,SAAQ,SAAQ,UAAU,MAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,WAAW,KAAA,CAAM,GAAG,UAAA,UAE1F;AAAA,QACAH,2BAAAA,IAACG,OAAAA,QAAA,EAAO,UAAU,MAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,QAAQ,MAAA,CAAO,GAAG,UAAA,SAAA,CAExE;AAAA,MAAA,GACF;AAAA,MAGF,UAAAH,2BAAAA,IAACI,eAAAA,gBAAA,EAAe,QAAQ,OAAO,QAAQ,OAAc,UAAU,UAAU,UAAU,UAAU,OAAO,EAAE,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA;AAGhH;;"}
|