quadwork 1.19.3 → 2.0.1

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 (118) hide show
  1. package/README.md +19 -35
  2. package/bin/quadwork.js +48 -1118
  3. package/out/404.html +1 -1
  4. package/out/__next.__PAGE__.txt +3 -3
  5. package/out/__next._full.txt +14 -14
  6. package/out/__next._head.txt +4 -4
  7. package/out/__next._index.txt +8 -8
  8. package/out/__next._tree.txt +2 -2
  9. package/out/_next/static/chunks/{030cjkhts487t.js → 079wdniva~de1.js} +1 -1
  10. package/out/_next/static/chunks/{0n~dq4kpx9xxx.js → 07lhk_q6pmm3r.js} +1 -1
  11. package/out/_next/static/chunks/0_79hkefw1mo2.js +1 -0
  12. package/out/_next/static/chunks/{08tog0xc~.es_.js → 0jllnzexn48._.js} +1 -1
  13. package/out/_next/static/chunks/0oxv9vrvc17to.js +2 -0
  14. package/out/_next/static/chunks/0py7102i226n5.js +1 -0
  15. package/out/_next/static/chunks/{13fv-yi7.v52g.js → 0q4bm04c1jl_3.js} +1 -1
  16. package/out/_next/static/chunks/{0_idxioyl0p7h.js → 0sjhy6oe3mbon.js} +1 -1
  17. package/out/_next/static/chunks/{11khe5i7gu158.js → 0z.9wnba-t6z8.js} +1 -1
  18. package/out/_next/static/chunks/13xk0vgfbrcld.css +2 -0
  19. package/out/_next/static/chunks/163_ddkdca5q4.js +25 -0
  20. package/out/_next/static/chunks/{turbopack-0qm-e3ifrz~2u.js → turbopack-0y2u-q0l2m67w.js} +1 -1
  21. package/out/_not-found/__next._full.txt +13 -13
  22. package/out/_not-found/__next._head.txt +4 -4
  23. package/out/_not-found/__next._index.txt +8 -8
  24. package/out/_not-found/__next._not-found.__PAGE__.txt +2 -2
  25. package/out/_not-found/__next._not-found.txt +3 -3
  26. package/out/_not-found/__next._tree.txt +2 -2
  27. package/out/_not-found.html +1 -1
  28. package/out/_not-found.txt +13 -13
  29. package/out/app-shell/__next._full.txt +13 -13
  30. package/out/app-shell/__next._head.txt +4 -4
  31. package/out/app-shell/__next._index.txt +8 -8
  32. package/out/app-shell/__next._tree.txt +2 -2
  33. package/out/app-shell/__next.app-shell.__PAGE__.txt +2 -2
  34. package/out/app-shell/__next.app-shell.txt +3 -3
  35. package/out/app-shell.html +1 -1
  36. package/out/app-shell.txt +13 -13
  37. package/out/index.html +1 -1
  38. package/out/index.txt +14 -14
  39. package/out/project/_/__next._full.txt +14 -14
  40. package/out/project/_/__next._head.txt +4 -4
  41. package/out/project/_/__next._index.txt +8 -8
  42. package/out/project/_/__next._tree.txt +2 -2
  43. package/out/project/_/__next.project.$d$id.__PAGE__.txt +3 -3
  44. package/out/project/_/__next.project.$d$id.txt +3 -3
  45. package/out/project/_/__next.project.txt +3 -3
  46. package/out/project/_/queue/__next._full.txt +14 -14
  47. package/out/project/_/queue/__next._head.txt +4 -4
  48. package/out/project/_/queue/__next._index.txt +8 -8
  49. package/out/project/_/queue/__next._tree.txt +2 -2
  50. package/out/project/_/queue/__next.project.$d$id.queue.__PAGE__.txt +3 -3
  51. package/out/project/_/queue/__next.project.$d$id.queue.txt +3 -3
  52. package/out/project/_/queue/__next.project.$d$id.txt +3 -3
  53. package/out/project/_/queue/__next.project.txt +3 -3
  54. package/out/project/_/queue.html +1 -1
  55. package/out/project/_/queue.txt +14 -14
  56. package/out/project/_.html +1 -1
  57. package/out/project/_.txt +14 -14
  58. package/out/settings/__next._full.txt +14 -14
  59. package/out/settings/__next._head.txt +4 -4
  60. package/out/settings/__next._index.txt +8 -8
  61. package/out/settings/__next._tree.txt +2 -2
  62. package/out/settings/__next.settings.__PAGE__.txt +3 -3
  63. package/out/settings/__next.settings.txt +3 -3
  64. package/out/settings.html +1 -1
  65. package/out/settings.txt +14 -14
  66. package/out/setup/__next._full.txt +14 -14
  67. package/out/setup/__next._head.txt +4 -4
  68. package/out/setup/__next._index.txt +8 -8
  69. package/out/setup/__next._tree.txt +2 -2
  70. package/out/setup/__next.setup.__PAGE__.txt +3 -3
  71. package/out/setup/__next.setup.txt +3 -3
  72. package/out/setup.html +1 -1
  73. package/out/setup.txt +14 -14
  74. package/package.json +4 -2
  75. package/server/ac-restore.js +128 -0
  76. package/server/bridges/discord.js +244 -0
  77. package/server/bridges/telegram.js +258 -0
  78. package/server/config.js +4 -60
  79. package/server/file-chat.js +318 -0
  80. package/server/index.js +129 -1294
  81. package/server/install-agentchattr.js +3 -284
  82. package/server/mcp-chat-shim.js +171 -0
  83. package/server/migrate-ac.js +158 -0
  84. package/server/pty-dispatcher.js +188 -0
  85. package/server/routes.js +155 -1398
  86. package/templates/CLAUDE.md +2 -2
  87. package/templates/OVERNIGHT-QUEUE.md +1 -1
  88. package/templates/seeds/butler.CLAUDE.md +30 -62
  89. package/templates/seeds/dev.AGENTS.md +10 -1
  90. package/templates/seeds/head.AGENTS.md +12 -8
  91. package/templates/seeds/re1.AGENTS.md +3 -3
  92. package/templates/seeds/re2.AGENTS.md +3 -3
  93. package/bridges/discord/__pycache__/discord_bridge.cpython-314.pyc +0 -0
  94. package/bridges/discord/discord_bridge.py +0 -666
  95. package/bridges/discord/requirements.txt +0 -2
  96. package/out/_next/static/chunks/08kw.2kplxa.6.css +0 -2
  97. package/out/_next/static/chunks/0_nm7se0m3twm.js +0 -25
  98. package/out/_next/static/chunks/0uz5svjlo9dwl.js +0 -1
  99. package/out/_next/static/chunks/0zahstmgdrpy5.js +0 -1
  100. package/out/_next/static/chunks/0zfotsowwll1x.js +0 -2
  101. package/server/__tests__/bridge-auto-stop-guard.test.js +0 -134
  102. package/server/__tests__/rate-limit-handling.test.js +0 -168
  103. package/server/__tests__/scrub-secrets.test.js +0 -235
  104. package/server/__tests__/v1110-security-qa.test.js +0 -312
  105. package/server/agentchattr-registry.js +0 -188
  106. package/server/install-agentchattr.patchCrashTimeout.test.js +0 -71
  107. package/server/queue-watcher.js +0 -171
  108. package/server/queue-watcher.test.js +0 -64
  109. package/server/routes.batchProgress.test.js +0 -94
  110. package/server/routes.chatWsSend.test.js +0 -161
  111. package/server/routes.discordBridge.test.js +0 -80
  112. package/server/routes.parseActiveBatch.test.js +0 -88
  113. package/server/routes.telegramBridge.test.js +0 -241
  114. package/templates/config.toml +0 -72
  115. package/templates/wrapper.py +0 -70
  116. /package/out/_next/static/{D66Um4H226QD5y4w5xTKq → MmPC1Rj12BOy4-HvMJjEX}/_buildManifest.js +0 -0
  117. /package/out/_next/static/{D66Um4H226QD5y4w5xTKq → MmPC1Rj12BOy4-HvMJjEX}/_clientMiddlewareManifest.js +0 -0
  118. /package/out/_next/static/{D66Um4H226QD5y4w5xTKq → MmPC1Rj12BOy4-HvMJjEX}/_ssgManifest.js +0 -0
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.09zddjkbdep5a.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/08kw.2kplxa.6.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0ze4gu236oq96.js"/><script src="/_next/static/chunks/0.bbxho1vnxin.js" async=""></script><script src="/_next/static/chunks/0n~dq4kpx9xxx.js" async=""></script><script src="/_next/static/chunks/0zfotsowwll1x.js" async=""></script><script src="/_next/static/chunks/0pqt~8bl3ukh4.js" async=""></script><script src="/_next/static/chunks/turbopack-0qm-e3ifrz~2u.js" async=""></script><script src="/_next/static/chunks/13fv-yi7.v52g.js" async=""></script><script src="/_next/static/chunks/0d3shmwh5_nmn.js" async=""></script><script src="/_next/static/chunks/0uz5svjlo9dwl.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.05o2q2p4kvnq_.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" aria-hidden="true"></header><div class="flex flex-1 min-h-0"><button type="button" class="fixed top-14 left-2 z-30 lg:hidden w-10 h-10 flex items-center justify-center bg-bg-surface border border-border text-text-muted hover:text-accent"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M3 5h14M3 10h14M3 15h14"></path></svg></button><aside class="fixed inset-y-0 left-0 z-50 w-52 bg-bg-surface border-r border-border flex flex-col py-3 px-2 items-stretch overflow-y-auto transition-transform duration-200 ease-in-out lg:hidden -translate-x-full"><button type="button" class="self-end shrink-0 w-10 h-10 flex items-center justify-center text-text-muted hover:text-accent mb-1"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M5 5l10 10M15 5L5 15"></path></svg></button><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Home</span></a><div class="h-px bg-border my-2 "></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 "><a class="flex items-center gap-2 rounded-full transition-colors px-2 py-2 border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] rounded-sm" 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><span class="text-xs text-text-muted">New Project</span></a></div><div class="h-px bg-border my-2 "></div><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Settings</span></a></aside><aside class="hidden lg:flex shrink-0 h-full border-r border-border bg-bg-surface flex-col py-3 transition-[width] duration-200 ease-in-out overflow-hidden w-16 items-center"><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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="h-px bg-border my-2 w-6 self-center"></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 items-center"><a class="flex items-center gap-2 rounded-full transition-colors w-10 h-10 justify-center border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a]" 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="h-px bg-border my-2 w-6 self-center"></div><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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><div class="h-1"></div><button class="flex shrink-0 items-center justify-center w-10 h-10 rounded-sm border border-border text-text-muted hover:text-accent hover:border-accent/50 transition-colors self-center" title="Expand sidebar"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3l5 5-5 5"></path></svg></button></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0ze4gu236oq96.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[52368,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"LocaleProvider\"]\n3:I[43688,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n4:I[26704,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n5:I[22140,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n6:I[39756,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n8:I[94810,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0uz5svjlo9dwl.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\na:\"$Sreact.suspense\"\nd:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\n11:I[68027,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/08kw.2kplxa.6.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.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/08kw.2kplxa.6.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/13fv-yi7.v52g.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0d3shmwh5_nmn.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,{\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",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,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L8\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0uz5svjlo9dwl.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@b\"}]}]]}],{},null,false,null]},null,false,\"$@c\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L10\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/08kw.2kplxa.6.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"D66Um4H226QD5y4w5xTKq\"}\n"])</script><script>self.__next_f.push([1,"12:[]\nc:\"$W12\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/13fv-yi7.v52g.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\nb:null\n10:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.05o2q2p4kvnq_.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"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.09zddjkbdep5a.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/chunks/13xk0vgfbrcld.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0ze4gu236oq96.js"/><script src="/_next/static/chunks/0.bbxho1vnxin.js" async=""></script><script src="/_next/static/chunks/07lhk_q6pmm3r.js" async=""></script><script src="/_next/static/chunks/0oxv9vrvc17to.js" async=""></script><script src="/_next/static/chunks/0pqt~8bl3ukh4.js" async=""></script><script src="/_next/static/chunks/turbopack-0y2u-q0l2m67w.js" async=""></script><script src="/_next/static/chunks/0q4bm04c1jl_3.js" async=""></script><script src="/_next/static/chunks/0d3shmwh5_nmn.js" async=""></script><script src="/_next/static/chunks/0py7102i226n5.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.05o2q2p4kvnq_.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" aria-hidden="true"></header><div class="flex flex-1 min-h-0"><button type="button" class="fixed top-14 left-2 z-30 lg:hidden w-10 h-10 flex items-center justify-center bg-bg-surface border border-border text-text-muted hover:text-accent"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M3 5h14M3 10h14M3 15h14"></path></svg></button><aside class="fixed inset-y-0 left-0 z-50 w-52 bg-bg-surface border-r border-border flex flex-col py-3 px-2 items-stretch overflow-y-auto transition-transform duration-200 ease-in-out lg:hidden -translate-x-full"><button type="button" class="self-end shrink-0 w-10 h-10 flex items-center justify-center text-text-muted hover:text-accent mb-1"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M5 5l10 10M15 5L5 15"></path></svg></button><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Home</span></a><div class="h-px bg-border my-2 "></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 "><a class="flex items-center gap-2 rounded-full transition-colors px-2 py-2 border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a] rounded-sm" 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><span class="text-xs text-text-muted">New Project</span></a></div><div class="h-px bg-border my-2 "></div><a class="flex items-center gap-2 rounded-sm transition-colors px-2 py-2 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><span class="text-xs">Settings</span></a></aside><aside class="hidden lg:flex shrink-0 h-full border-r border-border bg-bg-surface flex-col py-3 transition-[width] duration-200 ease-in-out overflow-hidden w-16 items-center"><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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="h-px bg-border my-2 w-6 self-center"></div><div class="flex-1 flex flex-col gap-2 overflow-y-auto min-h-0 items-center"><a class="flex items-center gap-2 rounded-full transition-colors w-10 h-10 justify-center border border-dashed border-border text-text-muted hover:text-text hover:bg-[#1a1a1a]" 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="h-px bg-border my-2 w-6 self-center"></div><a class="flex items-center gap-2 rounded-sm transition-colors w-10 h-10 justify-center self-center 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><div class="h-1"></div><button class="flex shrink-0 items-center justify-center w-10 h-10 rounded-sm border border-border text-text-muted hover:text-accent hover:border-accent/50 transition-colors self-center" title="Expand sidebar"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 3l5 5-5 5"></path></svg></button></aside><main class="flex-1 min-w-0 overflow-auto"><div class="h-full overflow-y-auto"></div><!--$--><!--/$--></main></div><script src="/_next/static/chunks/0ze4gu236oq96.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[52368,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"LocaleProvider\"]\n3:I[43688,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n4:I[26704,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n5:I[22140,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n6:I[39756,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\"]\n8:I[94810,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\",\"/_next/static/chunks/0py7102i226n5.js\"],\"default\"]\n9:I[97367,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"OutletBoundary\"]\na:\"$Sreact.suspense\"\nd:I[97367,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"ViewportBoundary\"]\nf:I[97367,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"MetadataBoundary\"]\n11:I[68027,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/13xk0vgfbrcld.css\",\"style\"]\n:HL[\"/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.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/13xk0vgfbrcld.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/0d3shmwh5_nmn.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,{\"children\":[[\"$\",\"$L3\",null,{}],[\"$\",\"$L4\",null,{}],[\"$\",\"div\",null,{\"className\":\"flex flex-1 min-h-0\",\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"main\",null,{\"className\":\"flex-1 min-w-0 overflow-auto\",\"children\":[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",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,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L8\",null,{}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0py7102i226n5.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@b\"}]}]]}],{},null,false,null]},null,false,\"$@c\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"$a\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L10\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/13xk0vgfbrcld.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"MmPC1Rj12BOy4-HvMJjEX\"}\n"])</script><script>self.__next_f.push([1,"12:[]\nc:\"$W12\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"13:I[27201,[\"/_next/static/chunks/0q4bm04c1jl_3.js\",\"/_next/static/chunks/0d3shmwh5_nmn.js\"],\"IconMark\"]\nb:null\n10:[[\"$\",\"title\",\"0\",{\"children\":\"QuadWork\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Unified dashboard for multi-agent coding teams\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.05o2q2p4kvnq_.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L13\",\"3\",{}]]\n"])</script></body></html>
package/out/setup.txt CHANGED
@@ -1,22 +1,22 @@
1
1
  1:"$Sreact.fragment"
2
- 2:I[52368,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"LocaleProvider"]
3
- 3:I[43688,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
4
- 4:I[26704,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
5
- 5:I[22140,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
6
- 6:I[39756,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
7
- 7:I[37457,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
8
- 8:I[94810,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js","/_next/static/chunks/0uz5svjlo9dwl.js"],"default"]
9
- 9:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"OutletBoundary"]
2
+ 2:I[52368,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"LocaleProvider"]
3
+ 3:I[43688,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
4
+ 4:I[26704,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
5
+ 5:I[22140,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
6
+ 6:I[39756,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
7
+ 7:I[37457,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default"]
8
+ 8:I[94810,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js","/_next/static/chunks/0py7102i226n5.js"],"default"]
9
+ 9:I[97367,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"OutletBoundary"]
10
10
  a:"$Sreact.suspense"
11
- d:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"ViewportBoundary"]
12
- f:I[97367,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"MetadataBoundary"]
13
- 11:I[68027,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default",1]
14
- :HL["/_next/static/chunks/08kw.2kplxa.6.css","style"]
11
+ d:I[97367,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"ViewportBoundary"]
12
+ f:I[97367,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"MetadataBoundary"]
13
+ 11:I[68027,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"default",1]
14
+ :HL["/_next/static/chunks/13xk0vgfbrcld.css","style"]
15
15
  :HL["/_next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
16
- 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/08kw.2kplxa.6.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/13fv-yi7.v52g.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0d3shmwh5_nmn.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,{"children":[["$","$L3",null,{}],["$","$L4",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L5",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",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,["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0uz5svjlo9dwl.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,null]},null,false,"$@c"]},null,false,null],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/08kw.2kplxa.6.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"D66Um4H226QD5y4w5xTKq"}
16
+ 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/13xk0vgfbrcld.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0q4bm04c1jl_3.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0d3shmwh5_nmn.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,{"children":[["$","$L3",null,{}],["$","$L4",null,{}],["$","div",null,{"className":"flex flex-1 min-h-0","children":[["$","$L5",null,{}],["$","main",null,{"className":"flex-1 min-w-0 overflow-auto","children":["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",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,["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{}],[["$","script","script-0",{"src":"/_next/static/chunks/0py7102i226n5.js","async":true,"nonce":"$undefined"}]],["$","$L9",null,{"children":["$","$a",null,{"name":"Next.MetadataOutlet","children":"$@b"}]}]]}],{},null,false,null]},null,false,"$@c"]},null,false,null],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$a",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/13xk0vgfbrcld.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"MmPC1Rj12BOy4-HvMJjEX"}
17
17
  12:[]
18
18
  c:"$W12"
19
19
  e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
20
- 13:I[27201,["/_next/static/chunks/13fv-yi7.v52g.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"IconMark"]
20
+ 13:I[27201,["/_next/static/chunks/0q4bm04c1jl_3.js","/_next/static/chunks/0d3shmwh5_nmn.js"],"IconMark"]
21
21
  b:null
22
22
  10:[["$","title","0",{"children":"QuadWork"}],["$","meta","1",{"name":"description","content":"Unified dashboard for multi-agent coding teams"}],["$","link","2",{"rel":"icon","href":"/favicon.ico?favicon.05o2q2p4kvnq_.ico","sizes":"256x256","type":"image/x-icon"}],["$","$L13","3",{}]]
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "quadwork",
3
- "version": "1.19.3",
3
+ "version": "2.0.1",
4
4
  "description": "Unified dashboard for multi-agent coding teams — 4 AI agents, one terminal",
5
5
  "bin": {
6
6
  "quadwork": "./bin/quadwork.js"
7
7
  },
8
8
  "files": [
9
9
  "bin/",
10
- "bridges/",
11
10
  "server/",
11
+ "!server/**/*.test.js",
12
+ "!server/__tests__/",
12
13
  "templates/",
13
14
  "out/"
14
15
  ],
@@ -43,6 +44,7 @@
43
44
  },
44
45
  "license": "MIT",
45
46
  "dependencies": {
47
+ "discord.js": "^14.18.0",
46
48
  "express": "^5.2.1",
47
49
  "multer": "^2.1.1",
48
50
  "node-pty": "^1.2.0-beta.12",
@@ -0,0 +1,128 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const os = require("os");
4
+ const crypto = require("crypto");
5
+ const { ensureSecureDir } = require("./config");
6
+
7
+ function convertToAcFormat(record) {
8
+ const acRecord = {
9
+ ...(record._legacy || {}),
10
+ id: record.id,
11
+ sender: record.sender,
12
+ text: record.text,
13
+ channel: record.channel,
14
+ timestamp: record.ts,
15
+ type: record.type,
16
+ _quadwork_restored_id: record.id,
17
+ };
18
+ return acRecord;
19
+ }
20
+
21
+ function normalizeTs(ts) {
22
+ if (typeof ts === "number") return new Date(ts * 1000).toISOString();
23
+ return String(ts || "");
24
+ }
25
+
26
+ function contentHash(record) {
27
+ const key = `${normalizeTs(record.ts)}|${record.sender}|${record.channel}|${record.text}`;
28
+ return crypto.createHash("sha1").update(key).digest("hex");
29
+ }
30
+
31
+ function restoreProject(projectId) {
32
+ const chatFile = path.join(os.homedir(), ".quadwork", projectId, "chat", "general.jsonl");
33
+ if (!fs.existsSync(chatFile)) return null;
34
+
35
+ const acDataDir = path.join(os.homedir(), ".quadwork", projectId, "agentchattr", "data");
36
+ const acLogPath = path.join(acDataDir, "agentchattr_log.jsonl");
37
+
38
+ const existingHashes = new Set();
39
+ const existingRestoredIds = new Set();
40
+ if (fs.existsSync(acLogPath)) {
41
+ const existing = fs.readFileSync(acLogPath, "utf-8");
42
+ for (const line of existing.split("\n")) {
43
+ if (!line.trim()) continue;
44
+ try {
45
+ const rec = JSON.parse(line);
46
+ existingHashes.add(contentHash({
47
+ ts: rec.timestamp,
48
+ sender: rec.sender,
49
+ channel: rec.channel,
50
+ text: rec.text,
51
+ }));
52
+ if (rec._quadwork_restored_id !== undefined) {
53
+ existingRestoredIds.add(rec._quadwork_restored_id);
54
+ }
55
+ } catch {}
56
+ }
57
+ }
58
+
59
+ const content = fs.readFileSync(chatFile, "utf-8");
60
+ const lines = content.split("\n");
61
+ const toAppend = [];
62
+ let skipped = 0;
63
+
64
+ for (const line of lines) {
65
+ if (!line.trim()) continue;
66
+ let record;
67
+ try {
68
+ record = JSON.parse(line);
69
+ } catch {
70
+ skipped++;
71
+ continue;
72
+ }
73
+
74
+ if (record.type === "system" && record.sender === "system" &&
75
+ record.text && record.text.startsWith("Chat history migrated from AC")) {
76
+ skipped++;
77
+ continue;
78
+ }
79
+
80
+ if (existingRestoredIds.has(record.id)) {
81
+ skipped++;
82
+ continue;
83
+ }
84
+
85
+ const acRecord = convertToAcFormat(record);
86
+ const hash = contentHash({
87
+ ts: acRecord.timestamp,
88
+ sender: acRecord.sender,
89
+ channel: acRecord.channel,
90
+ text: acRecord.text,
91
+ });
92
+ if (existingHashes.has(hash)) {
93
+ skipped++;
94
+ continue;
95
+ }
96
+
97
+ toAppend.push(acRecord);
98
+ existingHashes.add(hash);
99
+ }
100
+
101
+ if (toAppend.length === 0) {
102
+ console.log(`[ac-restore] ${projectId}: no new messages to restore (${skipped} skipped)`);
103
+ return { restored: 0, skipped };
104
+ }
105
+
106
+ ensureSecureDir(acDataDir);
107
+ const output = toAppend.map((r) => JSON.stringify(r)).join("\n") + "\n";
108
+ fs.appendFileSync(acLogPath, output, { mode: 0o600 });
109
+ try { fs.chmodSync(acLogPath, 0o600); } catch {}
110
+
111
+ console.log(`[ac-restore] ${projectId}: restored ${toAppend.length} messages, ${skipped} skipped`);
112
+ return { restored: toAppend.length, skipped };
113
+ }
114
+
115
+ function runAcRestore(config, projectFilter) {
116
+ const projects = config.projects || [];
117
+ for (const project of projects) {
118
+ if (!project || !project.id) continue;
119
+ if (projectFilter && project.id !== projectFilter) continue;
120
+ try {
121
+ restoreProject(project.id);
122
+ } catch (err) {
123
+ console.error(`[ac-restore] ${project.id}: failed — ${err.message}`);
124
+ }
125
+ }
126
+ }
127
+
128
+ module.exports = { runAcRestore, restoreProject, convertToAcFormat, contentHash };
@@ -0,0 +1,244 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const os = require("os");
4
+
5
+ const CONFIG_DIR = path.join(os.homedir(), ".quadwork");
6
+
7
+ const instances = new Map();
8
+
9
+ // #782: cursor-lag threshold beyond which a valid cursor is treated as
10
+ // stale (bridge stopped mid-backlog) and reseeded to latest on start.
11
+ // Small lags within this window keep continuity for graceful restarts.
12
+ //
13
+ // #786: intentional trade-off — if the bridge was down while 11+ messages
14
+ // arrived, those messages are skipped (not replayed to Discord). This
15
+ // prevents the "old message flood" bug. If continuity is needed for long
16
+ // downtimes, increase this threshold or remove the stale-cursor check.
17
+ const STALE_CURSOR_THRESHOLD = 10;
18
+
19
+ function cursorPath(projectId) {
20
+ return path.join(CONFIG_DIR, `dc-bridge-cursor-${projectId}.json`);
21
+ }
22
+
23
+ function readCursor(projectId) {
24
+ try {
25
+ const data = JSON.parse(fs.readFileSync(cursorPath(projectId), "utf-8"));
26
+ return data.last_seen_id || 0;
27
+ } catch {
28
+ return 0;
29
+ }
30
+ }
31
+
32
+ function writeCursor(projectId, sinceId) {
33
+ try {
34
+ fs.writeFileSync(cursorPath(projectId), JSON.stringify({ last_seen_id: sinceId }), { mode: 0o600 });
35
+ } catch {}
36
+ }
37
+
38
+ let Discord;
39
+ function getDiscordLib() {
40
+ if (!Discord) {
41
+ try {
42
+ Discord = require("discord.js");
43
+ } catch {
44
+ throw new Error("Discord bridge requires discord.js — reinstall or update QuadWork to get it");
45
+ }
46
+ }
47
+ return Discord;
48
+ }
49
+
50
+ async function pollLoop(projectId, channelObj, qwPort) {
51
+ const inst = instances.get(projectId);
52
+ if (!inst || inst.stopping) return;
53
+
54
+ try {
55
+ let sinceId = inst.cursor;
56
+ const r = await fetch(
57
+ `http://127.0.0.1:${qwPort}/api/chat?project=${encodeURIComponent(projectId)}&since_id=${sinceId}&limit=50`,
58
+ { signal: AbortSignal.timeout(5000) }
59
+ );
60
+ if (!r.ok) throw new Error(`Chat API ${r.status}`);
61
+ const messages = await r.json();
62
+
63
+ for (const msg of messages) {
64
+ if (inst.stopping) return;
65
+ if (msg.sender === "dc" || msg.sender === "discord-bridge" || (msg.sender && msg.sender.startsWith("dc:"))) continue;
66
+ if (inst.forwardedIds.has(msg.id)) continue;
67
+
68
+ const text = `**${msg.sender}**: ${msg.text}`;
69
+ const truncated = text.length > 2000 ? text.slice(0, 2000) + "…" : text;
70
+ await channelObj.send(truncated);
71
+
72
+ inst.forwardedIds.add(msg.id);
73
+ if (inst.forwardedIds.size > 2000) {
74
+ const arr = [...inst.forwardedIds];
75
+ inst.forwardedIds = new Set(arr.slice(-1000));
76
+ }
77
+
78
+ if (msg.id > inst.cursor) {
79
+ inst.cursor = msg.id;
80
+ writeCursor(projectId, inst.cursor);
81
+ }
82
+ }
83
+ } catch (err) {
84
+ inst.lastError = err.message;
85
+ }
86
+
87
+ if (!inst.stopping) {
88
+ inst.timer = setTimeout(() => pollLoop(projectId, channelObj, qwPort), 2000);
89
+ }
90
+ }
91
+
92
+ async function start(projectId, botToken, channelId, qwPort) {
93
+ if (instances.has(projectId)) return;
94
+
95
+ const oldCursor = path.join(CONFIG_DIR, `discord-bridge-cursor-${projectId}.json`);
96
+ const newCursor = cursorPath(projectId);
97
+ if (!fs.existsSync(newCursor) && fs.existsSync(oldCursor)) {
98
+ try { fs.renameSync(oldCursor, newCursor); } catch {}
99
+ }
100
+
101
+ const { Client, GatewayIntentBits } = getDiscordLib();
102
+
103
+ const client = new Client({
104
+ intents: [
105
+ GatewayIntentBits.Guilds,
106
+ GatewayIntentBits.GuildMessages,
107
+ GatewayIntentBits.MessageContent,
108
+ ],
109
+ });
110
+
111
+ const inst = {
112
+ cursor: readCursor(projectId),
113
+ forwardedIds: new Set(),
114
+ timer: null,
115
+ stopping: false,
116
+ lastError: null,
117
+ startedAt: Date.now(),
118
+ client,
119
+ channelId,
120
+ };
121
+ instances.set(projectId, inst);
122
+
123
+ try {
124
+ await client.login(botToken);
125
+ } catch (err) {
126
+ instances.delete(projectId);
127
+ throw new Error(`Discord login failed: ${err.message}`);
128
+ }
129
+
130
+ let channel;
131
+ try {
132
+ channel = await client.channels.fetch(channelId);
133
+ if (!channel) throw new Error("Channel not found");
134
+ } catch (err) {
135
+ client.destroy();
136
+ instances.delete(projectId);
137
+ throw new Error(`Discord channel fetch failed: ${err.message}`);
138
+ }
139
+
140
+ client.on("messageCreate", async (message) => {
141
+ try {
142
+ if (inst.stopping) return;
143
+ if (message.author.bot) return;
144
+ if (message.channel.id !== channelId) return;
145
+
146
+ const from = message.author.username || "unknown";
147
+ console.log(`[bridge] discord ${projectId}: received message from ${from}`);
148
+ if (!message.content) {
149
+ console.warn(`[bridge] discord ${projectId}: empty message content — check MESSAGE_CONTENT intent`);
150
+ }
151
+ const res = await fetch(`http://127.0.0.1:${qwPort}/api/chat?project=${encodeURIComponent(projectId)}`, {
152
+ method: "POST",
153
+ headers: {
154
+ "Content-Type": "application/json",
155
+ "X-Bridge-Sender": `dc:${from}`,
156
+ },
157
+ body: JSON.stringify({
158
+ project: projectId,
159
+ text: message.content,
160
+ channel: "general",
161
+ }),
162
+ signal: AbortSignal.timeout(5000),
163
+ });
164
+ if (!res.ok) {
165
+ console.error(`[bridge] discord ${projectId} inbound POST failed: ${res.status}`);
166
+ }
167
+ } catch (err) {
168
+ if (!inst.stopping) {
169
+ console.error(`[bridge] discord ${projectId} inbound error: ${err.message}`);
170
+ inst.lastError = err.message;
171
+ }
172
+ }
173
+ });
174
+
175
+ client.on("error", (err) => {
176
+ console.error(`[bridge] discord ${projectId} client error: ${err?.message || err}`);
177
+ });
178
+ client.on("warn", (msg) => {
179
+ console.warn(`[bridge] discord ${projectId} client warn: ${msg}`);
180
+ });
181
+
182
+ // #782: seed cursor to latest on first enable (no cursor file, or
183
+ // cursor=0) AND on stale-cursor restarts where the cursor lags the
184
+ // latest chat message by more than STALE_CURSOR_THRESHOLD. The stale
185
+ // case covers bridges stopped mid-backlog (e.g. the plottoon scenario:
186
+ // cursor=83 with 127 messages — without this guard the next start
187
+ // replays 44 old messages to Discord). Small lags (graceful restart
188
+ // mid-conversation) keep continuity.
189
+ const cursorFileExists = fs.existsSync(cursorPath(projectId));
190
+ try {
191
+ const r = await fetch(
192
+ `http://127.0.0.1:${qwPort}/api/chat?project=${encodeURIComponent(projectId)}&limit=1`,
193
+ { signal: AbortSignal.timeout(5000) }
194
+ );
195
+ if (r.ok) {
196
+ const msgs = await r.json();
197
+ if (msgs.length > 0) {
198
+ const latestId = msgs[msgs.length - 1].id;
199
+ const stale = !cursorFileExists
200
+ || inst.cursor === 0
201
+ || (latestId - inst.cursor) > STALE_CURSOR_THRESHOLD;
202
+ if (stale) {
203
+ inst.cursor = latestId;
204
+ writeCursor(projectId, inst.cursor);
205
+ }
206
+ }
207
+ } else {
208
+ // #786: surface HTTP failures so non-OK responses don't fall
209
+ // through silently (the catch only fires on thrown errors).
210
+ console.warn(`[bridge] discord ${projectId}: cursor seed fetch returned ${r.status}`);
211
+ }
212
+ } catch (err) {
213
+ console.warn(`[bridge] discord ${projectId}: cursor seed failed (${err.message})`);
214
+ }
215
+
216
+ pollLoop(projectId, channel, qwPort).catch((err) => {
217
+ console.error(`[bridge] discord ${projectId} poll crashed: ${err.message}`);
218
+ inst.lastError = err.message;
219
+ stop(projectId);
220
+ });
221
+
222
+ console.log(`[bridge] discord ${projectId}: started`);
223
+ }
224
+
225
+ function stop(projectId) {
226
+ const inst = instances.get(projectId);
227
+ if (!inst) return;
228
+ inst.stopping = true;
229
+ if (inst.timer) clearTimeout(inst.timer);
230
+ try { inst.client.destroy(); } catch {}
231
+ instances.delete(projectId);
232
+ console.log(`[bridge] discord ${projectId}: stopped`);
233
+ }
234
+
235
+ function isRunning(projectId) {
236
+ return instances.has(projectId);
237
+ }
238
+
239
+ function getLastError(projectId) {
240
+ const inst = instances.get(projectId);
241
+ return inst?.lastError || null;
242
+ }
243
+
244
+ module.exports = { start, stop, isRunning, getLastError, readCursor };