@polpo-ai/dashboard 0.1.4 → 0.15.8

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 (184) hide show
  1. package/LICENSE +3 -1
  2. package/README.md +13 -40
  3. package/dist/components.d.ts +53 -0
  4. package/dist/components.d.ts.map +1 -0
  5. package/dist/components.js +81 -0
  6. package/dist/components.js.map +1 -0
  7. package/dist/host.d.ts +24 -0
  8. package/dist/host.d.ts.map +1 -0
  9. package/dist/host.js +18 -0
  10. package/dist/host.js.map +1 -0
  11. package/dist/index.d.ts +13 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +11 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/test/setup.d.ts +2 -0
  16. package/dist/test/setup.d.ts.map +1 -0
  17. package/dist/test/setup.js +2 -0
  18. package/dist/test/setup.js.map +1 -0
  19. package/dist/views/agent-detail.d.ts +4 -0
  20. package/dist/views/agent-detail.d.ts.map +1 -0
  21. package/dist/views/agent-detail.js +31 -0
  22. package/dist/views/agent-detail.js.map +1 -0
  23. package/dist/views/agents.d.ts +2 -0
  24. package/dist/views/agents.d.ts.map +1 -0
  25. package/dist/views/agents.js +81 -0
  26. package/dist/views/agents.js.map +1 -0
  27. package/dist/views/files.d.ts +2 -0
  28. package/dist/views/files.d.ts.map +1 -0
  29. package/dist/views/files.js +30 -0
  30. package/dist/views/files.js.map +1 -0
  31. package/dist/views/memory.d.ts +2 -0
  32. package/dist/views/memory.d.ts.map +1 -0
  33. package/dist/views/memory.js +19 -0
  34. package/dist/views/memory.js.map +1 -0
  35. package/dist/views/playground.d.ts +4 -0
  36. package/dist/views/playground.d.ts.map +1 -0
  37. package/dist/views/playground.js +43 -0
  38. package/dist/views/playground.js.map +1 -0
  39. package/dist/views/session-detail.d.ts +4 -0
  40. package/dist/views/session-detail.d.ts.map +1 -0
  41. package/dist/views/session-detail.js +23 -0
  42. package/dist/views/session-detail.js.map +1 -0
  43. package/dist/views/sessions.d.ts +2 -0
  44. package/dist/views/sessions.d.ts.map +1 -0
  45. package/dist/views/sessions.js +17 -0
  46. package/dist/views/sessions.js.map +1 -0
  47. package/dist/views/skills.d.ts +2 -0
  48. package/dist/views/skills.d.ts.map +1 -0
  49. package/dist/views/skills.js +16 -0
  50. package/dist/views/skills.js.map +1 -0
  51. package/package.json +47 -83
  52. package/src/styles.css +169 -0
  53. package/app/(dashboard)/error.tsx +0 -47
  54. package/app/(dashboard)/layout.tsx +0 -41
  55. package/app/(dashboard)/loading.tsx +0 -30
  56. package/app/(dashboard)/projects/[id]/agents/[name]/memory/view.tsx +0 -36
  57. package/app/(dashboard)/projects/[id]/agents/[name]/models-view.tsx +0 -30
  58. package/app/(dashboard)/projects/[id]/agents/[name]/page.tsx +0 -51
  59. package/app/(dashboard)/projects/[id]/agents/[name]/prompt/view.tsx +0 -211
  60. package/app/(dashboard)/projects/[id]/agents/[name]/skills/view.tsx +0 -84
  61. package/app/(dashboard)/projects/[id]/agents/[name]/tools/view.tsx +0 -525
  62. package/app/(dashboard)/projects/[id]/agents/[name]/vault/view.tsx +0 -61
  63. package/app/(dashboard)/projects/[id]/agents/page.tsx +0 -39
  64. package/app/(dashboard)/projects/[id]/agents/view.tsx +0 -283
  65. package/app/(dashboard)/projects/[id]/layout.tsx +0 -11
  66. package/app/(dashboard)/projects/[id]/logs/page.tsx +0 -27
  67. package/app/(dashboard)/projects/[id]/logs/view.tsx +0 -184
  68. package/app/(dashboard)/projects/[id]/memory/page.tsx +0 -40
  69. package/app/(dashboard)/projects/[id]/memory/view.tsx +0 -17
  70. package/app/(dashboard)/projects/[id]/missions/[missionId]/page.tsx +0 -88
  71. package/app/(dashboard)/projects/[id]/missions/[missionId]/view.tsx +0 -569
  72. package/app/(dashboard)/projects/[id]/missions/page.tsx +0 -32
  73. package/app/(dashboard)/projects/[id]/missions/view.tsx +0 -282
  74. package/app/(dashboard)/projects/[id]/onboarding-checklist.tsx +0 -359
  75. package/app/(dashboard)/projects/[id]/page.tsx +0 -68
  76. package/app/(dashboard)/projects/[id]/playbooks/[name]/page.tsx +0 -5
  77. package/app/(dashboard)/projects/[id]/playbooks/[name]/view.tsx +0 -433
  78. package/app/(dashboard)/projects/[id]/playbooks/page.tsx +0 -5
  79. package/app/(dashboard)/projects/[id]/playbooks/view.tsx +0 -222
  80. package/app/(dashboard)/projects/[id]/schedules/page.tsx +0 -44
  81. package/app/(dashboard)/projects/[id]/schedules/view.tsx +0 -385
  82. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/page.tsx +0 -55
  83. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/raw-view.tsx +0 -373
  84. package/app/(dashboard)/projects/[id]/sessions/[sessionId]/view.tsx +0 -124
  85. package/app/(dashboard)/projects/[id]/sessions/page.tsx +0 -31
  86. package/app/(dashboard)/projects/[id]/sessions/view.tsx +0 -242
  87. package/app/(dashboard)/projects/[id]/settings/page.tsx +0 -52
  88. package/app/(dashboard)/projects/[id]/skills/[name]/page.tsx +0 -65
  89. package/app/(dashboard)/projects/[id]/skills/[name]/view.tsx +0 -227
  90. package/app/(dashboard)/projects/[id]/skills/page.tsx +0 -31
  91. package/app/(dashboard)/projects/[id]/skills/view.tsx +0 -243
  92. package/app/(dashboard)/projects/[id]/storage/page.tsx +0 -5
  93. package/app/(dashboard)/projects/[id]/storage/view.tsx +0 -385
  94. package/app/(dashboard)/projects/[id]/tasks/[taskId]/activity/view.tsx +0 -336
  95. package/app/(dashboard)/projects/[id]/tasks/[taskId]/assessment/view.tsx +0 -113
  96. package/app/(dashboard)/projects/[id]/tasks/[taskId]/blueprint.ts +0 -72
  97. package/app/(dashboard)/projects/[id]/tasks/[taskId]/output/view.tsx +0 -90
  98. package/app/(dashboard)/projects/[id]/tasks/[taskId]/page.tsx +0 -63
  99. package/app/(dashboard)/projects/[id]/tasks/[taskId]/view.tsx +0 -137
  100. package/app/(dashboard)/projects/[id]/tasks/page.tsx +0 -40
  101. package/app/(dashboard)/projects/[id]/tasks/view.tsx +0 -421
  102. package/app/(dashboard)/projects/[id]/view.tsx +0 -421
  103. package/app/(dashboard)/projects/[id]/welcome-banner.tsx +0 -156
  104. package/app/(dashboard)/projects/projects-list.tsx +0 -126
  105. package/app/(playground)/error.tsx +0 -42
  106. package/app/(playground)/layout.tsx +0 -27
  107. package/app/(playground)/projects/[id]/playground/page.tsx +0 -57
  108. package/app/(playground)/projects/[id]/playground/view.tsx +0 -167
  109. package/app/(playground)/projects/[id]/playground-legacy/page.tsx +0 -47
  110. package/app/(playground)/projects/[id]/playground-legacy/skeleton.tsx +0 -63
  111. package/app/(playground)/projects/[id]/playground-legacy/view.tsx +0 -237
  112. package/app/favicon.ico +0 -0
  113. package/app/globals.css +0 -385
  114. package/app/icon.svg +0 -6
  115. package/app/layout.tsx +0 -39
  116. package/app/page.tsx +0 -11
  117. package/components/ai-elements/code-block.tsx +0 -562
  118. package/components/dashboard/agent-capabilities.tsx +0 -326
  119. package/components/dashboard/agent-identity-header.tsx +0 -50
  120. package/components/dashboard/agent-model-picker.tsx +0 -195
  121. package/components/dashboard/agent-model-selector.tsx +0 -121
  122. package/components/dashboard/agent-picker-card.tsx +0 -46
  123. package/components/dashboard/agent-studio.tsx +0 -242
  124. package/components/dashboard/agents-table.tsx +0 -48
  125. package/components/dashboard/breadcrumb.tsx +0 -70
  126. package/components/dashboard/builder-chat.tsx +0 -418
  127. package/components/dashboard/chat-shell.tsx +0 -40
  128. package/components/dashboard/client-picker.tsx +0 -63
  129. package/components/dashboard/command-snippet.tsx +0 -77
  130. package/components/dashboard/connect-dialog.tsx +0 -680
  131. package/components/dashboard/copy-button.tsx +0 -45
  132. package/components/dashboard/copy-card.tsx +0 -48
  133. package/components/dashboard/file-browser.tsx +0 -161
  134. package/components/dashboard/hint.tsx +0 -22
  135. package/components/dashboard/inference-mode.tsx +0 -15
  136. package/components/dashboard/manual-refresh-button.tsx +0 -52
  137. package/components/dashboard/markdown.tsx +0 -31
  138. package/components/dashboard/mcp-install-panel.tsx +0 -196
  139. package/components/dashboard/mission-graph.tsx +0 -262
  140. package/components/dashboard/nav-tabs.tsx +0 -86
  141. package/components/dashboard/polpo-chat.tsx +0 -468
  142. package/components/dashboard/project-copilot.tsx +0 -253
  143. package/components/dashboard/sdk-snippet-panel.tsx +0 -194
  144. package/components/dashboard/section-header.tsx +0 -37
  145. package/components/dashboard/settings-form.tsx +0 -2477
  146. package/components/dashboard/sidebar.tsx +0 -385
  147. package/components/dashboard/skeletons.tsx +0 -1054
  148. package/components/dashboard/skills-install-wizard.tsx +0 -192
  149. package/components/dashboard/swarm-runs.tsx +0 -316
  150. package/components/dashboard/tab-toggle.tsx +0 -35
  151. package/components/dashboard/task-studio.tsx +0 -224
  152. package/components/dashboard/top-header.tsx +0 -203
  153. package/components/dashboard/webhook-deliveries.tsx +0 -234
  154. package/components/icons/coding-agents.tsx +0 -151
  155. package/components/json-ld.tsx +0 -8
  156. package/components/providers.tsx +0 -25
  157. package/components/ui/badge.tsx +0 -52
  158. package/components/ui/button.tsx +0 -60
  159. package/components/ui/card.tsx +0 -103
  160. package/components/ui/chart.tsx +0 -356
  161. package/components/ui/command.tsx +0 -196
  162. package/components/ui/dialog.tsx +0 -157
  163. package/components/ui/input-group.tsx +0 -158
  164. package/components/ui/input.tsx +0 -20
  165. package/components/ui/multi-select.tsx +0 -161
  166. package/components/ui/popover.tsx +0 -90
  167. package/components/ui/select.tsx +0 -201
  168. package/components/ui/separator.tsx +0 -25
  169. package/components/ui/sheet.tsx +0 -135
  170. package/components/ui/skeleton.tsx +0 -13
  171. package/components/ui/tabs.tsx +0 -56
  172. package/components/ui/textarea.tsx +0 -18
  173. package/components/ui/tooltip.tsx +0 -66
  174. package/hooks/use-desktop-sidebar.tsx +0 -50
  175. package/hooks/use-mobile-sidebar.tsx +0 -37
  176. package/index.ts +0 -17
  177. package/lib/api.ts +0 -194
  178. package/lib/builder-context.ts +0 -60
  179. package/lib/data-client.ts +0 -68
  180. package/lib/get-query-client.ts +0 -25
  181. package/lib/polpo-client.tsx +0 -49
  182. package/lib/tool-catalog.ts +0 -234
  183. package/lib/use-event-catalog.ts +0 -28
  184. package/lib/utils.ts +0 -6
@@ -1,36 +0,0 @@
1
- import Link from "next/link";
2
- import { Markdown } from "../../../../../../../components/dashboard/markdown";
3
- import { CopyButton } from "../../../../../../../components/dashboard/copy-button";
4
- import { Hint } from "../../../../../../../components/dashboard/hint";
5
-
6
- export default function AgentMemoryView({ id, content }: { id: string; content: string }) {
7
- return (
8
- <div>
9
- <div className="mb-4">
10
- <Hint action={content ? <CopyButton value={content} label="Copy" className="shrink-0" /> : undefined}>
11
- Private memory this agent accumulates across sessions. It also inherits the
12
- shared project memory.
13
- </Hint>
14
- </div>
15
-
16
- {content ? (
17
- <div data-testid="agent-memory-content" className="border border-border bg-card p-6">
18
- <Markdown content={content} />
19
- </div>
20
- ) : (
21
- <div className="border border-border p-8 text-center text-sm text-muted-foreground">
22
- No memory yet. Memory is created automatically when the agent works.
23
- </div>
24
- )}
25
-
26
- <div className="mt-4">
27
- <Link
28
- href={`/projects/${id}/memory`}
29
- className="text-xs text-muted-foreground hover:text-foreground transition-colors"
30
- >
31
- View shared project memory &rarr;
32
- </Link>
33
- </div>
34
- </div>
35
- );
36
- }
@@ -1,30 +0,0 @@
1
- import type { AgentConfig } from "@polpo-ai/core";
2
- import { AgentCapabilities } from "../../../../../../components/dashboard/agent-capabilities";
3
-
4
- /** Models tab — the per-capability model grid (one row per modality). */
5
- export default function AgentModelsView({
6
- agent,
7
- projectId,
8
- agentName,
9
- }: {
10
- agent: AgentConfig | null;
11
- projectId: string;
12
- agentName: string;
13
- }) {
14
- if (!agent) {
15
- return (
16
- <div
17
- data-testid="agent-not-found"
18
- className="mt-4 border border-border p-8 text-center text-sm text-muted-foreground"
19
- >
20
- Agent not found.
21
- </div>
22
- );
23
- }
24
-
25
- return (
26
- <section className="pt-2">
27
- <AgentCapabilities agent={agent} projectId={projectId} agentName={agentName} />
28
- </section>
29
- );
30
- }
@@ -1,51 +0,0 @@
1
- import { Suspense } from "react";
2
- import { dataApi, getAgent } from "../../../../../../lib/api";
3
- import { AgentProfileSkeleton } from "../../../../../../components/dashboard/skeletons";
4
- import { AgentStudio, type VaultEntry } from "../../../../../../components/dashboard/agent-studio";
5
-
6
- const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:4000";
7
-
8
- async function AgentData({ id, name }: { id: string; name: string }) {
9
- // The agent detail IS the Studio (chat canvas). Fetch everything its
10
- // tabs need (agent + memory + vault) up front, server-side.
11
- const [agent, memoryContent, vaultEntries] = await Promise.all([
12
- getAgent(id, name),
13
- dataApi<{ ok: boolean; data: { content: string } }>(
14
- id,
15
- `/v1/memory/agent/${encodeURIComponent(name)}`,
16
- )
17
- .then((r) => r.data?.content ?? "")
18
- .catch(() => ""),
19
- dataApi<{ ok: boolean; data: VaultEntry[] }>(
20
- id,
21
- `/v1/vault/entries/${encodeURIComponent(name)}`,
22
- )
23
- .then((r) => r.data ?? [])
24
- .catch(() => [] as VaultEntry[]),
25
- ]);
26
-
27
- return (
28
- <AgentStudio
29
- projectId={id}
30
- apiUrl={API_URL}
31
- agent={agent}
32
- memoryContent={memoryContent}
33
- vaultEntries={vaultEntries}
34
- />
35
- );
36
- }
37
-
38
- export default async function AgentDetailPage({
39
- params,
40
- }: {
41
- params: Promise<{ id: string; name: string }>;
42
- }) {
43
- const { id, name } = await params;
44
- const decodedName = decodeURIComponent(name);
45
-
46
- return (
47
- <Suspense fallback={<AgentProfileSkeleton />}>
48
- <AgentData id={id} name={decodedName} />
49
- </Suspense>
50
- );
51
- }
@@ -1,211 +0,0 @@
1
- "use client";
2
-
3
- import { useState } from "react";
4
- import { Eye } from "lucide-react";
5
- import type { AgentConfig } from "@polpo-ai/core";
6
- import { Markdown } from "../../../../../../../components/dashboard/markdown";
7
- import { CopyButton } from "../../../../../../../components/dashboard/copy-button";
8
- import { Hint } from "../../../../../../../components/dashboard/hint";
9
- import {
10
- Dialog,
11
- DialogContent,
12
- DialogDescription,
13
- DialogHeader,
14
- DialogTitle,
15
- } from "../../../../../../../components/ui/dialog";
16
-
17
- const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:4000";
18
-
19
- /** Rough token estimate — ~4 chars/token, good enough for a budget hint. */
20
- const approxTokens = (s: string) => Math.round(s.length / 4);
21
-
22
- export default function AgentPromptView({
23
- agent,
24
- projectId,
25
- agentName,
26
- }: {
27
- agent: AgentConfig | null;
28
- projectId: string;
29
- agentName: string;
30
- }) {
31
- if (!agent) {
32
- return (
33
- <div className="mt-4 border border-border p-8 text-center text-sm text-muted-foreground">
34
- Agent not found.
35
- </div>
36
- );
37
- }
38
-
39
- const instructions = agent.systemPrompt ?? "";
40
- const chars = instructions.length;
41
-
42
- return (
43
- <div>
44
- <Hint action={<PreviewButton projectId={projectId} agentName={agentName} />}>
45
- Extra instructions added on top of the agent&apos;s base prompt — they shape
46
- tone and rules without replacing Polpo&apos;s defaults. Hit Preview for the
47
- full composed prompt.
48
- </Hint>
49
-
50
- {instructions ? (
51
- <>
52
- <div className="mt-2 flex items-center gap-2">
53
- <span className="inline-flex items-center gap-1 border border-border bg-secondary/40 px-2 py-0.5 font-mono text-[11px] font-medium text-foreground">
54
- {chars.toLocaleString()}
55
- <span className="text-muted-foreground">chars</span>
56
- </span>
57
- <span className="inline-flex items-center gap-1 border border-border bg-secondary/40 px-2 py-0.5 font-mono text-[11px] font-medium text-foreground">
58
- ~{approxTokens(instructions).toLocaleString()}
59
- <span className="text-muted-foreground">tokens</span>
60
- </span>
61
- </div>
62
- <div className="mt-3 border border-border bg-card p-6">
63
- <Markdown content={instructions} />
64
- </div>
65
- </>
66
- ) : (
67
- <div className="mt-3 border border-border p-8 text-center">
68
- <p className="text-sm text-muted-foreground">No extra instructions configured.</p>
69
- <p className="mt-1 text-xs text-muted-foreground">
70
- This agent runs on the default base prompt. Preview it to see what that includes.
71
- </p>
72
- </div>
73
- )}
74
- </div>
75
- );
76
- }
77
-
78
- /**
79
- * Loading state for the prompt preview — a sharp skeleton that mimics the
80
- * composed prompt materialising (metadata bar + paragraph blocks of
81
- * varying width), in keeping with the rest of the surface.
82
- */
83
- function PromptSkeleton() {
84
- // Width pattern per "paragraph" — last line of each block is shorter,
85
- // so it reads as real prose rather than a uniform block.
86
- const blocks = [
87
- ["w-1/3"],
88
- ["w-full", "w-full", "w-11/12", "w-2/3"],
89
- ["w-full", "w-5/6", "w-full", "w-1/2"],
90
- ["w-3/4", "w-full", "w-4/5"],
91
- ];
92
- let line = 0;
93
- return (
94
- <div className="flex min-h-0 flex-1 flex-col">
95
- <div className="flex items-center justify-between gap-4 border-y border-border py-2">
96
- <span className="h-3 w-40 animate-pulse bg-muted" />
97
- <span className="h-6 w-16 animate-pulse bg-muted" />
98
- </div>
99
- <div className="min-h-0 flex-1 space-y-5 overflow-hidden bg-card p-4">
100
- {blocks.map((widths, b) => (
101
- <div key={b} className="space-y-2">
102
- {widths.map((w) => {
103
- const delay = (line++ % 6) * 90;
104
- return (
105
- <div
106
- key={w + line}
107
- className={`h-3 ${w} animate-pulse bg-muted`}
108
- style={{ animationDelay: `${delay}ms` }}
109
- />
110
- );
111
- })}
112
- </div>
113
- ))}
114
- </div>
115
- <p className="border-t border-border pt-2 font-mono text-[11px] text-muted-foreground/60">
116
- Composing the full prompt…
117
- </p>
118
- </div>
119
- );
120
- }
121
-
122
- /**
123
- * Preview — fetches the FULLY composed system prompt from the data plane
124
- * (`GET /v1/agents/:name/prompt`), which runs the same `buildAgentSystemPrompt`
125
- * + skill-loading the runtime uses. Shows the exact text sent to the model.
126
- */
127
- function PreviewButton({
128
- projectId,
129
- agentName,
130
- }: {
131
- projectId: string;
132
- agentName: string;
133
- }) {
134
- const [open, setOpen] = useState(false);
135
- const [loading, setLoading] = useState(false);
136
- const [prompt, setPrompt] = useState<string | null>(null);
137
- const [error, setError] = useState<string | null>(null);
138
-
139
- async function load() {
140
- setOpen(true);
141
- setLoading(true);
142
- setError(null);
143
- setPrompt(null);
144
- try {
145
- const res = await fetch(
146
- `${API_URL}/v1/projects/${projectId}/data/v1/agents/${encodeURIComponent(agentName)}/prompt`,
147
- { credentials: "include" },
148
- );
149
- const body = await res.json().catch(() => ({}));
150
- if (!res.ok || !body.ok) {
151
- setError(body.error ?? `Failed to compose prompt (${res.status})`);
152
- } else {
153
- setPrompt(body.data?.prompt ?? "");
154
- }
155
- } catch (err) {
156
- setError((err as Error).message ?? "Failed to compose prompt");
157
- }
158
- setLoading(false);
159
- }
160
-
161
- return (
162
- <>
163
- <button
164
- type="button"
165
- onClick={() => void load()}
166
- className="inline-flex shrink-0 items-center gap-1.5 border border-border bg-card px-2.5 py-1.5 text-xs font-medium text-muted-foreground transition-colors hover:border-foreground/30 hover:text-foreground"
167
- >
168
- <Eye className="h-3.5 w-3.5" strokeWidth={1.5} />
169
- Preview
170
- </button>
171
-
172
- <Dialog open={open} onOpenChange={setOpen}>
173
- <DialogContent className="flex max-h-[85vh] flex-col overflow-hidden sm:max-w-3xl">
174
- <DialogHeader>
175
- <DialogTitle>Composed system prompt</DialogTitle>
176
- <DialogDescription>
177
- The complete prompt the platform sends to the model — base prompt,
178
- identity, your instructions and loaded skills, exactly as the
179
- runtime composes it.
180
- </DialogDescription>
181
- </DialogHeader>
182
-
183
- {loading ? (
184
- <PromptSkeleton />
185
- ) : error ? (
186
- <p className="py-6 text-sm text-destructive">{error}</p>
187
- ) : prompt !== null ? (
188
- <>
189
- <div className="flex items-center justify-between gap-4 border-y border-border py-2">
190
- <div className="flex items-center gap-2">
191
- <span className="inline-flex items-center gap-1 border border-border bg-secondary/40 px-2 py-0.5 font-mono text-[11px] font-medium text-foreground">
192
- {prompt.length.toLocaleString()}
193
- <span className="text-muted-foreground">chars</span>
194
- </span>
195
- <span className="inline-flex items-center gap-1 border border-border bg-secondary/40 px-2 py-0.5 font-mono text-[11px] font-medium text-foreground">
196
- ~{approxTokens(prompt).toLocaleString()}
197
- <span className="text-muted-foreground">tokens</span>
198
- </span>
199
- </div>
200
- <CopyButton value={prompt} label="Copy" className="shrink-0" />
201
- </div>
202
- <div className="min-h-0 flex-1 overflow-auto bg-card p-4">
203
- <Markdown content={prompt} />
204
- </div>
205
- </>
206
- ) : null}
207
- </DialogContent>
208
- </Dialog>
209
- </>
210
- );
211
- }
@@ -1,84 +0,0 @@
1
- import Link from "next/link";
2
- import type { AgentConfig } from "@polpo-ai/core";
3
- import { BookMarked, ExternalLink } from "lucide-react";
4
- import { SectionHeader } from "../../../../../../../components/dashboard/section-header";
5
-
6
- export default function AgentSkillsView({
7
- agent,
8
- projectId,
9
- }: {
10
- agent: AgentConfig | null;
11
- projectId: string;
12
- }) {
13
- if (!agent) {
14
- return (
15
- <div
16
- data-testid="agent-not-found"
17
- className="border border-border p-8 text-center text-sm text-muted-foreground"
18
- >
19
- Agent not found.
20
- </div>
21
- );
22
- }
23
-
24
- const skills = agent.skills ?? [];
25
-
26
- return (
27
- <div>
28
- <SectionHeader
29
- description={
30
- <>
31
- Installed skills extend this agent with reusable procedures. Manage
32
- them with <span className="font-mono">polpo install</span> or in the
33
- agent config <span className="font-mono">skills</span> field.
34
- </>
35
- }
36
- />
37
-
38
- {skills.length === 0 ? (
39
- <div className="mt-4 border border-dashed border-border p-8 text-center">
40
- <BookMarked
41
- className="mx-auto h-5 w-5 text-muted-foreground/40"
42
- strokeWidth={1.5}
43
- />
44
- <p className="mt-2 text-sm text-muted-foreground">No skills installed.</p>
45
- <p className="mt-1 text-xs text-muted-foreground/60">
46
- Browse the catalog at{" "}
47
- <a
48
- href="https://docs.polpo.sh/docs/agents/skills"
49
- target="_blank"
50
- rel="noopener noreferrer"
51
- className="underline decoration-dotted underline-offset-2 transition-colors hover:text-foreground"
52
- >
53
- docs.polpo.sh
54
- </a>
55
- .
56
- </p>
57
- </div>
58
- ) : (
59
- <div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
60
- {skills.map((skill) => (
61
- <Link
62
- key={skill}
63
- href={`/projects/${projectId}/skills/${encodeURIComponent(skill)}`}
64
- target="_blank"
65
- rel="noopener noreferrer"
66
- className="group flex items-center gap-2.5 border border-border bg-card p-3 transition-colors hover:border-foreground/30"
67
- >
68
- <span className="grid size-7 shrink-0 place-items-center bg-secondary text-muted-foreground">
69
- <BookMarked className="h-3.5 w-3.5" strokeWidth={1.5} />
70
- </span>
71
- <span className="min-w-0 flex-1 truncate font-mono text-sm text-foreground">
72
- {skill}
73
- </span>
74
- <ExternalLink
75
- className="h-3.5 w-3.5 shrink-0 text-muted-foreground/40 transition-colors group-hover:text-foreground"
76
- strokeWidth={1.5}
77
- />
78
- </Link>
79
- ))}
80
- </div>
81
- )}
82
- </div>
83
- );
84
- }