quadwork 1.1.0 → 1.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/bin/quadwork.js +88 -37
- package/out/404.html +1 -1
- package/out/__next.__PAGE__.txt +3 -3
- package/out/__next._full.txt +16 -15
- package/out/__next._head.txt +4 -4
- package/out/__next._index.txt +6 -5
- package/out/__next._tree.txt +2 -2
- package/out/_next/static/chunks/064engxz5n7u9.js +1 -0
- package/out/_next/static/chunks/0738cfu-x.0ul.js +24 -0
- package/out/_next/static/chunks/{00cs~pv62864f.js → 0o97ax9om2kj1.js} +1 -1
- package/out/_next/static/chunks/0r-00ph4jahrl.css +2 -0
- package/out/_next/static/chunks/0spbjcw4anq15.js +1 -0
- package/out/_next/static/chunks/{0io_y3d0p5v~b.js → 15i5_ay.0ap.6.js} +2 -2
- package/out/_next/static/chunks/{turbopack-0sammtvunroor.js → turbopack-0wh29ykoy-rb5.js} +1 -1
- package/out/_not-found/__next._full.txt +17 -16
- package/out/_not-found/__next._head.txt +4 -4
- package/out/_not-found/__next._index.txt +6 -5
- package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/out/_not-found/__next._not-found.txt +3 -3
- package/out/_not-found/__next._tree.txt +2 -2
- package/out/_not-found.html +1 -1
- package/out/_not-found.txt +17 -16
- package/out/app-shell/__next._full.txt +17 -16
- package/out/app-shell/__next._head.txt +4 -4
- package/out/app-shell/__next._index.txt +6 -5
- package/out/app-shell/__next._tree.txt +2 -2
- package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
- package/out/app-shell/__next.app-shell.txt +3 -3
- package/out/app-shell.html +1 -1
- package/out/app-shell.txt +17 -16
- package/out/index.html +1 -1
- package/out/index.txt +16 -15
- package/out/project/_/__next._full.txt +18 -17
- package/out/project/_/__next._head.txt +4 -4
- package/out/project/_/__next._index.txt +6 -5
- package/out/project/_/__next._tree.txt +2 -2
- package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
- package/out/project/_/__next.project.$d$id.txt +3 -3
- package/out/project/_/__next.project.txt +3 -3
- package/out/project/_/memory/__next._full.txt +18 -17
- package/out/project/_/memory/__next._head.txt +4 -4
- package/out/project/_/memory/__next._index.txt +6 -5
- package/out/project/_/memory/__next._tree.txt +2 -2
- package/out/project/_/memory/__next.project.$d$id.memory.__PAGE__.txt +3 -3
- package/out/project/_/memory/__next.project.$d$id.memory.txt +3 -3
- package/out/project/_/memory/__next.project.$d$id.txt +3 -3
- package/out/project/_/memory/__next.project.txt +3 -3
- package/out/project/_/memory.html +1 -1
- package/out/project/_/memory.txt +18 -17
- package/out/project/_/queue/__next._full.txt +18 -17
- package/out/project/_/queue/__next._head.txt +4 -4
- package/out/project/_/queue/__next._index.txt +6 -5
- package/out/project/_/queue/__next._tree.txt +2 -2
- package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
- package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
- package/out/project/_/queue/__next.project.$d$id.txt +3 -3
- package/out/project/_/queue/__next.project.txt +3 -3
- package/out/project/_/queue.html +1 -1
- package/out/project/_/queue.txt +18 -17
- package/out/project/_.html +1 -1
- package/out/project/_.txt +18 -17
- package/out/settings/__next._full.txt +18 -17
- package/out/settings/__next._head.txt +4 -4
- package/out/settings/__next._index.txt +6 -5
- package/out/settings/__next._tree.txt +2 -2
- package/out/settings/__next.settings.__PAGE__.txt +3 -3
- package/out/settings/__next.settings.txt +3 -3
- package/out/settings.html +1 -1
- package/out/settings.txt +18 -17
- package/out/setup/__next._full.txt +18 -17
- package/out/setup/__next._head.txt +4 -4
- package/out/setup/__next._index.txt +6 -5
- package/out/setup/__next._tree.txt +2 -2
- package/out/setup/__next.setup.__PAGE__.txt +3 -3
- package/out/setup/__next.setup.txt +3 -3
- package/out/setup.html +1 -1
- package/out/setup.txt +18 -17
- package/package.json +2 -1
- package/server/index.js +139 -2
- package/server/routes.js +124 -3
- package/templates/OVERNIGHT-QUEUE.md +35 -0
- package/templates/seeds/dev.AGENTS.md +9 -0
- package/templates/seeds/head.AGENTS.md +29 -2
- package/templates/seeds/reviewer1.AGENTS.md +9 -0
- package/templates/seeds/reviewer2.AGENTS.md +9 -0
- package/out/_next/static/chunks/08fgie1bcjynm.js +0 -1
- package/out/_next/static/chunks/0g7f4hvbz_1u~.js +0 -20
- package/out/_next/static/chunks/10b3c4k.q.yw..css +0 -2
- package/out/_next/static/chunks/14kr4rvjq-2md.js +0 -1
- /package/out/_next/static/{zx5_zAjM3qhPvkFrygZp8 → 2NHQV76k9j9SbWmUaPhY3}/_buildManifest.js +0 -0
- /package/out/_next/static/{zx5_zAjM3qhPvkFrygZp8 → 2NHQV76k9j9SbWmUaPhY3}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{zx5_zAjM3qhPvkFrygZp8 → 2NHQV76k9j9SbWmUaPhY3}/_ssgManifest.js +0 -0
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[
|
|
3
|
-
3:I[
|
|
4
|
-
4:I[
|
|
5
|
-
5:I[
|
|
6
|
-
6:I[
|
|
7
|
-
7:"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:
|
|
2
|
+
2:I[34852,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
3
|
+
3:I[86081,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
4
|
+
4:I[12527,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
5
|
+
5:I[59763,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
6
|
+
6:I[64618,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/0caq73v0knw_w.js"],"default"]
|
|
7
|
+
7:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
|
|
8
|
+
8:"$Sreact.suspense"
|
|
9
|
+
b:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
|
|
10
|
+
d:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
|
|
11
|
+
f:I[92243,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default",1]
|
|
12
|
+
:HL["/_next/static/chunks/0r-00ph4jahrl.css","style"]
|
|
12
13
|
:HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
13
|
-
0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0r-00ph4jahrl.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/064engxz5n7u9.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0ox7p_szjhn69.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_mono_8d43a2aa-module__8Li5zG__variable h-full","children":["$","body",null,{"className":"h-full flex flex-col","children":[["$","$L2",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}]]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0caq73v0knw_w.js","async":true,"nonce":"$undefined"}]],["$","$L7",null,{"children":["$","$8",null,{"name":"Next.MetadataOutlet","children":"$@9"}]}]]}],{},null,false,null]},null,false,"$@a"]},null,false,null],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$8",null,{"name":"Next.Metadata","children":"$Le"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$f",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0r-00ph4jahrl.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"2NHQV76k9j9SbWmUaPhY3"}
|
|
15
|
+
10:[]
|
|
16
|
+
a:"$W10"
|
|
17
|
+
c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
18
|
+
11:I[80070,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
|
|
19
|
+
9:null
|
|
20
|
+
e:[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L11","3",{}]]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[11717,["/_next/static/chunks/
|
|
3
|
-
3:I[11717,["/_next/static/chunks/
|
|
2
|
+
2:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
|
|
3
|
+
3:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
|
|
4
4
|
4:"$Sreact.suspense"
|
|
5
|
-
5:I[80070,["/_next/static/chunks/
|
|
6
|
-
0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"
|
|
5
|
+
5:I[80070,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
|
|
6
|
+
0:{"rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L5","3",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"2NHQV76k9j9SbWmUaPhY3"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[
|
|
3
|
-
3:I[
|
|
4
|
-
4:I[
|
|
5
|
-
:
|
|
6
|
-
|
|
2
|
+
2:I[34852,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
3
|
+
3:I[86081,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
4
|
+
4:I[12527,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
5
|
+
5:I[59763,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
6
|
+
:HL["/_next/static/chunks/0r-00ph4jahrl.css","style"]
|
|
7
|
+
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0r-00ph4jahrl.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/064engxz5n7u9.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/0ox7p_szjhn69.js","async":true}]],["$","html",null,{"lang":"en","className":"geist_mono_8d43a2aa-module__8Li5zG__variable h-full","children":["$","body",null,{"className":"h-full flex flex-col","children":[["$","$L2",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L4",null,{"parallelRouterKey":"children","template":["$","$L5",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]]}]]}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"2NHQV76k9j9SbWmUaPhY3"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
:HL["/_next/static/chunks/
|
|
1
|
+
:HL["/_next/static/chunks/0r-00ph4jahrl.css","style"]
|
|
2
2
|
:HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
3
|
-
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"setup","param":null,"prefetchHints":0,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}}}},"staleTime":300,"buildId":"
|
|
3
|
+
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"setup","param":null,"prefetchHints":0,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}}}},"staleTime":300,"buildId":"2NHQV76k9j9SbWmUaPhY3"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[64618,["/_next/static/chunks/
|
|
3
|
-
3:I[11717,["/_next/static/chunks/
|
|
2
|
+
2:I[64618,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/0caq73v0knw_w.js"],"default"]
|
|
3
|
+
3:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
|
|
4
4
|
4:"$Sreact.suspense"
|
|
5
|
-
0:{"rsc":["$","$1","c",{"children":[["$","$L2",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0caq73v0knw_w.js","async":true}]],["$","$L3",null,{"children":["$","$4",null,{"name":"Next.MetadataOutlet","children":"$@5"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"
|
|
5
|
+
0:{"rsc":["$","$1","c",{"children":[["$","$L2",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0caq73v0knw_w.js","async":true}]],["$","$L3",null,{"children":["$","$4",null,{"name":"Next.MetadataOutlet","children":"$@5"}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"2NHQV76k9j9SbWmUaPhY3"}
|
|
6
6
|
5:null
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[12527,["/_next/static/chunks/
|
|
3
|
-
3:I[59763,["/_next/static/chunks/
|
|
2
|
+
2:I[12527,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
3
|
+
3:I[59763,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
4
4
|
4:[]
|
|
5
|
-
0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"
|
|
5
|
+
0:{"rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"isPartial":false,"staleTime":300,"varyParams":"$W4","buildId":"2NHQV76k9j9SbWmUaPhY3"}
|
package/out/setup.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en" class="geist_mono_8d43a2aa-module__8Li5zG__variable h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/10b3c4k.q.yw..css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0z~0.4hivi.f2.js"/><script src="/_next/static/chunks/0ezniz80psxr6.js" async=""></script><script src="/_next/static/chunks/0r7t_sj_sejq9.js" async=""></script><script src="/_next/static/chunks/0io_y3d0p5v~b.js" async=""></script><script src="/_next/static/chunks/0excsn2a_5qsb.js" async=""></script><script src="/_next/static/chunks/turbopack-0sammtvunroor.js" async=""></script><script src="/_next/static/chunks/08fgie1bcjynm.js" async=""></script><script src="/_next/static/chunks/0ox7p_szjhn69.js" async=""></script><script src="/_next/static/chunks/0caq73v0knw_w.js" async=""></script><meta name="next-size-adjust" content=""/><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.0x3dzn~oxb6tn.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script></head><body class="h-full flex"><div hidden=""><!--$--><!--/$--></div><aside class="w-16 shrink-0 h-full border-r border-border bg-bg-surface flex flex-col items-center py-3"><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Home" href="/"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10L10 3l7 7"></path><path d="M5 8.5V16h3.5v-4h3v4H15V8.5"></path></svg></a><div class="w-6 h-px bg-border my-2"></div><div class="flex-1 flex flex-col items-center gap-2 overflow-y-auto min-h-0"><a class="w-10 h-10 flex items-center justify-center rounded-full border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] transition-colors" title="Add project" href="/setup"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 3v10M3 8h10"></path></svg></a></div><div class="w-6 h-px bg-border my-2"></div><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Settings" href="/settings"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="2.5"></circle><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 011.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 010 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 01-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 01-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 010-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 011.3-.7z"></path></svg></a></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"><div class="px-6 pt-6 pb-4 border-b border-border"><h1 class="text-lg font-semibold text-text tracking-tight">Set Up Your AI Dev Team</h1><p class="text-[11px] text-text-muted mt-1">Configure agents, connect your repo, and launch a multi-agent development workflow in minutes.</p></div><div class="flex h-[calc(100%-80px)]"><div class="flex-1 flex gap-6 p-6 overflow-y-auto"><div class="w-44 shrink-0"><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-accent text-accent bg-accent/10">1</span><div><span class="text-[11px] block leading-tight text-text font-semibold">Project Name</span><span class="text-[10px] text-text-muted block">Name your project</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">2</span><div><span class="text-[11px] block leading-tight text-text-muted">GitHub Repo</span><span class="text-[10px] text-text-muted block">Connect a repository</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">3</span><div><span class="text-[11px] block leading-tight text-text-muted">Agent Models</span><span class="text-[10px] text-text-muted block">Configure CLI backends</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">4</span><div><span class="text-[11px] block leading-tight text-text-muted">Working Directory</span><span class="text-[10px] text-text-muted block">Set the local path</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">5</span><div><span class="text-[11px] block leading-tight text-text-muted">Create Workspaces</span><span class="text-[10px] text-text-muted block">Worktrees + seed files</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">6</span><div><span class="text-[11px] block leading-tight text-text-muted">Ready to Launch</span><span class="text-[10px] text-text-muted block">Review & start</span></div></div></div><div class="flex-1 border border-border p-5 min-h-0"><div><h2 class="text-sm font-semibold text-text mb-1">Name your project</h2><p class="text-[11px] text-text-muted mb-4">This name identifies your project in the dashboard and agent configs.</p><input placeholder="e.g. My DeFi App" class="w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-4" autofocus="" value=""/><button disabled="" class="px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50">Next</button></div></div></div><div class="w-64 shrink-0 border-l border-border p-4 overflow-y-auto bg-bg-surface/50"><h3 class="text-[11px] font-semibold text-text-muted uppercase tracking-wider mb-3">Configuration Preview</h3><div class="space-y-3 text-[11px]"><div><span class="text-text-muted block mb-0.5">Project</span><span class="text-text">—</span></div><div><span class="text-text-muted block mb-0.5">Repository</span><span class="text-text">—</span></div><div><span class="text-text-muted block mb-0.5">Backends</span><div class="flex justify-between"><span class="text-text capitalize">head</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">reviewer1</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">reviewer2</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">dev</span><span class="text-accent">claude</span></div></div><div><span class="text-text-muted block mb-0.5">Directory</span><span class="text-text font-mono text-[10px]">—</span></div><div><span class="text-text-muted block mb-0.5">Status</span><div class="space-y-0.5"><div class="flex items-center gap-1.5"><span class="text-[10px] text-text">●</span><span class="text-[10px] text-text">Project Name</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">GitHub Repo</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Agent Models</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Working Directory</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Create Workspaces</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Ready to Launch</span></div></div></div></div></div></div></div><!--$--><!--/$--></main><script src="/_next/static/chunks/0z~0.4hivi.f2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[86081,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n3:I[12527,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n4:I[59763,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n5:I[64618,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\",\"/_next/static/chunks/0caq73v0knw_w.js\"],\"default\"]\n6:I[11717,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\na:I[11717,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"ViewportBoundary\"]\nc:I[11717,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"MetadataBoundary\"]\ne:I[92243,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/10b3c4k.q.yw..css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"setup\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"setup\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/10b3c4k.q.yw..css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/08fgie1bcjynm.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0ox7p_szjhn69.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"geist_mono_8d43a2aa-module__8Li5zG__variable h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"h-full flex\",\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L5\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0caq73v0knw_w.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Ld\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/10b3c4k.q.yw..css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"zx5_zAjM3qhPvkFrygZp8\"}\n"])</script><script>self.__next_f.push([1,"f:[]\n9:\"$Wf\"\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[80070,[\"/_next/static/chunks/08fgie1bcjynm.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"IconMark\"]\n8:null\nd:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0x3dzn~oxb6tn.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L10\",\"3\",{}]]\n"])</script></body></html>
|
|
1
|
+
<!DOCTYPE html><html lang="en" class="geist_mono_8d43a2aa-module__8Li5zG__variable h-full"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/0r-00ph4jahrl.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0z~0.4hivi.f2.js"/><script src="/_next/static/chunks/0ezniz80psxr6.js" async=""></script><script src="/_next/static/chunks/0r7t_sj_sejq9.js" async=""></script><script src="/_next/static/chunks/15i5_ay.0ap.6.js" async=""></script><script src="/_next/static/chunks/0excsn2a_5qsb.js" async=""></script><script src="/_next/static/chunks/turbopack-0wh29ykoy-rb5.js" async=""></script><script src="/_next/static/chunks/064engxz5n7u9.js" async=""></script><script src="/_next/static/chunks/0ox7p_szjhn69.js" async=""></script><script src="/_next/static/chunks/0caq73v0knw_w.js" async=""></script><meta name="next-size-adjust" content=""/><title>QuadWork</title><meta name="description" content="Unified dashboard for multi-agent coding teams"/><link rel="icon" href="/favicon.ico?favicon.0x3dzn~oxb6tn.ico" sizes="256x256" type="image/x-icon"/><script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script></head><body class="h-full flex flex-col"><div hidden=""><!--$--><!--/$--></div><header class="sticky top-0 z-40 flex h-12 items-center justify-between border-b border-white/10 bg-neutral-950/90 px-4 backdrop-blur"><div class="flex items-center gap-3 min-w-0"><a class="text-sm font-bold text-white hover:text-blue-400 shrink-0" href="/">QuadWork</a><span class="hidden sm:inline text-neutral-600">|</span><span class="hidden sm:inline text-[13px] text-neutral-400 truncate">Your AI dev team while you<!-- --> <span class="text-neutral-200"></span><span class="ml-0.5 inline-block w-[1px] h-[12px] align-middle bg-neutral-400 animate-qw-blink"></span></span></div><div class="flex items-center gap-3 shrink-0"><button type="button" aria-label="About QuadWork" class="rounded p-1 text-neutral-400 hover:bg-white/5 hover:text-white"><svg width="18" height="18" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="10" cy="10" r="8"></circle><path d="M10 9v5" stroke-linecap="round"></path><circle cx="10" cy="6.5" r="0.8" fill="currentColor"></circle></svg></button><a href="https://github.com/realproject7/quadwork" target="_blank" rel="noopener noreferrer" class="text-[12px] text-neutral-400 hover:text-white">QuadWork github</a></div></header><div class="flex flex-1 min-h-0"><aside class="w-16 shrink-0 h-full border-r border-border bg-bg-surface flex flex-col items-center py-3"><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Home" href="/"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 10L10 3l7 7"></path><path d="M5 8.5V16h3.5v-4h3v4H15V8.5"></path></svg></a><div class="w-6 h-px bg-border my-2"></div><div class="flex-1 flex flex-col items-center gap-2 overflow-y-auto min-h-0"><a class="w-10 h-10 flex items-center justify-center rounded-full border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] transition-colors" title="Add project" href="/setup"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M8 3v10M3 8h10"></path></svg></a></div><div class="w-6 h-px bg-border my-2"></div><a class="w-10 h-10 flex items-center justify-center rounded-sm transition-colors text-text-muted hover:text-text hover:bg-[#1a1a1a]" title="Settings" href="/settings"><svg width="18" height="18" viewBox="0 0 18 18" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="9" r="2.5"></circle><path d="M7.5 1.5h3l.4 2.1a5.5 5.5 0 011.3.7l2-.8 1.5 2.6-1.6 1.3a5.5 5.5 0 010 1.5l1.6 1.3-1.5 2.6-2-.8a5.5 5.5 0 01-1.3.7l-.4 2.1h-3l-.4-2.1a5.5 5.5 0 01-1.3-.7l-2 .8-1.5-2.6 1.6-1.3a5.5 5.5 0 010-1.5L2.3 6.1l1.5-2.6 2 .8a5.5 5.5 0 011.3-.7z"></path></svg></a></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"><div class="px-6 pt-6 pb-4 border-b border-border"><h1 class="text-lg font-semibold text-text tracking-tight">Set Up Your AI Dev Team</h1><p class="text-[11px] text-text-muted mt-1">Configure agents, connect your repo, and launch a multi-agent development workflow in minutes.</p></div><div class="flex h-[calc(100%-80px)]"><div class="flex-1 flex gap-6 p-6 overflow-y-auto"><div class="w-44 shrink-0"><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-accent text-accent bg-accent/10">1</span><div><span class="text-[11px] block leading-tight text-text font-semibold">Project Name</span><span class="text-[10px] text-text-muted block">Name your project</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">2</span><div><span class="text-[11px] block leading-tight text-text-muted">GitHub Repo</span><span class="text-[10px] text-text-muted block">Connect a repository</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">3</span><div><span class="text-[11px] block leading-tight text-text-muted">Agent Models</span><span class="text-[10px] text-text-muted block">Configure CLI backends</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">4</span><div><span class="text-[11px] block leading-tight text-text-muted">Working Directory</span><span class="text-[10px] text-text-muted block">Set the local path</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">5</span><div><span class="text-[11px] block leading-tight text-text-muted">Create Workspaces</span><span class="text-[10px] text-text-muted block">Worktrees + seed files</span></div></div><div class="flex items-start gap-2 py-2"><span class="w-5 h-5 flex items-center justify-center text-[10px] border shrink-0 mt-0.5 border-border text-text-muted">6</span><div><span class="text-[11px] block leading-tight text-text-muted">Ready to Launch</span><span class="text-[10px] text-text-muted block">Review & start</span></div></div></div><div class="flex-1 border border-border p-5 min-h-0"><div><h2 class="text-sm font-semibold text-text mb-1">Name your project</h2><p class="text-[11px] text-text-muted mb-4">This name identifies your project in the dashboard and agent configs.</p><input placeholder="e.g. My DeFi App" class="w-full bg-transparent border border-border px-2 py-1.5 text-[12px] text-text outline-none focus:border-accent mb-4" autofocus="" value=""/><button disabled="" class="px-4 py-1.5 bg-accent text-bg text-[12px] font-semibold hover:bg-accent-dim transition-colors disabled:opacity-50">Next</button></div></div></div><div class="w-64 shrink-0 border-l border-border p-4 overflow-y-auto bg-bg-surface/50"><h3 class="text-[11px] font-semibold text-text-muted uppercase tracking-wider mb-3">Configuration Preview</h3><div class="space-y-3 text-[11px]"><div><span class="text-text-muted block mb-0.5">Project</span><span class="text-text">—</span></div><div><span class="text-text-muted block mb-0.5">Repository</span><span class="text-text">—</span></div><div><span class="text-text-muted block mb-0.5">Backends</span><div class="flex justify-between"><span class="text-text capitalize">head</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">reviewer1</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">reviewer2</span><span class="text-accent">claude</span></div><div class="flex justify-between"><span class="text-text capitalize">dev</span><span class="text-accent">claude</span></div></div><div><span class="text-text-muted block mb-0.5">Directory</span><span class="text-text font-mono text-[10px]">—</span></div><div><span class="text-text-muted block mb-0.5">Status</span><div class="space-y-0.5"><div class="flex items-center gap-1.5"><span class="text-[10px] text-text">●</span><span class="text-[10px] text-text">Project Name</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">GitHub Repo</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Agent Models</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Working Directory</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Create Workspaces</span></div><div class="flex items-center gap-1.5"><span class="text-[10px] text-text-muted">○</span><span class="text-[10px] text-text-muted">Ready to Launch</span></div></div></div></div></div></div></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0z~0.4hivi.f2.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[34852,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n3:I[86081,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n4:I[12527,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n5:I[59763,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\"]\n6:I[64618,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\",\"/_next/static/chunks/0caq73v0knw_w.js\"],\"default\"]\n7:I[11717,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"OutletBoundary\"]\n8:\"$Sreact.suspense\"\nb:I[11717,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"ViewportBoundary\"]\nd:I[11717,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"MetadataBoundary\"]\nf:I[92243,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0r-00ph4jahrl.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"setup\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"setup\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0r-00ph4jahrl.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/064engxz5n7u9.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0ox7p_szjhn69.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"geist_mono_8d43a2aa-module__8Li5zG__variable h-full\",\"children\":[\"$\",\"body\",null,{\"className\":\"h-full flex flex-col\",\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L4\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L5\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L6\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0caq73v0knw_w.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L7\",null,{\"children\":[\"$\",\"$8\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@9\"}]}]]}],{},null,false,null]},null,false,\"$@a\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lb\",null,{\"children\":\"$Lc\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$8\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Le\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0r-00ph4jahrl.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"2NHQV76k9j9SbWmUaPhY3\"}\n"])</script><script>self.__next_f.push([1,"10:[]\na:\"$W10\"\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"11:I[80070,[\"/_next/static/chunks/064engxz5n7u9.js\",\"/_next/static/chunks/0ox7p_szjhn69.js\"],\"IconMark\"]\n9:null\ne:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0x3dzn~oxb6tn.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L11\",\"3\",{}]]\n"])</script></body></html>
|
package/out/setup.txt
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[
|
|
3
|
-
3:I[
|
|
4
|
-
4:I[
|
|
5
|
-
5:I[
|
|
6
|
-
6:I[
|
|
7
|
-
7:"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:
|
|
2
|
+
2:I[34852,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
3
|
+
3:I[86081,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
4
|
+
4:I[12527,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
5
|
+
5:I[59763,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default"]
|
|
6
|
+
6:I[64618,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js","/_next/static/chunks/0caq73v0knw_w.js"],"default"]
|
|
7
|
+
7:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"OutletBoundary"]
|
|
8
|
+
8:"$Sreact.suspense"
|
|
9
|
+
b:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"ViewportBoundary"]
|
|
10
|
+
d:I[11717,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"MetadataBoundary"]
|
|
11
|
+
f:I[92243,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"default",1]
|
|
12
|
+
:HL["/_next/static/chunks/0r-00ph4jahrl.css","style"]
|
|
12
13
|
:HL["/_next/static/media/797e433ab948586e-s.p.0.q-h669a_dqa.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
13
|
-
0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
0:{"P":null,"c":["","setup"],"q":"","i":false,"f":[[["",{"children":["setup",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0r-00ph4jahrl.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/064engxz5n7u9.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0ox7p_szjhn69.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"geist_mono_8d43a2aa-module__8Li5zG__variable h-full","children":["$","body",null,{"className":"h-full flex flex-col","children":[["$","$L2",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]]}]]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0caq73v0knw_w.js","async":true,"nonce":"$undefined"}]],["$","$L7",null,{"children":["$","$8",null,{"name":"Next.MetadataOutlet","children":"$@9"}]}]]}],{},null,false,null]},null,false,"$@a"]},null,false,null],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$8",null,{"name":"Next.Metadata","children":"$Le"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$f",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0r-00ph4jahrl.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"2NHQV76k9j9SbWmUaPhY3"}
|
|
15
|
+
10:[]
|
|
16
|
+
a:"$W10"
|
|
17
|
+
c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
18
|
+
11:I[80070,["/_next/static/chunks/064engxz5n7u9.js","/_next/static/chunks/0ox7p_szjhn69.js"],"IconMark"]
|
|
19
|
+
9:null
|
|
20
|
+
e:[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.0x3dzn~oxb6tn.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L11","3",{}]]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quadwork",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Unified dashboard for multi-agent coding teams — 4 AI agents, one terminal",
|
|
5
5
|
"bin": {
|
|
6
6
|
"quadwork": "./bin/quadwork.js"
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"node-pty": "^1.2.0-beta.12",
|
|
47
47
|
"react": "19.2.4",
|
|
48
48
|
"react-dom": "19.2.4",
|
|
49
|
+
"react-markdown": "^10.1.0",
|
|
49
50
|
"ws": "^8.20.0"
|
|
50
51
|
},
|
|
51
52
|
"devDependencies": {
|
package/server/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require("fs");
|
|
|
5
5
|
const { WebSocketServer } = require("ws");
|
|
6
6
|
const pty = require("node-pty");
|
|
7
7
|
const { spawn } = require("child_process");
|
|
8
|
-
const { readConfig, resolveAgentCwd, resolveAgentCommand, resolveProjectChattr, resolveChattrSpawn, syncChattrToken } = require("./config");
|
|
8
|
+
const { readConfig, resolveAgentCwd, resolveAgentCommand, resolveProjectChattr, resolveChattrSpawn, syncChattrToken, CONFIG_PATH } = require("./config");
|
|
9
9
|
const routes = require("./routes");
|
|
10
10
|
|
|
11
11
|
const net = require("net");
|
|
@@ -740,6 +740,7 @@ async function sendTriggerMessage(projectId) {
|
|
|
740
740
|
|
|
741
741
|
app.get("/api/triggers", (_req, res) => {
|
|
742
742
|
const result = {};
|
|
743
|
+
// Include active runtime triggers first.
|
|
743
744
|
for (const [id, info] of triggers) {
|
|
744
745
|
result[id] = {
|
|
745
746
|
enabled: true,
|
|
@@ -748,8 +749,41 @@ app.get("/api/triggers", (_req, res) => {
|
|
|
748
749
|
nextAt: info.nextAt,
|
|
749
750
|
lastError: info.lastError || null,
|
|
750
751
|
expiresAt: info.expiresAt || null,
|
|
752
|
+
message: null, // filled in below from config
|
|
753
|
+
intervalMin: null, // filled in below — last-used interval in minutes
|
|
754
|
+
durationMin: null, // filled in below — last-used duration in minutes
|
|
751
755
|
};
|
|
752
756
|
}
|
|
757
|
+
// Enrich with the persisted message AND last-used interval/duration
|
|
758
|
+
// for every project in config.json — even projects that don't
|
|
759
|
+
// currently have a running trigger. The Scheduled Trigger widget
|
|
760
|
+
// (#210) hydrates all three controls from this on page reload.
|
|
761
|
+
try {
|
|
762
|
+
const cfg = readConfig();
|
|
763
|
+
for (const p of (cfg.projects || [])) {
|
|
764
|
+
const msg = typeof p.trigger_message === "string" ? p.trigger_message : null;
|
|
765
|
+
const intervalMin = Number.isFinite(p.trigger_interval_min) ? p.trigger_interval_min : null;
|
|
766
|
+
const durationMin = Number.isFinite(p.trigger_duration_min) ? p.trigger_duration_min : null;
|
|
767
|
+
const existing = result[p.id];
|
|
768
|
+
if (existing) {
|
|
769
|
+
existing.message = msg;
|
|
770
|
+
existing.intervalMin = intervalMin;
|
|
771
|
+
existing.durationMin = durationMin;
|
|
772
|
+
} else if (msg !== null || intervalMin !== null || durationMin !== null) {
|
|
773
|
+
result[p.id] = {
|
|
774
|
+
enabled: false,
|
|
775
|
+
interval: intervalMin !== null ? intervalMin * 60 * 1000 : 0,
|
|
776
|
+
lastSent: null,
|
|
777
|
+
nextAt: null,
|
|
778
|
+
lastError: null,
|
|
779
|
+
expiresAt: null,
|
|
780
|
+
message: msg,
|
|
781
|
+
intervalMin,
|
|
782
|
+
durationMin,
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
} catch { /* non-fatal */ }
|
|
753
787
|
res.json(result);
|
|
754
788
|
});
|
|
755
789
|
|
|
@@ -764,16 +798,43 @@ function stopTrigger(project) {
|
|
|
764
798
|
|
|
765
799
|
app.post("/api/triggers/:project/start", (req, res) => {
|
|
766
800
|
const { project } = req.params;
|
|
767
|
-
const { interval, duration } = req.body || {};
|
|
801
|
+
const { interval, duration, message, sendImmediately } = req.body || {};
|
|
768
802
|
const ms = (interval || 30) * 60 * 1000;
|
|
769
803
|
const durationMs = duration ? duration * 60 * 1000 : 0; // duration in minutes, 0 = indefinite
|
|
770
804
|
|
|
805
|
+
// #210: persist the custom message AND the last-used interval +
|
|
806
|
+
// duration on the project entry so reopening an idle project
|
|
807
|
+
// pre-fills all three controls from the saved state (not just the
|
|
808
|
+
// message). Without persisting interval/duration, the widget
|
|
809
|
+
// would snap back to its defaults (15 min / 3 hr) after every
|
|
810
|
+
// reload even if the operator had picked something else.
|
|
811
|
+
try {
|
|
812
|
+
const cfg = readConfig();
|
|
813
|
+
const entry = (cfg.projects || []).find((p) => p.id === project);
|
|
814
|
+
if (entry) {
|
|
815
|
+
if (typeof message === "string" && message.length > 0) entry.trigger_message = message;
|
|
816
|
+
if (Number.isFinite(interval) && interval > 0) entry.trigger_interval_min = interval;
|
|
817
|
+
if (Number.isFinite(duration) && duration >= 0) entry.trigger_duration_min = duration;
|
|
818
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
819
|
+
}
|
|
820
|
+
} catch (e) { /* non-fatal — timer still runs with its in-memory values */ }
|
|
821
|
+
|
|
771
822
|
const existing = triggers.get(project);
|
|
772
823
|
if (existing) {
|
|
773
824
|
if (existing.timer) clearInterval(existing.timer);
|
|
774
825
|
if (existing.durationTimer) clearTimeout(existing.durationTimer);
|
|
775
826
|
}
|
|
776
827
|
|
|
828
|
+
// #210: the Scheduled Trigger widget's "Send Message and Start
|
|
829
|
+
// Trigger" button expects an immediate send, not the first fire
|
|
830
|
+
// one interval in the future. setInterval won't do that on its
|
|
831
|
+
// own, so trigger a one-shot send when sendImmediately is true.
|
|
832
|
+
if (sendImmediately) {
|
|
833
|
+
// Don't await — keep the response fast. sendTriggerMessage logs
|
|
834
|
+
// its own errors and updates lastError on the trigger info.
|
|
835
|
+
sendTriggerMessage(project).catch(() => {});
|
|
836
|
+
}
|
|
837
|
+
|
|
777
838
|
const timer = setInterval(() => sendTriggerMessage(project), ms);
|
|
778
839
|
const expiresAt = durationMs > 0 ? Date.now() + durationMs : null;
|
|
779
840
|
|
|
@@ -818,6 +879,61 @@ app.post("/api/triggers/sync", (_req, res) => {
|
|
|
818
879
|
// Expose syncTriggers for migrated routes (config PUT, rename)
|
|
819
880
|
app.set("syncTriggers", syncTriggersFromConfig);
|
|
820
881
|
|
|
882
|
+
// --- OVERNIGHT-QUEUE.md viewer/editor (#209) ---------------------------------
|
|
883
|
+
// Read/write the per-project ~/.quadwork/{id}/OVERNIGHT-QUEUE.md file from
|
|
884
|
+
// the operator panel. The id must resolve to a project already saved in
|
|
885
|
+
// config.json — we never touch an arbitrary path on disk.
|
|
886
|
+
function resolveQueueProject(projectId) {
|
|
887
|
+
if (!projectId || typeof projectId !== "string") return null;
|
|
888
|
+
if (projectId.includes("/") || projectId.includes("\\") || projectId.includes("..")) return null;
|
|
889
|
+
const cfg = readConfig();
|
|
890
|
+
return (cfg.projects || []).find((p) => p.id === projectId) || null;
|
|
891
|
+
}
|
|
892
|
+
function queuePathFor(projectId) {
|
|
893
|
+
return path.join(os.homedir(), ".quadwork", projectId, "OVERNIGHT-QUEUE.md");
|
|
894
|
+
}
|
|
895
|
+
const OVERNIGHT_TEMPLATES_DIR = path.resolve(__dirname, "..", "templates");
|
|
896
|
+
|
|
897
|
+
app.get("/api/queue", (req, res) => {
|
|
898
|
+
const projectId = String(req.query.project || "");
|
|
899
|
+
if (!resolveQueueProject(projectId)) return res.status(404).json({ error: "Unknown project" });
|
|
900
|
+
const p = queuePathFor(projectId);
|
|
901
|
+
if (!fs.existsSync(p)) return res.json({ ok: true, exists: false, content: "" });
|
|
902
|
+
try { return res.json({ ok: true, exists: true, content: fs.readFileSync(p, "utf-8") }); }
|
|
903
|
+
catch (e) { return res.status(500).json({ error: e.message }); }
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
app.put("/api/queue", express.json({ limit: "512kb" }), (req, res) => {
|
|
907
|
+
const projectId = String(req.query.project || "");
|
|
908
|
+
if (!resolveQueueProject(projectId)) return res.status(404).json({ error: "Unknown project" });
|
|
909
|
+
const content = typeof req.body?.content === "string" ? req.body.content : null;
|
|
910
|
+
if (content === null) return res.status(400).json({ error: "Missing content" });
|
|
911
|
+
const p = queuePathFor(projectId);
|
|
912
|
+
try {
|
|
913
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
914
|
+
fs.writeFileSync(p, content);
|
|
915
|
+
return res.json({ ok: true });
|
|
916
|
+
} catch (e) { return res.status(500).json({ error: e.message }); }
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
app.post("/api/queue", (req, res) => {
|
|
920
|
+
const projectId = String(req.query.project || "");
|
|
921
|
+
const project = resolveQueueProject(projectId);
|
|
922
|
+
if (!project) return res.status(404).json({ error: "Unknown project" });
|
|
923
|
+
const p = queuePathFor(projectId);
|
|
924
|
+
if (fs.existsSync(p)) return res.json({ ok: true, existed: true });
|
|
925
|
+
const tpl = path.join(OVERNIGHT_TEMPLATES_DIR, "OVERNIGHT-QUEUE.md");
|
|
926
|
+
if (!fs.existsSync(tpl)) return res.status(500).json({ error: "Template missing" });
|
|
927
|
+
try {
|
|
928
|
+
let content = fs.readFileSync(tpl, "utf-8");
|
|
929
|
+
content = content.replace(/\{\{project_name\}\}/g, project.name || projectId);
|
|
930
|
+
content = content.replace(/\{\{repo\}\}/g, project.repo || "");
|
|
931
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
932
|
+
fs.writeFileSync(p, content);
|
|
933
|
+
return res.json({ ok: true, existed: false });
|
|
934
|
+
} catch (e) { return res.status(500).json({ error: e.message }); }
|
|
935
|
+
});
|
|
936
|
+
|
|
821
937
|
// --- Serve static frontend (built Next.js export) ---
|
|
822
938
|
|
|
823
939
|
// Strip trailing slashes (redirect /settings/ → /settings, /setup/ → /setup)
|
|
@@ -997,3 +1113,24 @@ server.listen(PORT, "127.0.0.1", () => {
|
|
|
997
1113
|
syncChattrToken(p.id);
|
|
998
1114
|
}
|
|
999
1115
|
});
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Send SIGTERM to every AgentChattr child currently tracked by the
|
|
1119
|
+
* server. Exported so bin/quadwork.js (`cmdInit` / `cmdStart`) can
|
|
1120
|
+
* call it from its own SIGINT handler — AgentChattr children spawned
|
|
1121
|
+
* by the dashboard's /api/agentchattr/{id}/start endpoint live in
|
|
1122
|
+
* this process's in-memory `chattrProcesses` Map and are otherwise
|
|
1123
|
+
* invisible to the CLI. Without this, a Ctrl+C in the foreground
|
|
1124
|
+
* quadwork terminal would exit the Node process and orphan every
|
|
1125
|
+
* dashboard-started python run.py. See review on quadwork#213.
|
|
1126
|
+
*/
|
|
1127
|
+
function shutdownChattrProcesses() {
|
|
1128
|
+
for (const [, proc] of chattrProcesses) {
|
|
1129
|
+
if (proc && proc.process) {
|
|
1130
|
+
try { proc.process.kill("SIGTERM"); } catch {}
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
chattrProcesses.clear();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
module.exports = { shutdownChattrProcesses };
|