@jx0/agency 0.2.1 → 0.4.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.
Files changed (62) hide show
  1. package/README.md +120 -52
  2. package/dashboard/out/404.html +1 -1
  3. package/dashboard/out/_next/static/chunks/app/_not-found/{page-ad40673d821037f6.js → page-5cb94002960ab71a.js} +1 -1
  4. package/dashboard/out/_next/static/chunks/app/layout-6249f74085ad56b1.js +1 -0
  5. package/dashboard/out/_next/static/chunks/app/page-0a5ee03ddf4553ab.js +1 -0
  6. package/dashboard/out/_next/static/chunks/{main-app-1d848b791b823fa6.js → main-app-0398d52862f5c730.js} +1 -1
  7. package/dashboard/out/_next/static/css/a13af72b10a7d74f.css +1 -0
  8. package/dashboard/out/index.html +1 -1
  9. package/dashboard/out/index.txt +4 -4
  10. package/docs/images/agency_cli_ps.png +0 -0
  11. package/docs/images/agency_ui_ai_prodivder_settings.png +0 -0
  12. package/docs/images/agency_ui_aws_settings.png +0 -0
  13. package/docs/images/agency_ui_identity_settings.png +0 -0
  14. package/docs/images/agency_ui_import_skills.jpeg +0 -0
  15. package/docs/images/agency_ui_knowledge.png +0 -0
  16. package/docs/images/agency_ui_mission_control.png +0 -0
  17. package/docs/images/agency_ui_skills_marketplace.png +0 -0
  18. package/docs/images/agent_ui_agent_config.png +0 -0
  19. package/package.json +1 -1
  20. package/src/api/db/migrations/004_nullable_human_refs.ts +129 -0
  21. package/src/api/db/migrations/005_agent_skills.ts +14 -0
  22. package/src/api/db/migrations/006_runtime_machine.ts +24 -0
  23. package/src/api/db/seed.ts +62 -46
  24. package/src/api/index.ts +11 -4
  25. package/src/api/lib/deploy.ts +412 -0
  26. package/src/api/lib/env-vars.ts +19 -0
  27. package/src/api/lib/exec.ts +77 -0
  28. package/src/api/lib/fleet-sync.ts +49 -32
  29. package/src/api/lib/fs-store.ts +350 -0
  30. package/src/api/lib/import-skills.ts +105 -0
  31. package/src/api/lib/metrics.ts +183 -0
  32. package/src/api/lib/processes.ts +82 -12
  33. package/src/api/lib/provision-openclaw.ts +376 -0
  34. package/src/api/lib/remote-deploy.ts +77 -0
  35. package/src/api/lib/ssh.ts +97 -0
  36. package/src/api/lib/sync-skills.ts +171 -0
  37. package/src/api/lib/tunnels.ts +7 -38
  38. package/src/api/routes/agents.ts +184 -132
  39. package/src/api/routes/documents.ts +24 -5
  40. package/src/api/routes/knowledge.ts +7 -5
  41. package/src/api/routes/machines.ts +107 -0
  42. package/src/api/routes/messages.ts +23 -19
  43. package/src/api/routes/repos.ts +74 -0
  44. package/src/api/routes/role-configs.ts +29 -46
  45. package/src/api/routes/skills.ts +198 -40
  46. package/src/api/routes/tasks.ts +24 -11
  47. package/src/cli/commands/init.ts +47 -18
  48. package/src/cli/commands/machines.ts +97 -0
  49. package/src/cli/commands/ps.ts +6 -4
  50. package/src/cli/commands/repos.ts +78 -0
  51. package/src/cli/commands/ssh.ts +14 -36
  52. package/src/cli/index.ts +5 -1
  53. package/src/daemon.ts +120 -1
  54. package/src/templates/solo/agents-config.md +39 -0
  55. package/src/templates/solo/agents.md +41 -0
  56. package/src/templates/solo/heartbeat.md +48 -0
  57. package/src/templates/solo/tools.md +35 -0
  58. package/dashboard/out/_next/static/chunks/app/layout-056f12675e691d12.js +0 -1
  59. package/dashboard/out/_next/static/chunks/app/page-80f01fdbb09b43c8.js +0 -1
  60. package/dashboard/out/_next/static/css/27d1ea794f04e96a.css +0 -1
  61. /package/dashboard/out/_next/static/{BRrkKiSxqTmex5oLQlOY5 → TCwq0pYHnHPlPIcOGjzu7}/_buildManifest.js +0 -0
  62. /package/dashboard/out/_next/static/{BRrkKiSxqTmex5oLQlOY5 → TCwq0pYHnHPlPIcOGjzu7}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,::backdrop,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial}}}@layer theme{:host,:root{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-green-500:oklch(72.3% .219 149.579);--color-gray-400:oklch(70.7% .022 261.325);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xl:36rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,::backdrop,:after,:before{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}:host,html{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}menu,ol,ul{list-style:none}audio,canvas,embed,iframe,img,object,svg,video{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,optgroup,select,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.top-1\/2{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-2{right:calc(var(--spacing)*2)}.bottom-0{bottom:calc(var(--spacing)*0)}.left-0{left:calc(var(--spacing)*0)}.z-40{z-index:40}.z-50{z-index:50}.mx-3{margin-inline:calc(var(--spacing)*3)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.ml-2{margin-left:calc(var(--spacing)*2)}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.hidden{display:none}.inline-block{display:inline-block}.h-0\.5{height:calc(var(--spacing)*.5)}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-14{height:calc(var(--spacing)*14)}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[90vh\]{max-height:90vh}.min-h-screen{min-height:100vh}.w-2{width:calc(var(--spacing)*2)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-8{width:calc(var(--spacing)*8)}.w-12{width:calc(var(--spacing)*12)}.w-20{width:calc(var(--spacing)*20)}.w-32{width:calc(var(--spacing)*32)}.w-\[200px\]{width:200px}.w-\[240px\]{width:240px}.w-\[260px\]{width:260px}.w-\[300px\]{width:300px}.w-\[400px\]{width:400px}.w-\[420px\]{width:420px}.w-\[480px\]{width:480px}.w-\[600px\]{width:600px}.w-full{width:100%}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0{gap:calc(var(--spacing)*0)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.gap-6{gap:calc(var(--spacing)*6)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*.5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*.5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e+38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.bg-black\/20{background-color:#0003}@supports (color:color-mix(in lab,red,red)){.bg-black\/20{background-color:color-mix(in oklab,var(--color-black)20%,transparent)}}.bg-gray-400{background-color:var(--color-gray-400)}.bg-green-500{background-color:var(--color-green-500)}.bg-red-500{background-color:var(--color-red-500)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-8{padding-block:calc(var(--spacing)*8)}.pt-3{padding-top:calc(var(--spacing)*3)}.pr-4{padding-right:calc(var(--spacing)*4)}.pr-10{padding-right:calc(var(--spacing)*10)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-white{color:var(--color-white)}.opacity-0{opacity:0}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-500{--tw-duration:.5s;transition-duration:.5s}.select-none{-webkit-user-select:none;user-select:none}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:bg-black\/5:hover{background-color:#0000000d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/5:hover{background-color:color-mix(in oklab,var(--color-black)5%,transparent)}}.hover\:bg-black\/\[0\.02\]:hover{background-color:#00000005}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/\[0\.02\]:hover{background-color:color-mix(in oklab,var(--color-black)2%,transparent)}}.hover\:bg-black\/\[0\.03\]:hover{background-color:#00000008}@supports (color:color-mix(in lab,red,red)){.hover\:bg-black\/\[0\.03\]:hover{background-color:color-mix(in oklab,var(--color-black)3%,transparent)}}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}}:root{--bg-primary:#faf9f7;--bg-secondary:#fff;--bg-tertiary:#f5f4f2;--text-primary:#1a1a1a;--text-secondary:#6b6b6b;--text-muted:#9b9b9b;--border:#e5e3df;--border-light:#f0eeea;--accent-green:#5c7c5a;--accent-olive:#6b7c5a;--accent-red:#c45c5c;--accent-yellow:#c4a35c;--accent-blue:#5c6b8c}body{background:var(--bg-primary);color:var(--text-primary);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,system-ui,sans-serif}.line-numbers{counter-reset:line}.line-numbers .line:before{counter-increment:line;content:counter(line);text-align:right;width:3rem;color:var(--text-muted);margin-right:1rem;font-size:.8rem;display:inline-block}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}
@@ -1 +1 @@
1
- <!DOCTYPE html><!--BRrkKiSxqTmex5oLQlOY5--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/27d1ea794f04e96a.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-4e6bf084ac60582b.js"/><script src="/_next/static/chunks/4bd1b696-c023c6e3521b1417.js" async=""></script><script src="/_next/static/chunks/255-67e8754147461423.js" async=""></script><script src="/_next/static/chunks/main-app-1d848b791b823fa6.js" async=""></script><script src="/_next/static/chunks/app/page-80f01fdbb09b43c8.js" async=""></script><title>Mission Control</title><meta name="description" content="Agency AI Dashboard"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="min-h-screen"><div hidden=""><!--$--><!--/$--></div><div class="h-screen flex flex-col"><header style="background:var(--bg-secondary);border-bottom:1px solid var(--border)" class="h-14 flex items-center justify-between px-5 shrink-0"><div class="flex items-center gap-6"><div class="flex items-center gap-2"><div class="w-7 h-7 rounded-md flex items-center justify-center text-white text-xs font-bold" style="background:var(--accent-green)">A</div><span class="font-semibold text-sm">Agency</span></div><nav class="flex gap-1"><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:var(--bg-tertiary);color:var(--text-primary)">Mission Control</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Agent Config</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Settings</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Skills</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Roles</button></nav></div><div class="flex items-center gap-5 text-sm"><div class="flex items-center gap-4" style="color:var(--text-secondary)"><span><span class="font-semibold" style="color:var(--text-primary)">0</span> <!-- -->agents active</span><span><span class="font-semibold" style="color:var(--text-primary)">0</span> <!-- -->in queue</span></div><div class="relative"><button class="relative px-2 py-1 rounded text-sm" style="color:var(--text-secondary)">Bell</button></div><div class="flex items-center gap-2" style="color:var(--text-muted)"><span class="font-mono text-xs"></span><span class="w-2 h-2 rounded-full bg-green-500"></span></div></div></header><div class="flex flex-1 overflow-hidden"><div class="w-[200px] shrink-0 overflow-y-auto border-r" style="border-color:var(--border);background:var(--bg-secondary)"><div class="px-4 py-3 text-xs font-bold tracking-wider" style="color:var(--text-muted)">AGENTS</div><div class="space-y-0.5 px-2"></div></div><div class="flex-1 overflow-x-auto p-4"><div class="flex gap-4 min-w-0"><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">INBOX</h3><button class="w-5 h-5 flex items-center justify-center rounded text-xs font-bold leading-none" style="background:var(--bg-tertiary);color:var(--text-secondary)" title="Create task">+</button><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">ASSIGNED</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">IN PROGRESS</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">REVIEW</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">DONE</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div></div></div><div class="w-[300px] shrink-0 overflow-y-auto border-l flex flex-col" style="border-color:var(--border);background:var(--bg-secondary)"><div class="px-4 py-3"><div class="text-xs font-bold tracking-wider mb-3" style="color:var(--text-muted)">LIVE FEED</div><div class="flex gap-1 mb-3"><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:var(--bg-tertiary);color:var(--text-primary)">All</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Tasks</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Comments</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Status</button></div><div class="flex flex-wrap gap-1 mb-3"><button class="px-2 py-0.5 rounded-full text-[11px] font-medium transition-colors" style="background:var(--accent-green);color:white">All Agents</button></div></div><div class="flex-1 overflow-y-auto px-4 pb-4 space-y-3"><div class="text-sm text-center py-8" style="color:var(--text-muted)">No activity yet</div></div></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-4e6bf084ac60582b.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[9766,[],\"\"]\n3:I[8924,[],\"\"]\n4:I[1959,[],\"ClientPageRoot\"]\n5:I[5313,[\"974\",\"static/chunks/app/page-80f01fdbb09b43c8.js\"],\"default\"]\n8:I[4431,[],\"OutletBoundary\"]\na:I[5278,[],\"AsyncMetadataOutlet\"]\nc:I[4431,[],\"ViewportBoundary\"]\ne:I[4431,[],\"MetadataBoundary\"]\nf:\"$Sreact.suspense\"\n11:I[7150,[],\"\"]\n:HL[\"/_next/static/css/27d1ea794f04e96a.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"BRrkKiSxqTmex5oLQlOY5\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/27d1ea794f04e96a.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"min-h-screen\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",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\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L4\",null,{\"Component\":\"$5\",\"searchParams\":{},\"params\":{},\"promises\":[\"$@6\",\"$@7\"]}],null,[\"$\",\"$L8\",null,{\"children\":[\"$L9\",[\"$\",\"$La\",null,{\"promise\":\"$@b\"}]]}]]}],{},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$Lc\",null,{\"children\":\"$Ld\"}],null],[\"$\",\"$Le\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$f\",null,{\"fallback\":null,\"children\":\"$L10\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"6:{}\n7:\"$0:f:0:1:2:children:1:props:children:0:props:params\"\n"])</script><script>self.__next_f.push([1,"d:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n9:null\n"])</script><script>self.__next_f.push([1,"b:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Mission Control\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Agency AI Dashboard\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"10:\"$b:metadata\"\n"])</script></body></html>
1
+ <!DOCTYPE html><!--TCwq0pYHnHPlPIcOGjzu7--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/a13af72b10a7d74f.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-4e6bf084ac60582b.js"/><script src="/_next/static/chunks/4bd1b696-c023c6e3521b1417.js" async=""></script><script src="/_next/static/chunks/255-67e8754147461423.js" async=""></script><script src="/_next/static/chunks/main-app-0398d52862f5c730.js" async=""></script><script src="/_next/static/chunks/app/page-0a5ee03ddf4553ab.js" async=""></script><title>Agency</title><meta name="description" content="Agency AI Dashboard"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="min-h-screen"><div hidden=""><!--$--><!--/$--></div><div class="h-screen flex flex-col"><header style="background:var(--bg-secondary);border-bottom:1px solid var(--border)" class="h-14 flex items-center justify-between px-5 shrink-0"><div class="flex items-center gap-6"><div class="flex items-center gap-2"><div class="w-7 h-7 rounded-md flex items-center justify-center text-white text-xs font-bold" style="background:var(--accent-green)">A</div><span class="font-semibold text-sm">Agency</span></div><nav class="flex gap-1"><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:var(--bg-tertiary);color:var(--text-primary)">Tasks</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Agents</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Roles</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Skills</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Docs</button><button class="px-3 py-1.5 rounded-md text-sm font-medium transition-colors" style="background:transparent;color:var(--text-secondary)">Knowledge</button></nav></div><div class="flex items-center gap-4 text-sm"><button class="w-8 h-8 rounded-md flex items-center justify-center transition-colors" style="background:transparent;color:var(--text-secondary)" title="Settings"><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.86 1.45a1.2 1.2 0 0 1 2.28 0l.2.6a1.2 1.2 0 0 0 1.57.7l.58-.24a1.2 1.2 0 0 1 1.6 1.14l-.02.63a1.2 1.2 0 0 0 1.04 1.22l.62.1a1.2 1.2 0 0 1 .8 1.97l-.43.46a1.2 1.2 0 0 0 0 1.6l.43.46a1.2 1.2 0 0 1-.8 1.97l-.62.1a1.2 1.2 0 0 0-1.04 1.22l.02.63a1.2 1.2 0 0 1-1.6 1.14l-.58-.24a1.2 1.2 0 0 0-1.57.7l-.2.6a1.2 1.2 0 0 1-2.28 0l-.2-.6a1.2 1.2 0 0 0-1.57-.7l-.58.24a1.2 1.2 0 0 1-1.6-1.14l.02-.63a1.2 1.2 0 0 0-1.04-1.22l-.62-.1a1.2 1.2 0 0 1-.8-1.97l.43-.46a1.2 1.2 0 0 0 0-1.6l-.43-.46a1.2 1.2 0 0 1 .8-1.97l.62-.1A1.2 1.2 0 0 0 2.91 4.3l-.02-.63a1.2 1.2 0 0 1 1.6-1.14l.58.24a1.2 1.2 0 0 0 1.57-.7l.2-.6Z"></path><circle cx="8" cy="8" r="2.5"></circle></svg></button><div class="flex items-center gap-2" style="color:var(--text-muted)"><span class="font-mono text-xs"></span><span class="w-2 h-2 rounded-full bg-green-500"></span></div></div></header><div class="flex flex-1 overflow-hidden"><div class="w-[200px] shrink-0 overflow-y-auto border-r" style="border-color:var(--border);background:var(--bg-secondary)"><div class="px-4 py-3 text-xs font-bold tracking-wider" style="color:var(--text-muted)">AGENTS</div><div class="space-y-0.5 px-2"></div></div><div class="flex-1 overflow-x-auto p-4"><div class="flex gap-4 min-w-0"><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">INBOX</h3><button class="w-5 h-5 flex items-center justify-center rounded text-xs font-bold leading-none" style="background:var(--bg-tertiary);color:var(--text-secondary)" title="Create task">+</button><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">ASSIGNED</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">IN PROGRESS</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">REVIEW</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div><div class="flex-1 min-w-[200px]"><div class="flex items-center gap-2 mb-3 px-1"><h3 class="text-xs font-bold tracking-wider" style="color:var(--text-muted)">DONE</h3><span class="text-[11px] font-medium px-1.5 rounded-full" style="background:var(--bg-tertiary);color:var(--text-muted)">0</span></div><div class="space-y-2"></div></div></div></div><div class="w-[300px] shrink-0 overflow-y-auto border-l flex flex-col" style="border-color:var(--border);background:var(--bg-secondary)"><div class="px-4 py-3"><div class="text-xs font-bold tracking-wider mb-3" style="color:var(--text-muted)">LIVE FEED</div><div class="flex gap-1 mb-3"><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:var(--bg-tertiary);color:var(--text-primary)">All</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Tasks</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Comments</button><button class="px-2 py-1 rounded text-xs font-medium transition-colors" style="background:transparent;color:var(--text-muted)">Status</button></div><div class="flex flex-wrap gap-1 mb-3"><button class="px-2 py-0.5 rounded-full text-[11px] font-medium transition-colors" style="background:var(--accent-green);color:white">All Agents</button></div></div><div class="flex-1 overflow-y-auto px-4 pb-4 space-y-3"><div class="text-sm text-center py-8" style="color:var(--text-muted)">No activity yet</div></div></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-4e6bf084ac60582b.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[9766,[],\"\"]\n3:I[8924,[],\"\"]\n4:I[1959,[],\"ClientPageRoot\"]\n5:I[2139,[\"974\",\"static/chunks/app/page-0a5ee03ddf4553ab.js\"],\"default\"]\n8:I[4431,[],\"OutletBoundary\"]\na:I[5278,[],\"AsyncMetadataOutlet\"]\nc:I[4431,[],\"ViewportBoundary\"]\ne:I[4431,[],\"MetadataBoundary\"]\nf:\"$Sreact.suspense\"\n11:I[7150,[],\"\"]\n:HL[\"/_next/static/css/a13af72b10a7d74f.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"TCwq0pYHnHPlPIcOGjzu7\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/a13af72b10a7d74f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"min-h-screen\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",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\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L4\",null,{\"Component\":\"$5\",\"searchParams\":{},\"params\":{},\"promises\":[\"$@6\",\"$@7\"]}],null,[\"$\",\"$L8\",null,{\"children\":[\"$L9\",[\"$\",\"$La\",null,{\"promise\":\"$@b\"}]]}]]}],{},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$Lc\",null,{\"children\":\"$Ld\"}],null],[\"$\",\"$Le\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$f\",null,{\"fallback\":null,\"children\":\"$L10\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[]],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"6:{}\n7:\"$0:f:0:1:2:children:1:props:children:0:props:params\"\n"])</script><script>self.__next_f.push([1,"d:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n9:null\n"])</script><script>self.__next_f.push([1,"b:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"Agency\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Agency AI Dashboard\"}]],\"error\":null,\"digest\":\"$undefined\"}\n"])</script><script>self.__next_f.push([1,"10:\"$b:metadata\"\n"])</script></body></html>
@@ -2,18 +2,18 @@
2
2
  2:I[9766,[],""]
3
3
  3:I[8924,[],""]
4
4
  4:I[1959,[],"ClientPageRoot"]
5
- 5:I[5313,["974","static/chunks/app/page-80f01fdbb09b43c8.js"],"default"]
5
+ 5:I[2139,["974","static/chunks/app/page-0a5ee03ddf4553ab.js"],"default"]
6
6
  8:I[4431,[],"OutletBoundary"]
7
7
  a:I[5278,[],"AsyncMetadataOutlet"]
8
8
  c:I[4431,[],"ViewportBoundary"]
9
9
  e:I[4431,[],"MetadataBoundary"]
10
10
  f:"$Sreact.suspense"
11
11
  11:I[7150,[],""]
12
- :HL["/_next/static/css/27d1ea794f04e96a.css","style"]
13
- 0:{"P":null,"b":"BRrkKiSxqTmex5oLQlOY5","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/27d1ea794f04e96a.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"min-h-screen","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",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":["__PAGE__",["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","searchParams":{},"params":{},"promises":["$@6","$@7"]}],null,["$","$L8",null,{"children":["$L9",["$","$La",null,{"promise":"$@b"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$Lc",null,{"children":"$Ld"}],null],["$","$Le",null,{"children":["$","div",null,{"hidden":true,"children":["$","$f",null,{"fallback":null,"children":"$L10"}]}]}]]}],false]],"m":"$undefined","G":["$11",[]],"s":false,"S":true}
12
+ :HL["/_next/static/css/a13af72b10a7d74f.css","style"]
13
+ 0:{"P":null,"b":"TCwq0pYHnHPlPIcOGjzu7","p":"","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/a13af72b10a7d74f.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"min-h-screen","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",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":["__PAGE__",["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","searchParams":{},"params":{},"promises":["$@6","$@7"]}],null,["$","$L8",null,{"children":["$L9",["$","$La",null,{"promise":"$@b"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$Lc",null,{"children":"$Ld"}],null],["$","$Le",null,{"children":["$","div",null,{"hidden":true,"children":["$","$f",null,{"fallback":null,"children":"$L10"}]}]}]]}],false]],"m":"$undefined","G":["$11",[]],"s":false,"S":true}
14
14
  6:{}
15
15
  7:"$0:f:0:1:2:children:1:props:children:0:props:params"
16
16
  d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
17
17
  9:null
18
- b:{"metadata":[["$","title","0",{"children":"Mission Control"}],["$","meta","1",{"name":"description","content":"Agency AI Dashboard"}]],"error":null,"digest":"$undefined"}
18
+ b:{"metadata":[["$","title","0",{"children":"Agency"}],["$","meta","1",{"name":"description","content":"Agency AI Dashboard"}]],"error":null,"digest":"$undefined"}
19
19
  10:"$b:metadata"
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx0/agency",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "agency": "./bin/agency.js"
@@ -0,0 +1,129 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ /**
5
+ * Make created_by and from_agent nullable so we don't need a "human" agent.
6
+ * NULL = created/sent by human user.
7
+ */
8
+ export async function up(db: Kysely<any>): Promise<void> {
9
+ // SQLite doesn't support ALTER COLUMN, so we need to recreate tables
10
+
11
+ // 1. Recreate tasks with nullable created_by
12
+ await sql`
13
+ CREATE TABLE tasks_new (
14
+ id TEXT PRIMARY KEY,
15
+ title TEXT NOT NULL,
16
+ description TEXT NOT NULL,
17
+ design TEXT,
18
+ acceptance TEXT,
19
+ status TEXT NOT NULL DEFAULT 'backlog',
20
+ priority INTEGER NOT NULL DEFAULT 0,
21
+ task_type TEXT NOT NULL DEFAULT 'task',
22
+ parent_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
23
+ created_by TEXT REFERENCES agents(id),
24
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
25
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
26
+ )
27
+ `.execute(db);
28
+
29
+ await sql`
30
+ INSERT INTO tasks_new SELECT * FROM tasks
31
+ `.execute(db);
32
+
33
+ await sql`DROP TABLE tasks`.execute(db);
34
+ await sql`ALTER TABLE tasks_new RENAME TO tasks`.execute(db);
35
+
36
+ await db.schema.createIndex("idx_tasks_status").on("tasks").column("status").execute();
37
+ await db.schema.createIndex("idx_tasks_parent").on("tasks").column("parent_id").execute();
38
+
39
+ // 2. Recreate messages with nullable from_agent
40
+ await sql`
41
+ CREATE TABLE messages_new (
42
+ id TEXT PRIMARY KEY,
43
+ task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
44
+ from_agent TEXT REFERENCES agents(id),
45
+ content TEXT NOT NULL,
46
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
47
+ )
48
+ `.execute(db);
49
+
50
+ await sql`
51
+ INSERT INTO messages_new SELECT * FROM messages
52
+ `.execute(db);
53
+
54
+ await sql`DROP TABLE messages`.execute(db);
55
+ await sql`ALTER TABLE messages_new RENAME TO messages`.execute(db);
56
+
57
+ await db.schema.createIndex("idx_messages_task").on("messages").column("task_id").execute();
58
+
59
+ // 3. Recreate documents with nullable created_by
60
+ await sql`
61
+ CREATE TABLE documents_new (
62
+ id TEXT PRIMARY KEY,
63
+ title TEXT NOT NULL,
64
+ content TEXT NOT NULL,
65
+ doc_type TEXT NOT NULL,
66
+ task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
67
+ created_by TEXT REFERENCES agents(id),
68
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
69
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
70
+ )
71
+ `.execute(db);
72
+
73
+ await sql`
74
+ INSERT INTO documents_new SELECT * FROM documents
75
+ `.execute(db);
76
+
77
+ await sql`DROP TABLE documents`.execute(db);
78
+ await sql`ALTER TABLE documents_new RENAME TO documents`.execute(db);
79
+
80
+ // 4. Recreate activities with nullable agent_id
81
+ await sql`
82
+ CREATE TABLE activities_new (
83
+ id TEXT PRIMARY KEY,
84
+ type TEXT NOT NULL,
85
+ agent_id TEXT REFERENCES agents(id),
86
+ task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
87
+ summary TEXT NOT NULL,
88
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
89
+ )
90
+ `.execute(db);
91
+
92
+ await sql`
93
+ INSERT INTO activities_new SELECT * FROM activities
94
+ `.execute(db);
95
+
96
+ await sql`DROP TABLE activities`.execute(db);
97
+ await sql`ALTER TABLE activities_new RENAME TO activities`.execute(db);
98
+
99
+ await db.schema.createIndex("idx_activities_created").on("activities").column("created_at").execute();
100
+
101
+ // 5. Set existing human agent references to NULL and delete human agent
102
+ await sql`
103
+ UPDATE tasks SET created_by = NULL
104
+ WHERE created_by IN (SELECT id FROM agents WHERE name = 'human')
105
+ `.execute(db);
106
+
107
+ await sql`
108
+ UPDATE messages SET from_agent = NULL
109
+ WHERE from_agent IN (SELECT id FROM agents WHERE name = 'human')
110
+ `.execute(db);
111
+
112
+ await sql`
113
+ UPDATE documents SET created_by = NULL
114
+ WHERE created_by IN (SELECT id FROM agents WHERE name = 'human')
115
+ `.execute(db);
116
+
117
+ await sql`
118
+ UPDATE activities SET agent_id = NULL
119
+ WHERE agent_id IN (SELECT id FROM agents WHERE name = 'human')
120
+ `.execute(db);
121
+
122
+ await sql`DELETE FROM agents WHERE name = 'human'`.execute(db);
123
+ }
124
+
125
+ export async function down(db: Kysely<any>): Promise<void> {
126
+ // Re-create human agent and restore NOT NULL constraints
127
+ // This is destructive - any NULL refs would fail
128
+ throw new Error("Migration 004 down not implemented - would lose data");
129
+ }
@@ -0,0 +1,14 @@
1
+ import type { Kysely } from "kysely";
2
+
3
+ export async function up(db: Kysely<unknown>): Promise<void> {
4
+ await db.schema
5
+ .createTable("agent_skills")
6
+ .addColumn("agent_id", "text", (col) => col.notNull().references("agents.id").onDelete("cascade"))
7
+ .addColumn("skill_name", "text", (col) => col.notNull())
8
+ .addPrimaryKeyConstraint("agent_skills_pk", ["agent_id", "skill_name"])
9
+ .execute();
10
+ }
11
+
12
+ export async function down(db: Kysely<unknown>): Promise<void> {
13
+ await db.schema.dropTable("agent_skills").execute();
14
+ }
@@ -0,0 +1,24 @@
1
+ import type { Kysely } from "kysely";
2
+ import { sql } from "kysely";
3
+
4
+ export async function up(db: Kysely<any>): Promise<void> {
5
+ // Add new columns
6
+ await sql`ALTER TABLE agents ADD COLUMN runtime TEXT`.execute(db);
7
+ await sql`ALTER TABLE agents ADD COLUMN machine TEXT`.execute(db);
8
+
9
+ // Backfill from location:
10
+ // local → runtime: system
11
+ // docker → runtime: docker
12
+ // remote → runtime: system (machine filled from fleet.json separately)
13
+ // NULL/missing → runtime: system
14
+ await sql`UPDATE agents SET runtime = CASE
15
+ WHEN location = 'docker' THEN 'docker'
16
+ ELSE 'system'
17
+ END WHERE runtime IS NULL`.execute(db);
18
+ }
19
+
20
+ export async function down(db: Kysely<any>): Promise<void> {
21
+ // SQLite doesn't support DROP COLUMN before 3.35.0, so we leave them
22
+ // and just clear the values
23
+ await sql`UPDATE agents SET runtime = NULL, machine = NULL`.execute(db);
24
+ }
@@ -1,6 +1,12 @@
1
1
  import { db } from "./client.js";
2
2
  import * as fs from "fs";
3
3
  import * as path from "path";
4
+ import {
5
+ getRoleConfig,
6
+ putRoleConfig,
7
+ putSkill,
8
+ configTypeToFilename,
9
+ } from "../lib/fs-store.js";
4
10
 
5
11
  const TEMPLATES_DIR = path.join(import.meta.dir, "../../templates");
6
12
 
@@ -40,18 +46,25 @@ export async function seedDefaults(options: SeedOptions = {}) {
40
46
  { key: "ai.oauth_refresh_token", value: "", category: "ai", description: "Claude OAuth refresh token", sensitive: 1, input_type: "password" },
41
47
  { key: "ai.oauth_expires_at", value: "", category: "ai", description: "Token expiry (ISO string)", sensitive: 0, input_type: "readonly" },
42
48
  { key: "ai.oauth_subscription_type", value: "", category: "ai", description: "Subscription type (max, pro, etc.)", sensitive: 0, input_type: "readonly" },
43
- // AWS
44
- { key: "aws.access_key_id", value: "", category: "aws", description: "AWS Access Key ID", sensitive: 1, input_type: "password" },
45
- { key: "aws.secret_access_key", value: "", category: "aws", description: "AWS Secret Access Key", sensitive: 1, input_type: "password" },
46
- { key: "aws.region", value: "", category: "aws", description: "AWS region", sensitive: 0, input_type: "text" },
47
- { key: "aws.ami_id", value: "", category: "aws", description: "AMI for EC2 agents", sensitive: 0, input_type: "text" },
48
- { key: "aws.instance_type", value: "", category: "aws", description: "Default EC2 instance type", sensitive: 0, input_type: "text" },
49
- { key: "aws.s3_bucket_prefix", value: "", category: "aws", description: "S3 bucket prefix", sensitive: 0, input_type: "text" },
50
- // SSH
51
- { key: "ssh.private_key", value: "", category: "ssh", description: "SSH private key content", sensitive: 1, input_type: "textarea" },
52
- { key: "ssh.public_key", value: "", category: "ssh", description: "SSH public key (for display/copy)", sensitive: 0, input_type: "textarea" },
53
- { key: "ssh.key_name", value: "", category: "ssh", description: "SSH key name", sensitive: 0, input_type: "text" },
54
- { key: "ssh.user", value: "", category: "ssh", description: "SSH username", sensitive: 0, input_type: "text" },
49
+ // OpenClaw Agent Defaults
50
+ { key: "agent.model", value: "claude-sonnet-4-20250514", category: "agent", description: "Primary model for all agents", sensitive: 0, input_type: "text" },
51
+ { key: "agent.model_fallbacks", value: "", category: "agent", description: "Comma-separated fallback models", sensitive: 0, input_type: "text" },
52
+ { key: "agent.thinking", value: "low", category: "agent", description: "Extended thinking mode: off, low, medium, high", sensitive: 0, input_type: "select:off,low,medium,high" },
53
+ { key: "agent.timeout_seconds", value: "600", category: "agent", description: "Agent run timeout in seconds", sensitive: 0, input_type: "text" },
54
+ { key: "agent.max_concurrent", value: "1", category: "agent", description: "Max parallel agent runs per instance", sensitive: 0, input_type: "text" },
55
+ { key: "agent.sandbox_mode", value: "non-main", category: "agent", description: "Sandboxing: off, non-main, always", sensitive: 0, input_type: "select:off,non-main,always" },
56
+ { key: "agent.sandbox_scope", value: "agent", category: "agent", description: "Sandbox lifecycle: agent, session, message", sensitive: 0, input_type: "select:agent,session,message" },
57
+ { key: "agent.tools_profile", value: "full", category: "agent", description: "Tool allowlist profile: full, standard, minimal", sensitive: 0, input_type: "select:full,standard,minimal" },
58
+ { key: "agent.tools_allow", value: "", category: "agent", description: "Comma-separated tool allowlist (overrides profile)", sensitive: 0, input_type: "text" },
59
+ { key: "agent.tools_deny", value: "", category: "agent", description: "Comma-separated tool denylist", sensitive: 0, input_type: "text" },
60
+ { key: "agent.web_search", value: "true", category: "agent", description: "Enable web search tool", sensitive: 0, input_type: "select:true,false" },
61
+ { key: "agent.exec_timeout_sec", value: "1800", category: "agent", description: "Process execution kill timeout (seconds)", sensitive: 0, input_type: "text" },
62
+ { key: "agent.browser_enabled", value: "true", category: "agent", description: "Start managed browser instance", sensitive: 0, input_type: "select:true,false" },
63
+ { key: "agent.logging_level", value: "info", category: "agent", description: "Log verbosity: debug, info, warn, error", sensitive: 0, input_type: "select:debug,info,warn,error" },
64
+ { key: "agent.logging_redact", value: "tools", category: "agent", description: "Redact sensitive data: off, tools, all", sensitive: 0, input_type: "select:off,tools,all" },
65
+ { key: "agent.context_pruning", value: "adaptive", category: "agent", description: "Context pruning mode: off, adaptive, aggressive", sensitive: 0, input_type: "select:off,adaptive,aggressive" },
66
+ { key: "agent.compaction", value: "default", category: "agent", description: "Memory compaction: off, default, aggressive", sensitive: 0, input_type: "select:off,default,aggressive" },
67
+ { key: "agent.heartbeat_interval", value: "30m", category: "agent", description: "Heartbeat check interval (e.g. 30m, 1h)", sensitive: 0, input_type: "text" },
55
68
  ];
56
69
 
57
70
  for (const s of defaultSettings) {
@@ -63,7 +76,12 @@ export async function seedDefaults(options: SeedOptions = {}) {
63
76
  }
64
77
 
65
78
  // Clean up removed settings
66
- const removedKeys = ["slack.team_channel", "slack.human_user_id", "ssh.key_path", "aws.profile"];
79
+ const removedKeys = [
80
+ "slack.team_channel", "slack.human_user_id", "ssh.key_path", "aws.profile",
81
+ "aws.access_key_id", "aws.secret_access_key", "aws.region", "aws.ami_id",
82
+ "aws.instance_type", "aws.s3_bucket_prefix",
83
+ "ssh.private_key", "ssh.public_key", "ssh.key_name", "ssh.user",
84
+ ];
67
85
  for (const key of removedKeys) {
68
86
  await db.deleteFrom("settings").where("key", "=", key).execute();
69
87
  }
@@ -79,7 +97,35 @@ export async function seedDefaults(options: SeedOptions = {}) {
79
97
  .replace(/\{\{team\.name\}\}/g, teamName);
80
98
  }
81
99
 
82
- // Seed role configs for each role
100
+ // Migrate existing DB role_configs to filesystem (one-time)
101
+ try {
102
+ const dbConfigs = await db.selectFrom("role_configs").selectAll().execute();
103
+ for (const row of dbConfigs) {
104
+ if (getRoleConfig(row.role, row.config_type) === null) {
105
+ putRoleConfig(row.role, row.config_type, row.content);
106
+ console.log(`[seed] migrated role_config to fs: ${row.role}/${row.config_type}`);
107
+ }
108
+ }
109
+ } catch {
110
+ // Table may not exist if fresh install — that's fine
111
+ }
112
+
113
+ // Migrate existing DB skills to filesystem (one-time)
114
+ try {
115
+ const dbSkills = await db.selectFrom("skills").selectAll().execute();
116
+ for (const row of dbSkills) {
117
+ const { getSkill } = await import("../lib/fs-store.js");
118
+ if (!getSkill(row.name)) {
119
+ const tags = JSON.parse(row.tags) as string[];
120
+ putSkill(row.name, row.body, row.category, tags);
121
+ console.log(`[seed] migrated skill to fs: ${row.name}`);
122
+ }
123
+ }
124
+ } catch {
125
+ // Table may not exist — fine
126
+ }
127
+
128
+ // Seed role configs to filesystem from templates
83
129
  const ROLE_SPECIFIC = ["heartbeat", "agents-config", "tools", "agents"];
84
130
  const SHARED_CONFIGS: { configType: string; template: string }[] = [
85
131
  { configType: "environment", template: "environment.md" },
@@ -95,44 +141,14 @@ export async function seedDefaults(options: SeedOptions = {}) {
95
141
  ];
96
142
 
97
143
  for (const { configType, segments } of configs) {
98
- const existing = await db
99
- .selectFrom("role_configs")
100
- .where("role", "=", role)
101
- .where("config_type", "=", configType)
102
- .selectAll()
103
- .executeTakeFirst();
104
-
105
- if (!existing) {
144
+ if (getRoleConfig(role, configType) === null) {
106
145
  const content = interpolate(readTemplate(...segments));
107
- await db.insertInto("role_configs").values({
108
- id: crypto.randomUUID(),
109
- role,
110
- config_type: configType,
111
- content,
112
- }).execute();
146
+ putRoleConfig(role, configType, content);
113
147
  console.log(`[seed] role_config: ${role}/${configType}`);
114
148
  }
115
149
  }
116
150
  }
117
151
 
118
- // Ensure "human" agent exists
119
- const humanExists = await db
120
- .selectFrom("agents")
121
- .where("name", "=", "human")
122
- .selectAll()
123
- .executeTakeFirst();
124
-
125
- if (!humanExists) {
126
- await db.insertInto("agents").values({
127
- id: crypto.randomUUID(),
128
- name: "human",
129
- role: "human",
130
- status: "active",
131
- current_task: null,
132
- session_key: "agent:human:main",
133
- }).execute();
134
- console.log("[seed] created human agent");
135
- }
136
152
  }
137
153
 
138
154
  // Run directly if executed as a script
package/src/api/index.ts CHANGED
@@ -14,6 +14,8 @@ import { settings } from "./routes/settings.js";
14
14
  import { oauth } from "./routes/oauth.js";
15
15
  import { skills } from "./routes/skills.js";
16
16
  import { roleConfigs } from "./routes/role-configs.js";
17
+ import { repos } from "./routes/repos.js";
18
+ import { machines } from "./routes/machines.js";
17
19
 
18
20
  const app = new Hono();
19
21
 
@@ -43,6 +45,8 @@ app.route("/settings", settings);
43
45
  app.route("/oauth", oauth);
44
46
  app.route("/skills", skills);
45
47
  app.route("/role-configs", roleConfigs);
48
+ app.route("/repos", repos);
49
+ app.route("/machines", machines);
46
50
 
47
51
  // Serve the dashboard static export
48
52
  const dashboardPaths = [
@@ -61,10 +65,13 @@ if (dashboardDir) {
61
65
  app.use("*", serveStatic({ root: dashboardDir, rewriteRequestPath: () => "/index.html" }));
62
66
  }
63
67
 
64
- // Reconcile fleet.json → DB on startup, then watch for changes
65
- reconcileDbFromFleet()
66
- .then(() => startWatcher())
67
- .catch((err) => console.error("[startup] fleet sync failed:", err));
68
+ /**
69
+ * Initialize fleet sync — call AFTER migrations have run.
70
+ */
71
+ export async function initFleetSync() {
72
+ await reconcileDbFromFleet();
73
+ startWatcher();
74
+ }
68
75
 
69
76
  export default {
70
77
  port: Number(process.env.PORT ?? 3100),