agent-state-machine 2.2.1 → 2.3.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/bin/cli.js +33 -5
- package/lib/file-tree.js +1 -1
- package/lib/runtime/agent.js +6 -2
- package/lib/runtime/interaction.js +2 -1
- package/lib/runtime/prompt.js +37 -1
- package/lib/runtime/runtime.js +67 -5
- package/lib/setup.js +4 -4
- package/package.json +1 -1
- package/templates/project-builder/agents/code-fixer.md +50 -0
- package/templates/project-builder/agents/code-writer.md +3 -0
- package/templates/project-builder/agents/sanity-checker.md +6 -0
- package/templates/project-builder/agents/test-planner.md +3 -1
- package/templates/project-builder/config.js +4 -4
- package/templates/project-builder/scripts/workflow-helpers.js +104 -2
- package/templates/project-builder/workflow.js +151 -14
- package/templates/starter/config.js +1 -1
- package/vercel-server/api/submit/[token].js +0 -11
- package/vercel-server/local-server.js +0 -19
- package/vercel-server/public/remote/assets/index-BTLc1QSv.js +168 -0
- package/vercel-server/public/remote/assets/index-DLa4X08t.css +1 -0
- package/vercel-server/public/remote/index.html +2 -2
- package/vercel-server/ui/src/App.jsx +53 -18
- package/vercel-server/ui/src/components/ChoiceInteraction.jsx +69 -18
- package/vercel-server/ui/src/components/ConfirmInteraction.jsx +7 -7
- package/vercel-server/ui/src/components/ContentCard.jsx +607 -103
- package/vercel-server/ui/src/components/EventsLog.jsx +20 -13
- package/vercel-server/ui/src/components/Footer.jsx +9 -4
- package/vercel-server/ui/src/components/Header.jsx +12 -3
- package/vercel-server/ui/src/components/SendingCard.jsx +33 -0
- package/vercel-server/ui/src/components/TextInteraction.jsx +8 -8
- package/vercel-server/ui/src/index.css +82 -10
- package/vercel-server/public/remote/assets/index-CbgeVnKw.js +0 -148
- package/vercel-server/public/remote/assets/index-DHL_iHQW.css +0 -1
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { Terminal, Send, Play, AlertCircle, CheckCircle2 } from "lucide-react";
|
|
2
2
|
|
|
3
3
|
const getEventIcon = (event) => {
|
|
4
|
-
|
|
4
|
+
const base = "w-3.5 h-3.5 text-black/70 dark:text-white/70";
|
|
5
|
+
if (!event) return <Terminal className={`${base} opacity-40`} />;
|
|
5
6
|
const e = event.toUpperCase();
|
|
6
|
-
if (e.includes("STARTED") || e.includes("START")) return <Play className=
|
|
7
|
-
if (e.includes("SUBMITTED") || e.includes("ANSWERED") || e.includes("SUCCESS")
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return <
|
|
7
|
+
if (e.includes("STARTED") || e.includes("START")) return <Play className={`${base} opacity-70`} />;
|
|
8
|
+
if (e.includes("SUBMITTED") || e.includes("ANSWERED") || e.includes("SUCCESS") || e.includes("RESOLVED")) {
|
|
9
|
+
return <CheckCircle2 className={`${base} opacity-80`} />;
|
|
10
|
+
}
|
|
11
|
+
if (e.includes("REQUESTED") || e.includes("REQUEST")) return <Send className={`${base} opacity-60`} />;
|
|
12
|
+
if (e.includes("ERROR") || e.includes("FAILED")) return <AlertCircle className={`${base} opacity-90`} />;
|
|
13
|
+
return <Terminal className={`${base} opacity-40`} />;
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
const getEventSummary = (item) => {
|
|
@@ -18,9 +21,13 @@ const getEventSummary = (item) => {
|
|
|
18
21
|
|
|
19
22
|
return (
|
|
20
23
|
<div className="flex flex-col gap-0.5">
|
|
21
|
-
{subText &&
|
|
24
|
+
{subText && (
|
|
25
|
+
<span className="text-black/60 dark:text-white/60 font-medium text-[10px] tracking-[0.24em] uppercase">
|
|
26
|
+
{subText}
|
|
27
|
+
</span>
|
|
28
|
+
)}
|
|
22
29
|
{mainText && (
|
|
23
|
-
<span className="opacity-
|
|
30
|
+
<span className="opacity-70 truncate max-w-md">
|
|
24
31
|
{typeof mainText === "string" ? mainText : JSON.stringify(mainText)}
|
|
25
32
|
</span>
|
|
26
33
|
)}
|
|
@@ -31,7 +38,7 @@ const getEventSummary = (item) => {
|
|
|
31
38
|
export default function EventsLog({ history, onJump }) {
|
|
32
39
|
return (
|
|
33
40
|
<div className="w-full h-full flex flex-col overflow-hidden bg-bg">
|
|
34
|
-
<div className="flex-1 overflow-y-auto custom-scroll px-6 py-
|
|
41
|
+
<div className="flex-1 overflow-y-auto custom-scroll px-6 sm:px-8 lg:px-10 py-20">
|
|
35
42
|
<div className="max-w-4xl mx-auto space-y-1">
|
|
36
43
|
{history.length === 0 ? (
|
|
37
44
|
<div className="h-[40vh] flex flex-col items-center justify-center opacity-20 space-y-4">
|
|
@@ -51,10 +58,10 @@ export default function EventsLog({ history, onJump }) {
|
|
|
51
58
|
<button
|
|
52
59
|
key={idx}
|
|
53
60
|
onClick={() => onJump(idx)}
|
|
54
|
-
className="w-full text-left group flex items-start gap-6 p-
|
|
61
|
+
className="w-full text-left group flex items-start gap-6 p-5 rounded-2xl transition-all border border-black/10 dark:border-white/10 hover:bg-black/[0.03] dark:hover:bg-white/[0.04]"
|
|
55
62
|
>
|
|
56
63
|
<div className="flex-shrink-0 w-20 pt-1">
|
|
57
|
-
<span className="text-[10px] font-mono font-medium opacity-
|
|
64
|
+
<span className="text-[10px] font-mono font-medium opacity-30 group-hover:opacity-60 transition-opacity">
|
|
58
65
|
{time}
|
|
59
66
|
</span>
|
|
60
67
|
</div>
|
|
@@ -64,10 +71,10 @@ export default function EventsLog({ history, onJump }) {
|
|
|
64
71
|
</div>
|
|
65
72
|
|
|
66
73
|
<div className="flex-1 min-w-0 flex flex-col gap-1">
|
|
67
|
-
<div className="text-[10px] font-
|
|
74
|
+
<div className="text-[10px] font-semibold tracking-[0.28em] uppercase opacity-40 group-hover:opacity-70 transition-opacity">
|
|
68
75
|
{item.event?.replace(/_/g, " ") || "EVENT"}
|
|
69
76
|
</div>
|
|
70
|
-
<div className="text-sm leading-relaxed truncate group-hover:text-
|
|
77
|
+
<div className="text-sm leading-relaxed truncate group-hover:text-black dark:group-hover:text-white transition-colors">
|
|
71
78
|
{getEventSummary(item)}
|
|
72
79
|
</div>
|
|
73
80
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
3
3
|
|
|
4
|
-
export default function Footer({ page, total, onNext, onPrev, onJump, hasNew, onJumpToLatest, className = "" }) {
|
|
4
|
+
export default function Footer({ page, total, onNext, onPrev, onJump, hasNew, onJumpToLatest, className = "", leftSlot = null }) {
|
|
5
5
|
const [inputValue, setInputValue] = useState(page + 1);
|
|
6
6
|
useEffect(() => setInputValue(page + 1), [page]);
|
|
7
7
|
|
|
@@ -16,11 +16,16 @@ export default function Footer({ page, total, onNext, onPrev, onJump, hasNew, on
|
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
18
|
<footer className={`nav-footer transition-opacity duration-300 ${className}`}>
|
|
19
|
+
{leftSlot ? (
|
|
20
|
+
<div className="fixed bottom-6 left-2 sm:left-4 z-40">
|
|
21
|
+
{leftSlot}
|
|
22
|
+
</div>
|
|
23
|
+
) : null}
|
|
19
24
|
<div className="footer-control">
|
|
20
25
|
<button
|
|
21
26
|
onClick={onPrev}
|
|
22
27
|
disabled={page === 0}
|
|
23
|
-
className="tooltip p-1 hover:text-
|
|
28
|
+
className="tooltip p-1 hover:text-black dark:hover:text-white disabled:opacity-0 transition-all pointer-events-auto"
|
|
24
29
|
data-tooltip="Previous"
|
|
25
30
|
aria-label="Previous event"
|
|
26
31
|
>
|
|
@@ -43,7 +48,7 @@ export default function Footer({ page, total, onNext, onPrev, onJump, hasNew, on
|
|
|
43
48
|
<button
|
|
44
49
|
onClick={onNext}
|
|
45
50
|
disabled={page === total - 1}
|
|
46
|
-
className="tooltip p-1 hover:text-
|
|
51
|
+
className="tooltip p-1 hover:text-black dark:hover:text-white disabled:opacity-0 transition-all pointer-events-auto"
|
|
47
52
|
data-tooltip="Next"
|
|
48
53
|
aria-label="Next event"
|
|
49
54
|
>
|
|
@@ -53,7 +58,7 @@ export default function Footer({ page, total, onNext, onPrev, onJump, hasNew, on
|
|
|
53
58
|
{hasNew ? (
|
|
54
59
|
<button
|
|
55
60
|
onClick={onJumpToLatest}
|
|
56
|
-
className="tooltip px-3 py-1 rounded-full text-[10px] font-bold tracking-[0.2em] uppercase bg-
|
|
61
|
+
className="tooltip px-3 py-1 rounded-full text-[10px] font-bold tracking-[0.2em] uppercase bg-black text-white dark:bg-white dark:text-black shadow-[0_10px_30px_rgba(0,0,0,0.2)] dark:shadow-[0_10px_30px_rgba(255,255,255,0.1)] hover:scale-[1.02] transition-transform"
|
|
57
62
|
data-tooltip="Latest"
|
|
58
63
|
aria-label="Jump to latest event"
|
|
59
64
|
>
|
|
@@ -3,10 +3,19 @@ import CopyButton from "./CopyButton.jsx";
|
|
|
3
3
|
|
|
4
4
|
export default function Header({ workflowName, status, theme, toggleTheme, viewMode, setViewMode, history }) {
|
|
5
5
|
return (
|
|
6
|
-
<header className="fixed top-0 inset-x-0 h-20 px-12 flex items-center justify-between z-50 bg-bg/80 backdrop-blur-3xl">
|
|
6
|
+
<header className="fixed top-0 inset-x-0 h-20 px-6 sm:px-10 lg:px-12 flex items-center justify-between z-50 bg-bg/80 backdrop-blur-3xl">
|
|
7
7
|
<div className="flex items-center gap-4">
|
|
8
|
-
<div
|
|
9
|
-
|
|
8
|
+
<div
|
|
9
|
+
className={`w-2.5 h-2.5 rounded-full border ${
|
|
10
|
+
status === "connected"
|
|
11
|
+
? "bg-black border-black dark:bg-white dark:border-white"
|
|
12
|
+
: "bg-transparent border-black/30 dark:border-white/30"
|
|
13
|
+
}`}
|
|
14
|
+
aria-hidden="true"
|
|
15
|
+
/>
|
|
16
|
+
<span className="font-semibold text-[10px] tracking-[0.32em] uppercase text-black/50 dark:text-white/50 truncate max-w-[300px]">
|
|
17
|
+
{workflowName || "Workflow"}
|
|
18
|
+
</span>
|
|
10
19
|
</div>
|
|
11
20
|
|
|
12
21
|
<div className="flex items-center gap-2">
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Loader2 } from "lucide-react";
|
|
2
|
+
|
|
3
|
+
export default function SendingCard({ submission }) {
|
|
4
|
+
const subtitle = submission?.slug
|
|
5
|
+
? `Waiting for the CLI to receive ${submission.slug} and log the next event.`
|
|
6
|
+
: "Waiting for the CLI to receive the response and log the next event.";
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="w-full h-full flex items-center justify-center px-6 py-12 bg-white text-black dark:bg-black dark:text-white">
|
|
10
|
+
<div className="content-width w-full flex flex-col items-center text-center gap-6">
|
|
11
|
+
<div className="relative">
|
|
12
|
+
<div
|
|
13
|
+
className="absolute -inset-4 rounded-[36px] bg-black/10 dark:bg-white/10 blur-2xl opacity-60"
|
|
14
|
+
aria-hidden="true"
|
|
15
|
+
/>
|
|
16
|
+
<div className="relative w-20 h-20 rounded-[28px] border border-black/10 dark:border-white/10 bg-black/[0.03] dark:bg-white/[0.03] flex items-center justify-center shadow-2xl shadow-black/20 dark:shadow-white/10">
|
|
17
|
+
<Loader2 className="w-9 h-9 text-black dark:text-white animate-spin" />
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div className="space-y-3">
|
|
22
|
+
<div className="text-4xl font-black tracking-tight">Sending response</div>
|
|
23
|
+
<div className="text-lg font-medium text-black/60 dark:text-white/60 max-w-xl break-words">
|
|
24
|
+
{subtitle}
|
|
25
|
+
</div>
|
|
26
|
+
<div className="text-[10px] font-bold tracking-[0.35em] uppercase opacity-30">
|
|
27
|
+
Keep this tab open
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -35,14 +35,14 @@ export default function TextInteraction({ interaction, onSubmit, disabled }) {
|
|
|
35
35
|
<div className="w-full h-full flex flex-col items-stretch overflow-hidden">
|
|
36
36
|
<div className="flex-1 overflow-y-auto custom-scroll px-6 py-12 space-y-8 flex flex-col items-center">
|
|
37
37
|
<div className="space-y-4 shrink-0">
|
|
38
|
-
<div className="w-16 h-16 rounded-3xl bg-
|
|
38
|
+
<div className="w-16 h-16 rounded-3xl bg-black text-white dark:bg-white dark:text-black flex items-center justify-center mx-auto shadow-2xl shadow-black/20 dark:shadow-white/10">
|
|
39
39
|
<Bot className="w-8 h-8" />
|
|
40
40
|
</div>
|
|
41
|
-
<h3 className="text-4xl font-extrabold tracking-tight text-fg pt-4 text-center">Action required.</h3>
|
|
41
|
+
<h3 className="text-3xl sm:text-4xl font-extrabold tracking-tight text-fg pt-4 text-center">Action required.</h3>
|
|
42
42
|
</div>
|
|
43
43
|
|
|
44
44
|
<div className="w-full max-w-2xl space-y-4">
|
|
45
|
-
<div className="text-xl font-medium text-fg/70 text-center whitespace-pre-wrap">
|
|
45
|
+
<div className="text-lg sm:text-xl font-medium text-fg/70 text-center whitespace-pre-wrap break-words">
|
|
46
46
|
{prompt || question || "Provide your response."}
|
|
47
47
|
</div>
|
|
48
48
|
<textarea
|
|
@@ -50,15 +50,15 @@ export default function TextInteraction({ interaction, onSubmit, disabled }) {
|
|
|
50
50
|
onChange={(event) => { setText(event.target.value); setError(null); }}
|
|
51
51
|
disabled={disabled}
|
|
52
52
|
placeholder={placeholder || "Your response..."}
|
|
53
|
-
className={`w-full h-64 p-8 rounded-[32px] bg-black/[0.
|
|
54
|
-
error ? "border-
|
|
55
|
-
} focus:
|
|
53
|
+
className={`w-full h-64 p-8 rounded-[32px] bg-black/[0.02] dark:bg-white/[0.03] border-2 ${
|
|
54
|
+
error ? "border-black dark:border-white" : "border-transparent"
|
|
55
|
+
} focus:border-black dark:focus:border-white focus:outline-none text-xl sm:text-2xl font-medium transition-all text-center placeholder:opacity-20`}
|
|
56
56
|
/>
|
|
57
|
-
{error && <div className="text-
|
|
57
|
+
{error && <div className="text-black dark:text-white text-center text-sm font-semibold">{error}</div>}
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
60
60
|
|
|
61
|
-
<div className="p-4 flex justify-center bg-gradient-to-t from-bg via-bg to-transparent shrink-0 border-t border-white/
|
|
61
|
+
<div className="p-4 flex justify-center bg-gradient-to-t from-bg via-bg to-transparent shrink-0 border-t border-black/10 dark:border-white/10">
|
|
62
62
|
<button
|
|
63
63
|
onClick={handleSubmit}
|
|
64
64
|
disabled={disabled || !text.trim()}
|
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
:root {
|
|
6
6
|
--bg: #ffffff;
|
|
7
|
-
--fg: #
|
|
8
|
-
--subtle:
|
|
9
|
-
--border: rgba(0, 0, 0, 0.
|
|
10
|
-
--accent: #
|
|
7
|
+
--fg: #000000;
|
|
8
|
+
--subtle: rgba(0, 0, 0, 0.45);
|
|
9
|
+
--border: rgba(0, 0, 0, 0.12);
|
|
10
|
+
--accent: #000000;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.dark {
|
|
14
14
|
--bg: #000000;
|
|
15
|
-
--fg: #
|
|
16
|
-
--subtle:
|
|
17
|
-
--border: rgba(255, 255, 255, 0.
|
|
18
|
-
--accent: #
|
|
15
|
+
--fg: #ffffff;
|
|
16
|
+
--subtle: rgba(255, 255, 255, 0.45);
|
|
17
|
+
--border: rgba(255, 255, 255, 0.18);
|
|
18
|
+
--accent: #ffffff;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
body {
|
|
@@ -45,7 +45,7 @@ body {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.markdown-body pre {
|
|
48
|
-
background: rgba(
|
|
48
|
+
background: rgba(0, 0, 0, 0.05);
|
|
49
49
|
padding: 1.5rem;
|
|
50
50
|
border-radius: 12px;
|
|
51
51
|
overflow-x: auto;
|
|
@@ -53,6 +53,10 @@ body {
|
|
|
53
53
|
line-height: 1.6;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
.dark .markdown-body pre {
|
|
57
|
+
background: rgba(255, 255, 255, 0.08);
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
.content-width {
|
|
57
61
|
width: 100%;
|
|
58
62
|
max-width: 900px;
|
|
@@ -106,12 +110,16 @@ body {
|
|
|
106
110
|
align-items: center;
|
|
107
111
|
gap: 1.5rem;
|
|
108
112
|
padding: 0.5rem 1.2rem;
|
|
109
|
-
background: rgba(
|
|
113
|
+
background: rgba(0, 0, 0, 0.04);
|
|
110
114
|
backdrop-filter: blur(20px);
|
|
111
115
|
border-radius: 99px;
|
|
112
116
|
border: 1px solid var(--border);
|
|
113
117
|
}
|
|
114
118
|
|
|
119
|
+
.dark .footer-control {
|
|
120
|
+
background: rgba(255, 255, 255, 0.08);
|
|
121
|
+
}
|
|
122
|
+
|
|
115
123
|
.tooltip {
|
|
116
124
|
position: relative;
|
|
117
125
|
}
|
|
@@ -143,3 +151,67 @@ body {
|
|
|
143
151
|
opacity: 1;
|
|
144
152
|
transform: translateX(-50%) translateY(0);
|
|
145
153
|
}
|
|
154
|
+
|
|
155
|
+
.raw-json-block {
|
|
156
|
+
margin: 0;
|
|
157
|
+
padding: 1.5rem;
|
|
158
|
+
border-radius: 24px;
|
|
159
|
+
border: 1px solid var(--border);
|
|
160
|
+
background: rgba(0, 0, 0, 0.04);
|
|
161
|
+
color: rgba(0, 0, 0, 0.85);
|
|
162
|
+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "monospace";
|
|
163
|
+
font-size: 0.85rem;
|
|
164
|
+
line-height: 1.6;
|
|
165
|
+
white-space: pre-wrap;
|
|
166
|
+
word-break: break-word;
|
|
167
|
+
overflow: auto;
|
|
168
|
+
max-height: 70vh;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.raw-json-block--full {
|
|
172
|
+
max-height: none;
|
|
173
|
+
overflow: visible;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.dark .raw-json-block {
|
|
177
|
+
background: rgba(255, 255, 255, 0.08);
|
|
178
|
+
color: rgba(255, 255, 255, 0.9);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.json-token-key {
|
|
182
|
+
color: rgba(0, 0, 0, 0.75);
|
|
183
|
+
font-weight: 600;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.json-token-string {
|
|
187
|
+
color: rgba(0, 0, 0, 0.6);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.json-token-number {
|
|
191
|
+
color: rgba(0, 0, 0, 0.85);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.json-token-boolean {
|
|
195
|
+
color: rgba(0, 0, 0, 0.85);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.json-token-null {
|
|
199
|
+
color: rgba(0, 0, 0, 0.45);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.dark .json-token-key {
|
|
203
|
+
color: rgba(255, 255, 255, 0.8);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.dark .json-token-string {
|
|
207
|
+
color: rgba(255, 255, 255, 0.65);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.dark .json-token-number,
|
|
211
|
+
.dark .json-token-boolean {
|
|
212
|
+
color: rgba(255, 255, 255, 0.9);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.dark .json-token-null {
|
|
216
|
+
color: rgba(255, 255, 255, 0.55);
|
|
217
|
+
}
|