agent-state-machine 2.2.1 → 2.2.2

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 (31) hide show
  1. package/bin/cli.js +30 -2
  2. package/lib/runtime/agent.js +6 -2
  3. package/lib/runtime/interaction.js +2 -1
  4. package/lib/runtime/prompt.js +37 -1
  5. package/lib/runtime/runtime.js +67 -5
  6. package/package.json +1 -1
  7. package/templates/project-builder/agents/code-fixer.md +50 -0
  8. package/templates/project-builder/agents/code-writer.md +3 -0
  9. package/templates/project-builder/agents/sanity-checker.md +6 -0
  10. package/templates/project-builder/agents/test-planner.md +3 -1
  11. package/templates/project-builder/config.js +4 -4
  12. package/templates/project-builder/scripts/workflow-helpers.js +104 -2
  13. package/templates/project-builder/workflow.js +151 -14
  14. package/templates/starter/config.js +1 -1
  15. package/vercel-server/api/submit/[token].js +0 -11
  16. package/vercel-server/local-server.js +0 -19
  17. package/vercel-server/public/remote/assets/index-BsJsLDKc.css +1 -0
  18. package/vercel-server/public/remote/assets/index-CmtT6ADh.js +168 -0
  19. package/vercel-server/public/remote/index.html +2 -2
  20. package/vercel-server/ui/src/App.jsx +69 -19
  21. package/vercel-server/ui/src/components/ChoiceInteraction.jsx +69 -18
  22. package/vercel-server/ui/src/components/ConfirmInteraction.jsx +7 -7
  23. package/vercel-server/ui/src/components/ContentCard.jsx +600 -104
  24. package/vercel-server/ui/src/components/EventsLog.jsx +20 -13
  25. package/vercel-server/ui/src/components/Footer.jsx +9 -4
  26. package/vercel-server/ui/src/components/Header.jsx +12 -3
  27. package/vercel-server/ui/src/components/SendingCard.jsx +33 -0
  28. package/vercel-server/ui/src/components/TextInteraction.jsx +8 -8
  29. package/vercel-server/ui/src/index.css +82 -10
  30. package/vercel-server/public/remote/assets/index-CbgeVnKw.js +0 -148
  31. 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
- if (!event) return <Terminal className="w-3.5 h-3.5 opacity-40" />;
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="w-3.5 h-3.5 text-blue-500" />;
7
- if (e.includes("SUBMITTED") || e.includes("ANSWERED") || e.includes("SUCCESS")) return <CheckCircle2 className="w-3.5 h-3.5 text-green-500" />;
8
- if (e.includes("REQUESTED") || e.includes("REQUEST")) return <Send className="w-3.5 h-3.5 text-accent" />;
9
- if (e.includes("ERROR") || e.includes("FAILED")) return <AlertCircle className="w-3.5 h-3.5 text-red-500" />;
10
- return <Terminal className="w-3.5 h-3.5 opacity-40" />;
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 && <span className="text-accent font-medium text-[10px] tracking-wider uppercase opacity-80">{subText}</span>}
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-80 truncate max-w-md">
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-24">
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-4 rounded-2xl hover:bg-black/[0.03] dark:hover:bg-white/[0.03] transition-all border border-transparent hover:border-border"
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-20 group-hover:opacity-40 transition-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-bold tracking-[0.2em] uppercase opacity-30 group-hover:opacity-50 transition-opacity">
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-accent transition-colors">
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-accent disabled:opacity-0 transition-all pointer-events-auto"
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-accent disabled:opacity-0 transition-all pointer-events-auto"
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-accent text-white shadow-[0_10px_30px_rgba(0,122,255,0.25)] hover:scale-[1.02] transition-transform"
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 className={`w-2 h-2 rounded-full ${status === "connected" ? "bg-green-500 shadow-[0_0_15px_rgba(34,197,94,0.6)]" : "bg-red-500"}`}></div>
9
- <span className="font-bold text-[10px] tracking-[0.4em] uppercase opacity-30 truncate max-w-[300px]">{workflowName || "Workflow"}</span>
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-accent text-white flex items-center justify-center mx-auto shadow-2xl shadow-accent/40">
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.03] dark:bg-white/[0.03] border-2 ${
54
- error ? "border-red-500" : "border-transparent"
55
- } focus:ring-4 focus:ring-accent/10 focus:outline-none text-2xl font-medium transition-all text-center placeholder:opacity-20`}
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-red-500 text-center text-sm">{error}</div>}
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/5">
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: #1d1d1f;
8
- --subtle: #86868b;
9
- --border: rgba(0, 0, 0, 0.06);
10
- --accent: #007aff;
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: #f5f5f7;
16
- --subtle: #86868b;
17
- --border: rgba(255, 255, 255, 0.1);
18
- --accent: #0a84ff;
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(127, 127, 127, 0.05);
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(127, 127, 127, 0.05);
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
+ }