@anchrd/intel-ui 0.8.8 → 0.9.1
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 +2 -2
- package/package.json +5 -2
- package/src/agent/agent-avatar/agent-avatar.tsx +34 -0
- package/src/agent/agent-calendar/agent-calendar.tsx +79 -0
- package/src/agent/agent-chat/agent-chat.tsx +116 -0
- package/src/agent/agent-cron/agent-cron.ts +132 -0
- package/src/agent/agent-definition/agent-definition.ts +64 -0
- package/src/agent/agent-entry-title/agent-entry-title.ts +29 -0
- package/src/agent/agent-log/agent-log.tsx +159 -0
- package/src/agent/agent-models/agent-models.ts +63 -0
- package/src/agent/agent-profile/agent-profile.tsx +547 -0
- package/src/agent/agent-state/agent-state.ts +48 -0
- package/src/agent/agent.tsx +361 -0
- package/src/app/app-sidebar/app-sidebar.tsx +2 -2
- package/src/app/app-tree/app-tree.tsx +151 -23
- package/src/app/app.tsx +2 -2
- package/src/app/header-search/header-search.tsx +16 -16
- package/src/app/tree-move/tree-move.tsx +10 -10
- package/src/archive/archive.tsx +8 -8
- package/src/components/ui/avatar.tsx +39 -0
- package/src/components/ui/select.tsx +163 -0
- package/src/components/ui/tabs.tsx +52 -0
- package/src/data/agent-runtime/agent-runtime.ts +93 -0
- package/src/data/intel-data-provider/intel-data-provider.ts +201 -120
- package/src/data/intel-data-provider/intel-data-provider.types.ts +112 -54
- package/src/entry-picker/entry-picker.tsx +53 -17
- package/src/flow-runs/flow-runs.tsx +1 -1
- package/src/flows/flows.tsx +20 -20
- package/src/folder-contents/folder-contents.tsx +7 -7
- package/src/graph-pane/graph-pane.tsx +1 -1
- package/src/hooks/use-capabilities.ts +22 -0
- package/src/i18n/en.json +147 -64
- package/src/kind-icon.ts +5 -2
- package/src/{knowledge-editor/knowledge-editor.tsx → node-editor/node-editor.tsx} +20 -20
- package/src/{knowledge-graph → node-graph}/graph-notice.tsx +1 -1
- package/src/{knowledge-graph/knowledge-graph.tsx → node-graph/node-graph.tsx} +4 -4
- package/src/{knowledge-table/knowledge-table.tsx → node-table/node-table.tsx} +14 -14
- package/src/{knowledge/knowledge.tsx → nodes/nodes.tsx} +47 -29
- package/src/resource-menu/resource-menu.tsx +105 -62
- package/src/router/router.tsx +5 -5
- package/src/title-row/title-row.tsx +20 -6
- package/vite.config.ts +4 -0
- /package/src/{knowledge-graph/knowledge-graph.ts → node-graph/node-graph.ts} +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
2
|
+
import { Select as SelectPrimitive } from "radix-ui";
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
8
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
|
12
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SelectTrigger({
|
|
16
|
+
className,
|
|
17
|
+
size = "default",
|
|
18
|
+
children,
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & { size?: "sm" | "default" }) {
|
|
21
|
+
return (
|
|
22
|
+
<SelectPrimitive.Trigger
|
|
23
|
+
data-slot="select-trigger"
|
|
24
|
+
data-size={size}
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 dark:bg-input/30 dark:hover:bg-input/50 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
<SelectPrimitive.Icon asChild>
|
|
33
|
+
{/* ⚠️ The chevron is not decoration: it is what tells a reader this is something to open
|
|
34
|
+
rather than a word beside a label. #143 asks for it explicitly on the role tags. */}
|
|
35
|
+
<ChevronDownIcon className="size-4 opacity-50" />
|
|
36
|
+
</SelectPrimitive.Icon>
|
|
37
|
+
</SelectPrimitive.Trigger>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function SelectContent({
|
|
42
|
+
className,
|
|
43
|
+
children,
|
|
44
|
+
position = "popper",
|
|
45
|
+
...props
|
|
46
|
+
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
47
|
+
return (
|
|
48
|
+
<SelectPrimitive.Portal>
|
|
49
|
+
<SelectPrimitive.Content
|
|
50
|
+
data-slot="select-content"
|
|
51
|
+
className={cn(
|
|
52
|
+
"relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
|
|
53
|
+
position === "popper" &&
|
|
54
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
55
|
+
className,
|
|
56
|
+
)}
|
|
57
|
+
position={position}
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
<SelectScrollUpButton />
|
|
61
|
+
<SelectPrimitive.Viewport
|
|
62
|
+
className={cn(
|
|
63
|
+
"p-1",
|
|
64
|
+
position === "popper" &&
|
|
65
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1",
|
|
66
|
+
)}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</SelectPrimitive.Viewport>
|
|
70
|
+
<SelectScrollDownButton />
|
|
71
|
+
</SelectPrimitive.Content>
|
|
72
|
+
</SelectPrimitive.Portal>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
|
77
|
+
return (
|
|
78
|
+
<SelectPrimitive.Label
|
|
79
|
+
data-slot="select-label"
|
|
80
|
+
className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function SelectItem({
|
|
87
|
+
className,
|
|
88
|
+
children,
|
|
89
|
+
...props
|
|
90
|
+
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
|
91
|
+
return (
|
|
92
|
+
<SelectPrimitive.Item
|
|
93
|
+
data-slot="select-item"
|
|
94
|
+
className={cn(
|
|
95
|
+
"relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
96
|
+
className,
|
|
97
|
+
)}
|
|
98
|
+
{...props}
|
|
99
|
+
>
|
|
100
|
+
<span className="absolute right-2 flex size-3.5 items-center justify-center">
|
|
101
|
+
<SelectPrimitive.ItemIndicator>
|
|
102
|
+
<CheckIcon className="size-4" />
|
|
103
|
+
</SelectPrimitive.ItemIndicator>
|
|
104
|
+
</span>
|
|
105
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
106
|
+
</SelectPrimitive.Item>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function SelectSeparator({
|
|
111
|
+
className,
|
|
112
|
+
...props
|
|
113
|
+
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
114
|
+
return (
|
|
115
|
+
<SelectPrimitive.Separator
|
|
116
|
+
data-slot="select-separator"
|
|
117
|
+
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function SelectScrollUpButton({
|
|
124
|
+
className,
|
|
125
|
+
...props
|
|
126
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
127
|
+
return (
|
|
128
|
+
<SelectPrimitive.ScrollUpButton
|
|
129
|
+
data-slot="select-scroll-up-button"
|
|
130
|
+
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
|
131
|
+
{...props}
|
|
132
|
+
>
|
|
133
|
+
<ChevronUpIcon className="size-4" />
|
|
134
|
+
</SelectPrimitive.ScrollUpButton>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function SelectScrollDownButton({
|
|
139
|
+
className,
|
|
140
|
+
...props
|
|
141
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
142
|
+
return (
|
|
143
|
+
<SelectPrimitive.ScrollDownButton
|
|
144
|
+
data-slot="select-scroll-down-button"
|
|
145
|
+
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
|
146
|
+
{...props}
|
|
147
|
+
>
|
|
148
|
+
<ChevronDownIcon className="size-4" />
|
|
149
|
+
</SelectPrimitive.ScrollDownButton>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export {
|
|
154
|
+
Select,
|
|
155
|
+
SelectContent,
|
|
156
|
+
SelectItem,
|
|
157
|
+
SelectLabel,
|
|
158
|
+
SelectScrollDownButton,
|
|
159
|
+
SelectScrollUpButton,
|
|
160
|
+
SelectSeparator,
|
|
161
|
+
SelectTrigger,
|
|
162
|
+
SelectValue,
|
|
163
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Tabs as TabsPrimitive } from "radix-ui";
|
|
2
|
+
import type * as React from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
function Tabs({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
7
|
+
return (
|
|
8
|
+
<TabsPrimitive.Root
|
|
9
|
+
data-slot="tabs"
|
|
10
|
+
className={cn("flex flex-col gap-2", className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function TabsList({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.List>) {
|
|
17
|
+
return (
|
|
18
|
+
<TabsPrimitive.List
|
|
19
|
+
data-slot="tabs-list"
|
|
20
|
+
className={cn(
|
|
21
|
+
"inline-flex w-fit items-center justify-center rounded-lg bg-muted p-[3px] text-muted-foreground",
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
|
30
|
+
return (
|
|
31
|
+
<TabsPrimitive.Trigger
|
|
32
|
+
data-slot="tabs-trigger"
|
|
33
|
+
className={cn(
|
|
34
|
+
"inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground transition-[color,box-shadow] focus-visible:border-ring focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:shadow-sm dark:text-muted-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
35
|
+
className,
|
|
36
|
+
)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
43
|
+
return (
|
|
44
|
+
<TabsPrimitive.Content
|
|
45
|
+
data-slot="tabs-content"
|
|
46
|
+
className={cn("flex-1 outline-none", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What the agent runtime answers, read back defensively.
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ These shapes are NOT in `@anchrd/intel-contract`, and that is deliberate rather than an
|
|
7
|
+
* oversight: the runtime (`packages/agent`) imports nothing from the contract either, so a run
|
|
8
|
+
* record has no shared declaration anywhere. It crosses a network boundary into this package, so it
|
|
9
|
+
* is parsed here — tolerantly, in the same spirit the runtime reads a definition, because a field
|
|
10
|
+
* the runtime adds must not blank the log screen.
|
|
11
|
+
*/
|
|
12
|
+
export const AgentRunTarget = z.object({
|
|
13
|
+
kind: z.enum(["chat", "document", "flow", "mail", "task"]),
|
|
14
|
+
id: z.string().nullable(),
|
|
15
|
+
});
|
|
16
|
+
export type AgentRunTarget = z.infer<typeof AgentRunTarget>;
|
|
17
|
+
|
|
18
|
+
export const AgentRun = z.object({
|
|
19
|
+
id: z.string(),
|
|
20
|
+
trigger: z.enum(["chat", "schedule", "mail", "task", "manual"]),
|
|
21
|
+
target: AgentRunTarget,
|
|
22
|
+
status: z.enum(["running", "completed", "failed"]),
|
|
23
|
+
startedAt: z.string(),
|
|
24
|
+
finishedAt: z.string().nullable(),
|
|
25
|
+
steps: z.number(),
|
|
26
|
+
error: z.string().nullable(),
|
|
27
|
+
});
|
|
28
|
+
export type AgentRun = z.infer<typeof AgentRun>;
|
|
29
|
+
|
|
30
|
+
/** Whether the agent is switched off. Runtime state, never part of the definition (#179). */
|
|
31
|
+
export const AgentState = z.object({
|
|
32
|
+
paused: z.boolean(),
|
|
33
|
+
pausedAt: z.string().nullable(),
|
|
34
|
+
alarmAt: z.number().nullable(),
|
|
35
|
+
});
|
|
36
|
+
export type AgentState = z.infer<typeof AgentState>;
|
|
37
|
+
|
|
38
|
+
/** What "run now" answers: the run exists, and it is on its way. */
|
|
39
|
+
export const AgentManualRun = z.object({
|
|
40
|
+
runId: z.string(),
|
|
41
|
+
status: z.string(),
|
|
42
|
+
});
|
|
43
|
+
export type AgentManualRun = z.infer<typeof AgentManualRun>;
|
|
44
|
+
|
|
45
|
+
export const AgentLogEntry = z.object({
|
|
46
|
+
id: z.string(),
|
|
47
|
+
runId: z.string(),
|
|
48
|
+
at: z.string(),
|
|
49
|
+
level: z.enum(["info", "warn", "error"]),
|
|
50
|
+
event: z.string(),
|
|
51
|
+
detail: z.string(),
|
|
52
|
+
});
|
|
53
|
+
export type AgentLogEntry = z.infer<typeof AgentLogEntry>;
|
|
54
|
+
|
|
55
|
+
export const AgentRunList = z.object({ items: z.array(AgentRun) });
|
|
56
|
+
export type AgentRunList = z.infer<typeof AgentRunList>;
|
|
57
|
+
|
|
58
|
+
export const AgentRunDetail = z.object({ run: AgentRun, log: z.array(AgentLogEntry) });
|
|
59
|
+
export type AgentRunDetail = z.infer<typeof AgentRunDetail>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The runtime's own address, for the one thing that is dialled from outside this page.
|
|
63
|
+
*
|
|
64
|
+
* ⚠️ Only the agent's MCP endpoint is reached here, and only as a string somebody copies. A portal
|
|
65
|
+
* or another agent dials it directly with its own credential (ADR-0005 §7), so it has to be the
|
|
66
|
+
* runtime's real hostname — a deployment that puts the runtime somewhere else sets
|
|
67
|
+
* `VITE_AGENT_RUNTIME_URL` at build time. Empty means "the origin this page came from".
|
|
68
|
+
*
|
|
69
|
+
* ⚠️ NOT the browser's path any more (#178). Everything this page fetches goes through intel, which
|
|
70
|
+
* proxies it to the runtime over a service binding; see `agentRuntimePath` below.
|
|
71
|
+
*/
|
|
72
|
+
export function agentRuntimeBaseUrl(): string {
|
|
73
|
+
return (import.meta.env.VITE_AGENT_RUNTIME_URL ?? "").replace(/\/$/, "");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function agentMcpAddress(agentId: string): string {
|
|
77
|
+
return `${agentRuntimeBaseUrl()}/agents/${encodeURIComponent(agentId)}/mcp`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Where the browser asks, which is intel and nothing else.
|
|
82
|
+
*
|
|
83
|
+
* ⚠️ One door, one origin, one credential: the page carries its intel session cookie, intel opens
|
|
84
|
+
* it, and intel forwards the call to the runtime with the Gate token of the person who asked. That
|
|
85
|
+
* is why there is no CORS here, no second hostname to configure, and above all no Gate token in
|
|
86
|
+
* browser JavaScript — the runtime still demands `agents/run`, it just hears it from intel.
|
|
87
|
+
*
|
|
88
|
+
* The path is relative on purpose. It is joined to intel's `/api/v1` by the data provider, which is
|
|
89
|
+
* the only module that knows where intel is.
|
|
90
|
+
*/
|
|
91
|
+
export function agentRuntimePath(agentId: string, route: string): string {
|
|
92
|
+
return `/agents/${encodeURIComponent(agentId)}${route}`;
|
|
93
|
+
}
|