@nocobase/portal-template-default 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.MD +10 -5
- package/package.json +17 -17
- package/registry/nocobase-ai/components/chat/chat-message.tsx +8 -6
- package/registry/nocobase-ai/components/chat/chat-messages.tsx +8 -3
- package/registry/nocobase-ai/components/chat/markdown-message.tsx +26 -0
- package/registry/nocobase-ai/components/chat/sub-agent-conversation.tsx +3 -3
- package/registry/nocobase-ai/demo/configuration-gate.tsx +83 -35
- package/registry/nocobase-i18n/README.md +23 -32
- package/registry/nocobase-i18n/components/language-switcher.tsx +1 -1
- package/registry/nocobase-i18n/demo/index.tsx +2 -2
- package/registry/nocobase-i18n/demo/prompt-generator.tsx +3 -2
- package/registry/nocobase-i18n/extension.tsx +3 -4
- package/registry/nocobase-i18n/index.ts +4 -3
- package/registry/nocobase-i18n/locales/en-US.ts +2 -52
- package/registry/nocobase-i18n/locales/index.ts +8 -0
- package/registry/nocobase-i18n/locales/zh-CN.ts +2 -52
- package/registry/nocobase-i18n/provider.tsx +18 -6
- package/registry/nocobase-i18n/server-resources.ts +13 -31
- package/registry/nocobase-i18n/tests/i18n-regression.mjs +14 -5
- package/registry/nocobase-route-surfaces/README.md +21 -0
- package/registry/nocobase-route-surfaces/demo/index.tsx +266 -0
- package/{src/extensions/nocobase-acl → registry/nocobase-route-surfaces}/demo/lazy-route.tsx +2 -1
- package/registry/nocobase-route-surfaces/demo/prompt-generator.tsx +90 -0
- package/registry/nocobase-route-surfaces/demo/scenarios.ts +95 -0
- package/registry/nocobase-route-surfaces/extension.tsx +119 -0
- package/registry/nocobase-route-surfaces/index.ts +7 -0
- package/registry/nocobase-route-surfaces/route-dialog.tsx +145 -0
- package/registry/nocobase-route-surfaces/route-drawer.tsx +186 -0
- package/registry/nocobase-route-surfaces/route-page.tsx +29 -0
- package/registry/nocobase-route-surfaces/route-surface-context.ts +13 -0
- package/registry/nocobase-route-surfaces/use-refine-unsaved-changes.tsx +106 -0
- package/registry/nocobase-route-surfaces/use-route-surface-close.ts +15 -0
- package/registry/nocobase-route-surfaces/use-route-surface-state.ts +65 -0
- package/registry.config.json +30 -3
- package/scripts/registry.mjs +0 -2
- package/src/App.tsx +65 -35
- package/src/app/extension.ts +1 -2
- package/src/app/extensions.tsx +0 -14
- package/src/components/app-shell/breadcrumb.tsx +67 -2
- package/src/components/app-shell/sidebar.tsx +2 -2
- package/src/components/resources/views/list-view.tsx +3 -2
- package/src/components/ui/sheet.tsx +22 -21
- package/src/lib/nocobase/client.ts +6 -1
- package/src/locales/en-US.ts +81 -0
- package/src/locales/zh-CN.ts +77 -0
- package/src/pages/users/create.tsx +76 -53
- package/src/pages/users/edit.tsx +87 -56
- package/src/pages/users/index.ts +3 -0
- package/src/pages/users/layout.tsx +15 -0
- package/src/pages/users/list.tsx +19 -21
- package/src/pages/users/role-badges.tsx +43 -0
- package/src/pages/users/role-detail.tsx +272 -0
- package/src/pages/users/role-utils.ts +6 -0
- package/src/pages/users/routes.ts +24 -0
- package/src/pages/users/show.tsx +195 -104
- package/src/pages/users/types.ts +13 -0
- package/src/providers/i18n/index.ts +3 -0
- package/{registry/nocobase-i18n → src/providers/i18n}/runtime.ts +63 -16
- package/src/providers/system-settings/context.ts +26 -0
- package/src/providers/system-settings/index.ts +2 -0
- package/src/providers/system-settings/provider.tsx +94 -0
- package/src/extensions/nocobase-acl/README.md +0 -19
- package/src/extensions/nocobase-acl/components/acl-boundary.tsx +0 -106
- package/src/extensions/nocobase-acl/components/index.ts +0 -3
- package/src/extensions/nocobase-acl/components/role-options.ts +0 -36
- package/src/extensions/nocobase-acl/components/role-switcher.tsx +0 -135
- package/src/extensions/nocobase-acl/demo/boundary-api.tsx +0 -186
- package/src/extensions/nocobase-acl/demo/components.tsx +0 -231
- package/src/extensions/nocobase-acl/demo/index.tsx +0 -505
- package/src/extensions/nocobase-acl/demo/prompt-generator.tsx +0 -134
- package/src/extensions/nocobase-acl/demo/role-switcher-prompt-generator.tsx +0 -198
- package/src/extensions/nocobase-acl/demo/scenario-section.tsx +0 -37
- package/src/extensions/nocobase-acl/extension.tsx +0 -71
- package/src/extensions/nocobase-acl/index.ts +0 -1
- package/src/extensions/nocobase-ai/README.md +0 -70
- package/src/extensions/nocobase-ai/adapters/react-hook-form.ts +0 -20
- package/src/extensions/nocobase-ai/assets/nocobase-ai-chat.svg +0 -50
- package/src/extensions/nocobase-ai/components/ai-root-provider.tsx +0 -32
- package/src/extensions/nocobase-ai/components/chat/ai-employee-avatar.tsx +0 -31
- package/src/extensions/nocobase-ai/components/chat/chat-attachment.tsx +0 -92
- package/src/extensions/nocobase-ai/components/chat/chat-compact.tsx +0 -90
- package/src/extensions/nocobase-ai/components/chat/chat-composer.tsx +0 -429
- package/src/extensions/nocobase-ai/components/chat/chat-empty-state.tsx +0 -51
- package/src/extensions/nocobase-ai/components/chat/chat-header.tsx +0 -88
- package/src/extensions/nocobase-ai/components/chat/chat-history-dialog.tsx +0 -77
- package/src/extensions/nocobase-ai/components/chat/chat-message.tsx +0 -252
- package/src/extensions/nocobase-ai/components/chat/chat-messages.tsx +0 -173
- package/src/extensions/nocobase-ai/components/chat/chat-window.tsx +0 -118
- package/src/extensions/nocobase-ai/components/chat/conversation-list.tsx +0 -343
- package/src/extensions/nocobase-ai/components/chat/markdown-message.tsx +0 -165
- package/src/extensions/nocobase-ai/components/chat/model-select-options.tsx +0 -30
- package/src/extensions/nocobase-ai/components/chat/reasoning-panel.tsx +0 -29
- package/src/extensions/nocobase-ai/components/chat/sub-agent-conversation.tsx +0 -142
- package/src/extensions/nocobase-ai/components/chat/tool-call-card.tsx +0 -316
- package/src/extensions/nocobase-ai/components/chat/user-prompt-editor.tsx +0 -99
- package/src/extensions/nocobase-ai/components/chat/work-context-chip.tsx +0 -114
- package/src/extensions/nocobase-ai/components/index.ts +0 -59
- package/src/extensions/nocobase-ai/components/page-elements/ai-form.tsx +0 -44
- package/src/extensions/nocobase-ai/components/page-elements/page-element-provider.tsx +0 -469
- package/src/extensions/nocobase-ai/components/surfaces/chat-dialog.tsx +0 -31
- package/src/extensions/nocobase-ai/components/surfaces/chat-inline.tsx +0 -18
- package/src/extensions/nocobase-ai/components/surfaces/chat-page.tsx +0 -18
- package/src/extensions/nocobase-ai/components/surfaces/chat-side-panel-layout.tsx +0 -54
- package/src/extensions/nocobase-ai/components/surfaces/chat-side-panel.tsx +0 -74
- package/src/extensions/nocobase-ai/components/surfaces/chat-surface-actions.tsx +0 -54
- package/src/extensions/nocobase-ai/components/tools/builtin-tool-renderers.tsx +0 -31
- package/src/extensions/nocobase-ai/components/tools/business-report-dialog.tsx +0 -364
- package/src/extensions/nocobase-ai/components/tools/business-report-renderer.tsx +0 -122
- package/src/extensions/nocobase-ai/components/tools/business-report-utils.tsx +0 -282
- package/src/extensions/nocobase-ai/components/tools/chart-renderer.tsx +0 -99
- package/src/extensions/nocobase-ai/components/tools/echarts-preview.tsx +0 -59
- package/src/extensions/nocobase-ai/components/tools/echarts-runtime-advanced.ts +0 -18
- package/src/extensions/nocobase-ai/components/tools/echarts-runtime-common.ts +0 -20
- package/src/extensions/nocobase-ai/components/tools/echarts-runtime-components.ts +0 -34
- package/src/extensions/nocobase-ai/components/tools/echarts-runtime-hierarchy.ts +0 -24
- package/src/extensions/nocobase-ai/components/tools/echarts-runtime.ts +0 -138
- package/src/extensions/nocobase-ai/components/tools/sub-agent-renderer.tsx +0 -67
- package/src/extensions/nocobase-ai/components/tools/suggestions-renderer.tsx +0 -59
- package/src/extensions/nocobase-ai/components/tools/tool-renderer-provider.tsx +0 -55
- package/src/extensions/nocobase-ai/components/tools/tool-renderer-utils.ts +0 -18
- package/src/extensions/nocobase-ai/components/tools/workflow-renderer.tsx +0 -108
- package/src/extensions/nocobase-ai/components/triggers/ai-chat-floating-trigger.tsx +0 -73
- package/src/extensions/nocobase-ai/components/triggers/ai-employee-shortcut.tsx +0 -149
- package/src/extensions/nocobase-ai/demo/configuration-gate.tsx +0 -49
- package/src/extensions/nocobase-ai/demo/container-showcase.tsx +0 -210
- package/src/extensions/nocobase-ai/demo/floating.tsx +0 -134
- package/src/extensions/nocobase-ai/demo/index.tsx +0 -346
- package/src/extensions/nocobase-ai/demo/interaction-showcase.tsx +0 -151
- package/src/extensions/nocobase-ai/demo/page-context-prompt-generator.tsx +0 -355
- package/src/extensions/nocobase-ai/demo/page-context.tsx +0 -884
- package/src/extensions/nocobase-ai/demo/page-element-showcase.tsx +0 -197
- package/src/extensions/nocobase-ai/demo/prompt-card.tsx +0 -41
- package/src/extensions/nocobase-ai/demo/prompt-generator.tsx +0 -452
- package/src/extensions/nocobase-ai/demo/shortcut.tsx +0 -1207
- package/src/extensions/nocobase-ai/demo/tool-cards.tsx +0 -530
- package/src/extensions/nocobase-ai/extension.tsx +0 -158
- package/src/extensions/nocobase-ai/global-ai-chat.tsx +0 -213
- package/src/extensions/nocobase-ai/index.ts +0 -3
- package/src/extensions/nocobase-ai/providers/ai-provider.tsx +0 -323
- package/src/extensions/nocobase-ai/providers/avatars.ts +0 -817
- package/src/extensions/nocobase-ai/providers/chat-context.tsx +0 -109
- package/src/extensions/nocobase-ai/providers/chat-controller.ts +0 -84
- package/src/extensions/nocobase-ai/providers/chat-message-utils.ts +0 -198
- package/src/extensions/nocobase-ai/providers/chat-provider.tsx +0 -871
- package/src/extensions/nocobase-ai/providers/chat-reducer.ts +0 -147
- package/src/extensions/nocobase-ai/providers/chat-task-utils.ts +0 -105
- package/src/extensions/nocobase-ai/providers/chat-transport.ts +0 -184
- package/src/extensions/nocobase-ai/providers/form-registry.tsx +0 -271
- package/src/extensions/nocobase-ai/providers/frontend-tool-registry.tsx +0 -231
- package/src/extensions/nocobase-ai/providers/index.ts +0 -61
- package/src/extensions/nocobase-ai/providers/model.ts +0 -32
- package/src/extensions/nocobase-ai/providers/page-context.tsx +0 -136
- package/src/extensions/nocobase-ai/providers/stream-coalescer.ts +0 -60
- package/src/extensions/nocobase-ai/providers/stream-event-utils.ts +0 -82
- package/src/extensions/nocobase-ai/providers/stream-parser.ts +0 -61
- package/src/extensions/nocobase-ai/providers/sub-agent-stream.ts +0 -316
- package/src/extensions/nocobase-ai/providers/types.ts +0 -183
- package/src/extensions/nocobase-ai/providers/ui-message-stream.ts +0 -463
- package/src/extensions/nocobase-ai/providers/use-automatic-tool-approval.ts +0 -94
- package/src/extensions/nocobase-ai/providers/use-chat-attachments.ts +0 -206
- package/src/extensions/nocobase-ai/providers/use-chat-message-actions.ts +0 -554
- package/src/extensions/nocobase-ai/providers/use-chat-runtime.ts +0 -210
- package/src/extensions/nocobase-ai/providers/use-chat-work-context.ts +0 -93
- package/src/extensions/nocobase-ai/providers/use-conversation-catalog.ts +0 -108
- package/src/extensions/nocobase-ai/providers/use-conversation-history.ts +0 -178
- package/src/extensions/nocobase-ai/services/index.ts +0 -7
- package/src/extensions/nocobase-ai/services/nocobase-ai-service.ts +0 -454
- package/src/extensions/nocobase-ai/services/types.ts +0 -82
- /package/{registry/nocobase-i18n → src/providers/i18n}/i18n-provider.ts +0 -0
- /package/{registry/nocobase-i18n → src/providers/i18n}/locale-store.ts +0 -0
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { Check, Copy } from "lucide-react";
|
|
2
|
-
import { useMemo, useState } from "react";
|
|
3
|
-
|
|
4
|
-
import { Button } from "@/components/ui/button";
|
|
5
|
-
import {
|
|
6
|
-
Card,
|
|
7
|
-
CardContent,
|
|
8
|
-
CardDescription,
|
|
9
|
-
CardHeader,
|
|
10
|
-
CardTitle,
|
|
11
|
-
} from "@/components/ui/card";
|
|
12
|
-
import { Input } from "@/components/ui/input";
|
|
13
|
-
import { Label } from "@/components/ui/label";
|
|
14
|
-
import {
|
|
15
|
-
Select,
|
|
16
|
-
SelectContent,
|
|
17
|
-
SelectItem,
|
|
18
|
-
SelectTrigger,
|
|
19
|
-
SelectValue,
|
|
20
|
-
} from "@/components/ui/select";
|
|
21
|
-
import { Textarea } from "@/components/ui/textarea";
|
|
22
|
-
|
|
23
|
-
type Placement = "header" | "user-menu" | "settings" | "custom";
|
|
24
|
-
type UnavailableState = "hide" | "current-role";
|
|
25
|
-
|
|
26
|
-
const placementLabels: Record<Placement, string> = {
|
|
27
|
-
header: "Application header",
|
|
28
|
-
"user-menu": "User menu",
|
|
29
|
-
settings: "Account settings",
|
|
30
|
-
custom: "Custom surface",
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const unavailableStateLabels: Record<UnavailableState, string> = {
|
|
34
|
-
"current-role": "Show current role",
|
|
35
|
-
hide: "Hide component",
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const placementInstructions: Record<Placement, string> = {
|
|
39
|
-
header:
|
|
40
|
-
"Place it in the application header beside the existing account controls. Keep the trigger compact and preserve the responsive user menu.",
|
|
41
|
-
"user-menu":
|
|
42
|
-
"Place it inside the existing user/account popover as a full-width menu section, separated from profile and sign-out actions.",
|
|
43
|
-
settings:
|
|
44
|
-
"Place it in an account settings section with a field label and short explanation of how the active role changes visible data and actions.",
|
|
45
|
-
custom:
|
|
46
|
-
"Place it in the application surface described below, matching the surrounding layout and spacing.",
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export function RoleSwitcherPromptGenerator() {
|
|
50
|
-
const [placement, setPlacement] = useState<Placement>("user-menu");
|
|
51
|
-
const [label, setLabel] = useState("Working as");
|
|
52
|
-
const [unavailableState, setUnavailableState] =
|
|
53
|
-
useState<UnavailableState>("current-role");
|
|
54
|
-
const [surface, setSurface] = useState(
|
|
55
|
-
"Use the Starter's existing account controls and visual language. Do not create a separate demo page."
|
|
56
|
-
);
|
|
57
|
-
const [copied, setCopied] = useState(false);
|
|
58
|
-
const [copyError, setCopyError] = useState(false);
|
|
59
|
-
|
|
60
|
-
const prompt = useMemo(
|
|
61
|
-
() => `Integrate the RoleSwitcher into the existing NocoBase Admin Starter.
|
|
62
|
-
|
|
63
|
-
Target placement
|
|
64
|
-
- Placement: ${placementLabels[placement]}
|
|
65
|
-
- ${placementInstructions[placement]}
|
|
66
|
-
- Application context: ${surface}
|
|
67
|
-
|
|
68
|
-
Component presentation
|
|
69
|
-
- Label: ${label.trim() ? label : "No label; pass label={false}."}
|
|
70
|
-
- When role switching is unavailable: ${
|
|
71
|
-
unavailableState === "current-role"
|
|
72
|
-
? "Keep the current identity visible by passing showWhenUnavailable."
|
|
73
|
-
: "Hide the component by keeping showWhenUnavailable false."
|
|
74
|
-
}
|
|
75
|
-
- Use className and triggerClassName only to fit the existing surface; do not fork or restyle the internal Select implementation.
|
|
76
|
-
|
|
77
|
-
Integration requirements
|
|
78
|
-
- Import and reuse RoleSwitcher from the installed local entry point at @/extensions/nocobase-acl.
|
|
79
|
-
- Update the existing application surface instead of creating an isolated example page.
|
|
80
|
-
- Do not fetch, hard-code, or pass a duplicate role list. The component reads roles from the signed-in identity.
|
|
81
|
-
- Do not reimplement Full permissions, Anonymous, or role-mode logic. The component derives these options from the Starter ACL store.
|
|
82
|
-
- Do not add a separate role-switch mutation. The component already calls users:setDefaultRole and reloads the application after a successful switch.
|
|
83
|
-
- Preserve existing account, responsive navigation, and sign-out behavior.
|
|
84
|
-
- Return the complete updated component for the target surface and mention any imports that were added.`,
|
|
85
|
-
[label, placement, surface, unavailableState]
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
return (
|
|
89
|
-
<div className="grid items-start gap-5 xl:grid-cols-[360px_minmax(0,1fr)]">
|
|
90
|
-
<Card className="gap-0 py-0">
|
|
91
|
-
<CardHeader className="border-b py-4">
|
|
92
|
-
<CardTitle className="text-base">Placement settings</CardTitle>
|
|
93
|
-
<CardDescription>
|
|
94
|
-
Choose where the shared role switcher belongs and how its compact
|
|
95
|
-
state should appear.
|
|
96
|
-
</CardDescription>
|
|
97
|
-
</CardHeader>
|
|
98
|
-
<CardContent className="space-y-5 py-5">
|
|
99
|
-
<div className="space-y-2">
|
|
100
|
-
<Label>Placement</Label>
|
|
101
|
-
<Select
|
|
102
|
-
value={placement}
|
|
103
|
-
onValueChange={(value) =>
|
|
104
|
-
value && setPlacement(value as Placement)
|
|
105
|
-
}
|
|
106
|
-
>
|
|
107
|
-
<SelectTrigger className="w-full">
|
|
108
|
-
<SelectValue>{placementLabels[placement]}</SelectValue>
|
|
109
|
-
</SelectTrigger>
|
|
110
|
-
<SelectContent>
|
|
111
|
-
<SelectItem value="header">Application header</SelectItem>
|
|
112
|
-
<SelectItem value="user-menu">User menu</SelectItem>
|
|
113
|
-
<SelectItem value="settings">Account settings</SelectItem>
|
|
114
|
-
<SelectItem value="custom">Custom surface</SelectItem>
|
|
115
|
-
</SelectContent>
|
|
116
|
-
</Select>
|
|
117
|
-
</div>
|
|
118
|
-
<div className="space-y-2">
|
|
119
|
-
<Label htmlFor="role-switcher-label">Label</Label>
|
|
120
|
-
<Input
|
|
121
|
-
id="role-switcher-label"
|
|
122
|
-
value={label}
|
|
123
|
-
onChange={(event) => setLabel(event.target.value)}
|
|
124
|
-
placeholder="Leave empty for no label"
|
|
125
|
-
/>
|
|
126
|
-
</div>
|
|
127
|
-
<div className="space-y-2">
|
|
128
|
-
<Label>Single-role behavior</Label>
|
|
129
|
-
<Select
|
|
130
|
-
value={unavailableState}
|
|
131
|
-
onValueChange={(value) =>
|
|
132
|
-
value && setUnavailableState(value as UnavailableState)
|
|
133
|
-
}
|
|
134
|
-
>
|
|
135
|
-
<SelectTrigger className="w-full">
|
|
136
|
-
<SelectValue>
|
|
137
|
-
{unavailableStateLabels[unavailableState]}
|
|
138
|
-
</SelectValue>
|
|
139
|
-
</SelectTrigger>
|
|
140
|
-
<SelectContent>
|
|
141
|
-
<SelectItem value="current-role">Show current role</SelectItem>
|
|
142
|
-
<SelectItem value="hide">Hide component</SelectItem>
|
|
143
|
-
</SelectContent>
|
|
144
|
-
</Select>
|
|
145
|
-
</div>
|
|
146
|
-
<div className="space-y-2">
|
|
147
|
-
<Label htmlFor="role-switcher-surface">Application context</Label>
|
|
148
|
-
<Textarea
|
|
149
|
-
id="role-switcher-surface"
|
|
150
|
-
value={surface}
|
|
151
|
-
onChange={(event) => setSurface(event.target.value)}
|
|
152
|
-
className="min-h-28"
|
|
153
|
-
/>
|
|
154
|
-
</div>
|
|
155
|
-
</CardContent>
|
|
156
|
-
</Card>
|
|
157
|
-
|
|
158
|
-
<Card className="gap-0 overflow-hidden py-0">
|
|
159
|
-
<div className="flex items-center justify-between gap-3 border-b px-4 py-3">
|
|
160
|
-
<div>
|
|
161
|
-
<div className="text-sm font-medium">
|
|
162
|
-
Generated integration prompt
|
|
163
|
-
</div>
|
|
164
|
-
<div className="text-xs text-muted-foreground">
|
|
165
|
-
Updates as you change placement and presentation settings.
|
|
166
|
-
</div>
|
|
167
|
-
</div>
|
|
168
|
-
<Button
|
|
169
|
-
size="sm"
|
|
170
|
-
onClick={async () => {
|
|
171
|
-
try {
|
|
172
|
-
await navigator.clipboard.writeText(prompt);
|
|
173
|
-
setCopyError(false);
|
|
174
|
-
setCopied(true);
|
|
175
|
-
window.setTimeout(() => setCopied(false), 1500);
|
|
176
|
-
} catch {
|
|
177
|
-
setCopyError(true);
|
|
178
|
-
}
|
|
179
|
-
}}
|
|
180
|
-
>
|
|
181
|
-
{copied ? <Check /> : <Copy />}
|
|
182
|
-
{copied ? "Copied" : "Copy prompt"}
|
|
183
|
-
</Button>
|
|
184
|
-
</div>
|
|
185
|
-
{copyError ? (
|
|
186
|
-
<p className="border-b px-4 py-2 text-xs text-destructive">
|
|
187
|
-
Clipboard access failed. Select the prompt and copy it manually.
|
|
188
|
-
</p>
|
|
189
|
-
) : null}
|
|
190
|
-
<CardContent className="p-0">
|
|
191
|
-
<pre className="max-h-[560px] overflow-auto whitespace-pre-wrap bg-muted/25 p-5 font-mono text-xs leading-5 text-muted-foreground">
|
|
192
|
-
{prompt}
|
|
193
|
-
</pre>
|
|
194
|
-
</CardContent>
|
|
195
|
-
</Card>
|
|
196
|
-
</div>
|
|
197
|
-
);
|
|
198
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
|
|
3
|
-
import { Badge } from "@/components/ui/badge";
|
|
4
|
-
import {
|
|
5
|
-
AclScenarioPromptGenerator,
|
|
6
|
-
type AclPromptGeneratorConfig,
|
|
7
|
-
} from "./prompt-generator";
|
|
8
|
-
|
|
9
|
-
export function AclScenarioSection({
|
|
10
|
-
eyebrow,
|
|
11
|
-
title,
|
|
12
|
-
description,
|
|
13
|
-
children,
|
|
14
|
-
prompt,
|
|
15
|
-
}: {
|
|
16
|
-
eyebrow: string;
|
|
17
|
-
title: string;
|
|
18
|
-
description: string;
|
|
19
|
-
children: ReactNode;
|
|
20
|
-
prompt: AclPromptGeneratorConfig;
|
|
21
|
-
}) {
|
|
22
|
-
return (
|
|
23
|
-
<section className="space-y-5 border-t pt-8">
|
|
24
|
-
<div>
|
|
25
|
-
<Badge variant="outline">{eyebrow}</Badge>
|
|
26
|
-
<h2 className="mt-3 text-2xl font-semibold tracking-[-0.025em]">
|
|
27
|
-
{title}
|
|
28
|
-
</h2>
|
|
29
|
-
<p className="mt-2 max-w-3xl text-sm leading-6 text-muted-foreground">
|
|
30
|
-
{description}
|
|
31
|
-
</p>
|
|
32
|
-
</div>
|
|
33
|
-
{children}
|
|
34
|
-
<AclScenarioPromptGenerator config={prompt} />
|
|
35
|
-
</section>
|
|
36
|
-
);
|
|
37
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import type { AppExtension } from "@/app/extension";
|
|
2
|
-
import { Blocks, PanelsTopLeft, ShieldCheck } from "lucide-react";
|
|
3
|
-
import { lazy } from "react";
|
|
4
|
-
import { Outlet, Route } from "react-router";
|
|
5
|
-
import { LazyAclRoute } from "./demo/lazy-route";
|
|
6
|
-
|
|
7
|
-
const AclComponentsPage = lazy(() =>
|
|
8
|
-
import("./demo/components").then((module) => ({
|
|
9
|
-
default: module.AclComponentsPage,
|
|
10
|
-
}))
|
|
11
|
-
);
|
|
12
|
-
const AclPatternsPage = lazy(() =>
|
|
13
|
-
import("./demo").then((module) => ({ default: module.AclPatternsPage }))
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
const nocobaseAclExtension: AppExtension = {
|
|
17
|
-
id: "nocobase-acl",
|
|
18
|
-
resources: [
|
|
19
|
-
{
|
|
20
|
-
name: "acl-integration",
|
|
21
|
-
meta: {
|
|
22
|
-
label: "Access control",
|
|
23
|
-
icon: <ShieldCheck />,
|
|
24
|
-
description: "NocoBase ACL integration for admin applications.",
|
|
25
|
-
acl: { type: "authenticated" },
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: "acl-components",
|
|
30
|
-
list: "/acl",
|
|
31
|
-
meta: {
|
|
32
|
-
parent: "acl-integration",
|
|
33
|
-
label: "Role switcher",
|
|
34
|
-
icon: <Blocks />,
|
|
35
|
-
acl: { type: "authenticated" },
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "acl-patterns",
|
|
40
|
-
list: "/acl/patterns",
|
|
41
|
-
meta: {
|
|
42
|
-
parent: "acl-integration",
|
|
43
|
-
label: "Permission patterns",
|
|
44
|
-
icon: <PanelsTopLeft />,
|
|
45
|
-
acl: { type: "authenticated" },
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
routes: (
|
|
50
|
-
<Route key="nocobase-acl" path="/acl" element={<Outlet />}>
|
|
51
|
-
<Route
|
|
52
|
-
index
|
|
53
|
-
element={
|
|
54
|
-
<LazyAclRoute>
|
|
55
|
-
<AclComponentsPage />
|
|
56
|
-
</LazyAclRoute>
|
|
57
|
-
}
|
|
58
|
-
/>
|
|
59
|
-
<Route
|
|
60
|
-
path="patterns"
|
|
61
|
-
element={
|
|
62
|
-
<LazyAclRoute>
|
|
63
|
-
<AclPatternsPage />
|
|
64
|
-
</LazyAclRoute>
|
|
65
|
-
}
|
|
66
|
-
/>
|
|
67
|
-
</Route>
|
|
68
|
-
),
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
export default nocobaseAclExtension;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./components";
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# NocoBase AI Registry
|
|
2
|
-
|
|
3
|
-
The Registry is split by capability so applications only install the code and dependencies they use.
|
|
4
|
-
|
|
5
|
-
These entries target the compatible NocoBase admin starter family. The host must
|
|
6
|
-
provide the `@` source alias, `@/lib/nocobase/client`, the standard shadcn UI
|
|
7
|
-
components, and (for `@nocobase/ai`) the `@/app/extension` discovery contract.
|
|
8
|
-
Applications with a different host can still reuse the providers and components,
|
|
9
|
-
but should supply their own `AIService` adapter and integration entry.
|
|
10
|
-
|
|
11
|
-
- `@nocobase/ai-runtime`: NocoBase service adapter, chat state, streaming transport, conversation history, Tool execution, and page-context registries.
|
|
12
|
-
- `@nocobase/ai-chat`: Chat windows, containers, triggers, page-element APIs, built-in Tool cards, and the high-level `NocoBaseAIRootProvider`.
|
|
13
|
-
- `@nocobase/ai-react-hook-form`: Optional React Hook Form adapter for the built-in Form filler.
|
|
14
|
-
- `@nocobase/ai`: The complete Demo extension and routes.
|
|
15
|
-
|
|
16
|
-
## Recommended provider
|
|
17
|
-
|
|
18
|
-
Use one root provider around every chat surface and page element that should participate in AI interactions:
|
|
19
|
-
|
|
20
|
-
```tsx
|
|
21
|
-
<NocoBaseAIRootProvider service={service}>
|
|
22
|
-
<YourApplication />
|
|
23
|
-
</NocoBaseAIRootProvider>
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
It installs the AI runtime, built-in Tool renderers, Form registry, frontend Tool registry, and page-context resolver in the required order. The lower-level providers remain available for advanced integrations.
|
|
27
|
-
|
|
28
|
-
## Page context
|
|
29
|
-
|
|
30
|
-
Prefer `useAIPageElementHandle` when a page element is both registered and referenced by a task or scope:
|
|
31
|
-
|
|
32
|
-
```tsx
|
|
33
|
-
const customer = useAIPageElementHandle({
|
|
34
|
-
id: "customer-detail",
|
|
35
|
-
title: "Customer detail",
|
|
36
|
-
getContext: () => customerRecord,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<AIPageContextScope context={customer.context}>
|
|
41
|
-
<section ref={customer.ref}>...</section>
|
|
42
|
-
</AIPageContextScope>
|
|
43
|
-
);
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Context is resolved again immediately before sending, so the model receives the latest page values. Resolution failures block the request by default. Set `contextFailurePolicy="omit"` on `NocoBaseAIRootProvider` only when sending without unavailable context is an intentional product decision.
|
|
47
|
-
|
|
48
|
-
Nested scopes replace the parent scope by default. Use `mode="append"` to compose parent and child context.
|
|
49
|
-
|
|
50
|
-
## Form filler
|
|
51
|
-
|
|
52
|
-
Register forms with `useAIForm`. Sending a registered form Context automatically enables the fixed `formFiller` Tool; tasks do not need to add it to `skillSettings.tools`.
|
|
53
|
-
|
|
54
|
-
The runtime applies only declared, editable, type-compatible fields. It never submits or saves the form. React Hook Form users can install `@nocobase/ai-react-hook-form` and import `applyReactHookFormValues` from `src/extensions/nocobase-ai/adapters/react-hook-form`.
|
|
55
|
-
|
|
56
|
-
## Frontend Tools
|
|
57
|
-
|
|
58
|
-
Frontend Tools are page-local browser actions and remain separate from Form filler. Use `defineAIFrontendTool` for typed registration, provide a JSON input schema, and choose `ASK` or `ALLOW`. Runtime permission controls approval; prompts should not simulate approval behavior.
|
|
59
|
-
|
|
60
|
-
## Tool cards
|
|
61
|
-
|
|
62
|
-
Pass application-specific message renderers through `NocoBaseAIRootProvider.toolRenderers`. Built-in renderers remain available automatically. A custom renderer receives the Tool part, disabled state, edit/approve/reject actions, and a composer-focus callback.
|
|
63
|
-
|
|
64
|
-
## Local Registry development
|
|
65
|
-
|
|
66
|
-
- `pnpm registry:build` regenerates `registry.json` and the static shadcn Registry output.
|
|
67
|
-
- `pnpm registry:install` installs the Registry source only when the target directory is missing.
|
|
68
|
-
- `pnpm registry:preview` intentionally replaces the local installed preview with the authoritative source.
|
|
69
|
-
|
|
70
|
-
Normal install and `postinstall` never overwrite an existing `src/extensions/nocobase-ai` directory, so downstream applications can edit and commit installed source.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FieldValues,
|
|
3
|
-
Path,
|
|
4
|
-
PathValue,
|
|
5
|
-
UseFormReturn,
|
|
6
|
-
} from "react-hook-form";
|
|
7
|
-
|
|
8
|
-
export function applyReactHookFormValues<TValues extends FieldValues>(
|
|
9
|
-
form: Pick<UseFormReturn<TValues>, "setValue">,
|
|
10
|
-
values: Record<string, unknown>
|
|
11
|
-
) {
|
|
12
|
-
for (const [name, value] of Object.entries(values)) {
|
|
13
|
-
const path = name as Path<TValues>;
|
|
14
|
-
form.setValue(path, value as PathValue<TValues, typeof path>, {
|
|
15
|
-
shouldDirty: true,
|
|
16
|
-
shouldTouch: true,
|
|
17
|
-
shouldValidate: true,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<svg width="878" height="878" viewBox="0 0 878 878" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<g clip-path="url(#clip0_2002_119)">
|
|
3
|
-
<circle cx="439" cy="439" r="439" fill="url(#paint0_linear_2002_119)"/>
|
|
4
|
-
<mask id="mask0_2002_119" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="878" height="878">
|
|
5
|
-
<path d="M0 439C0 196.547 196.547 0 439 0C681.453 0 878 196.547 878 439C878 681.453 681.453 878 439 878C196.547 878 0 681.453 0 439Z" fill="url(#paint1_linear_2002_119)"/>
|
|
6
|
-
</mask>
|
|
7
|
-
<g mask="url(#mask0_2002_119)">
|
|
8
|
-
<path d="M159.539 597.752V635.001C159.539 642.174 57.0002 639.762 57.0002 629.419C57.0002 619.684 57.1917 575.572 57.0002 530.188C34.0374 499.434 34.0374 480.212 52.1937 460.346C70.3489 440.48 199.594 430.547 199.594 430.547C199.594 430.547 209.291 526.913 210.81 553.053C211.42 563.566 218.02 597.752 192.385 597.752H159.539Z" fill="#D1B9F0"/>
|
|
9
|
-
<g style="mix-blend-mode:multiply">
|
|
10
|
-
<path d="M159.501 594.57C138.626 592.216 118.452 585.408 100.258 574.574C100.258 574.574 113.075 606.029 159.501 614.565V594.57Z" fill="#A9A5A5"/>
|
|
11
|
-
</g>
|
|
12
|
-
<path d="M276.491 709.179C286.66 730.543 294.672 765.86 300.524 815.131H-84C-78.1446 765.855 -70.1337 730.537 -59.9672 709.179C-49.8351 687.89 44.1751 646.917 44.1751 646.917C44.1751 646.917 46.0459 628.189 50.5832 625.504C55.1205 622.819 160.537 622.82 165.941 625.504C171.345 628.187 172.35 646.907 172.35 646.907C172.35 646.907 266.379 687.934 276.491 709.179Z" fill="#9066ED"/>
|
|
13
|
-
<path d="M110.043 539.15C102.51 520.344 81.7101 442.202 105.803 442.202C125.737 456.505 137.339 461.708 163.674 433.567C168.878 449.972 179.314 452.938 197.425 455.486L206.888 496.108V446.392C217.781 447.525 226.438 448.753 228.565 441.044C230.692 433.336 216.952 423.763 216.952 423.763C216.952 423.763 237.172 428.326 236.875 417.291C236.578 406.256 216.918 398.121 216.918 398.121C216.918 398.121 240.567 401.572 240.08 385.273C239.595 368.974 120.799 335.204 61.8955 393.059C43.4601 389.953 33.4321 388.948 22.6513 404.113C15.7356 421.257 23.7293 428.994 35.9311 443.119C26.8545 443.818 25.5811 446.238 23.6146 452.927C21.6481 459.617 30.268 472.499 40.1055 483.145C31.7259 488.149 27.5177 488.165 28.5129 496.108C29.5081 504.049 40.2321 507.547 40.2321 507.547L57.9336 531.281V576.013L68.8192 500.923C81.5994 519.66 90.5075 538.781 95.6122 563.173C102.025 593.822 142.911 606.248 183.797 606.248C207.847 606.248 223.079 586.367 211.054 553.233C210.253 556.547 203.358 562.061 190.211 564.001C173.375 566.487 119.663 563.173 110.043 539.15Z" fill="black"/>
|
|
14
|
-
<path d="M110.043 539.15C102.51 520.344 81.7101 442.202 105.803 442.202C125.737 456.505 137.339 461.708 163.674 433.567C168.878 449.972 179.314 452.938 197.425 455.486L206.888 496.108V446.392C217.781 447.525 226.438 448.753 228.565 441.044C230.692 433.336 216.952 423.763 216.952 423.763C216.952 423.763 237.172 428.326 236.875 417.291C236.578 406.256 216.918 398.121 216.918 398.121C216.918 398.121 240.567 401.572 240.08 385.273C239.595 368.974 120.799 335.204 61.8955 393.059C43.4601 389.953 33.4321 388.948 22.6513 404.113C15.7356 421.257 23.7293 428.994 35.9311 443.119C26.8545 443.818 25.5811 446.238 23.6146 452.927C21.6481 459.617 30.268 472.499 40.1055 483.145C31.7259 488.149 27.5177 488.165 28.5129 496.108C29.5081 504.049 40.2321 507.547 40.2321 507.547L57.9336 531.281V576.013L68.8192 500.923C81.5994 519.66 90.5075 538.781 95.6122 563.173C102.025 593.822 142.911 606.248 183.797 606.248C207.847 606.248 223.079 586.367 211.054 553.233C210.253 556.547 203.358 562.061 190.211 564.001C173.375 566.487 119.663 563.173 110.043 539.15Z" fill="#644B85"/>
|
|
15
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M196.196 541.84C196.707 542.848 196.33 544.094 195.354 544.622C176.02 555.08 162.648 546.013 158.266 539.686C157.625 538.76 157.832 537.473 158.728 536.81C159.623 536.148 160.87 536.362 161.51 537.287C164.852 542.112 176.106 550.382 193.505 540.97C194.48 540.442 195.685 540.832 196.196 541.84Z" fill="white"/>
|
|
16
|
-
<path d="M800.108 409.771C788.692 373.235 768.964 361 738.848 361C683.204 361 619.222 404.799 623.145 468.797C627.354 537.442 613.508 572.319 594.223 584.629C594.223 584.629 634.771 610.274 714.717 605.851C696.088 590.271 686.276 565.652 685.976 545.035C685.787 532.138 689.398 483.926 689.66 476.918C753.943 480.935 788.097 455.857 788.097 455.857C788.097 455.857 760.834 507.024 764.93 531.742C769.026 556.461 761.872 582.422 759.673 590.727C758.274 596.015 846.798 590.957 852.722 584.629C856.103 581.018 838.5 549.238 836.522 525.644C834.281 498.915 846.908 479.995 842.654 460.314C836.488 431.782 825.643 411.778 800.108 409.771Z" fill="#644B85"/>
|
|
17
|
-
<path d="M682.801 617.325C682.801 602.148 682.303 527.288 682.328 526.023C642.156 532.165 642.969 452.906 683.614 472.3C692.556 478.201 717.755 472.3 715.317 423.396C759.213 472.3 810.176 415.26 814.546 461.74C820.514 525.205 814.511 591.624 776.485 591.629C772.325 591.576 768.177 591.147 764.09 590.344V617.325C764.09 634.189 793.354 642.62 793.354 642.62C793.354 642.62 742.805 692.031 721.82 691.757C700.834 691.484 653.537 642.62 653.537 642.62C653.537 642.62 682.801 634.189 682.801 617.325Z" fill="#D1B9F0"/>
|
|
18
|
-
<g style="mix-blend-mode:multiply">
|
|
19
|
-
<path d="M764.083 590.336C743.914 585.695 724.801 577.049 707.8 564.874C707.8 564.874 721.828 600.443 764.031 607.192L764.083 590.336Z" fill="#9F9F9F"/>
|
|
20
|
-
</g>
|
|
21
|
-
<path d="M873.111 715.2C884.91 752.604 891 866 891 866H556C556 866 562.09 752.604 573.888 715.2C584.225 682.434 652.335 644.813 672.295 634C683.82 652.392 700.336 664.159 723.5 664.159C746.663 664.159 763.18 652.392 774.704 634C794.664 644.813 862.775 682.434 873.111 715.2Z" fill="#E1CBED"/>
|
|
22
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M810.507 513.765C823.869 514.972 835.644 504.715 836.808 490.855C837.972 476.995 828.083 464.781 814.721 463.574C801.36 462.367 789.584 472.624 788.42 486.483C787.256 500.343 797.145 512.557 810.507 513.765ZM810.156 517.948C825.744 519.356 839.482 507.39 840.84 491.22C842.198 475.051 830.662 460.8 815.073 459.392C799.484 457.983 785.746 469.95 784.388 486.119C783.03 502.289 794.566 516.539 810.156 517.948Z" fill="white"/>
|
|
23
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M742.179 517.072C755.541 518.279 767.317 508.022 768.482 494.163C769.645 480.303 759.757 468.089 746.395 466.881C733.033 465.674 721.257 475.931 720.094 489.791C718.929 503.651 728.817 515.865 742.179 517.072ZM741.828 521.254C757.418 522.663 771.155 510.697 772.513 494.528C773.872 478.357 762.335 464.107 746.746 462.699C731.157 461.29 717.419 473.256 716.061 489.427C714.703 505.596 726.239 519.846 741.828 521.254Z" fill="white"/>
|
|
24
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M772.23 484.946C774.285 483.156 776.941 482.285 779.614 482.527C782.288 482.768 784.76 484.102 786.485 486.234C788.212 488.366 789.05 491.121 788.817 493.894L784.785 493.53C784.925 491.866 784.421 490.213 783.386 488.934C782.351 487.655 780.867 486.854 779.263 486.71C777.659 486.565 776.065 487.086 774.832 488.161C773.599 489.235 772.828 490.774 772.688 492.437L768.656 492.073C768.888 489.3 770.173 486.736 772.23 484.946Z" fill="white"/>
|
|
25
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M687.49 492.673L718.216 489.656L718.597 493.835L687.872 496.854L687.49 492.673Z" fill="white"/>
|
|
26
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M810.507 513.765C823.869 514.972 835.644 504.715 836.808 490.855C837.972 476.995 828.083 464.781 814.721 463.574C801.36 462.367 789.584 472.624 788.42 486.483C787.256 500.343 797.145 512.557 810.507 513.765ZM810.156 517.948C825.744 519.356 839.482 507.39 840.84 491.22C842.198 475.051 830.662 460.8 815.073 459.392C799.484 457.983 785.746 469.95 784.388 486.119C783.03 502.289 794.566 516.539 810.156 517.948Z" fill="white"/>
|
|
27
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M742.179 517.072C755.541 518.279 767.317 508.023 768.482 494.164C769.645 480.304 759.757 468.09 746.395 466.882C733.033 465.675 721.257 475.931 720.094 489.791C718.929 503.651 728.817 515.865 742.179 517.072ZM741.828 521.255C757.418 522.663 771.155 510.697 772.513 494.528C773.872 478.358 762.335 464.108 746.746 462.699C731.157 461.29 717.419 473.257 716.061 489.427C714.703 505.596 726.239 519.846 741.828 521.255Z" fill="white"/>
|
|
28
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M772.23 484.946C774.285 483.156 776.941 482.285 779.614 482.527C782.288 482.768 784.76 484.102 786.485 486.234C788.212 488.366 789.05 491.121 788.817 493.894L784.785 493.53C784.925 491.866 784.421 490.213 783.386 488.934C782.351 487.655 780.867 486.854 779.263 486.709C777.659 486.565 776.065 487.086 774.832 488.161C773.599 489.235 772.828 490.773 772.688 492.437L768.656 492.073C768.888 489.3 770.173 486.736 772.23 484.946Z" fill="white"/>
|
|
29
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M687.49 492.673L718.216 489.656L718.597 493.835L687.872 496.854L687.49 492.673Z" fill="white"/>
|
|
30
|
-
<path d="M612.419 368.971C612.419 437.401 538.694 459.726 496.644 408.286L531.072 546.095C644.606 610.588 726.741 719.073 724.77 755.925L612.419 878L478.386 792.778C189.822 708.017 217.548 527.13 267.481 447.283C259.597 233.536 389.773 220.01 478.386 286.051C579.305 258.412 609.791 329.813 612.419 368.971Z" fill="#644B85"/>
|
|
31
|
-
<path d="M180.406 720.095C162.803 754.212 154 878.494 154 878.494H648.497C648.497 878.494 639.694 754.212 622.091 720.095C595.687 668.921 401.249 603.124 401.249 603.124C401.249 603.124 206.811 668.921 180.406 720.095Z" fill="#E1CBED"/>
|
|
32
|
-
<path d="M343.645 632.11C343.645 632.11 374.877 671.364 403.068 671.364C431.26 671.364 458.867 632.11 458.867 632.11V578.968C464.932 579.932 471.075 580.3 477.211 580.064C534.794 580.06 556.506 495.66 545.284 392.973C538.083 392.973 521.279 392.973 497.275 359.155C503.275 406.258 433.662 399.011 407.258 361.571C420.459 406.258 385.653 436.453 355.647 418.336C296.809 382.81 283.582 491.106 343.645 492.009V632.11Z" fill="#D1B9F0"/>
|
|
33
|
-
<path d="M458.879 578.971C429.101 573.454 400.607 562.396 374.862 546.362C374.862 546.362 404.868 598.295 458.879 598.295V578.971Z" fill="#80728F"/>
|
|
34
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M282.556 506.505C282.556 488.239 297.272 473.43 315.425 473.43V467.416C293.972 467.416 276.579 484.918 276.579 506.505C276.579 528.093 293.972 545.595 315.425 545.595C336.878 545.595 354.271 528.093 354.271 506.505C354.271 496.741 349.363 488.796 345.13 481.944C344.751 481.329 344.376 480.723 344.011 480.125L344.005 480.116L342.619 477.86L337.536 481.027L338.918 483.273L338.921 483.277C339.257 483.826 339.592 484.372 339.923 484.913C344.296 492.03 348.294 498.537 348.294 506.505C348.294 524.772 333.578 539.581 315.425 539.581C297.272 539.581 282.556 524.772 282.556 506.505Z" fill="white"/>
|
|
35
|
-
</g>
|
|
36
|
-
</g>
|
|
37
|
-
<defs>
|
|
38
|
-
<linearGradient id="paint0_linear_2002_119" x1="726" y1="116" x2="63" y2="699.5" gradientUnits="userSpaceOnUse">
|
|
39
|
-
<stop stop-color="#9169EB"/>
|
|
40
|
-
<stop offset="1" stop-color="#FBC2EB"/>
|
|
41
|
-
</linearGradient>
|
|
42
|
-
<linearGradient id="paint1_linear_2002_119" x1="101.5" y1="712.5" x2="684.5" y2="81.5" gradientUnits="userSpaceOnUse">
|
|
43
|
-
<stop stop-color="#E6C1DC"/>
|
|
44
|
-
<stop offset="1" stop-color="#8E64EE"/>
|
|
45
|
-
</linearGradient>
|
|
46
|
-
<clipPath id="clip0_2002_119">
|
|
47
|
-
<rect width="878" height="878" fill="white"/>
|
|
48
|
-
</clipPath>
|
|
49
|
-
</defs>
|
|
50
|
-
</svg>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AIProvider,
|
|
3
|
-
type AIProviderProps,
|
|
4
|
-
} from "../providers/ai-provider";
|
|
5
|
-
import { AIPageElementProvider } from "./page-elements/page-element-provider";
|
|
6
|
-
import {
|
|
7
|
-
AIToolRendererProvider,
|
|
8
|
-
type AIToolRendererMap,
|
|
9
|
-
} from "./tools/tool-renderer-provider";
|
|
10
|
-
import type { AIPageContextFailurePolicy } from "./page-elements/page-element-provider";
|
|
11
|
-
|
|
12
|
-
export type NocoBaseAIRootProviderProps = AIProviderProps & {
|
|
13
|
-
toolRenderers?: AIToolRendererMap;
|
|
14
|
-
contextFailurePolicy?: AIPageContextFailurePolicy;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export function NocoBaseAIRootProvider({
|
|
18
|
-
children,
|
|
19
|
-
toolRenderers,
|
|
20
|
-
contextFailurePolicy,
|
|
21
|
-
...aiProviderProps
|
|
22
|
-
}: NocoBaseAIRootProviderProps) {
|
|
23
|
-
return (
|
|
24
|
-
<AIProvider {...aiProviderProps}>
|
|
25
|
-
<AIToolRendererProvider renderers={toolRenderers}>
|
|
26
|
-
<AIPageElementProvider contextFailurePolicy={contextFailurePolicy}>
|
|
27
|
-
{children}
|
|
28
|
-
</AIPageElementProvider>
|
|
29
|
-
</AIToolRendererProvider>
|
|
30
|
-
</AIProvider>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { cn } from "@/lib/utils";
|
|
2
|
-
import { getAIEmployeeAvatar, type AIEmployee } from "../../providers";
|
|
3
|
-
import type { CSSProperties } from "react";
|
|
4
|
-
|
|
5
|
-
export function AIEmployeeAvatar({
|
|
6
|
-
employee,
|
|
7
|
-
flip = false,
|
|
8
|
-
className,
|
|
9
|
-
style,
|
|
10
|
-
}: {
|
|
11
|
-
employee?: AIEmployee;
|
|
12
|
-
flip?: boolean;
|
|
13
|
-
className?: string;
|
|
14
|
-
style?: CSSProperties;
|
|
15
|
-
}) {
|
|
16
|
-
return (
|
|
17
|
-
<span
|
|
18
|
-
className={cn(
|
|
19
|
-
"relative flex size-8 shrink-0 overflow-hidden rounded-full bg-transparent",
|
|
20
|
-
className
|
|
21
|
-
)}
|
|
22
|
-
style={style}
|
|
23
|
-
>
|
|
24
|
-
<img
|
|
25
|
-
src={getAIEmployeeAvatar(employee?.avatar, { flip })}
|
|
26
|
-
alt={employee?.nickname ?? "AI employee"}
|
|
27
|
-
className="size-full object-cover"
|
|
28
|
-
/>
|
|
29
|
-
</span>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { Button } from "@/components/ui/button";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
3
|
-
import type { AIChatAttachment } from "../../providers";
|
|
4
|
-
import { FileText, LoaderCircle, TriangleAlert, X } from "lucide-react";
|
|
5
|
-
|
|
6
|
-
export function ChatAttachment({
|
|
7
|
-
attachment,
|
|
8
|
-
removable = false,
|
|
9
|
-
onRemove,
|
|
10
|
-
}: {
|
|
11
|
-
attachment: AIChatAttachment;
|
|
12
|
-
removable?: boolean;
|
|
13
|
-
onRemove?: () => void;
|
|
14
|
-
}) {
|
|
15
|
-
const preview =
|
|
16
|
-
attachment.preview ??
|
|
17
|
-
(attachment.mimetype?.startsWith("image/") ? attachment.url : undefined);
|
|
18
|
-
const content = (
|
|
19
|
-
<div
|
|
20
|
-
className={cn(
|
|
21
|
-
"relative flex h-14 min-w-0 items-center gap-2 rounded-lg border bg-background p-1.5 pr-2",
|
|
22
|
-
attachment.status === "error" && "border-destructive/40"
|
|
23
|
-
)}
|
|
24
|
-
>
|
|
25
|
-
<div className="flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted">
|
|
26
|
-
{preview ? (
|
|
27
|
-
<img src={preview} alt="" className="size-full object-cover" />
|
|
28
|
-
) : (
|
|
29
|
-
<FileText className="size-4 text-muted-foreground" />
|
|
30
|
-
)}
|
|
31
|
-
</div>
|
|
32
|
-
<div className="min-w-0 flex-1">
|
|
33
|
-
<div className="max-w-40 truncate text-xs font-medium">
|
|
34
|
-
{attachment.filename}
|
|
35
|
-
</div>
|
|
36
|
-
<div className="mt-0.5 flex items-center gap-1 text-[11px] text-muted-foreground">
|
|
37
|
-
{attachment.status === "uploading" ? (
|
|
38
|
-
<>
|
|
39
|
-
<LoaderCircle className="size-3 animate-spin" /> Uploading…
|
|
40
|
-
</>
|
|
41
|
-
) : attachment.status === "error" ? (
|
|
42
|
-
<>
|
|
43
|
-
<TriangleAlert className="size-3 text-destructive" />
|
|
44
|
-
<span className="truncate text-destructive">
|
|
45
|
-
{attachment.error ?? "Upload failed"}
|
|
46
|
-
</span>
|
|
47
|
-
</>
|
|
48
|
-
) : (
|
|
49
|
-
formatFileSize(attachment.size)
|
|
50
|
-
)}
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
{removable ? (
|
|
54
|
-
<Button
|
|
55
|
-
type="button"
|
|
56
|
-
variant="ghost"
|
|
57
|
-
size="icon-xs"
|
|
58
|
-
className="shrink-0 rounded-full"
|
|
59
|
-
aria-label={`Remove ${attachment.filename}`}
|
|
60
|
-
onClick={(event) => {
|
|
61
|
-
event.preventDefault();
|
|
62
|
-
event.stopPropagation();
|
|
63
|
-
onRemove?.();
|
|
64
|
-
}}
|
|
65
|
-
>
|
|
66
|
-
<X />
|
|
67
|
-
</Button>
|
|
68
|
-
) : null}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (!removable && attachment.url) {
|
|
73
|
-
return (
|
|
74
|
-
<a
|
|
75
|
-
href={attachment.url}
|
|
76
|
-
target="_blank"
|
|
77
|
-
rel="noreferrer"
|
|
78
|
-
className="block rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
79
|
-
>
|
|
80
|
-
{content}
|
|
81
|
-
</a>
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
return content;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function formatFileSize(size?: number) {
|
|
88
|
-
if (!size) return "File";
|
|
89
|
-
if (size < 1024) return `${size} B`;
|
|
90
|
-
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`;
|
|
91
|
-
return `${(size / 1024 / 1024).toFixed(1)} MB`;
|
|
92
|
-
}
|