khotan-data 0.1.1 → 0.2.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.
- package/README.md +29 -0
- package/dist/cli.js +132 -46
- package/dist/factory.cjs +79 -9
- package/dist/factory.cjs.map +1 -1
- package/dist/factory.d.cts +38 -1
- package/dist/factory.d.ts +38 -1
- package/dist/factory.js +79 -10
- package/dist/factory.js.map +1 -1
- package/dist/templates/api-state.tsx +249 -0
- package/dist/templates/debug-index-page.tsx +56 -36
- package/dist/templates/hub.tsx +9 -23
- package/dist/templates/khotan-config.ts +17 -0
- package/dist/templates/mapping-browser.tsx +56 -44
- package/dist/templates/plug-debugger.tsx +15 -7
- package/dist/templates/runs-table.tsx +133 -130
- package/dist/templates/skill-setup.md +37 -2
- package/dist/templates/topology-canvas.tsx +19 -30
- package/dist/templates/var-panel.tsx +33 -10
- package/dist/templates/webhook-events-table.tsx +105 -102
- package/dist/templates/wire-panel.tsx +30 -8
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
|
+
import { khotanFetch, ApiErrorState } from "./api-state";
|
|
4
5
|
import { Badge } from "@/components/ui/badge";
|
|
5
6
|
import { Button } from "@/components/ui/button";
|
|
6
7
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
@@ -75,7 +76,7 @@ export function KhotanWebhookEventsTable({
|
|
|
75
76
|
const [data, setData] = useState<PageResponse<WebhookEventItem> | null>(null);
|
|
76
77
|
const [offset, setOffset] = useState(0);
|
|
77
78
|
const [loading, setLoading] = useState(true);
|
|
78
|
-
const [error, setError] = useState<
|
|
79
|
+
const [error, setError] = useState<unknown>(null);
|
|
79
80
|
const [refreshKey, setRefreshKey] = useState(0);
|
|
80
81
|
|
|
81
82
|
useEffect(() => {
|
|
@@ -85,19 +86,15 @@ export function KhotanWebhookEventsTable({
|
|
|
85
86
|
setLoading(true);
|
|
86
87
|
setError(null);
|
|
87
88
|
try {
|
|
88
|
-
const
|
|
89
|
+
const json = await khotanFetch<PageResponse<WebhookEventItem>>(
|
|
89
90
|
`/api/khotan/webhook-events?limit=${String(pageSize)}&offset=${String(offset)}`,
|
|
90
91
|
);
|
|
91
|
-
if (!res.ok) {
|
|
92
|
-
throw new Error("Failed to load webhook events");
|
|
93
|
-
}
|
|
94
|
-
const json = (await res.json()) as PageResponse<WebhookEventItem>;
|
|
95
92
|
if (!cancelled) {
|
|
96
93
|
setData(json);
|
|
97
94
|
}
|
|
98
95
|
} catch (err) {
|
|
99
96
|
if (!cancelled) {
|
|
100
|
-
setError(err
|
|
97
|
+
setError(err);
|
|
101
98
|
}
|
|
102
99
|
} finally {
|
|
103
100
|
if (!cancelled) {
|
|
@@ -131,110 +128,116 @@ export function KhotanWebhookEventsTable({
|
|
|
131
128
|
</CardHeader>
|
|
132
129
|
<CardContent className="space-y-4">
|
|
133
130
|
{error ? (
|
|
134
|
-
<
|
|
135
|
-
{error}
|
|
136
|
-
|
|
131
|
+
<ApiErrorState
|
|
132
|
+
error={error}
|
|
133
|
+
onRetry={() => setRefreshKey((v) => v + 1)}
|
|
134
|
+
compact
|
|
135
|
+
/>
|
|
137
136
|
) : null}
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
<
|
|
142
|
-
<TableHead>Received</TableHead>
|
|
143
|
-
<TableHead>Event</TableHead>
|
|
144
|
-
<TableHead>Handler</TableHead>
|
|
145
|
-
<TableHead>Plug</TableHead>
|
|
146
|
-
<TableHead>Run</TableHead>
|
|
147
|
-
<TableHead>Payload</TableHead>
|
|
148
|
-
</TableRow>
|
|
149
|
-
</TableHeader>
|
|
150
|
-
<TableBody>
|
|
151
|
-
{loading ? (
|
|
138
|
+
{error ? null : (
|
|
139
|
+
<Table>
|
|
140
|
+
<TableHeader>
|
|
152
141
|
<TableRow>
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
>
|
|
157
|
-
|
|
158
|
-
</
|
|
142
|
+
<TableHead>Received</TableHead>
|
|
143
|
+
<TableHead>Event</TableHead>
|
|
144
|
+
<TableHead>Handler</TableHead>
|
|
145
|
+
<TableHead>Plug</TableHead>
|
|
146
|
+
<TableHead>Run</TableHead>
|
|
147
|
+
<TableHead>Payload</TableHead>
|
|
159
148
|
</TableRow>
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<TableCell className="text-sm text-muted-foreground">
|
|
170
|
-
{formatHandler(item)}
|
|
171
|
-
</TableCell>
|
|
172
|
-
<TableCell className="text-muted-foreground">
|
|
173
|
-
{item.plugName ?? "-"}
|
|
174
|
-
</TableCell>
|
|
175
|
-
<TableCell className="space-y-1 text-xs">
|
|
176
|
-
<div className="font-mono text-muted-foreground">
|
|
177
|
-
{item.khotanRunId}
|
|
178
|
-
</div>
|
|
179
|
-
<div className="flex flex-wrap items-center gap-2">
|
|
180
|
-
{item.runStatus ? (
|
|
181
|
-
<Badge variant={statusVariant[item.runStatus]}>
|
|
182
|
-
{item.runStatus}
|
|
183
|
-
</Badge>
|
|
184
|
-
) : null}
|
|
185
|
-
<span className="font-mono text-muted-foreground">
|
|
186
|
-
{item.workflowRunId ?? "-"}
|
|
187
|
-
</span>
|
|
188
|
-
</div>
|
|
149
|
+
</TableHeader>
|
|
150
|
+
<TableBody>
|
|
151
|
+
{loading ? (
|
|
152
|
+
<TableRow>
|
|
153
|
+
<TableCell
|
|
154
|
+
colSpan={6}
|
|
155
|
+
className="text-sm text-muted-foreground"
|
|
156
|
+
>
|
|
157
|
+
Loading webhook events...
|
|
189
158
|
</TableCell>
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
159
|
+
</TableRow>
|
|
160
|
+
) : data?.items.length ? (
|
|
161
|
+
data.items.map((item) => (
|
|
162
|
+
<TableRow key={item.id}>
|
|
163
|
+
<TableCell className="text-sm text-muted-foreground">
|
|
164
|
+
{formatDateTime(item.receivedAt)}
|
|
165
|
+
</TableCell>
|
|
166
|
+
<TableCell className="font-medium">
|
|
167
|
+
{item.eventType}
|
|
168
|
+
</TableCell>
|
|
169
|
+
<TableCell className="text-sm text-muted-foreground">
|
|
170
|
+
{formatHandler(item)}
|
|
171
|
+
</TableCell>
|
|
172
|
+
<TableCell className="text-muted-foreground">
|
|
173
|
+
{item.plugName ?? "-"}
|
|
174
|
+
</TableCell>
|
|
175
|
+
<TableCell className="space-y-1 text-xs">
|
|
176
|
+
<div className="font-mono text-muted-foreground">
|
|
177
|
+
{item.khotanRunId}
|
|
178
|
+
</div>
|
|
179
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
180
|
+
{item.runStatus ? (
|
|
181
|
+
<Badge variant={statusVariant[item.runStatus]}>
|
|
182
|
+
{item.runStatus}
|
|
183
|
+
</Badge>
|
|
184
|
+
) : null}
|
|
185
|
+
<span className="font-mono text-muted-foreground">
|
|
186
|
+
{item.workflowRunId ?? "-"}
|
|
187
|
+
</span>
|
|
188
|
+
</div>
|
|
189
|
+
</TableCell>
|
|
190
|
+
<TableCell className="max-w-80">
|
|
191
|
+
<details>
|
|
192
|
+
<summary className="cursor-pointer text-sm text-primary">
|
|
193
|
+
View payload
|
|
194
|
+
</summary>
|
|
195
|
+
<pre className="mt-2 max-h-64 overflow-auto rounded-md bg-muted p-3 text-xs">
|
|
196
|
+
{JSON.stringify(item.payload, null, 2)}
|
|
197
|
+
</pre>
|
|
198
|
+
</details>
|
|
199
|
+
</TableCell>
|
|
200
|
+
</TableRow>
|
|
201
|
+
))
|
|
202
|
+
) : (
|
|
203
|
+
<TableRow>
|
|
204
|
+
<TableCell
|
|
205
|
+
colSpan={6}
|
|
206
|
+
className="text-sm text-muted-foreground"
|
|
207
|
+
>
|
|
208
|
+
No webhook events recorded yet.
|
|
199
209
|
</TableCell>
|
|
200
210
|
</TableRow>
|
|
201
|
-
)
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
colSpan={6}
|
|
206
|
-
className="text-sm text-muted-foreground"
|
|
207
|
-
>
|
|
208
|
-
No webhook events recorded yet.
|
|
209
|
-
</TableCell>
|
|
210
|
-
</TableRow>
|
|
211
|
-
)}
|
|
212
|
-
</TableBody>
|
|
213
|
-
</Table>
|
|
211
|
+
)}
|
|
212
|
+
</TableBody>
|
|
213
|
+
</Table>
|
|
214
|
+
)}
|
|
214
215
|
|
|
215
|
-
|
|
216
|
-
<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
<
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
216
|
+
{error ? null : (
|
|
217
|
+
<div className="flex items-center justify-between gap-3">
|
|
218
|
+
<p className="text-sm text-muted-foreground">
|
|
219
|
+
Page {Math.floor(offset / pageSize) + 1}
|
|
220
|
+
</p>
|
|
221
|
+
<div className="flex items-center gap-2">
|
|
222
|
+
<Button
|
|
223
|
+
variant="outline"
|
|
224
|
+
size="sm"
|
|
225
|
+
disabled={offset === 0 || loading}
|
|
226
|
+
onClick={() => setOffset(Math.max(offset - pageSize, 0))}
|
|
227
|
+
>
|
|
228
|
+
Previous
|
|
229
|
+
</Button>
|
|
230
|
+
<Button
|
|
231
|
+
variant="outline"
|
|
232
|
+
size="sm"
|
|
233
|
+
disabled={!data?.page.hasMore || loading}
|
|
234
|
+
onClick={() => setOffset(offset + pageSize)}
|
|
235
|
+
>
|
|
236
|
+
Next
|
|
237
|
+
</Button>
|
|
238
|
+
</div>
|
|
236
239
|
</div>
|
|
237
|
-
|
|
240
|
+
)}
|
|
238
241
|
</CardContent>
|
|
239
242
|
</Card>
|
|
240
243
|
);
|
|
@@ -4,6 +4,7 @@ import { useEffect, useState, useCallback } from "react";
|
|
|
4
4
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
5
5
|
import { Badge } from "@/components/ui/badge";
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
|
+
import { khotanFetch, ApiErrorState } from "./api-state";
|
|
7
8
|
|
|
8
9
|
// ============================================================================
|
|
9
10
|
// Wire Panel — UI for managing webhook subscriptions
|
|
@@ -45,21 +46,23 @@ export function WirePanel({
|
|
|
45
46
|
const [loading, setLoading] = useState(true);
|
|
46
47
|
const [acting, setActing] = useState(false);
|
|
47
48
|
const [error, setError] = useState<string | null>(null);
|
|
49
|
+
const [loadError, setLoadError] = useState<unknown>(null);
|
|
48
50
|
|
|
49
51
|
const fetchWire = useCallback(async () => {
|
|
52
|
+
setLoading(true);
|
|
53
|
+
setLoadError(null);
|
|
50
54
|
try {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
const data = await res.json();
|
|
55
|
+
const data = await khotanFetch<{
|
|
56
|
+
configured?: boolean;
|
|
57
|
+
wire?: WireRecord | null;
|
|
58
|
+
}>(`${basePath}/wires/${plugName}`);
|
|
58
59
|
setConfigured(data.configured ?? false);
|
|
59
60
|
setWire(data.wire ?? null);
|
|
60
61
|
setError(null);
|
|
61
|
-
} catch {
|
|
62
|
+
} catch (err) {
|
|
62
63
|
setConfigured(false);
|
|
64
|
+
setWire(null);
|
|
65
|
+
setLoadError(err);
|
|
63
66
|
} finally {
|
|
64
67
|
setLoading(false);
|
|
65
68
|
}
|
|
@@ -136,6 +139,25 @@ export function WirePanel({
|
|
|
136
139
|
);
|
|
137
140
|
}
|
|
138
141
|
|
|
142
|
+
if (loadError) {
|
|
143
|
+
return (
|
|
144
|
+
<Card>
|
|
145
|
+
<CardHeader className="pb-2">
|
|
146
|
+
<CardTitle className="text-sm font-medium capitalize">
|
|
147
|
+
{displayName} Wire
|
|
148
|
+
</CardTitle>
|
|
149
|
+
</CardHeader>
|
|
150
|
+
<CardContent>
|
|
151
|
+
<ApiErrorState
|
|
152
|
+
error={loadError}
|
|
153
|
+
onRetry={() => void fetchWire()}
|
|
154
|
+
compact
|
|
155
|
+
/>
|
|
156
|
+
</CardContent>
|
|
157
|
+
</Card>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
139
161
|
if (!configured) return null;
|
|
140
162
|
|
|
141
163
|
const isActive = wire?.status === "active";
|