@flamingo-stack/openframe-frontend-core 0.0.225 → 0.0.227
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/dist/{chunk-2QURHTDV.js → chunk-CUBRHI6D.js} +2 -2
- package/dist/{chunk-NRJ53MIF.cjs → chunk-E3DB4D43.cjs} +9 -9
- package/dist/{chunk-NRJ53MIF.cjs.map → chunk-E3DB4D43.cjs.map} +1 -1
- package/dist/{chunk-3YTIV6C5.cjs → chunk-E3WJQQGW.cjs} +7 -7
- package/dist/{chunk-3YTIV6C5.cjs.map → chunk-E3WJQQGW.cjs.map} +1 -1
- package/dist/{chunk-SAJG77KY.js → chunk-EURLSRHW.js} +2 -2
- package/dist/{chunk-IWBDAGZQ.cjs → chunk-HO2VEMEX.cjs} +24 -24
- package/dist/{chunk-IWBDAGZQ.cjs.map → chunk-HO2VEMEX.cjs.map} +1 -1
- package/dist/{chunk-NHRVPMBU.js → chunk-K252FYE5.js} +3959 -3740
- package/dist/chunk-K252FYE5.js.map +1 -0
- package/dist/{chunk-5RELSRTS.cjs → chunk-LEM4FLCU.cjs} +10 -10
- package/dist/{chunk-5RELSRTS.cjs.map → chunk-LEM4FLCU.cjs.map} +1 -1
- package/dist/{chunk-HOQDRQ4M.cjs → chunk-QFC725WU.cjs} +746 -527
- package/dist/chunk-QFC725WU.cjs.map +1 -0
- package/dist/{chunk-RIEEPMJ6.js → chunk-X3KKG6IU.js} +2 -2
- package/dist/{chunk-NUOYDHUM.js → chunk-YE62NF6I.js} +2 -2
- package/dist/components/chat/approval-batch-message.d.ts +6 -0
- package/dist/components/chat/approval-batch-message.d.ts.map +1 -1
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/features/index.cjs +10 -2
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +9 -1
- package/dist/components/features/notifications/approval-request-notification-tile.d.ts +13 -0
- package/dist/components/features/notifications/approval-request-notification-tile.d.ts.map +1 -0
- package/dist/components/features/notifications/index.d.ts +4 -1
- package/dist/components/features/notifications/index.d.ts.map +1 -1
- package/dist/components/features/notifications/notification-drawer.d.ts +3 -1
- package/dist/components/features/notifications/notification-drawer.d.ts.map +1 -1
- package/dist/components/features/notifications/notification-popups.d.ts +3 -1
- package/dist/components/features/notifications/notification-popups.d.ts.map +1 -1
- package/dist/components/features/notifications/notification-tile.d.ts +6 -1
- package/dist/components/features/notifications/notification-tile.d.ts.map +1 -1
- package/dist/components/features/notifications/notifications-context.d.ts +5 -2
- package/dist/components/features/notifications/notifications-context.d.ts.map +1 -1
- package/dist/components/features/notifications/types.d.ts +30 -0
- package/dist/components/features/notifications/types.d.ts.map +1 -1
- package/dist/components/index.cjs +87 -77
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +14 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +25 -25
- package/dist/components/onboarding-guides/index.js +3 -3
- package/dist/components/tickets/index.cjs +64 -64
- package/dist/components/tickets/index.js +4 -4
- package/dist/components/ui/color-preset-select.d.ts.map +1 -1
- package/dist/components/ui/color-swatch.d.ts +7 -0
- package/dist/components/ui/color-swatch.d.ts.map +1 -0
- package/dist/components/ui/data-table/data-table-body.d.ts +8 -1
- package/dist/components/ui/data-table/data-table-body.d.ts.map +1 -1
- package/dist/components/ui/data-table/data-table-row.d.ts +4 -2
- package/dist/components/ui/data-table/data-table-row.d.ts.map +1 -1
- package/dist/components/ui/data-table/index.d.ts +1 -1
- package/dist/components/ui/index.cjs +4 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +3 -1
- package/dist/components/ui/ticket-status-config-row.d.ts.map +1 -1
- package/dist/components/ui/ticket-status-tag.d.ts.map +1 -1
- package/dist/index.cjs +12 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -1
- package/package.json +1 -1
- package/src/components/chat/approval-batch-message.tsx +26 -15
- package/src/components/features/notifications/approval-request-notification-tile.tsx +118 -0
- package/src/components/features/notifications/index.ts +10 -0
- package/src/components/features/notifications/notification-drawer.tsx +28 -11
- package/src/components/features/notifications/notification-popups.tsx +33 -19
- package/src/components/features/notifications/notification-tile.tsx +34 -19
- package/src/components/features/notifications/notifications-context.tsx +7 -1
- package/src/components/features/notifications/types.ts +50 -0
- package/src/components/ui/color-preset-select.tsx +1 -10
- package/src/components/ui/color-swatch.tsx +17 -0
- package/src/components/ui/data-table/data-table-body.tsx +9 -0
- package/src/components/ui/data-table/data-table-row.tsx +24 -3
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/modal-v2.tsx +2 -2
- package/src/components/ui/ticket-status-config-row.tsx +78 -39
- package/src/components/ui/ticket-status-tag.tsx +2 -7
- package/src/stories/NotificationDrawer.stories.tsx +148 -1
- package/dist/chunk-HOQDRQ4M.cjs.map +0 -1
- package/dist/chunk-NHRVPMBU.js.map +0 -1
- /package/dist/{chunk-2QURHTDV.js.map → chunk-CUBRHI6D.js.map} +0 -0
- /package/dist/{chunk-SAJG77KY.js.map → chunk-EURLSRHW.js.map} +0 -0
- /package/dist/{chunk-RIEEPMJ6.js.map → chunk-X3KKG6IU.js.map} +0 -0
- /package/dist/{chunk-NUOYDHUM.js.map → chunk-YE62NF6I.js.map} +0 -0
|
@@ -80,7 +80,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
|
|
80
80
|
data-state={state}
|
|
81
81
|
className={cn(
|
|
82
82
|
"absolute inset-0 bg-black/50 backdrop-blur-[2px] md:backdrop-blur-none",
|
|
83
|
-
"duration-200",
|
|
83
|
+
"duration-200 fill-mode-forwards",
|
|
84
84
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
85
85
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
86
86
|
// Hold the hidden end-state until unmount so the backdrop doesn't
|
|
@@ -101,7 +101,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
|
|
|
101
101
|
"bg-ods-bg md:bg-ods-card",
|
|
102
102
|
"border border-ods-border rounded-md shadow-xl",
|
|
103
103
|
"p-[var(--spacing-system-xl)] gap-[var(--spacing-system-l)]",
|
|
104
|
-
"duration-200",
|
|
104
|
+
"duration-200 fill-mode-forwards",
|
|
105
105
|
"data-[state=open]:animate-in data-[state=open]:fade-in-0",
|
|
106
106
|
"data-[state=open]:slide-in-from-bottom-4 md:data-[state=open]:slide-in-from-bottom-0 md:data-[state=open]:zoom-in-95",
|
|
107
107
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
|
|
@@ -37,12 +37,48 @@ export interface TicketStatusConfigRowProps {
|
|
|
37
37
|
isDragging?: boolean
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
let dismissOpenTooltip: (() => void) | null = null
|
|
41
|
+
|
|
40
42
|
function WithLeftTooltip({ content, children }: { content?: string; children: React.ReactElement }) {
|
|
43
|
+
const [open, setOpen] = React.useState(false)
|
|
44
|
+
const isTouchRef = React.useRef(false)
|
|
45
|
+
const close = React.useCallback(() => setOpen(false), [])
|
|
46
|
+
|
|
41
47
|
if (!content) return children
|
|
48
|
+
|
|
49
|
+
const toggleFromTouch = () => {
|
|
50
|
+
setOpen(prev => {
|
|
51
|
+
const next = !prev
|
|
52
|
+
if (next) {
|
|
53
|
+
if (dismissOpenTooltip && dismissOpenTooltip !== close) dismissOpenTooltip()
|
|
54
|
+
dismissOpenTooltip = close
|
|
55
|
+
} else if (dismissOpenTooltip === close) {
|
|
56
|
+
dismissOpenTooltip = null
|
|
57
|
+
}
|
|
58
|
+
return next
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
return (
|
|
43
63
|
<TooltipProvider delayDuration={150}>
|
|
44
|
-
<Tooltip>
|
|
45
|
-
<TooltipTrigger
|
|
64
|
+
<Tooltip open={open} onOpenChange={setOpen}>
|
|
65
|
+
<TooltipTrigger
|
|
66
|
+
asChild
|
|
67
|
+
onPointerDown={e => {
|
|
68
|
+
isTouchRef.current = e.pointerType === 'touch'
|
|
69
|
+
if (!isTouchRef.current) return
|
|
70
|
+
e.preventDefault()
|
|
71
|
+
toggleFromTouch()
|
|
72
|
+
}}
|
|
73
|
+
onFocus={e => {
|
|
74
|
+
if (isTouchRef.current) e.preventDefault()
|
|
75
|
+
}}
|
|
76
|
+
onClick={e => {
|
|
77
|
+
if (isTouchRef.current) e.preventDefault()
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
{children}
|
|
81
|
+
</TooltipTrigger>
|
|
46
82
|
<TooltipContent side="left" className="max-w-xs">
|
|
47
83
|
{content}
|
|
48
84
|
</TooltipContent>
|
|
@@ -75,16 +111,17 @@ export function TicketStatusConfigRow({
|
|
|
75
111
|
// Custom rows render as filled pills (no border); system rows take the
|
|
76
112
|
// page-configured variant (outline/primary). text-h5 already uppercases.
|
|
77
113
|
const previewVariant: SystemTagVariant | undefined = systemTagVariant ?? (isSystem ? undefined : 'primary')
|
|
114
|
+
const colClass = 'min-w-0 grow basis-[calc(50%-6px)] md:basis-0'
|
|
78
115
|
|
|
79
116
|
return (
|
|
80
117
|
<div
|
|
81
118
|
className={cn(
|
|
82
|
-
'flex w-full items-
|
|
119
|
+
'flex w-full items-start gap-3 rounded-md border border-ods-border bg-ods-card md:gap-[var(--spacing-system-m)]',
|
|
83
120
|
'p-[var(--spacing-system-m)]',
|
|
84
121
|
isDragging && 'opacity-70 shadow-lg',
|
|
85
122
|
)}
|
|
86
123
|
>
|
|
87
|
-
<div className="flex
|
|
124
|
+
<div className="flex h-11 w-8 shrink-0 items-center justify-center text-ods-text-secondary md:h-12">
|
|
88
125
|
{isSystem ? (
|
|
89
126
|
<DraggerIcon size={24} aria-hidden className="opacity-40" />
|
|
90
127
|
) : (
|
|
@@ -100,45 +137,47 @@ export function TicketStatusConfigRow({
|
|
|
100
137
|
)}
|
|
101
138
|
</div>
|
|
102
139
|
|
|
103
|
-
<div className="flex flex-1
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{showColorPicker ? (
|
|
115
|
-
<div className="flex flex-1 min-w-0">
|
|
116
|
-
<ColorPresetSelect value={color} presetKey={presetKey} onChange={onColorChange} />
|
|
140
|
+
<div className="flex min-w-0 flex-1 flex-wrap items-start gap-x-3 gap-y-4 md:flex-nowrap md:gap-[var(--spacing-system-m)]">
|
|
141
|
+
<div className={cn('flex flex-col gap-[var(--spacing-system-xxs)]', colClass)}>
|
|
142
|
+
<Input
|
|
143
|
+
value={name}
|
|
144
|
+
onChange={e => onNameChange?.(e.target.value)}
|
|
145
|
+
disabled={isSystem}
|
|
146
|
+
readOnly={isSystem}
|
|
147
|
+
aria-label="Status name"
|
|
148
|
+
maxLength={50}
|
|
149
|
+
/>
|
|
117
150
|
</div>
|
|
118
|
-
) : (
|
|
119
|
-
<div aria-hidden className="hidden flex-1 min-w-0 md:block" />
|
|
120
|
-
)}
|
|
121
151
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
152
|
+
{showColorPicker ? (
|
|
153
|
+
<div className={cn('flex', colClass)}>
|
|
154
|
+
<ColorPresetSelect value={color} presetKey={presetKey} onChange={onColorChange} />
|
|
155
|
+
</div>
|
|
156
|
+
) : (
|
|
157
|
+
<div aria-hidden className={cn('hidden md:block', colClass)} />
|
|
158
|
+
)}
|
|
129
159
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
160
|
+
{showColorPicker && isCustomColor ? (
|
|
161
|
+
<div className={cn('flex', colClass)}>
|
|
162
|
+
<ColorPickerInput value={color} onChange={next => onColorChange({ color: next, preset: undefined })} />
|
|
163
|
+
</div>
|
|
164
|
+
) : (
|
|
165
|
+
<div aria-hidden className={cn('hidden md:block', colClass)} />
|
|
166
|
+
)}
|
|
167
|
+
|
|
168
|
+
<div className={cn('flex h-11 items-center justify-start md:h-12 md:justify-end', colClass)}>
|
|
169
|
+
<TicketStatusTag
|
|
170
|
+
status={statusKey}
|
|
171
|
+
label={name || ' '}
|
|
172
|
+
color={previewColor}
|
|
173
|
+
variant={previewVariant}
|
|
174
|
+
showIcon={isSystem}
|
|
175
|
+
className="max-w-full"
|
|
176
|
+
/>
|
|
177
|
+
</div>
|
|
139
178
|
</div>
|
|
140
179
|
|
|
141
|
-
<div className="flex
|
|
180
|
+
<div className="flex h-11 w-12 shrink-0 items-center justify-center md:h-12">
|
|
142
181
|
{isSystem ? (
|
|
143
182
|
<WithLeftTooltip content={systemTooltip}>
|
|
144
183
|
<button
|
|
@@ -159,7 +198,7 @@ export function TicketStatusConfigRow({
|
|
|
159
198
|
aria-label="Delete status"
|
|
160
199
|
disabled={deleteDisabled}
|
|
161
200
|
onClick={deleteDisabled ? undefined : onDelete}
|
|
162
|
-
className=
|
|
201
|
+
className={cn('size-11 md:size-12', deleteDisabled && 'pointer-events-none')}
|
|
163
202
|
>
|
|
164
203
|
<TrashIcon className="text-ods-error"/>
|
|
165
204
|
</Button>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React from 'react'
|
|
4
4
|
import { ActionsMenuDropdown } from './actions-menu'
|
|
5
|
+
import { ColorSwatch } from './color-swatch'
|
|
5
6
|
import { Tag, type TagProps, tagVariants } from './tag'
|
|
6
7
|
import { CheckCircleIcon, Chevron02DownIcon } from '../icons-v2-generated'
|
|
7
8
|
import { cn } from '../../utils/cn'
|
|
@@ -257,13 +258,7 @@ export function TicketStatusTag({
|
|
|
257
258
|
items: options.map(option => ({
|
|
258
259
|
id: option.id,
|
|
259
260
|
label: option.name,
|
|
260
|
-
icon:
|
|
261
|
-
<span
|
|
262
|
-
className="size-2 shrink-0 rounded-full"
|
|
263
|
-
style={{ backgroundColor: option.color }}
|
|
264
|
-
aria-hidden
|
|
265
|
-
/>
|
|
266
|
-
),
|
|
261
|
+
icon: <ColorSwatch color={option.color} />,
|
|
267
262
|
onClick: () => onSelect(option.id),
|
|
268
263
|
disabled: isPending,
|
|
269
264
|
})),
|
|
@@ -2,13 +2,17 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Button } from '../components/ui/button';
|
|
4
4
|
import {
|
|
5
|
+
ADMIN_APPROVAL_REQUEST_CONTEXT_TYPE,
|
|
6
|
+
ApprovalRequestNotificationTile,
|
|
5
7
|
NotificationDrawer,
|
|
6
8
|
NotificationPopups,
|
|
7
9
|
NotificationTile,
|
|
8
10
|
NotificationsProvider,
|
|
11
|
+
isApprovalNotification,
|
|
9
12
|
useNotifications,
|
|
10
13
|
type Notification,
|
|
11
14
|
type NotificationVariant,
|
|
15
|
+
type RenderNotificationTile,
|
|
12
16
|
} from '../components/features/notifications';
|
|
13
17
|
import { Toaster } from '../components/ui/toaster';
|
|
14
18
|
|
|
@@ -235,9 +239,64 @@ export const DrawerWithSeedData: Story = {
|
|
|
235
239
|
* the same tile isn't shown twice. Toggle "Show Notifications" inside the
|
|
236
240
|
* drawer to disable pop-ups entirely.
|
|
237
241
|
*/
|
|
242
|
+
/** A deliberately long script so the command section overflows and scrolls. */
|
|
243
|
+
const LONG_POWERSHELL = [
|
|
244
|
+
'# Full diagnostic bundle — collect logs, configs and telemetry',
|
|
245
|
+
'$ErrorActionPreference = "Stop"',
|
|
246
|
+
'$stamp = Get-Date -Format "yyyyMMdd_HHmmss"',
|
|
247
|
+
'$out = "C:\\Logs\\diag_$stamp"',
|
|
248
|
+
'New-Item -ItemType Directory -Path $out -Force | Out-Null',
|
|
249
|
+
'',
|
|
250
|
+
'Write-Host "Collecting event logs..."',
|
|
251
|
+
'foreach ($log in "System","Application","Security","Setup") {',
|
|
252
|
+
' wevtutil epl $log "$out\\$log.evtx"',
|
|
253
|
+
'}',
|
|
254
|
+
'',
|
|
255
|
+
'Write-Host "Collecting installed software..."',
|
|
256
|
+
'Get-ItemProperty HKLM:\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* |',
|
|
257
|
+
' Select-Object DisplayName, DisplayVersion, Publisher, InstallDate |',
|
|
258
|
+
' Sort-Object DisplayName |',
|
|
259
|
+
' Export-Csv "$out\\software.csv" -NoTypeInformation',
|
|
260
|
+
'',
|
|
261
|
+
'Write-Host "Collecting running services and processes..."',
|
|
262
|
+
'Get-Service | Export-Csv "$out\\services.csv" -NoTypeInformation',
|
|
263
|
+
'Get-Process | Select-Object Name, Id, CPU, WorkingSet | Export-Csv "$out\\processes.csv" -NoTypeInformation',
|
|
264
|
+
'',
|
|
265
|
+
'Write-Host "Collecting network configuration..."',
|
|
266
|
+
'ipconfig /all > "$out\\ipconfig.txt"',
|
|
267
|
+
'Get-NetTCPConnection | Export-Csv "$out\\connections.csv" -NoTypeInformation',
|
|
268
|
+
'',
|
|
269
|
+
'Write-Host "Compressing bundle..."',
|
|
270
|
+
'Compress-Archive -Path "$out\\*" -DestinationPath "$out.zip" -Force',
|
|
271
|
+
'Remove-Item -Path $out -Recurse -Force',
|
|
272
|
+
'Write-Host "Diagnostic bundle ready at $out.zip"',
|
|
273
|
+
].join('\n');
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Renders approval-request notifications with the dedicated
|
|
277
|
+
* `ApprovalRequestNotificationTile` (collapsible command section + Approve /
|
|
278
|
+
* Reject), falling back to the default tile for everything else.
|
|
279
|
+
*/
|
|
280
|
+
const renderApprovalTile: RenderNotificationTile = (n, { onComplete, onSettle, liveDurationMs }) => {
|
|
281
|
+
if (!isApprovalNotification(n)) return undefined;
|
|
282
|
+
return (
|
|
283
|
+
<ApprovalRequestNotificationTile
|
|
284
|
+
notification={n}
|
|
285
|
+
onApprove={(id) => alert(`Approved ${id}`)}
|
|
286
|
+
onReject={(id) => alert(`Rejected ${id}`)}
|
|
287
|
+
onComplete={onComplete}
|
|
288
|
+
onSettle={onSettle}
|
|
289
|
+
liveDurationMs={liveDurationMs}
|
|
290
|
+
/>
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
238
294
|
export const LivePlayground: Story = {
|
|
239
295
|
render: () => (
|
|
240
|
-
<NotificationsProvider
|
|
296
|
+
<NotificationsProvider
|
|
297
|
+
onHistoryClick={() => alert('Navigate to /notifications')}
|
|
298
|
+
renderTile={renderApprovalTile}
|
|
299
|
+
>
|
|
241
300
|
<NotificationDrawer />
|
|
242
301
|
<NotificationPopups />
|
|
243
302
|
<PlaygroundControls />
|
|
@@ -249,6 +308,7 @@ export const LivePlayground: Story = {
|
|
|
249
308
|
function PlaygroundControls() {
|
|
250
309
|
const { addNotification, markAllRead, clear, toggle, notifications, unreadCount, showPopups } =
|
|
251
310
|
useNotifications();
|
|
311
|
+
const approvalSeq = React.useRef(0);
|
|
252
312
|
|
|
253
313
|
const fire = (variant: NotificationVariant, title: string, description: string) => {
|
|
254
314
|
addNotification({ variant, title, description });
|
|
@@ -263,6 +323,84 @@ function PlaygroundControls() {
|
|
|
263
323
|
});
|
|
264
324
|
};
|
|
265
325
|
|
|
326
|
+
const fireApproval = (
|
|
327
|
+
title: string,
|
|
328
|
+
description: string,
|
|
329
|
+
toolCalls: Array<Record<string, unknown>>,
|
|
330
|
+
) => {
|
|
331
|
+
const n = approvalSeq.current++;
|
|
332
|
+
addNotification({
|
|
333
|
+
variant: 'warning',
|
|
334
|
+
title,
|
|
335
|
+
description,
|
|
336
|
+
meta: {
|
|
337
|
+
contextType: ADMIN_APPROVAL_REQUEST_CONTEXT_TYPE,
|
|
338
|
+
approvalRequestId: `req-${n}`,
|
|
339
|
+
approvalType: 'ADMIN',
|
|
340
|
+
toolCalls: toolCalls.map((tc, i) => ({
|
|
341
|
+
toolExecutionRequestId: `ter-${n}-${i}`,
|
|
342
|
+
requiresApproval: true,
|
|
343
|
+
...tc,
|
|
344
|
+
})),
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const fireSingleApproval = () =>
|
|
350
|
+
fireApproval('Tech Required', 'Approval is required to execute the command.', [
|
|
351
|
+
{
|
|
352
|
+
toolName: 'run_command',
|
|
353
|
+
toolTitle: 'Run PowerShell command',
|
|
354
|
+
toolType: 'TACTICAL_RMM',
|
|
355
|
+
toolExplanation:
|
|
356
|
+
'Collects all events from System, Application, and Security logs for today and exports them to a CSV file at C:\\Logs\\today_logs.csv.',
|
|
357
|
+
toolCallArguments: {
|
|
358
|
+
command:
|
|
359
|
+
'$today = (Get-Date).Date\n$logs = Get-WinEvent -FilterHashtable @{ LogName = "System","Application","Security"; StartTime = $today }\n$logs | Export-Csv -Path "C:\\Logs\\today_logs.csv" -NoTypeInformation',
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
]);
|
|
363
|
+
|
|
364
|
+
const fireBatchApproval = () =>
|
|
365
|
+
fireApproval('Multiple actions need approval', 'Mingo wants to run 3 commands on SRV-DB01.', [
|
|
366
|
+
{
|
|
367
|
+
toolName: 'run_command',
|
|
368
|
+
toolTitle: 'Restart print spooler',
|
|
369
|
+
toolType: 'TACTICAL_RMM',
|
|
370
|
+
toolExplanation: 'Restarts the Spooler service to clear a stuck print queue.',
|
|
371
|
+
toolCallArguments: { command: 'Restart-Service -Name Spooler -Force' },
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
toolName: 'run_query',
|
|
375
|
+
toolTitle: 'Query disk usage',
|
|
376
|
+
toolType: 'OPENFRAME',
|
|
377
|
+
toolExplanation: 'Reports free space per logical volume.',
|
|
378
|
+
toolCallArguments: { query: 'SELECT device_id, free_space, size FROM logical_drives;' },
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
toolName: 'run_command',
|
|
382
|
+
toolTitle: 'Purge stale temp files',
|
|
383
|
+
toolType: 'TACTICAL_RMM',
|
|
384
|
+
toolExplanation: 'Deletes %TEMP% contents older than 7 days to reclaim space.',
|
|
385
|
+
toolCallArguments: {
|
|
386
|
+
command:
|
|
387
|
+
'Get-ChildItem $env:TEMP -Recurse | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue',
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
]);
|
|
391
|
+
|
|
392
|
+
const fireLongApproval = () =>
|
|
393
|
+
fireApproval('Tech Required', 'Approval is required to run a diagnostic script.', [
|
|
394
|
+
{
|
|
395
|
+
toolName: 'run_script',
|
|
396
|
+
toolTitle: 'Run full diagnostic bundle',
|
|
397
|
+
toolType: 'TACTICAL_RMM',
|
|
398
|
+
toolExplanation:
|
|
399
|
+
'Collects event logs, installed software, services, processes and network configuration, then compresses everything into a single uploadable archive.',
|
|
400
|
+
toolCallArguments: { script: LONG_POWERSHELL },
|
|
401
|
+
},
|
|
402
|
+
]);
|
|
403
|
+
|
|
266
404
|
return (
|
|
267
405
|
<div className="flex max-w-2xl flex-col gap-4">
|
|
268
406
|
<div className="rounded-md border border-ods-border bg-ods-card p-3">
|
|
@@ -311,6 +449,15 @@ function PlaygroundControls() {
|
|
|
311
449
|
<Button variant="outline" onClick={fireWithDeepLink}>
|
|
312
450
|
Fire with deep-link
|
|
313
451
|
</Button>
|
|
452
|
+
<Button variant="warning" onClick={fireSingleApproval}>
|
|
453
|
+
Fire approval
|
|
454
|
+
</Button>
|
|
455
|
+
<Button variant="warning" onClick={fireBatchApproval}>
|
|
456
|
+
Fire batch approval
|
|
457
|
+
</Button>
|
|
458
|
+
<Button variant="warning" onClick={fireLongApproval}>
|
|
459
|
+
Fire long-command approval
|
|
460
|
+
</Button>
|
|
314
461
|
</div>
|
|
315
462
|
|
|
316
463
|
<div className="flex flex-wrap gap-2">
|