@konglx/rotom 2.21.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 (189) hide show
  1. package/README.md +417 -0
  2. package/bin/mesh-master.sh +439 -0
  3. package/bin/rotom +29 -0
  4. package/bin/rotom-link.sh +136 -0
  5. package/bin/rotom-send-with-status +57 -0
  6. package/bin/rotom-up.sh +428 -0
  7. package/dist/cli/ask.js +62 -0
  8. package/dist/cli/common.js +321 -0
  9. package/dist/cli/config.js +65 -0
  10. package/dist/cli/directory.js +17 -0
  11. package/dist/cli/executor.js +58 -0
  12. package/dist/cli/fed.js +91 -0
  13. package/dist/cli/group.js +273 -0
  14. package/dist/cli/identity.js +62 -0
  15. package/dist/cli/init.js +268 -0
  16. package/dist/cli/issue.js +202 -0
  17. package/dist/cli/join.js +170 -0
  18. package/dist/cli/link.js +47 -0
  19. package/dist/cli/master.js +51 -0
  20. package/dist/cli/memory.js +307 -0
  21. package/dist/cli/note.js +68 -0
  22. package/dist/cli/repo.js +77 -0
  23. package/dist/cli/rotom.js +277 -0
  24. package/dist/cli/routes.js +118 -0
  25. package/dist/cli/run.js +45 -0
  26. package/dist/cli/schedule.js +237 -0
  27. package/dist/cli/skill.js +173 -0
  28. package/dist/cli/team.js +106 -0
  29. package/dist/executor/claude-code-hook.cjs +80 -0
  30. package/dist/executor/cli-executor.js +8 -0
  31. package/dist/executor/executors/claude-code.js +780 -0
  32. package/dist/executor/executors/codex.js +719 -0
  33. package/dist/executor/executors/hermes-cli.js +855 -0
  34. package/dist/executor/executors/openclaw.js +467 -0
  35. package/dist/executor/executors/pi.js +514 -0
  36. package/dist/executor/index.js +269 -0
  37. package/dist/executor/jsonrpc-transport.js +125 -0
  38. package/dist/executor/process-runner.js +101 -0
  39. package/dist/executor/reasoning-status.js +83 -0
  40. package/dist/executor/repo-cache.js +502 -0
  41. package/dist/executor/session-store.js +188 -0
  42. package/dist/executor/worker-chat.js +257 -0
  43. package/dist/executor/worker-connection.js +89 -0
  44. package/dist/executor/worker-issue.js +264 -0
  45. package/dist/executor/worker.js +877 -0
  46. package/dist/link/pending-requests.js +72 -0
  47. package/dist/link/server.js +233 -0
  48. package/dist/link/visibility-store.js +58 -0
  49. package/dist/master/api/agents.js +333 -0
  50. package/dist/master/api/artifacts.js +271 -0
  51. package/dist/master/api/domains.js +64 -0
  52. package/dist/master/api/groups.js +635 -0
  53. package/dist/master/api/guidance-templates.js +147 -0
  54. package/dist/master/api/index.js +89 -0
  55. package/dist/master/api/issues-patrol.js +172 -0
  56. package/dist/master/api/issues.js +663 -0
  57. package/dist/master/api/links-patrol.js +168 -0
  58. package/dist/master/api/links.js +114 -0
  59. package/dist/master/api/memory.js +259 -0
  60. package/dist/master/api/messages.js +157 -0
  61. package/dist/master/api/notes.js +77 -0
  62. package/dist/master/api/schedule-patterns.js +133 -0
  63. package/dist/master/api/schedules.js +272 -0
  64. package/dist/master/api/sessions.js +158 -0
  65. package/dist/master/api/share.js +269 -0
  66. package/dist/master/api/skills.js +190 -0
  67. package/dist/master/api/teams.js +122 -0
  68. package/dist/master/api/uploads.js +245 -0
  69. package/dist/master/auth.js +134 -0
  70. package/dist/master/dashboard/animations/calico-dozing.apng +0 -0
  71. package/dist/master/dashboard/animations/calico-error.apng +0 -0
  72. package/dist/master/dashboard/animations/calico-happy.apng +0 -0
  73. package/dist/master/dashboard/animations/calico-notification.apng +0 -0
  74. package/dist/master/dashboard/animations/calico-sleeping.apng +0 -0
  75. package/dist/master/dashboard/animations/calico-thinking.apng +0 -0
  76. package/dist/master/dashboard/animations/calico-waking.apng +0 -0
  77. package/dist/master/dashboard/assets/ApprovalCard-C38VV6ko.css +1 -0
  78. package/dist/master/dashboard/assets/ApprovalCard-CHPh2dmE.js +17 -0
  79. package/dist/master/dashboard/assets/ArtifactPanel-P_2gAP7v.js +1 -0
  80. package/dist/master/dashboard/assets/ArtifactPanel-aGHySny5.css +1 -0
  81. package/dist/master/dashboard/assets/css.worker-DaIe3gwK.js +84 -0
  82. package/dist/master/dashboard/assets/editor.worker-BCzxt1at.js +12 -0
  83. package/dist/master/dashboard/assets/html.worker-CKrFyw_2.js +461 -0
  84. package/dist/master/dashboard/assets/index-CChrTn81.css +32 -0
  85. package/dist/master/dashboard/assets/index-Dhu4SN1z.js +181 -0
  86. package/dist/master/dashboard/assets/json.worker-B7c_PmGb.js +49 -0
  87. package/dist/master/dashboard/assets/markdown-CeN5IgdF.js +29 -0
  88. package/dist/master/dashboard/assets/monaco-core-DyX1CsEw.css +1 -0
  89. package/dist/master/dashboard/assets/monaco-core-oQiQUisy.js +833 -0
  90. package/dist/master/dashboard/assets/monaco-setup-CiOPQdmo.js +1 -0
  91. package/dist/master/dashboard/assets/react-vendor-C8IxlyCR.js +67 -0
  92. package/dist/master/dashboard/assets/ts.worker-BhkL8olL.js +51334 -0
  93. package/dist/master/dashboard/assets/useMonaco-ILb4vyPh.js +12 -0
  94. package/dist/master/dashboard/assets/vite-preload-CxJPbCTl.js +1 -0
  95. package/dist/master/dashboard/debug-auth.html +197 -0
  96. package/dist/master/dashboard/favicon.ico +0 -0
  97. package/dist/master/dashboard/index.html +20 -0
  98. package/dist/master/dashboard/rotom-avatar.png +0 -0
  99. package/dist/master/db/agent-sessions.js +60 -0
  100. package/dist/master/db/agent-visibility.js +64 -0
  101. package/dist/master/db/agents.js +119 -0
  102. package/dist/master/db/ask-bridges.js +157 -0
  103. package/dist/master/db/build-update.js +59 -0
  104. package/dist/master/db/core.js +82 -0
  105. package/dist/master/db/domains.js +80 -0
  106. package/dist/master/db/groups.js +316 -0
  107. package/dist/master/db/guidance-templates.js +58 -0
  108. package/dist/master/db/index.js +12 -0
  109. package/dist/master/db/internal.js +45 -0
  110. package/dist/master/db/issues-patrol.js +81 -0
  111. package/dist/master/db/issues.js +373 -0
  112. package/dist/master/db/links.js +221 -0
  113. package/dist/master/db/master-node.js +43 -0
  114. package/dist/master/db/memory.js +272 -0
  115. package/dist/master/db/messages.js +210 -0
  116. package/dist/master/db/notes.js +55 -0
  117. package/dist/master/db/schedule-patterns.js +56 -0
  118. package/dist/master/db/schedules.js +135 -0
  119. package/dist/master/db/skills.js +144 -0
  120. package/dist/master/db/team.js +88 -0
  121. package/dist/master/db/types.js +10 -0
  122. package/dist/master/db.js +12 -0
  123. package/dist/master/embedded.js +133 -0
  124. package/dist/master/federation/client.js +283 -0
  125. package/dist/master/federation/identity.js +133 -0
  126. package/dist/master/federation/manager.js +267 -0
  127. package/dist/master/federation/publisher.js +87 -0
  128. package/dist/master/federation/self-publisher.js +69 -0
  129. package/dist/master/federation/server.js +487 -0
  130. package/dist/master/group-paths.js +208 -0
  131. package/dist/master/offline-queue.js +38 -0
  132. package/dist/master/opc-bootstrap.js +245 -0
  133. package/dist/master/patrol-terminal.js +275 -0
  134. package/dist/master/repo-scan.js +188 -0
  135. package/dist/master/router.js +214 -0
  136. package/dist/master/scheduler-handlers.js +510 -0
  137. package/dist/master/scheduler.js +201 -0
  138. package/dist/master/server.js +203 -0
  139. package/dist/master/services/link-collector.js +82 -0
  140. package/dist/master/services/link-patrol-bootstrap.js +50 -0
  141. package/dist/master/services/memory-extract-prompt.js +34 -0
  142. package/dist/master/services/patrol-bootstrap.js +63 -0
  143. package/dist/master/share-tokens.js +56 -0
  144. package/dist/master/terminal-hub.js +300 -0
  145. package/dist/master/uploads.js +108 -0
  146. package/dist/master/util/fs.js +100 -0
  147. package/dist/master/util/paths.js +50 -0
  148. package/dist/master/util/persona.js +10 -0
  149. package/dist/master/ws-hub/connection.js +928 -0
  150. package/dist/master/ws-hub/conversation.js +290 -0
  151. package/dist/master/ws-hub/directory.js +70 -0
  152. package/dist/master/ws-hub/dispatch-enrich.js +34 -0
  153. package/dist/master/ws-hub/hub.js +136 -0
  154. package/dist/master/ws-hub/index.js +9 -0
  155. package/dist/master/ws-hub/internal.js +35 -0
  156. package/dist/master/ws-hub/routing.js +295 -0
  157. package/dist/master/ws-hub/sessions.js +130 -0
  158. package/dist/master/ws-hub.js +11 -0
  159. package/dist/shared/agent-profile.js +44 -0
  160. package/dist/shared/constants.js +55 -0
  161. package/dist/shared/dedup.js +33 -0
  162. package/dist/shared/group-context.js +62 -0
  163. package/dist/shared/json-codec.js +33 -0
  164. package/dist/shared/logger.js +136 -0
  165. package/dist/shared/mention.js +22 -0
  166. package/dist/shared/network.js +40 -0
  167. package/dist/shared/parse.js +18 -0
  168. package/dist/shared/prompt-composer.js +171 -0
  169. package/dist/shared/protocol/client-messages.js +8 -0
  170. package/dist/shared/protocol/enums.js +6 -0
  171. package/dist/shared/protocol/federation.js +62 -0
  172. package/dist/shared/protocol/guards.js +87 -0
  173. package/dist/shared/protocol/server-messages.js +8 -0
  174. package/dist/shared/protocol/types.js +8 -0
  175. package/dist/shared/protocol.js +19 -0
  176. package/dist/shared/readonly-allowlist.js +122 -0
  177. package/dist/shared/rotom-cli-prompt.js +23 -0
  178. package/dist/shared/skill-context.js +19 -0
  179. package/dist/shared/skill-md.js +43 -0
  180. package/dist/shared/slash-commands.js +50 -0
  181. package/dist/shared/time.js +80 -0
  182. package/dist/shared/title.js +46 -0
  183. package/dist/shared/url-extractor.js +99 -0
  184. package/migrations/001-schema.sql +942 -0
  185. package/package.json +68 -0
  186. package/scripts/fix-node-pty-perms.mjs +46 -0
  187. package/skill/rotom-a2a-communicate/SKILL.md +257 -0
  188. package/skill/rotom-bus-host/SKILL.md +78 -0
  189. package/skill/rotom-bus-host/scripts/poll-replies.sh +148 -0
@@ -0,0 +1,12 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-core-DyX1CsEw.css"])))=>i.map(i=>d[i]);
2
+ import{r as a,W as T}from"./react-vendor-C8IxlyCR.js";import{_ as ye}from"./vite-preload-CxJPbCTl.js";function oe(e,t){(t==null||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function we(e){if(Array.isArray(e))return e}function Oe(e,t,r){return(t=Ie(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function je(e,t){var r=e==null?null:typeof Symbol<"u"&&e[Symbol.iterator]||e["@@iterator"];if(r!=null){var n,o,i,s,p=[],g=!0,v=!1;try{if(i=(r=r.call(e)).next,t!==0)for(;!(g=(n=i.call(r)).done)&&(p.push(n.value),p.length!==t);g=!0);}catch(E){v=!0,o=E}finally{try{if(!g&&r.return!=null&&(s=r.return(),Object(s)!==s))return}finally{if(v)throw o}}return p}}function Me(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
3
+ In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function ie(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function ue(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?ie(Object(r),!0).forEach(function(n){Oe(e,n,r[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):ie(Object(r)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))})}return e}function Ee(e,t){if(e==null)return{};var r,n,o=Pe(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)r=i[n],t.indexOf(r)===-1&&{}.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function Pe(e,t){if(e==null)return{};var r={};for(var n in e)if({}.hasOwnProperty.call(e,n)){if(t.indexOf(n)!==-1)continue;r[n]=e[n]}return r}function Se(e,t){return we(e)||je(e,t)||Ce(e,t)||Me()}function Re(e,t){if(typeof e!="object"||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var n=r.call(e,t);if(typeof n!="object")return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}function Ie(e){var t=Re(e,"string");return typeof t=="symbol"?t:t+""}function Ce(e,t){if(e){if(typeof e=="string")return oe(e,t);var r={}.toString.call(e).slice(8,-1);return r==="Object"&&e.constructor&&(r=e.constructor.name),r==="Map"||r==="Set"?Array.from(e):r==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?oe(e,t):void 0}}function Le(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ae(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),r.push.apply(r,n)}return r}function ce(e){for(var t=1;t<arguments.length;t++){var r=arguments[t]!=null?arguments[t]:{};t%2?ae(Object(r),!0).forEach(function(n){Le(e,n,r[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):ae(Object(r)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(r,n))})}return e}function Ae(){for(var e=arguments.length,t=new Array(e),r=0;r<e;r++)t[r]=arguments[r];return function(n){return t.reduceRight(function(o,i){return i(o)},n)}}function N(e){return function t(){for(var r=this,n=arguments.length,o=new Array(n),i=0;i<n;i++)o[i]=arguments[i];return o.length>=e.length?e.apply(this,o):function(){for(var s=arguments.length,p=new Array(s),g=0;g<s;g++)p[g]=arguments[g];return t.apply(r,[].concat(o,p))}}}function K(e){return{}.toString.call(e).includes("Object")}function Te(e){return!Object.keys(e).length}function z(e){return typeof e=="function"}function $e(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function De(e,t){return K(t)||S("changeType"),Object.keys(t).some(function(r){return!$e(e,r)})&&S("changeField"),t}function Ve(e){z(e)||S("selectorType")}function xe(e){z(e)||K(e)||S("handlerType"),K(e)&&Object.values(e).some(function(t){return!z(t)})&&S("handlersType")}function _e(e){e||S("initialIsRequired"),K(e)||S("initialType"),Te(e)&&S("initialContent")}function Ne(e,t){throw new Error(e[t]||e.default)}var qe={initialIsRequired:"initial state is required",initialType:"initial state should be an object",initialContent:"initial state shouldn't be an empty object",handlerType:"handler should be an object or a function",handlersType:"all handlers should be a functions",selectorType:"selector should be a function",changeType:"provided value of changes should be an object",changeField:'it seams you want to change a field in the state which is not specified in the "initial" state',default:"an unknown error accured in `state-local` package"},S=N(Ne)(qe),H={changes:De,selector:Ve,handler:xe,initial:_e};function ze(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};H.initial(e),H.handler(t);var r={current:e},n=N(We)(r,t),o=N(Ue)(r),i=N(H.changes)(e),s=N(Fe)(r);function p(){var v=arguments.length>0&&arguments[0]!==void 0?arguments[0]:function(E){return E};return H.selector(v),v(r.current)}function g(v){Ae(n,o,i,s)(v)}return[p,g]}function Fe(e,t){return z(t)?t(e.current):t}function Ue(e,t){return e.current=ce(ce({},e.current),t),t}function We(e,t,r){return z(t)?t(e.current):Object.keys(r).forEach(function(n){var o;return(o=t[n])===null||o===void 0?void 0:o.call(t,e.current[n])}),r}var He={create:ze},Be={paths:{vs:"https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs"}};function Ke(e){return function t(){for(var r=this,n=arguments.length,o=new Array(n),i=0;i<n;i++)o[i]=arguments[i];return o.length>=e.length?e.apply(this,o):function(){for(var s=arguments.length,p=new Array(s),g=0;g<s;g++)p[g]=arguments[g];return t.apply(r,[].concat(o,p))}}}function Ge(e){return{}.toString.call(e).includes("Object")}function Ye(e){return e||le("configIsRequired"),Ge(e)||le("configType"),e.urls?(Je(),{paths:{vs:e.urls.monacoBase}}):e}function Je(){console.warn(se.deprecation)}function Qe(e,t){throw new Error(e[t]||e.default)}var se={configIsRequired:"the configuration object is required",configType:"the configuration object should be an object",default:"an unknown error accured in `@monaco-editor/loader` package",deprecation:`Deprecation warning!
4
+ You are using deprecated way of configuration.
5
+
6
+ Instead of using
7
+ monaco.config({ urls: { monacoBase: '...' } })
8
+ use
9
+ monaco.config({ paths: { vs: '...' } })
10
+
11
+ For more please check the link https://github.com/suren-atoyan/monaco-loader#config
12
+ `},le=Ke(Qe)(se),Xe={config:Ye},Ze=function(){for(var t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return function(o){return r.reduceRight(function(i,s){return s(i)},o)}};function fe(e,t){return Object.keys(t).forEach(function(r){t[r]instanceof Object&&e[r]&&Object.assign(t[r],fe(e[r],t[r]))}),ue(ue({},e),t)}var ke={type:"cancelation",msg:"operation is manually canceled"};function ee(e){var t=!1,r=new Promise(function(n,o){e.then(function(i){return t?o(ke):n(i)}),e.catch(o)});return r.cancel=function(){return t=!0},r}var et=["monaco"],tt=He.create({config:Be,isInitialized:!1,resolve:null,reject:null,monaco:null}),de=Se(tt,2),F=de[0],G=de[1];function rt(e){var t=Xe.config(e),r=t.monaco,n=Ee(t,et);G(function(o){return{config:fe(o.config,n),monaco:r}})}function nt(){var e=F(function(t){var r=t.monaco,n=t.isInitialized,o=t.resolve;return{monaco:r,isInitialized:n,resolve:o}});if(!e.isInitialized){if(G({isInitialized:!0}),e.monaco)return e.resolve(e.monaco),ee(te);if(window.monaco&&window.monaco.editor)return pe(window.monaco),e.resolve(window.monaco),ee(te);Ze(ot,ut)(at)}return ee(te)}function ot(e){return document.body.appendChild(e)}function it(e){var t=document.createElement("script");return e&&(t.src=e),t}function ut(e){var t=F(function(n){var o=n.config,i=n.reject;return{config:o,reject:i}}),r=it("".concat(t.config.paths.vs,"/loader.js"));return r.onload=function(){return e()},r.onerror=t.reject,r}function at(){var e=F(function(r){var n=r.config,o=r.resolve,i=r.reject;return{config:n,resolve:o,reject:i}}),t=window.require;t.config(e.config),t(["vs/editor/editor.main"],function(r){var n=r.m||r;pe(n),e.resolve(n)},function(r){e.reject(r)})}function pe(e){F().monaco||G({monaco:e})}function ct(){return F(function(e){var t=e.monaco;return t})}var te=new Promise(function(e,t){return G({resolve:e,reject:t})}),ge={config:rt,init:nt,__getMonacoInstance:ct},lt={wrapper:{display:"flex",position:"relative",textAlign:"initial"},fullWidth:{width:"100%"},hide:{display:"none"}},re=lt,st={container:{display:"flex",height:"100%",width:"100%",justifyContent:"center",alignItems:"center"}},ft=st;function dt({children:e}){return T.createElement("div",{style:ft.container},e)}var pt=dt,gt=pt;function ht({width:e,height:t,isEditorReady:r,loading:n,_ref:o,className:i,wrapperProps:s}){return T.createElement("section",{style:{...re.wrapper,width:e,height:t},...s},!r&&T.createElement(gt,null,n),T.createElement("div",{ref:o,style:{...re.fullWidth,...!r&&re.hide},className:i}))}var vt=ht,he=a.memo(vt);function mt(e){a.useEffect(e,[])}var ve=mt;function bt(e,t,r=!0){let n=a.useRef(!0);a.useEffect(n.current||!r?()=>{n.current=!1}:e,t)}var j=bt;function q(){}function A(e,t,r,n){return yt(e,n)||wt(e,t,r,n)}function yt(e,t){return e.editor.getModel(me(e,t))}function wt(e,t,r,n){return e.editor.createModel(t,r,n?me(e,n):void 0)}function me(e,t){return e.Uri.parse(t)}function Ot({original:e,modified:t,language:r,originalLanguage:n,modifiedLanguage:o,originalModelPath:i,modifiedModelPath:s,keepCurrentOriginalModel:p=!1,keepCurrentModifiedModel:g=!1,theme:v="light",loading:E="Loading...",options:M={},height:Y="100%",width:J="100%",className:Q,wrapperProps:X={},beforeMount:Z=q,onMount:k=q}){let[w,$]=a.useState(!1),[R,m]=a.useState(!0),b=a.useRef(null),h=a.useRef(null),D=a.useRef(null),y=a.useRef(k),l=a.useRef(Z),I=a.useRef(!1);ve(()=>{let u=ge.init();return u.then(f=>(h.current=f)&&m(!1)).catch(f=>(f==null?void 0:f.type)!=="cancelation"&&console.error("Monaco initialization: error:",f)),()=>b.current?V():u.cancel()}),j(()=>{if(b.current&&h.current){let u=b.current.getOriginalEditor(),f=A(h.current,e||"",n||r||"text",i||"");f!==u.getModel()&&u.setModel(f)}},[i],w),j(()=>{if(b.current&&h.current){let u=b.current.getModifiedEditor(),f=A(h.current,t||"",o||r||"text",s||"");f!==u.getModel()&&u.setModel(f)}},[s],w),j(()=>{let u=b.current.getModifiedEditor();u.getOption(h.current.editor.EditorOption.readOnly)?u.setValue(t||""):t!==u.getValue()&&(u.executeEdits("",[{range:u.getModel().getFullModelRange(),text:t||"",forceMoveMarkers:!0}]),u.pushUndoStop())},[t],w),j(()=>{var u,f;(f=(u=b.current)==null?void 0:u.getModel())==null||f.original.setValue(e||"")},[e],w),j(()=>{let{original:u,modified:f}=b.current.getModel();h.current.editor.setModelLanguage(u,n||r||"text"),h.current.editor.setModelLanguage(f,o||r||"text")},[r,n,o],w),j(()=>{var u;(u=h.current)==null||u.editor.setTheme(v)},[v],w),j(()=>{var u;(u=b.current)==null||u.updateOptions(M)},[M],w);let U=a.useCallback(()=>{var P;if(!h.current)return;l.current(h.current);let u=A(h.current,e||"",n||r||"text",i||""),f=A(h.current,t||"",o||r||"text",s||"");(P=b.current)==null||P.setModel({original:u,modified:f})},[r,t,o,e,n,i,s]),W=a.useCallback(()=>{var u;!I.current&&D.current&&(b.current=h.current.editor.createDiffEditor(D.current,{automaticLayout:!0,...M}),U(),(u=h.current)==null||u.editor.setTheme(v),$(!0),I.current=!0)},[M,v,U]);a.useEffect(()=>{w&&y.current(b.current,h.current)},[w]),a.useEffect(()=>{!R&&!w&&W()},[R,w,W]);function V(){var f,P,C,x;let u=(f=b.current)==null?void 0:f.getModel();p||((P=u==null?void 0:u.original)==null||P.dispose()),g||((C=u==null?void 0:u.modified)==null||C.dispose()),(x=b.current)==null||x.dispose()}return T.createElement(he,{width:J,height:Y,isEditorReady:w,loading:E,_ref:D,className:Q,wrapperProps:X})}var jt=Ot,At=a.memo(jt);function Mt(e){let t=a.useRef();return a.useEffect(()=>{t.current=e},[e]),t.current}var Et=Mt,B=new Map;function Pt({defaultValue:e,defaultLanguage:t,defaultPath:r,value:n,language:o,path:i,theme:s="light",line:p,loading:g="Loading...",options:v={},overrideServices:E={},saveViewState:M=!0,keepCurrentModel:Y=!1,width:J="100%",height:Q="100%",className:X,wrapperProps:Z={},beforeMount:k=q,onMount:w=q,onChange:$,onValidate:R=q}){let[m,b]=a.useState(!1),[h,D]=a.useState(!0),y=a.useRef(null),l=a.useRef(null),I=a.useRef(null),U=a.useRef(w),W=a.useRef(k),V=a.useRef(),u=a.useRef(n),f=Et(i),P=a.useRef(!1),C=a.useRef(!1);ve(()=>{let c=ge.init();return c.then(d=>(y.current=d)&&D(!1)).catch(d=>(d==null?void 0:d.type)!=="cancelation"&&console.error("Monaco initialization: error:",d)),()=>l.current?be():c.cancel()}),j(()=>{var d,O,_,L;let c=A(y.current,e||n||"",t||o||"",i||r||"");c!==((d=l.current)==null?void 0:d.getModel())&&(M&&B.set(f,(O=l.current)==null?void 0:O.saveViewState()),(_=l.current)==null||_.setModel(c),M&&((L=l.current)==null||L.restoreViewState(B.get(i))))},[i],m),j(()=>{var c;(c=l.current)==null||c.updateOptions(v)},[v],m),j(()=>{!l.current||n===void 0||(l.current.getOption(y.current.editor.EditorOption.readOnly)?l.current.setValue(n):n!==l.current.getValue()&&(C.current=!0,l.current.executeEdits("",[{range:l.current.getModel().getFullModelRange(),text:n,forceMoveMarkers:!0}]),l.current.pushUndoStop(),C.current=!1))},[n],m),j(()=>{var d,O;let c=(d=l.current)==null?void 0:d.getModel();c&&o&&((O=y.current)==null||O.editor.setModelLanguage(c,o))},[o],m),j(()=>{var c;p!==void 0&&((c=l.current)==null||c.revealLine(p))},[p],m),j(()=>{var c;(c=y.current)==null||c.editor.setTheme(s)},[s],m);let x=a.useCallback(()=>{var c;if(!(!I.current||!y.current)&&!P.current){W.current(y.current);let d=i||r,O=A(y.current,n||e||"",t||o||"",d||"");l.current=(c=y.current)==null?void 0:c.editor.create(I.current,{model:O,automaticLayout:!0,...v},E),M&&l.current.restoreViewState(B.get(d)),y.current.editor.setTheme(s),p!==void 0&&l.current.revealLine(p),b(!0),P.current=!0}},[e,t,r,n,o,i,v,E,M,s,p]);a.useEffect(()=>{m&&U.current(l.current,y.current)},[m]),a.useEffect(()=>{!h&&!m&&x()},[h,m,x]),u.current=n,a.useEffect(()=>{var c,d;m&&$&&((c=V.current)==null||c.dispose(),V.current=(d=l.current)==null?void 0:d.onDidChangeModelContent(O=>{C.current||$(l.current.getValue(),O)}))},[m,$]),a.useEffect(()=>{if(m){let c=y.current.editor.onDidChangeMarkers(d=>{var _;let O=(_=l.current.getModel())==null?void 0:_.uri;if(O&&d.find(L=>L.path===O.path)){let L=y.current.editor.getModelMarkers({resource:O});R==null||R(L)}});return()=>{c==null||c.dispose()}}return()=>{}},[m,R]);function be(){var c,d;(c=V.current)==null||c.dispose(),Y?M&&B.set(i,l.current.saveViewState()):(d=l.current.getModel())==null||d.dispose(),l.current.dispose()}return T.createElement(he,{width:J,height:Q,isEditorReady:m,loading:g,_ref:I,className:X,wrapperProps:Z})}var St=Pt,Rt=a.memo(St),Tt=Rt;let ne=null;function It(){return ne||(ne=ye(()=>import("./monaco-setup-CiOPQdmo.js"),__vite__mapDeps([0])).then(e=>e.default)),ne}function $t(){const[e,t]=a.useState(!1),[r,n]=a.useState(null);return a.useEffect(()=>{let o=!1;return It().then(()=>{o||t(!0)},i=>{o||n(i instanceof Error?i:new Error(String(i)))}),()=>{o=!0}},[]),{ready:e,error:r}}export{Tt as F,ge as l,$t as u,At as w};
@@ -0,0 +1 @@
1
+ const p=(function(){const s=typeof document<"u"&&document.createElement("link").relList;return s&&s.supports&&s.supports("modulepreload")?"modulepreload":"preload"})(),E=function(i){return"/dashboard/"+i},f={},y=function(s,c,v){let u=Promise.resolve();if(c&&c.length>0){let n=function(t){return Promise.all(t.map(o=>Promise.resolve(o).then(l=>({status:"fulfilled",value:l}),l=>({status:"rejected",reason:l}))))};document.getElementsByTagName("link");const e=document.querySelector("meta[property=csp-nonce]"),d=(e==null?void 0:e.nonce)||(e==null?void 0:e.getAttribute("nonce"));u=n(c.map(t=>{if(t=E(t),t in f)return;f[t]=!0;const o=t.endsWith(".css"),l=o?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${t}"]${l}`))return;const r=document.createElement("link");if(r.rel=o?"stylesheet":p,o||(r.as="script"),r.crossOrigin="",r.href=t,d&&r.setAttribute("nonce",d),document.head.appendChild(r),o)return new Promise((m,h)=>{r.addEventListener("load",m),r.addEventListener("error",()=>h(new Error(`Unable to preload CSS for ${t}`)))})}))}function a(n){const e=new Event("vite:preloadError",{cancelable:!0});if(e.payload=n,window.dispatchEvent(e),!e.defaultPrevented)throw n}return u.then(n=>{for(const e of n||[])e.status==="rejected"&&a(e.reason);return s().catch(a)})};export{y as _};
@@ -0,0 +1,197 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Auth Debug - A2A WORKSPACE</title>
5
+ <style>
6
+ body {
7
+ font-family: monospace;
8
+ padding: 20px;
9
+ background: #1e1e1e;
10
+ color: #d4d4d4;
11
+ }
12
+ .section {
13
+ margin: 20px 0;
14
+ padding: 15px;
15
+ border: 1px solid #444;
16
+ border-radius: 5px;
17
+ }
18
+ .success { color: #4ec9b0; }
19
+ .error { color: #f48771; }
20
+ .info { color: #569cd6; }
21
+ button {
22
+ background: #0e639c;
23
+ color: white;
24
+ border: none;
25
+ padding: 10px 20px;
26
+ margin: 5px;
27
+ border-radius: 3px;
28
+ cursor: pointer;
29
+ }
30
+ button:hover { background: #1177bb; }
31
+ pre {
32
+ background: #2d2d2d;
33
+ padding: 10px;
34
+ border-radius: 3px;
35
+ overflow-x: auto;
36
+ }
37
+ </style>
38
+ </head>
39
+ <body>
40
+ <h1>🔍 Dashboard Authentication Debug</h1>
41
+
42
+ <div class="section">
43
+ <h2>1. Check LocalStorage</h2>
44
+ <button onclick="checkStorage()">Check Storage</button>
45
+ <pre id="storage-result">Click to check...</pre>
46
+ </div>
47
+
48
+ <div class="section">
49
+ <h2>2. Test Login</h2>
50
+ <button onclick="testLogin()">Test Login (admin/admin123)</button>
51
+ <pre id="login-result">Click to test...</pre>
52
+ </div>
53
+
54
+ <div class="section">
55
+ <h2>3. Test Authenticated Request</h2>
56
+ <button onclick="testAuthRequest()">Test /api/agents</button>
57
+ <pre id="auth-result">Click to test...</pre>
58
+ </div>
59
+
60
+ <div class="section">
61
+ <h2>4. Manual Token Test</h2>
62
+ <input type="text" id="manual-token" placeholder="Paste token here" style="width: 80%; padding: 5px;">
63
+ <button onclick="testManualToken()">Test Token</button>
64
+ <pre id="manual-result">Paste token and click test...</pre>
65
+ </div>
66
+
67
+ <script>
68
+ function checkStorage() {
69
+ const result = document.getElementById('storage-result');
70
+ const token = localStorage.getItem('auth_token');
71
+
72
+ if (token) {
73
+ // Decode JWT to see payload
74
+ try {
75
+ const payload = JSON.parse(atob(token.split('.')[1]));
76
+ result.innerHTML = `<span class="success">✓ Token found in localStorage</span>\n\n` +
77
+ `Token: ${token.substring(0, 50)}...\n\n` +
78
+ `Decoded payload:\n${JSON.stringify(payload, null, 2)}`;
79
+ } catch (e) {
80
+ result.innerHTML = `<span class="error">✗ Invalid token format</span>\n\n` +
81
+ `Token: ${token}`;
82
+ }
83
+ } else {
84
+ result.innerHTML = '<span class="error">✗ No token found in localStorage</span>';
85
+ }
86
+ }
87
+
88
+ async function testLogin() {
89
+ const result = document.getElementById('login-result');
90
+ result.innerHTML = '<span class="info">Testing login...</span>';
91
+
92
+ try {
93
+ const response = await fetch('/api/login', {
94
+ method: 'POST',
95
+ headers: {'Content-Type': 'application/json'},
96
+ body: JSON.stringify({username: 'admin', password: 'admin123'})
97
+ });
98
+
99
+ const data = await response.json();
100
+
101
+ if (response.ok) {
102
+ // Store token
103
+ localStorage.setItem('auth_token', data.token);
104
+
105
+ const payload = JSON.parse(atob(data.token.split('.')[1]));
106
+ result.innerHTML = `<span class="success">✓ Login successful!</span>\n\n` +
107
+ `Token: ${data.token.substring(0, 50)}...\n\n` +
108
+ `Decoded payload:\n${JSON.stringify(payload, null, 2)}\n\n` +
109
+ `Token stored to localStorage`;
110
+ } else {
111
+ result.innerHTML = `<span class="error">✗ Login failed</span>\n\n` +
112
+ `Status: ${response.status}\n` +
113
+ `Error: ${data.error || 'Unknown error'}`;
114
+ }
115
+ } catch (error) {
116
+ result.innerHTML = `<span class="error">✗ Network error</span>\n\n${error.message}`;
117
+ }
118
+ }
119
+
120
+ async function testAuthRequest() {
121
+ const result = document.getElementById('auth-result');
122
+ const token = localStorage.getItem('auth_token');
123
+
124
+ if (!token) {
125
+ result.innerHTML = '<span class="error">✗ No token in localStorage. Please login first.</span>';
126
+ return;
127
+ }
128
+
129
+ result.innerHTML = `<span class="info">Testing /api/agents with token...</span>\n\n` +
130
+ `Authorization header: Bearer ${token.substring(0, 30)}...`;
131
+
132
+ try {
133
+ const response = await fetch('/api/agents', {
134
+ method: 'GET',
135
+ headers: {
136
+ 'Authorization': `Bearer ${token}`,
137
+ 'Content-Type': 'application/json'
138
+ }
139
+ });
140
+
141
+ const text = await response.text();
142
+
143
+ if (response.ok) {
144
+ const data = JSON.parse(text);
145
+ result.innerHTML = `<span class="success">✓ Authenticated request successful!</span>\n\n` +
146
+ `Status: ${response.status}\n\n` +
147
+ `Response:\n${JSON.stringify(data, null, 2).substring(0, 500)}...`;
148
+ } else {
149
+ result.innerHTML = `<span class="error">✗ Authenticated request failed</span>\n\n` +
150
+ `Status: ${response.status}\n` +
151
+ `Response: ${text}`;
152
+ }
153
+ } catch (error) {
154
+ result.innerHTML = `<span class="error">✗ Network error</span>\n\n${error.message}`;
155
+ }
156
+ }
157
+
158
+ async function testManualToken() {
159
+ const result = document.getElementById('manual-result');
160
+ const token = document.getElementById('manual-token').value.trim();
161
+
162
+ if (!token) {
163
+ result.innerHTML = '<span class="error">✗ Please enter a token</span>';
164
+ return;
165
+ }
166
+
167
+ result.innerHTML = `<span class="info">Testing token...</span>`;
168
+
169
+ try {
170
+ const response = await fetch('/api/agents', {
171
+ method: 'GET',
172
+ headers: {
173
+ 'Authorization': `Bearer ${token}`,
174
+ 'Content-Type': 'application/json'
175
+ }
176
+ });
177
+
178
+ const text = await response.text();
179
+
180
+ if (response.ok) {
181
+ result.innerHTML = `<span class="success">✓ Token is valid!</span>\n\n` +
182
+ `Status: ${response.status}`;
183
+ } else {
184
+ result.innerHTML = `<span class="error">✗ Token is invalid or expired</span>\n\n` +
185
+ `Status: ${response.status}\n` +
186
+ `Response: ${text}`;
187
+ }
188
+ } catch (error) {
189
+ result.innerHTML = `<span class="error">✗ Network error</span>\n\n${error.message}`;
190
+ }
191
+ }
192
+
193
+ // Auto-check storage on load
194
+ window.onload = () => checkStorage();
195
+ </script>
196
+ </body>
197
+ </html>
@@ -0,0 +1,20 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/x-icon" href="/dashboard/favicon.ico" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Rotom · A2A WORKSPACE</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <link
11
+ rel="stylesheet"
12
+ href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap"
13
+ />
14
+ <script type="module" crossorigin src="/dashboard/assets/index-Dhu4SN1z.js"></script>
15
+ <link rel="stylesheet" crossorigin href="/dashboard/assets/index-CChrTn81.css">
16
+ </head>
17
+ <body>
18
+ <div id="root"></div>
19
+ </body>
20
+ </html>
@@ -0,0 +1,60 @@
1
+ import { nowBeijing } from "../../shared/time.js";
2
+ export const agentSessionMethods = {
3
+ /** 插入或更新一行。usage/model/cumulative 等字段全量覆盖;created_at
4
+ * 首次插入时写入,后续 upsert 不动;last_used_at 每次 upsert 刷新。 */
5
+ upsertAgentSession(s) {
6
+ const now = nowBeijing();
7
+ const u = s.usage;
8
+ this.db.prepare(`
9
+ INSERT INTO agent_sessions (
10
+ group_id, agent_name, cli_tool, session_id,
11
+ created_at, last_used_at,
12
+ input_tokens, output_tokens, cache_read_tokens, cache_creation_tokens,
13
+ total_cost_usd, model,
14
+ cumulative_cost_usd,
15
+ cumulative_input_tokens, cumulative_output_tokens,
16
+ cumulative_cache_read_tokens, cumulative_cache_creation_tokens,
17
+ invalidated_at
18
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)
19
+ ON CONFLICT(cli_tool, group_id, session_id) DO UPDATE SET
20
+ agent_name = excluded.agent_name,
21
+ last_used_at = excluded.last_used_at,
22
+ input_tokens = COALESCE(excluded.input_tokens, agent_sessions.input_tokens),
23
+ output_tokens = COALESCE(excluded.output_tokens, agent_sessions.output_tokens),
24
+ cache_read_tokens = COALESCE(excluded.cache_read_tokens, agent_sessions.cache_read_tokens),
25
+ cache_creation_tokens = COALESCE(excluded.cache_creation_tokens, agent_sessions.cache_creation_tokens),
26
+ total_cost_usd = COALESCE(excluded.total_cost_usd, agent_sessions.total_cost_usd),
27
+ model = COALESCE(excluded.model, agent_sessions.model),
28
+ cumulative_cost_usd = COALESCE(excluded.cumulative_cost_usd, agent_sessions.cumulative_cost_usd),
29
+ cumulative_input_tokens = COALESCE(excluded.cumulative_input_tokens, agent_sessions.cumulative_input_tokens),
30
+ cumulative_output_tokens = COALESCE(excluded.cumulative_output_tokens, agent_sessions.cumulative_output_tokens),
31
+ cumulative_cache_read_tokens = COALESCE(excluded.cumulative_cache_read_tokens, agent_sessions.cumulative_cache_read_tokens),
32
+ cumulative_cache_creation_tokens = COALESCE(excluded.cumulative_cache_creation_tokens, agent_sessions.cumulative_cache_creation_tokens),
33
+ invalidated_at = NULL
34
+ `).run(s.groupId, s.agentName, s.cliTool, s.sessionId, now, now, u?.inputTokens ?? null, u?.outputTokens ?? null, u?.cacheReadTokens ?? null, u?.cacheCreationTokens ?? null, u?.totalCostUsd ?? null, s.model ?? null, s.cumulativeCostUsd ?? 0, s.cumulativeInputTokens ?? 0, s.cumulativeOutputTokens ?? 0, s.cumulativeCacheReadTokens ?? 0, s.cumulativeCacheCreationTokens ?? 0);
35
+ },
36
+ /** 列出该群所有 session(包括已失效的),按最近使用倒序。Dashboard 用。 */
37
+ listAgentSessionsByGroup(groupId) {
38
+ return this.db.prepare("SELECT * FROM agent_sessions WHERE group_id = ? ORDER BY invalidated_at IS NOT NULL, last_used_at DESC").all(groupId);
39
+ },
40
+ /** 列出某 agent + cliTool 的所有 active session(未失效)。worker 启动时
41
+ * master 推 session_sync_push 用。 */
42
+ listActiveAgentSessions(agentName, cliTool) {
43
+ return this.db.prepare("SELECT * FROM agent_sessions WHERE agent_name = ? AND cli_tool = ? AND invalidated_at IS NULL ORDER BY last_used_at DESC").all(agentName, cliTool);
44
+ },
45
+ /** 标记失效:不删除行,只打 invalidated_at 戳。保留历史。 */
46
+ invalidateAgentSession(cliTool, groupId, sessionId) {
47
+ const now = nowBeijing();
48
+ const r = this.db.prepare("UPDATE agent_sessions SET invalidated_at = ? WHERE cli_tool = ? AND group_id = ? AND session_id = ?").run(now, cliTool, groupId, sessionId);
49
+ return r.changes > 0;
50
+ },
51
+ /** 硬删除:Dashboard 用户主动删 session 时调用。 */
52
+ deleteAgentSession(cliTool, groupId, sessionId) {
53
+ const r = this.db.prepare("DELETE FROM agent_sessions WHERE cli_tool = ? AND group_id = ? AND session_id = ?").run(cliTool, groupId, sessionId);
54
+ return r.changes > 0;
55
+ },
56
+ /** 反查单条(按 sessionId)。GET /sessions/:.../usage 用。 */
57
+ findAgentSession(sessionId) {
58
+ return this.db.prepare("SELECT * FROM agent_sessions WHERE session_id = ? ORDER BY invalidated_at IS NOT NULL, last_used_at DESC LIMIT 1").get(sessionId);
59
+ },
60
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * agent_visibility CRUD —— 跨 master 可见的 agent 发布记录。
3
+ *
4
+ * 协调侧权威:member 通过 FedAgentPublish 上报,协调侧 upsert。
5
+ * Member 侧缓存:从 FedDirectorySync 同步,只读;Routing 在本机找不到时查这里。
6
+ *
7
+ * PK 是 (team_id, master_id, agent_name),不用 hostname(hostname 只是 display,可改)。
8
+ * 历史命名:Phase 2 叫 department_id,migration 058 改名 team_id。
9
+ */
10
+ export const agentVisibilityMethods = {
11
+ listVisibleAgents(teamId) {
12
+ return this.db.prepare("SELECT * FROM agent_visibility WHERE team_id = ? ORDER BY hostname, agent_name").all(teamId);
13
+ },
14
+ /**
15
+ * UPSERT 协调侧权威记录(member 上报时调用)。
16
+ * 若 hostname 改了,只更新 display 列,master_id+name 主键不变。
17
+ */
18
+ upsertVisibleAgent(input) {
19
+ this.db.prepare(`
20
+ INSERT INTO agent_visibility
21
+ (team_id, master_id, agent_name, hostname, display_name, is_human, online, last_heartbeat)
22
+ VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
23
+ ON CONFLICT(team_id, master_id, agent_name) DO UPDATE SET
24
+ hostname = excluded.hostname,
25
+ display_name = COALESCE(excluded.display_name, agent_visibility.display_name),
26
+ is_human = excluded.is_human,
27
+ online = excluded.online,
28
+ last_heartbeat = datetime('now')
29
+ `).run(input.team_id, input.master_id, input.agent_name, input.hostname, input.display_name ?? null, input.is_human ? 1 : 0, input.online ? 1 : 0);
30
+ },
31
+ setVisibleOnline(teamId, masterId, agentName, online) {
32
+ this.db.prepare(`
33
+ UPDATE agent_visibility SET
34
+ online = ?,
35
+ last_heartbeat = datetime('now')
36
+ WHERE team_id = ? AND master_id = ? AND agent_name = ?
37
+ `).run(online ? 1 : 0, teamId, masterId, agentName);
38
+ },
39
+ removeVisibleAgent(teamId, masterId, agentName) {
40
+ const r = this.db.prepare("DELETE FROM agent_visibility WHERE team_id = ? AND master_id = ? AND agent_name = ?").run(teamId, masterId, agentName);
41
+ return r.changes > 0;
42
+ },
43
+ /** member 离开团队 / 协调 master 下线时:清掉该 master 在团队里的所有可见 agent */
44
+ clearVisibleAgentsForMaster(teamId, masterId) {
45
+ const r = this.db.prepare("DELETE FROM agent_visibility WHERE team_id = ? AND master_id = ?").run(teamId, masterId);
46
+ return r.changes;
47
+ },
48
+ /** 清掉整个团队的所有可见 agent(member 离开时) */
49
+ clearVisibleAgents(teamId) {
50
+ const r = this.db.prepare("DELETE FROM agent_visibility WHERE team_id = ?").run(teamId);
51
+ return r.changes;
52
+ },
53
+ /** 按 (hostname, name) 反查 —— Router 解析 "alice@hostB" 时用 */
54
+ findVisibleAgentByHostAndName(teamId, hostname, agentName) {
55
+ return this.db.prepare("SELECT * FROM agent_visibility WHERE team_id = ? AND hostname = ? AND agent_name = ?").get(teamId, hostname, agentName);
56
+ },
57
+ /**
58
+ * 按 name 反查(不带 hostname) —— Router 解析裸 "alice" 时用。
59
+ * 若团队内 name 唯一,返回单条;否则返回多条(调用方报歧义错误)。
60
+ */
61
+ findVisibleAgentsByName(teamId, agentName) {
62
+ return this.db.prepare("SELECT * FROM agent_visibility WHERE team_id = ? AND agent_name = ?").all(teamId, agentName);
63
+ },
64
+ };
@@ -0,0 +1,119 @@
1
+ import { nowBeijing } from "../../shared/time.js";
2
+ import { buildUpdate } from "./build-update.js";
3
+ export const agentMethods = {
4
+ getAgentByName(name) {
5
+ return this.db.prepare("SELECT * FROM agents WHERE name = ?").get(name);
6
+ },
7
+ /**
8
+ * 跨 hostname 维度查询(本机内仍按 hostname 复合键,但本机内 name 已 UNIQUE,
9
+ * 等价于 getAgentByName;留给 Phase 2 federation 使用)。
10
+ */
11
+ getAgentByHostAndName(hostname, name) {
12
+ return this.db.prepare("SELECT * FROM agents WHERE hostname = ? AND name = ?").get(hostname, name);
13
+ },
14
+ /**
15
+ * 本机 agent 查询:隐式注入本机 hostname(从 master_node 读)。
16
+ * Phase 1 的高频路径 —— 本机 executor / dashboard 调用都走这里。
17
+ * 如果 master_node 还没身份行(早期启动阶段),fallback 按 name 查(向后兼容)。
18
+ */
19
+ getLocalAgentByName(name) {
20
+ const localHostname = this.getLocalHostname();
21
+ if (localHostname) {
22
+ return this.db.prepare("SELECT * FROM agents WHERE hostname = ? AND name = ?").get(localHostname, name);
23
+ }
24
+ return this.db.prepare("SELECT * FROM agents WHERE name = ?").get(name);
25
+ },
26
+ getAgentById(id) {
27
+ return this.db.prepare("SELECT * FROM agents WHERE id = ?").get(id);
28
+ },
29
+ /** Lookup agent by token hash — used as fallback when name changes but token stays the same. */
30
+ getAgentByTokenHash(tokenHash) {
31
+ return this.db.prepare("SELECT * FROM agents WHERE token_hash = ?").get(tokenHash);
32
+ },
33
+ /** Update agent name (used when agent reconnects with a new name but same token). */
34
+ updateAgentName(id, name) {
35
+ this.db.prepare("UPDATE agents SET name = ?, updated_at = datetime('now') WHERE id = ?").run(name, id);
36
+ },
37
+ listAgents(filter) {
38
+ let sql = "SELECT * FROM agents WHERE 1=1";
39
+ const params = [];
40
+ if (filter?.status) {
41
+ sql += " AND status = ?";
42
+ params.push(filter.status);
43
+ }
44
+ if (filter?.domain) {
45
+ sql += " AND domain = ?";
46
+ params.push(filter.domain);
47
+ }
48
+ if (filter?.enabled !== undefined) {
49
+ sql += " AND enabled = ?";
50
+ params.push(filter.enabled ? 1 : 0);
51
+ }
52
+ sql += " ORDER BY name";
53
+ return this.db.prepare(sql).all(...params);
54
+ },
55
+ insertAgent(agent) {
56
+ this.db.prepare(`
57
+ INSERT INTO agents (id, name, description, domain, hostname, token_hash, token, profile)
58
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
59
+ `).run(agent.id, agent.name, agent.description || null, agent.domain || null, agent.hostname ?? null, agent.tokenHash, agent.token, agent.profile || null);
60
+ },
61
+ updateAgentMeta(id, meta) {
62
+ const built = buildUpdate({
63
+ table: "agents",
64
+ sets: {
65
+ description: meta.description,
66
+ domain: meta.domain,
67
+ profile: meta.profile,
68
+ avatar_url: meta.avatar_url,
69
+ },
70
+ where: "id = ?",
71
+ whereParams: [id],
72
+ updatedAt: "datetime-now",
73
+ });
74
+ if (built)
75
+ this.db.prepare(built.sql).run(...built.params);
76
+ },
77
+ updateAgentEnabled(id, enabled) {
78
+ this.db.prepare("UPDATE agents SET enabled = ?, updated_at = datetime('now') WHERE id = ?").run(enabled ? 1 : 0, id);
79
+ },
80
+ setAgentOnline(id, instance) {
81
+ this.db.prepare(`
82
+ UPDATE agents SET
83
+ status = 'online',
84
+ instance_id = ?,
85
+ hostname = ?,
86
+ platform = ?,
87
+ endpoint = ?,
88
+ version = ?,
89
+ connected_at = datetime('now'),
90
+ last_heartbeat = datetime('now'),
91
+ updated_at = datetime('now')
92
+ WHERE id = ?
93
+ `).run(instance?.instanceId || null, instance?.hostname || null, instance?.platform || null, instance?.endpoint || null, instance?.version || null, id);
94
+ },
95
+ setAgentOffline(id) {
96
+ this.db.prepare("UPDATE agents SET status = 'offline', updated_at = datetime('now') WHERE id = ?").run(id);
97
+ },
98
+ /** Reset all agents to offline — called on Master startup to clear stale state. */
99
+ resetAllOnline() {
100
+ const result = this.db.prepare("UPDATE agents SET status = 'offline', updated_at = datetime('now') WHERE status = 'online'").run();
101
+ return result.changes;
102
+ },
103
+ updateAgentToken(id, tokenHash, token) {
104
+ this.db.prepare("UPDATE agents SET token_hash = ?, token = ?, updated_at = datetime('now') WHERE id = ?").run(tokenHash, token, id);
105
+ // Record token refresh timestamp for JWT iat validation.
106
+ this.setConfig(`token_refreshed_at:${id}`, nowBeijing());
107
+ },
108
+ /** Get the timestamp when an agent's token was last refreshed. */
109
+ getTokenRefreshedAt(id) {
110
+ return this.getConfig(`token_refreshed_at:${id}`);
111
+ },
112
+ updateHeartbeat(id) {
113
+ this.db.prepare("UPDATE agents SET last_heartbeat = datetime('now') WHERE id = ?").run(id);
114
+ },
115
+ deleteAgent(id) {
116
+ this.db.prepare("DELETE FROM offline_messages WHERE target_agent = ?").run(id);
117
+ this.db.prepare("DELETE FROM agents WHERE id = ?").run(id);
118
+ },
119
+ };