@anchrd/intel-ui 0.8.8 → 0.9.0

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.
Files changed (43) hide show
  1. package/README.md +2 -2
  2. package/package.json +5 -2
  3. package/src/agent/agent-avatar/agent-avatar.tsx +34 -0
  4. package/src/agent/agent-calendar/agent-calendar.tsx +79 -0
  5. package/src/agent/agent-chat/agent-chat.tsx +116 -0
  6. package/src/agent/agent-cron/agent-cron.ts +132 -0
  7. package/src/agent/agent-definition/agent-definition.ts +64 -0
  8. package/src/agent/agent-entry-title/agent-entry-title.ts +29 -0
  9. package/src/agent/agent-log/agent-log.tsx +159 -0
  10. package/src/agent/agent-models/agent-models.ts +63 -0
  11. package/src/agent/agent-profile/agent-profile.tsx +512 -0
  12. package/src/agent/agent-state/agent-state.ts +48 -0
  13. package/src/agent/agent.tsx +361 -0
  14. package/src/app/app-sidebar/app-sidebar.tsx +2 -2
  15. package/src/app/app-tree/app-tree.tsx +151 -23
  16. package/src/app/app.tsx +2 -2
  17. package/src/app/header-search/header-search.tsx +16 -16
  18. package/src/app/tree-move/tree-move.tsx +10 -10
  19. package/src/archive/archive.tsx +8 -8
  20. package/src/components/ui/avatar.tsx +39 -0
  21. package/src/components/ui/select.tsx +163 -0
  22. package/src/components/ui/tabs.tsx +52 -0
  23. package/src/data/agent-runtime/agent-runtime.ts +93 -0
  24. package/src/data/intel-data-provider/intel-data-provider.ts +201 -120
  25. package/src/data/intel-data-provider/intel-data-provider.types.ts +112 -54
  26. package/src/entry-picker/entry-picker.tsx +53 -17
  27. package/src/flow-runs/flow-runs.tsx +1 -1
  28. package/src/flows/flows.tsx +20 -20
  29. package/src/folder-contents/folder-contents.tsx +7 -7
  30. package/src/graph-pane/graph-pane.tsx +1 -1
  31. package/src/hooks/use-capabilities.ts +22 -0
  32. package/src/i18n/en.json +148 -64
  33. package/src/kind-icon.ts +5 -2
  34. package/src/{knowledge-editor/knowledge-editor.tsx → node-editor/node-editor.tsx} +20 -20
  35. package/src/{knowledge-graph → node-graph}/graph-notice.tsx +1 -1
  36. package/src/{knowledge-graph/knowledge-graph.tsx → node-graph/node-graph.tsx} +4 -4
  37. package/src/{knowledge-table/knowledge-table.tsx → node-table/node-table.tsx} +14 -14
  38. package/src/{knowledge/knowledge.tsx → nodes/nodes.tsx} +46 -29
  39. package/src/resource-menu/resource-menu.tsx +105 -62
  40. package/src/router/router.tsx +5 -5
  41. package/src/title-row/title-row.tsx +13 -5
  42. package/vite.config.ts +4 -0
  43. /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
+ }