autoglm-gui 1.4.0__py3-none-any.whl → 1.5.0__py3-none-any.whl

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 (120) hide show
  1. AutoGLM_GUI/__init__.py +11 -0
  2. AutoGLM_GUI/__main__.py +26 -8
  3. AutoGLM_GUI/actions/__init__.py +6 -0
  4. AutoGLM_GUI/actions/handler.py +196 -0
  5. AutoGLM_GUI/actions/types.py +15 -0
  6. AutoGLM_GUI/adb/__init__.py +53 -0
  7. AutoGLM_GUI/adb/apps.py +227 -0
  8. AutoGLM_GUI/adb/connection.py +323 -0
  9. AutoGLM_GUI/adb/device.py +171 -0
  10. AutoGLM_GUI/adb/input.py +67 -0
  11. AutoGLM_GUI/adb/screenshot.py +11 -0
  12. AutoGLM_GUI/adb/timing.py +167 -0
  13. AutoGLM_GUI/adb_plus/keyboard_installer.py +4 -2
  14. AutoGLM_GUI/adb_plus/qr_pair.py +8 -8
  15. AutoGLM_GUI/adb_plus/screenshot.py +22 -1
  16. AutoGLM_GUI/adb_plus/serial.py +38 -20
  17. AutoGLM_GUI/adb_plus/touch.py +4 -9
  18. AutoGLM_GUI/agents/__init__.py +51 -0
  19. AutoGLM_GUI/agents/events.py +19 -0
  20. AutoGLM_GUI/agents/factory.py +153 -0
  21. AutoGLM_GUI/agents/glm/__init__.py +7 -0
  22. AutoGLM_GUI/agents/glm/agent.py +292 -0
  23. AutoGLM_GUI/agents/glm/message_builder.py +81 -0
  24. AutoGLM_GUI/agents/glm/parser.py +110 -0
  25. AutoGLM_GUI/agents/glm/prompts_en.py +77 -0
  26. AutoGLM_GUI/agents/glm/prompts_zh.py +75 -0
  27. AutoGLM_GUI/agents/mai/__init__.py +28 -0
  28. AutoGLM_GUI/agents/mai/agent.py +405 -0
  29. AutoGLM_GUI/agents/mai/parser.py +254 -0
  30. AutoGLM_GUI/agents/mai/prompts.py +103 -0
  31. AutoGLM_GUI/agents/mai/traj_memory.py +91 -0
  32. AutoGLM_GUI/agents/protocols.py +27 -0
  33. AutoGLM_GUI/agents/stream_runner.py +188 -0
  34. AutoGLM_GUI/api/__init__.py +71 -11
  35. AutoGLM_GUI/api/agents.py +190 -229
  36. AutoGLM_GUI/api/control.py +9 -6
  37. AutoGLM_GUI/api/devices.py +112 -28
  38. AutoGLM_GUI/api/health.py +13 -0
  39. AutoGLM_GUI/api/history.py +78 -0
  40. AutoGLM_GUI/api/layered_agent.py +306 -181
  41. AutoGLM_GUI/api/mcp.py +11 -10
  42. AutoGLM_GUI/api/media.py +64 -1
  43. AutoGLM_GUI/api/scheduled_tasks.py +98 -0
  44. AutoGLM_GUI/api/version.py +23 -10
  45. AutoGLM_GUI/api/workflows.py +2 -1
  46. AutoGLM_GUI/config.py +72 -14
  47. AutoGLM_GUI/config_manager.py +98 -27
  48. AutoGLM_GUI/device_adapter.py +263 -0
  49. AutoGLM_GUI/device_manager.py +248 -29
  50. AutoGLM_GUI/device_protocol.py +266 -0
  51. AutoGLM_GUI/devices/__init__.py +49 -0
  52. AutoGLM_GUI/devices/adb_device.py +200 -0
  53. AutoGLM_GUI/devices/mock_device.py +185 -0
  54. AutoGLM_GUI/devices/remote_device.py +177 -0
  55. AutoGLM_GUI/exceptions.py +3 -3
  56. AutoGLM_GUI/history_manager.py +164 -0
  57. AutoGLM_GUI/i18n.py +81 -0
  58. AutoGLM_GUI/metrics.py +13 -20
  59. AutoGLM_GUI/model/__init__.py +5 -0
  60. AutoGLM_GUI/model/message_builder.py +69 -0
  61. AutoGLM_GUI/model/types.py +24 -0
  62. AutoGLM_GUI/models/__init__.py +10 -0
  63. AutoGLM_GUI/models/history.py +96 -0
  64. AutoGLM_GUI/models/scheduled_task.py +71 -0
  65. AutoGLM_GUI/parsers/__init__.py +22 -0
  66. AutoGLM_GUI/parsers/base.py +50 -0
  67. AutoGLM_GUI/parsers/phone_parser.py +58 -0
  68. AutoGLM_GUI/phone_agent_manager.py +118 -367
  69. AutoGLM_GUI/platform_utils.py +31 -2
  70. AutoGLM_GUI/prompt_config.py +15 -0
  71. AutoGLM_GUI/prompts/__init__.py +32 -0
  72. AutoGLM_GUI/scheduler_manager.py +304 -0
  73. AutoGLM_GUI/schemas.py +272 -63
  74. AutoGLM_GUI/scrcpy_stream.py +159 -37
  75. AutoGLM_GUI/server.py +3 -1
  76. AutoGLM_GUI/socketio_server.py +114 -29
  77. AutoGLM_GUI/state.py +10 -30
  78. AutoGLM_GUI/static/assets/{about-DeclntHg.js → about-BQm96DAl.js} +1 -1
  79. AutoGLM_GUI/static/assets/alert-dialog-B42XxGPR.js +1 -0
  80. AutoGLM_GUI/static/assets/chat-C0L2gQYG.js +129 -0
  81. AutoGLM_GUI/static/assets/circle-alert-D4rSJh37.js +1 -0
  82. AutoGLM_GUI/static/assets/dialog-DZ78cEcj.js +45 -0
  83. AutoGLM_GUI/static/assets/history-DFBv7TGc.js +1 -0
  84. AutoGLM_GUI/static/assets/index-Bzyv2yQ2.css +1 -0
  85. AutoGLM_GUI/static/assets/{index-zQ4KKDHt.js → index-CmZSnDqc.js} +1 -1
  86. AutoGLM_GUI/static/assets/index-CssG-3TH.js +11 -0
  87. AutoGLM_GUI/static/assets/label-BCUzE_nm.js +1 -0
  88. AutoGLM_GUI/static/assets/logs-eoFxn5of.js +1 -0
  89. AutoGLM_GUI/static/assets/popover-DLsuV5Sx.js +1 -0
  90. AutoGLM_GUI/static/assets/scheduled-tasks-MyqGJvy_.js +1 -0
  91. AutoGLM_GUI/static/assets/square-pen-zGWYrdfj.js +1 -0
  92. AutoGLM_GUI/static/assets/textarea-BX6y7uM5.js +1 -0
  93. AutoGLM_GUI/static/assets/workflows-CYFs6ssC.js +1 -0
  94. AutoGLM_GUI/static/index.html +2 -2
  95. AutoGLM_GUI/types.py +142 -0
  96. {autoglm_gui-1.4.0.dist-info → autoglm_gui-1.5.0.dist-info}/METADATA +178 -92
  97. autoglm_gui-1.5.0.dist-info/RECORD +157 -0
  98. mai_agent/base.py +137 -0
  99. mai_agent/mai_grounding_agent.py +263 -0
  100. mai_agent/mai_naivigation_agent.py +526 -0
  101. mai_agent/prompt.py +148 -0
  102. mai_agent/unified_memory.py +67 -0
  103. mai_agent/utils.py +73 -0
  104. AutoGLM_GUI/api/dual_model.py +0 -311
  105. AutoGLM_GUI/dual_model/__init__.py +0 -53
  106. AutoGLM_GUI/dual_model/decision_model.py +0 -664
  107. AutoGLM_GUI/dual_model/dual_agent.py +0 -917
  108. AutoGLM_GUI/dual_model/protocols.py +0 -354
  109. AutoGLM_GUI/dual_model/vision_model.py +0 -442
  110. AutoGLM_GUI/mai_ui_adapter/agent_wrapper.py +0 -291
  111. AutoGLM_GUI/phone_agent_patches.py +0 -146
  112. AutoGLM_GUI/static/assets/chat-Iut2yhSw.js +0 -125
  113. AutoGLM_GUI/static/assets/dialog-BfdcBs1x.js +0 -45
  114. AutoGLM_GUI/static/assets/index-5hCCwHA7.css +0 -1
  115. AutoGLM_GUI/static/assets/index-DHF1NZh0.js +0 -12
  116. AutoGLM_GUI/static/assets/workflows-xiplap-r.js +0 -1
  117. autoglm_gui-1.4.0.dist-info/RECORD +0 -100
  118. {autoglm_gui-1.4.0.dist-info → autoglm_gui-1.5.0.dist-info}/WHEEL +0 -0
  119. {autoglm_gui-1.4.0.dist-info → autoglm_gui-1.5.0.dist-info}/entry_points.txt +0 -0
  120. {autoglm_gui-1.4.0.dist-info → autoglm_gui-1.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1 @@
1
+ import{o as l,j as r,b as i,r as o,ag as d}from"./index-CssG-3TH.js";const u=[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]],m=l("plus",u);function x({className:t,type:a,...e}){return r.jsx("input",{type:a,"data-slot":"input",className:i("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm","focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]","aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",t),...e})}var c="Label",s=o.forwardRef((t,a)=>r.jsx(d.label,{...t,ref:a,onMouseDown:e=>{e.target.closest("button, input, select, textarea")||(t.onMouseDown?.(e),!e.defaultPrevented&&e.detail>1&&e.preventDefault())}}));s.displayName=c;var n=s;const f=o.forwardRef(({className:t,...a},e)=>r.jsx(n,{ref:e,className:i("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-slate-900 dark:text-slate-100",t),...a}));f.displayName=n.displayName;export{x as I,f as L,m as P};
@@ -0,0 +1 @@
1
+ import{o as j,u as I,r as l,j as e,B as i,F as u}from"./index-CssG-3TH.js";import{C as d}from"./circle-alert-D4rSJh37.js";const A=[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2",key:"usdka0"}]],E=j("folder-open",A);const M=[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]],P=j("refresh-cw",M);function B(){const r=I(),[x,p]=l.useState([]),[o,v]=l.useState(null),[N,w]=l.useState(""),[m,h]=l.useState(!1),[b,g]=l.useState(!1),[f,a]=l.useState(""),[k,F]=l.useState(!1),n=l.useCallback(async()=>{try{h(!0),a("");const s=window.electronAPI;if(!s?.logs)return;const t=await s.logs.listFiles();p(t)}catch(s){const t=s instanceof Error?s.message:String(s);a(r.logs.loadFailed.replace("{error}",t))}finally{h(!1)}},[r.logs.loadFailed]);l.useEffect(()=>{window.electronAPI?.logs&&(F(!0),n())},[n]);const L=async s=>{g(!0),a("");try{const t=window.electronAPI;if(!t?.logs)return;const c=await t.logs.readFile(s);v(s),w(c)}catch(t){const c=t instanceof Error?t.message:String(t);a(r.logs.readFailed.replace("{error}",c))}finally{g(!1)}},y=async()=>{try{const s=window.electronAPI;if(!s?.logs)return;const t=await s.logs.openFolder();t.success||a(r.logs.openFolderFailed.replace("{error}",t.error||""))}catch(s){const t=s instanceof Error?s.message:String(s);a(r.logs.openFolderFailed.replace("{error}",t))}},C=s=>s<1024?s+" B":s<1024*1024?(s/1024).toFixed(1)+" KB":(s/(1024*1024)).toFixed(1)+" MB",S=s=>new Date(s).toLocaleString("zh-CN");return k?e.jsxs("div",{className:"h-full flex",children:[e.jsxs("div",{className:"w-80 border-r border-slate-200 dark:border-slate-800 flex flex-col",children:[e.jsxs("div",{className:"p-4 border-b border-slate-200 dark:border-slate-800",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("h2",{className:"text-lg font-semibold",children:r.logs.title}),e.jsx(i,{variant:"ghost",size:"icon",onClick:n,disabled:m,title:r.logs.refresh,children:e.jsx(P,{className:`w-4 h-4 ${m?"animate-spin":""}`})})]}),e.jsxs(i,{variant:"outline",className:"w-full",onClick:y,children:[e.jsx(E,{className:"w-4 h-4 mr-2"}),r.logs.openFolder]})]}),e.jsx("div",{className:"flex-1 overflow-y-auto",children:x.length===0?e.jsx("div",{className:"p-4 text-center text-slate-500 text-sm",children:r.logs.noLogs}):e.jsx("div",{className:"divide-y divide-slate-200 dark:divide-slate-800",children:x.map(s=>e.jsxs("div",{className:`p-4 hover:bg-slate-50 dark:hover:bg-slate-900 cursor-pointer transition-colors ${o===s.name?"bg-slate-50 dark:bg-slate-900":""}`,onClick:()=>!s.isCompressed&&L(s.name),children:[e.jsxs("div",{className:"flex items-start gap-3",children:[s.isError?e.jsx(d,{className:"w-5 h-5 text-red-500 flex-shrink-0 mt-0.5"}):e.jsx(u,{className:"w-5 h-5 text-slate-400 flex-shrink-0 mt-0.5"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"font-medium text-sm truncate",children:s.name}),e.jsxs("div",{className:"text-xs text-slate-500 mt-1",children:[C(s.size)," •"," ",S(s.modified)]})]})]}),s.isCompressed&&e.jsx("div",{className:"text-xs text-slate-400 mt-2 ml-8",children:r.logs.compressedFileNote})]},s.name))})})]}),e.jsx("div",{className:"flex-1 flex flex-col",children:o?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"p-4 border-b border-slate-200 dark:border-slate-800",children:e.jsx("h3",{className:"font-semibold",children:o})}),e.jsx("div",{className:"flex-1 overflow-auto p-4 bg-slate-50 dark:bg-slate-950",children:b?e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx("div",{className:"text-slate-500",children:r.logs.loading})}):e.jsx("pre",{className:"text-xs font-mono whitespace-pre-wrap break-all",children:N})})]}):e.jsx("div",{className:"flex-1 flex items-center justify-center text-slate-500",children:e.jsxs("div",{className:"text-center",children:[e.jsx(u,{className:"w-12 h-12 mx-auto mb-4 text-slate-300"}),e.jsx("p",{children:r.logs.selectLog})]})})}),f&&e.jsx("div",{className:"fixed bottom-4 right-4 max-w-md bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 shadow-lg",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(d,{className:"w-5 h-5 text-red-500 flex-shrink-0 mt-0.5"}),e.jsx("div",{className:"flex-1 text-sm text-red-600 dark:text-red-400",children:f}),e.jsx(i,{variant:"ghost",size:"icon",className:"h-6 w-6 text-red-400 hover:text-red-600",onClick:()=>a(""),children:"✕"})]})})]}):e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsxs("div",{className:"text-center",children:[e.jsx(d,{className:"w-12 h-12 mx-auto mb-4 text-slate-400"}),e.jsx("p",{className:"text-slate-600",dangerouslySetInnerHTML:{__html:r.logs.webVersionNotice}})]})})}export{B as component};
@@ -0,0 +1 @@
1
+ import{o as R,r as i,ah as _,E as z,j as s,ai as $,x as L,A as H,y as O,P as b,D as h,aj as j,H as w,ak as G,z as q,al as K,am as B,an as U,b as V}from"./index-CssG-3TH.js";import{i as W,R as X,u as Z,F as J}from"./dialog-DZ78cEcj.js";const Q=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],ge=R("chevron-down",Q);const Y=[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335",key:"yps3ct"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]],me=R("circle-check-big",Y);const ee=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]],Ce=R("circle-x",ee);var C="Popover",[y]=L(C,[_]),P=_(),[oe,l]=y(C),E=e=>{const{__scopePopover:n,children:o,open:a,defaultOpen:t,onOpenChange:r,modal:c=!1}=e,p=P(n),f=i.useRef(null),[v,g]=i.useState(!1),[m,d]=z({prop:a,defaultProp:t??!1,onChange:r,caller:C});return s.jsx($,{...p,children:s.jsx(oe,{scope:n,contentId:H(),triggerRef:f,open:m,onOpenChange:d,onOpenToggle:i.useCallback(()=>d(x=>!x),[d]),hasCustomAnchor:v,onCustomAnchorAdd:i.useCallback(()=>g(!0),[]),onCustomAnchorRemove:i.useCallback(()=>g(!1),[]),modal:c,children:o})})};E.displayName=C;var N="PopoverAnchor",te=i.forwardRef((e,n)=>{const{__scopePopover:o,...a}=e,t=l(N,o),r=P(o),{onCustomAnchorAdd:c,onCustomAnchorRemove:p}=t;return i.useEffect(()=>(c(),()=>p()),[c,p]),s.jsx(j,{...r,...a,ref:n})});te.displayName=N;var k="PopoverTrigger",F=i.forwardRef((e,n)=>{const{__scopePopover:o,...a}=e,t=l(k,o),r=P(o),c=O(n,t.triggerRef),p=s.jsx(b.button,{type:"button","aria-haspopup":"dialog","aria-expanded":t.open,"aria-controls":t.contentId,"data-state":T(t.open),...a,ref:c,onClick:h(e.onClick,t.onOpenToggle)});return t.hasCustomAnchor?p:s.jsx(j,{asChild:!0,...r,children:p})});F.displayName=k;var A="PopoverPortal",[re,ne]=y(A,{forceMount:void 0}),S=e=>{const{__scopePopover:n,forceMount:o,children:a,container:t}=e,r=l(A,n);return s.jsx(re,{scope:n,forceMount:o,children:s.jsx(w,{present:o||r.open,children:s.jsx(G,{asChild:!0,container:t,children:a})})})};S.displayName=A;var u="PopoverContent",D=i.forwardRef((e,n)=>{const o=ne(u,e.__scopePopover),{forceMount:a=o.forceMount,...t}=e,r=l(u,e.__scopePopover);return s.jsx(w,{present:a||r.open,children:r.modal?s.jsx(se,{...t,ref:n}):s.jsx(ce,{...t,ref:n})})});D.displayName=u;var ae=q("PopoverContent.RemoveScroll"),se=i.forwardRef((e,n)=>{const o=l(u,e.__scopePopover),a=i.useRef(null),t=O(n,a),r=i.useRef(!1);return i.useEffect(()=>{const c=a.current;if(c)return W(c)},[]),s.jsx(X,{as:ae,allowPinchZoom:!0,children:s.jsx(M,{...e,ref:t,trapFocus:o.open,disableOutsidePointerEvents:!0,onCloseAutoFocus:h(e.onCloseAutoFocus,c=>{c.preventDefault(),r.current||o.triggerRef.current?.focus()}),onPointerDownOutside:h(e.onPointerDownOutside,c=>{const p=c.detail.originalEvent,f=p.button===0&&p.ctrlKey===!0,v=p.button===2||f;r.current=v},{checkForDefaultPrevented:!1}),onFocusOutside:h(e.onFocusOutside,c=>c.preventDefault(),{checkForDefaultPrevented:!1})})})}),ce=i.forwardRef((e,n)=>{const o=l(u,e.__scopePopover),a=i.useRef(!1),t=i.useRef(!1);return s.jsx(M,{...e,ref:n,trapFocus:!1,disableOutsidePointerEvents:!1,onCloseAutoFocus:r=>{e.onCloseAutoFocus?.(r),r.defaultPrevented||(a.current||o.triggerRef.current?.focus(),r.preventDefault()),a.current=!1,t.current=!1},onInteractOutside:r=>{e.onInteractOutside?.(r),r.defaultPrevented||(a.current=!0,r.detail.originalEvent.type==="pointerdown"&&(t.current=!0));const c=r.target;o.triggerRef.current?.contains(c)&&r.preventDefault(),r.detail.originalEvent.type==="focusin"&&t.current&&r.preventDefault()}})}),M=i.forwardRef((e,n)=>{const{__scopePopover:o,trapFocus:a,onOpenAutoFocus:t,onCloseAutoFocus:r,disableOutsidePointerEvents:c,onEscapeKeyDown:p,onPointerDownOutside:f,onFocusOutside:v,onInteractOutside:g,...m}=e,d=l(u,o),x=P(o);return Z(),s.jsx(J,{asChild:!0,loop:!0,trapped:a,onMountAutoFocus:t,onUnmountAutoFocus:r,children:s.jsx(K,{asChild:!0,disableOutsidePointerEvents:c,onInteractOutside:g,onEscapeKeyDown:p,onPointerDownOutside:f,onFocusOutside:v,onDismiss:()=>d.onOpenChange(!1),children:s.jsx(B,{"data-state":T(d.open),role:"dialog",id:d.contentId,...x,...m,ref:n,style:{...m.style,"--radix-popover-content-transform-origin":"var(--radix-popper-transform-origin)","--radix-popover-content-available-width":"var(--radix-popper-available-width)","--radix-popover-content-available-height":"var(--radix-popper-available-height)","--radix-popover-trigger-width":"var(--radix-popper-anchor-width)","--radix-popover-trigger-height":"var(--radix-popper-anchor-height)"}})})})}),I="PopoverClose",ie=i.forwardRef((e,n)=>{const{__scopePopover:o,...a}=e,t=l(I,o);return s.jsx(b.button,{type:"button",...a,ref:n,onClick:h(e.onClick,()=>t.onOpenChange(!1))})});ie.displayName=I;var pe="PopoverArrow",le=i.forwardRef((e,n)=>{const{__scopePopover:o,...a}=e,t=P(o);return s.jsx(U,{...t,...a,ref:n})});le.displayName=pe;function T(e){return e?"open":"closed"}var de=E,ue=F,fe=S,ve=D;function xe({...e}){return s.jsx(de,{"data-slot":"popover",...e})}function Re({...e}){return s.jsx(ue,{"data-slot":"popover-trigger",...e})}function Ae({className:e,align:n="center",sideOffset:o=4,...a}){return s.jsx(fe,{children:s.jsx(ve,{"data-slot":"popover-content",align:n,sideOffset:o,className:V("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",e),...a})})}export{me as C,xe as P,Ce as a,Re as b,ge as c,Ae as d};
@@ -0,0 +1 @@
1
+ import{r as n,j as e,b as C,u as J,e as K,l as Q,g as U,B as i,f as Y,C as Z,h as $,i as ee,k as se,m as ae,n as le}from"./index-CssG-3TH.js";import{P as ne,L as x,I as D}from"./label-BCUzE_nm.js";import{L as _,C as te,a as re,b as ce,c as ie,T as oe,D as de,d as me,e as he,f as xe,g as ue}from"./dialog-DZ78cEcj.js";import{S,a as F,b as A,c as E,d as P,A as je,e as pe,f as fe,g as ke,h as ge,i as we,j as ve,k as Ne}from"./alert-dialog-B42XxGPR.js";import{C as Te,a as be}from"./popover-DLsuV5Sx.js";import{S as ye}from"./square-pen-zGWYrdfj.js";const L=n.forwardRef(({className:a,checked:r=!1,onCheckedChange:j,disabled:o,...p},d)=>e.jsx("button",{ref:d,role:"switch",type:"button","aria-checked":r,disabled:o,className:C("peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50",r?"bg-slate-900 dark:bg-slate-50":"bg-slate-200 dark:bg-slate-800",a),onClick:()=>j?.(!r),...p,children:e.jsx("span",{className:C("pointer-events-none block h-5 w-5 rounded-full bg-white shadow-lg ring-0 transition-transform dark:bg-slate-950",r?"translate-x-5":"translate-x-0")})}));L.displayName="Switch";const Ce=[{key:"everyHour",cron:"0 * * * *"},{key:"daily8am",cron:"0 8 * * *"},{key:"daily12pm",cron:"0 12 * * *"},{key:"daily6pm",cron:"0 18 * * *"},{key:"weeklyMonday",cron:"0 9 * * 1"}];function Pe(){const a=J(),[r,j]=n.useState([]),[o,p]=n.useState([]),[d,H]=n.useState([]),[O,g]=n.useState(!0),[W,m]=n.useState(!1),[f,w]=n.useState(null),[t,c]=n.useState({name:"",workflow_uuid:"",device_serialno:"",cron_expression:"",enabled:!0}),[v,N]=n.useState(!1),[z,k]=n.useState(!1),[T,b]=n.useState(null);n.useEffect(()=>{u()},[]);const u=async()=>{try{g(!0);const[s,l,h]=await Promise.all([K(),Q(),U()]);j(s.tasks),p(l.workflows),H(h)}catch(s){console.error("Failed to load data:",s)}finally{g(!1)}},B=()=>{w(null),c({name:"",workflow_uuid:"",device_serialno:"",cron_expression:"",enabled:!0}),m(!0)},R=s=>{w(s),c({name:s.name,workflow_uuid:s.workflow_uuid,device_serialno:s.device_serialno,cron_expression:s.cron_expression,enabled:s.enabled}),m(!0)},V=async()=>{try{N(!0),f?await se(f.id,t):await ae(t),m(!1),u()}catch(s){console.error("Failed to save task:",s)}finally{N(!1)}},I=async()=>{if(T){try{await le(T),u()}catch(s){console.error("Failed to delete task:",s)}k(!1),b(null)}},q=async s=>{try{s.enabled?await $(s.id):await ee(s.id),u()}catch(l){console.error("Failed to toggle task:",l)}},M=s=>o.find(h=>h.uuid===s)?.name||s,X=s=>d.find(h=>h.serial===s)?.model||s,y=s=>s?new Date(s).toLocaleString("zh-CN",{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"}):a.scheduledTasks.never,G=t.name.trim()&&t.workflow_uuid&&t.device_serialno&&t.cron_expression.trim();return e.jsxs("div",{className:"container mx-auto p-6 max-w-7xl",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-3xl font-bold",children:a.scheduledTasks.title}),e.jsxs(i,{onClick:B,children:[e.jsx(ne,{className:"w-4 h-4 mr-2"}),a.scheduledTasks.create]})]}),O?e.jsx("div",{className:"flex justify-center items-center h-64",children:e.jsx(_,{className:"w-8 h-8 animate-spin text-slate-400"})}):r.length===0?e.jsxs("div",{className:"text-center py-12",children:[e.jsx("p",{className:"text-slate-500 dark:text-slate-400",children:a.scheduledTasks.noTasks}),e.jsx("p",{className:"text-sm text-slate-400 dark:text-slate-500 mt-2",children:a.scheduledTasks.noTasksDesc})]}):e.jsx("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:r.map(s=>e.jsxs(te,{className:"hover:shadow-md transition-shadow",children:[e.jsx(re,{className:"pb-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(ce,{className:"text-lg truncate flex-1 mr-2",children:s.name}),e.jsx(L,{checked:s.enabled,onCheckedChange:()=>q(s)})]})}),e.jsx(ie,{children:e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"text-sm",children:[e.jsxs("span",{className:"text-slate-500 dark:text-slate-400",children:[a.scheduledTasks.workflow,":"," "]}),e.jsx("span",{className:"font-medium",children:M(s.workflow_uuid)})]}),e.jsxs("div",{className:"text-sm",children:[e.jsxs("span",{className:"text-slate-500 dark:text-slate-400",children:[a.scheduledTasks.device,":"," "]}),e.jsx("span",{className:"font-medium",children:X(s.device_serialno)})]}),e.jsx("div",{className:"text-sm",children:e.jsxs(Y,{variant:"outline",className:"font-mono",children:[e.jsx(Z,{className:"w-3 h-3 mr-1"}),s.cron_expression]})}),e.jsxs("div",{className:"text-sm flex items-center gap-2",children:[e.jsxs("span",{className:"text-slate-500 dark:text-slate-400",children:[a.scheduledTasks.lastRun,":"]}),s.last_run_time?e.jsxs(e.Fragment,{children:[s.last_run_success?e.jsx(Te,{className:"w-4 h-4 text-green-500"}):e.jsx(be,{className:"w-4 h-4 text-red-500"}),e.jsx("span",{children:y(s.last_run_time)})]}):e.jsx("span",{className:"text-slate-400",children:a.scheduledTasks.never})]}),e.jsxs("div",{className:"text-sm",children:[e.jsxs("span",{className:"text-slate-500 dark:text-slate-400",children:[a.scheduledTasks.nextRun,":"," "]}),e.jsx("span",{children:y(s.next_run_time)})]}),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsxs(i,{variant:"outline",size:"sm",onClick:()=>R(s),children:[e.jsx(ye,{className:"w-3 h-3 mr-1"}),a.common.edit]}),e.jsxs(i,{variant:"destructive",size:"sm",onClick:()=>{b(s.id),k(!0)},children:[e.jsx(oe,{className:"w-3 h-3 mr-1"}),a.common.delete]})]})]})})]},s.id))}),e.jsx(de,{open:W,onOpenChange:m,children:e.jsxs(me,{className:"sm:max-w-[500px]",children:[e.jsx(he,{children:e.jsx(xe,{children:f?a.scheduledTasks.edit:a.scheduledTasks.create})}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(x,{htmlFor:"name",children:a.scheduledTasks.taskName}),e.jsx(D,{id:"name",value:t.name,onChange:s=>c(l=>({...l,name:s.target.value})),placeholder:a.scheduledTasks.taskNamePlaceholder})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(x,{children:a.scheduledTasks.workflow}),o.length===0?e.jsx("p",{className:"text-sm text-amber-600 dark:text-amber-400",children:a.scheduledTasks.noWorkflows}):e.jsxs(S,{value:t.workflow_uuid,onValueChange:s=>c(l=>({...l,workflow_uuid:s})),children:[e.jsx(F,{children:e.jsx(A,{placeholder:a.scheduledTasks.selectWorkflow})}),e.jsx(E,{children:o.map(s=>e.jsx(P,{value:s.uuid,children:s.name},s.uuid))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(x,{children:a.scheduledTasks.device}),d.length===0?e.jsx("p",{className:"text-sm text-amber-600 dark:text-amber-400",children:a.scheduledTasks.noDevicesOnline}):e.jsxs(S,{value:t.device_serialno,onValueChange:s=>c(l=>({...l,device_serialno:s})),children:[e.jsx(F,{children:e.jsx(A,{placeholder:a.scheduledTasks.selectDevice})}),e.jsx(E,{children:d.map(s=>e.jsx(P,{value:s.serial,children:s.model||s.serial},s.serial))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(x,{htmlFor:"cron",children:a.scheduledTasks.cronExpression}),e.jsx(D,{id:"cron",value:t.cron_expression,onChange:s=>c(l=>({...l,cron_expression:s.target.value})),placeholder:a.scheduledTasks.cronPlaceholder,className:"font-mono"}),e.jsx("p",{className:"text-xs text-slate-500 dark:text-slate-400",children:a.scheduledTasks.cronHelp})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(x,{children:a.scheduledTasks.presets}),e.jsx("div",{className:"flex flex-wrap gap-2",children:Ce.map(s=>e.jsx(i,{variant:"outline",size:"sm",onClick:()=>c(l=>({...l,cron_expression:s.cron})),children:a.scheduledTasks.preset[s.key]},s.key))})]})]}),e.jsxs(ue,{children:[e.jsx(i,{variant:"outline",onClick:()=>m(!1),children:a.common.cancel}),e.jsx(i,{onClick:V,disabled:!G||v,children:v?e.jsxs(e.Fragment,{children:[e.jsx(_,{className:"w-4 h-4 mr-2 animate-spin"}),a.common.loading]}):a.common.save})]})]})}),e.jsx(je,{open:z,onOpenChange:k,children:e.jsxs(pe,{children:[e.jsxs(fe,{children:[e.jsx(ke,{children:a.common.delete}),e.jsx(ge,{children:a.scheduledTasks.deleteConfirm})]}),e.jsxs(we,{children:[e.jsx(ve,{children:a.common.cancel}),e.jsx(Ne,{onClick:I,children:a.common.confirm})]})]})})]})}export{Pe as component};
@@ -0,0 +1 @@
1
+ import{o as a}from"./index-CssG-3TH.js";const e=[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7",key:"1m0v6g"}],["path",{d:"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z",key:"ohrbg2"}]],r=a("square-pen",e);export{r as S};
@@ -0,0 +1 @@
1
+ import{r as s,j as a,b as i}from"./index-CssG-3TH.js";const l=s.forwardRef(({className:e,...r},t)=>a.jsx("textarea",{className:i("flex min-h-[40px] w-full rounded-full border border-slate-200 bg-white px-3 py-2 text-sm ring-offset-white file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#1d9bf0] focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-100 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus-visible:ring-[#1d9bf0] resize-none",e),ref:t,...r}));l.displayName="Textarea";export{l as T};
@@ -0,0 +1 @@
1
+ import{u as D,r as t,l as S,j as e,B as n,d as W,a as F,c as b}from"./index-CssG-3TH.js";import{P as T,L as u,I as E}from"./label-BCUzE_nm.js";import{T as L}from"./textarea-BX6y7uM5.js";import{L as j,C as P,a as z,b as B,c as H,T as I,D as q,d as O,e as R,f as A,g as G}from"./dialog-DZ78cEcj.js";import{S as J}from"./square-pen-zGWYrdfj.js";function X(){const a=D(),[m,p]=t.useState([]),[g,x]=t.useState(!0),[k,o]=t.useState(!1),[c,h]=t.useState(null),[l,i]=t.useState({name:"",text:""}),[w,f]=t.useState(!1);t.useEffect(()=>{d()},[]);const d=async()=>{try{x(!0);const s=await S();p(s.workflows)}catch(s){console.error("Failed to load workflows:",s)}finally{x(!1)}},v=()=>{h(null),i({name:"",text:""}),o(!0)},N=s=>{h(s),i({name:s.name,text:s.text}),o(!0)},C=async()=>{try{f(!0),c?await F(c.uuid,l):await b(l),o(!1),d()}catch(s){console.error("Failed to save workflow:",s)}finally{f(!1)}},y=async s=>{if(window.confirm(a.workflows.deleteConfirm))try{await W(s),d()}catch(r){console.error("Failed to delete workflow:",r)}};return e.jsxs("div",{className:"container mx-auto p-6 max-w-7xl",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-3xl font-bold",children:a.workflows.title}),e.jsxs(n,{onClick:v,children:[e.jsx(T,{className:"w-4 h-4 mr-2"}),a.workflows.createNew]})]}),g?e.jsx("div",{className:"flex justify-center items-center h-64",children:e.jsx(j,{className:"w-8 h-8 animate-spin text-slate-400"})}):m.length===0?e.jsx("div",{className:"text-center py-12",children:e.jsx("p",{className:"text-slate-500 dark:text-slate-400",children:a.workflows.empty})}):e.jsx("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-3",children:m.map(s=>e.jsxs(P,{className:"hover:shadow-md transition-shadow",children:[e.jsx(z,{children:e.jsx(B,{className:"text-lg",children:s.name})}),e.jsxs(H,{children:[e.jsx("p",{className:"text-sm text-slate-600 dark:text-slate-400 mb-4 line-clamp-3",children:s.text}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(n,{variant:"outline",size:"sm",onClick:()=>N(s),children:[e.jsx(J,{className:"w-3 h-3 mr-1"}),a.common.edit]}),e.jsxs(n,{variant:"destructive",size:"sm",onClick:()=>y(s.uuid),children:[e.jsx(I,{className:"w-3 h-3 mr-1"}),a.common.delete]})]})]})]},s.uuid))}),e.jsx(q,{open:k,onOpenChange:o,children:e.jsxs(O,{className:"sm:max-w-[600px]",children:[e.jsx(R,{children:e.jsx(A,{children:c?a.workflows.edit:a.workflows.create})}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{htmlFor:"name",children:a.workflows.name}),e.jsx(E,{id:"name",value:l.name,onChange:s=>i(r=>({...r,name:s.target.value})),placeholder:a.workflows.namePlaceholder})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(u,{htmlFor:"text",children:a.workflows.text}),e.jsx(L,{id:"text",value:l.text,onChange:s=>i(r=>({...r,text:s.target.value})),placeholder:a.workflows.textPlaceholder,rows:6,className:"resize-none !rounded-lg"})]})]}),e.jsxs(G,{children:[e.jsx(n,{variant:"outline",onClick:()=>o(!1),children:a.common.cancel}),e.jsx(n,{onClick:C,disabled:!l.name.trim()||!l.text.trim()||w,children:w?e.jsxs(e.Fragment,{children:[e.jsx(j,{className:"w-4 h-4 mr-2 animate-spin"}),a.common.loading]}):a.common.save})]})]})})]})}export{X as component};
@@ -11,8 +11,8 @@
11
11
  <link rel="icon" type="image/png" sizes="192x192" href="/logo-192.png" />
12
12
  <link rel="icon" type="image/png" sizes="512x512" href="/logo-512.png" />
13
13
  <meta name="theme-color" content="#f5f1e8" />
14
- <script type="module" crossorigin src="/assets/index-DHF1NZh0.js"></script>
15
- <link rel="stylesheet" crossorigin href="/assets/index-5hCCwHA7.css">
14
+ <script type="module" crossorigin src="/assets/index-CssG-3TH.js"></script>
15
+ <link rel="stylesheet" crossorigin href="/assets/index-Bzyv2yQ2.css">
16
16
  </head>
17
17
  <body>
18
18
  <div id="app"></div>
AutoGLM_GUI/types.py ADDED
@@ -0,0 +1,142 @@
1
+ from __future__ import annotations
2
+
3
+ from enum import Enum
4
+ from typing import Literal
5
+
6
+ from typing_extensions import TypedDict
7
+
8
+ ActionMetadata = Literal["do", "finish", "takeover"]
9
+ PhoneActionType = Literal[
10
+ "Tap", "Swipe", "Type", "Launch", "Wait", "Back", "Home", "Long Press", "Double Tap"
11
+ ]
12
+ MAIActionType = Literal[
13
+ "click",
14
+ "swipe",
15
+ "type",
16
+ "terminate",
17
+ "answer",
18
+ "wait",
19
+ "long_press",
20
+ "double_click",
21
+ "open",
22
+ "system_button",
23
+ "drag",
24
+ ]
25
+ SwipeDirection = Literal["up", "down", "left", "right"]
26
+ SystemButton = Literal["back", "home", "enter"]
27
+ TerminateStatus = Literal["success", "failure"]
28
+ MessageRole = Literal["system", "user", "assistant"]
29
+ ContentType = Literal["text", "image_url"]
30
+
31
+
32
+ class PhoneAgentAction(TypedDict, total=False):
33
+ _metadata: ActionMetadata
34
+ action: PhoneActionType
35
+ element: list[int]
36
+ text: str
37
+ app: str
38
+ start: list[int]
39
+ end: list[int]
40
+ duration: str
41
+ message: str
42
+
43
+
44
+ class MAIAction(TypedDict, total=False):
45
+ action: MAIActionType
46
+ coordinate: list[float]
47
+ direction: SwipeDirection
48
+ text: str
49
+ button: SystemButton
50
+ status: TerminateStatus
51
+ start_coordinate: list[float]
52
+ end_coordinate: list[float]
53
+
54
+
55
+ class SSEThinkingChunkData(TypedDict):
56
+ type: str
57
+ role: str
58
+ chunk: str
59
+
60
+
61
+ class SSEStepData(TypedDict, total=False):
62
+ type: str
63
+ role: str
64
+ step: int
65
+ thinking: str
66
+ action: PhoneAgentAction | None
67
+ success: bool
68
+ finished: bool
69
+
70
+
71
+ class SSEDoneData(TypedDict, total=False):
72
+ type: str
73
+ role: str
74
+ message: str
75
+ steps: int
76
+ success: bool
77
+
78
+
79
+ class SSEErrorData(TypedDict):
80
+ type: str
81
+ role: str
82
+ message: str
83
+
84
+
85
+ SSEEventData = SSEThinkingChunkData | SSEStepData | SSEDoneData | SSEErrorData
86
+
87
+
88
+ class MAIAgentSpecificConfig(TypedDict, total=False):
89
+ history_n: int
90
+ max_pixels: int
91
+ min_pixels: int
92
+ tools: list[dict[str, str]]
93
+ use_mai_prompt: bool
94
+
95
+
96
+ class GLMAgentSpecificConfig(TypedDict, total=False):
97
+ pass
98
+
99
+
100
+ AgentSpecificConfig = MAIAgentSpecificConfig | GLMAgentSpecificConfig
101
+
102
+
103
+ class TextContent(TypedDict):
104
+ type: ContentType
105
+ text: str
106
+
107
+
108
+ class ImageURLContent(TypedDict):
109
+ type: ContentType
110
+ image_url: dict[str, str]
111
+
112
+
113
+ MessageContent = str | list[TextContent | ImageURLContent]
114
+
115
+
116
+ class ChatMessage(TypedDict, total=False):
117
+ role: MessageRole
118
+ content: MessageContent
119
+
120
+
121
+ ConversationContext = list[ChatMessage]
122
+
123
+
124
+ class Observation(TypedDict, total=False):
125
+ screenshot: object
126
+ accessibility_tree: dict[str, object] | None
127
+
128
+
129
+ class DeviceConnectionType(Enum):
130
+ """Device connection type.
131
+
132
+ Unified enum for device connection types to avoid confusion
133
+ with phone_agent's ConnectionType.
134
+
135
+ - USB: Physical USB connection
136
+ - WIFI: ADB over WiFi (local network)
137
+ - REMOTE: HTTP Remote Device (via Device Agent Server)
138
+ """
139
+
140
+ USB = "usb"
141
+ WIFI = "wifi"
142
+ REMOTE = "remote"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: autoglm-gui
3
- Version: 1.4.0
3
+ Version: 1.5.0
4
4
  Summary: Web GUI for AutoGLM Phone Agent - AI-powered Android automation
5
5
  Project-URL: Homepage, https://github.com/suyiiyii/AutoGLM-GUI
6
6
  Project-URL: Repository, https://github.com/suyiiyii/AutoGLM-GUI
@@ -20,15 +20,19 @@ Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.10
23
+ Requires-Dist: apscheduler<4.0.0,>=3.10.0
23
24
  Requires-Dist: fastapi>=0.124.0
24
25
  Requires-Dist: fastmcp>=2.0.0
25
26
  Requires-Dist: httpx[socks]>=0.28.1
27
+ Requires-Dist: jinja2>=3.1.0
26
28
  Requires-Dist: loguru>=0.7.3
29
+ Requires-Dist: numpy>=1.24.0
27
30
  Requires-Dist: openai-agents>=0.6.4
28
31
  Requires-Dist: openai>=2.9.0
29
32
  Requires-Dist: pillow>=11.3.0
30
33
  Requires-Dist: prometheus-client>=0.21.0
31
34
  Requires-Dist: python-socketio>=5.11.0
35
+ Requires-Dist: pyyaml>=6.0.3
32
36
  Requires-Dist: uvicorn[standard]>=0.38.0
33
37
  Requires-Dist: zeroconf>=0.148.0
34
38
  Description-Content-Type: text/markdown
@@ -41,7 +45,7 @@ Description-Content-Type: text/markdown
41
45
 
42
46
  AutoGLM 手机助手的现代化 Web 图形界面 - 让 AI 自动化操作 Android 设备变得简单
43
47
 
44
- **🎉 双模型协作架构现已上线!决策大模型 + 视觉小模型,智能任务规划与精准执行分离,性能提升 60%!🎉**
48
+ **🆕 分层代理模式**:基于决策模型和视觉模型的双层协作架构,支持复杂任务规划与精准执行分离,适合需要多轮推理的高级任务。
45
49
 
46
50
  ![Python](https://img.shields.io/badge/python-3.10+-blue.svg)
47
51
  ![License](https://img.shields.io/badge/license-Apache%202.0-green.svg)
@@ -57,7 +61,7 @@ AutoGLM 手机助手的现代化 Web 图形界面 - 让 AI 自动化操作 Andro
57
61
 
58
62
  ## ✨ 特性
59
63
 
60
- - **🧠 双模型协作** - 🆕 决策大模型 + 视觉小模型协作架构,智能任务规划与精准执行分离,支持三种工作模式(DEEP/FAST/TURBO)
64
+ - **分层代理模式** - 🆕 决策模型 + 视觉模型双层协作架构,支持复杂任务规划与精准执行分离
61
65
  - **完全无线配对** - 🆕 支持 Android 11+ 二维码扫码配对,无需数据线即可连接设备
62
66
  - **多设备并发控制** - 同时管理和控制多个 Android 设备,设备间状态完全隔离
63
67
  - **对话式任务管理** - 通过聊天界面控制 Android 设备
@@ -76,9 +80,9 @@ AutoGLM 手机助手的现代化 Web 图形界面 - 让 AI 自动化操作 Andro
76
80
 
77
81
  | 操作系统 | 下载链接 | 说明 |
78
82
  |---------|---------|------|
79
- | 🪟 **Windows** (x64) | [📦 下载便携版 EXE](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.4.0/AutoGLM.GUI.1.4.0.exe) | 适用于 Windows 10/11,免安装 |
80
- | 🍎 **macOS** (Apple Silicon) | [📦 下载 DMG](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.4.0/AutoGLM.GUI-1.4.0-arm64.dmg) | 适用于 M 芯片 Mac |
81
- | 🐧 **Linux** (x64) | [📦 下载 AppImage](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.4.0/AutoGLM.GUI-1.4.0.AppImage) \| [deb](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.4.0/autoglm-gui_1.4.0_amd64.deb) \| [tar.gz](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.4.0/autoglm-gui-1.4.0.tar.gz) | 通用格式,支持主流发行版 |
83
+ | 🪟 **Windows** (x64) | [📦 下载便携版 EXE](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.5.0/AutoGLM.GUI.1.5.0.exe) | 适用于 Windows 10/11,免安装 |
84
+ | 🍎 **macOS** (Apple Silicon) | [📦 下载 DMG](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.5.0/AutoGLM.GUI-1.5.0-arm64.dmg) | 适用于 M 芯片 Mac |
85
+ | 🐧 **Linux** (x64) | [📦 下载 AppImage](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.5.0/AutoGLM.GUI-1.5.0.AppImage) \| [deb](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.5.0/autoglm-gui_1.5.0_amd64.deb) \| [tar.gz](https://github.com/suyiiyii/AutoGLM-GUI/releases/download/v1.5.0/autoglm-gui-1.5.0.tar.gz) | 通用格式,支持主流发行版 |
82
86
 
83
87
  </div>
84
88
 
@@ -106,19 +110,7 @@ uvx autoglm-gui
106
110
 
107
111
  ## 📸 界面预览
108
112
 
109
- 快速跳转: [普通模式](#mode-classic) · [双模型协作(增强)](#mode-dual) · [分层代理(增强)](#mode-layered)
110
-
111
- ### 双模型协作架构
112
-
113
- **决策大模型(如 GLM-4.7)+ 视觉小模型(AutoGLM-Phone)**:大模型负责规划与纠错,小模型负责观察与执行,适合更复杂、更长流程的任务。
114
-
115
- - 🧠 **决策层**:任务理解 / 步骤规划 / 异常纠错
116
- - 👁️ **执行层**:识别界面元素并点击/滑动/输入完成操作
117
- - 🔄 **运行方式**:规划 → 执行 → 反馈;必要时自动重规划
118
-
119
- **模式选择(Thinking Mode)**:TURBO(更省更快,推荐常规流程)/ DEEP(更稳,适合复杂任务)/ FAST(更快,适合轻量任务)。
120
-
121
- <img width="879" height="849" alt="双模型协作界面" src="https://github.com/user-attachments/assets/15e5cf51-5a19-403d-9af3-46f77c2068f5" />
113
+ 快速跳转: [普通模式](#mode-classic) · [分层代理(增强)](#mode-layered)
122
114
 
123
115
  ### 分层代理
124
116
 
@@ -138,49 +130,16 @@ uvx autoglm-gui
138
130
 
139
131
  ## 🚀 快速开始
140
132
 
141
- ## 🎯 模型服务配置
142
-
143
- AutoGLM-GUI 只需要一个 OpenAI 兼容的模型服务。你可以:
144
-
145
- - 使用官方已托管的第三方服务
146
- - 智谱 BigModel:`--base-url https://open.bigmodel.cn/api/paas/v4`,`--model autoglm-phone`,`--apikey <你的 API Key>`
147
- - ModelScope:`--base-url https://api-inference.modelscope.cn/v1`,`--model ZhipuAI/AutoGLM-Phone-9B`,`--apikey <你的 API Key>`
148
- - 或自建服务:参考上游项目的[部署文档](https://github.com/zai-org/Open-AutoGLM/blob/main/README.md)用 vLLM/SGLang 部署 `zai-org/AutoGLM-Phone-9B`,启动 OpenAI 兼容端口后将 `--base-url` 指向你的服务。
149
-
150
- 示例:
151
-
152
- ```bash
153
- # 使用智谱 BigModel
154
- pip install autoglm-gui
155
- autoglm-gui \
156
- --base-url https://open.bigmodel.cn/api/paas/v4 \
157
- --model autoglm-phone \
158
- --apikey sk-xxxxx
159
-
160
- # 使用 ModelScope
161
- pip install autoglm-gui
162
- autoglm-gui \
163
- --base-url https://api-inference.modelscope.cn/v1 \
164
- --model ZhipuAI/AutoGLM-Phone-9B \
165
- --apikey sk-xxxxx
166
-
167
- # 指向你自建的 vLLM/SGLang 服务
168
- pip install autoglm-gui
169
- autoglm-gui --base-url http://localhost:8000/v1 --model autoglm-phone-9b
170
- ```
171
-
172
133
  ### 前置要求
173
134
 
174
- - Python 3.10+
175
135
  - Android 设备(Android 11+ 支持完全无线配对,无需数据线)
176
- - 已安装 ADB 并添加到系统 PATH(桌面版已内置)
177
- - 一个 OpenAI 兼容的 API 端点
136
+ - 一个 OpenAI 兼容的 API 端点(支持智谱 BigModel、ModelScope 或自建服务)
178
137
 
179
138
  **关于设备连接**:
180
139
  - **Android 11+**:支持二维码扫码配对,完全无需数据线即可连接和控制设备
181
140
  - **Android 10 及更低版本**:需要先通过 USB 数据线连接并开启无线调试,之后可拔掉数据线无线使用
182
141
 
183
- ### 快捷运行(推荐)
142
+ ### 方式一:Python 包安装(推荐)
184
143
 
185
144
  **无需手动准备环境,直接安装运行:**
186
145
 
@@ -196,23 +155,86 @@ autoglm-gui --base-url http://localhost:8080/v1
196
155
  uvx autoglm-gui --base-url http://localhost:8080/v1
197
156
  ```
198
157
 
199
- ### 传统安装
158
+ ### 方式二:Docker 部署
159
+
160
+ AutoGLM-GUI 提供预构建的 Docker 镜像,支持 `linux/amd64` 和 `linux/arm64` 架构,适合服务器端远程控制 Android 设备的场景。
161
+
162
+ **使用 docker-compose(推荐):**
200
163
 
201
164
  ```bash
202
- # 从源码安装
203
- git clone https://github.com/your-repo/AutoGLM-GUI.git
204
- cd AutoGLM-GUI
205
- uv sync
165
+ # 1. 下载 docker-compose.yml
166
+ curl -O https://raw.githubusercontent.com/suyiiyii/AutoGLM-GUI/main/docker-compose.yml
206
167
 
207
- # 构建前端(必须)
208
- uv run python scripts/build.py
168
+ # 2. 启动服务
169
+ docker-compose up -d
209
170
 
210
- # 启动服务
211
- uv run autoglm-gui --base-url http://localhost:8080/v1
171
+ # 3. 访问 http://localhost:8000,在 Web 界面中配置模型 API
212
172
  ```
213
173
 
174
+ **或直接使用 docker run:**
175
+
176
+ ```bash
177
+ # 使用 host 网络模式运行(推荐)
178
+ docker run -d --network host \
179
+ -v autoglm_config:/root/.config/autoglm \
180
+ -v autoglm_logs:/app/logs \
181
+ ghcr.io/suyiiyii/autoglm-gui:main
182
+
183
+ # 访问 http://localhost:8000,在 Web 界面中配置模型 API
184
+ ```
185
+
186
+ **配置说明**:
187
+ - 默认使用 host 网络模式(推荐,便于 ADB 设备发现和二维码配对)
188
+ - 模型 API 配置可以在 Web 界面的设置页面中完成,无需提前配置环境变量
189
+ - 如果需要在启动时预配置,可以编辑 `docker-compose.yml` 取消注释 `environment` 部分
190
+
191
+ **连接远程设备**:
192
+
193
+ Docker 容器中连接 Android 设备推荐使用 **WiFi 调试**:
194
+
195
+ 1. 在 Android 设备上开启「开发者选项」→「无线调试」
196
+ 2. 记录设备的 IP 地址和端口号
197
+ 3. 在 Web 界面点击「添加无线设备」→ 输入 IP:端口 → 连接
198
+
199
+ > ⚠️ **注意**:二维码配对功能依赖 mDNS 多播,在 Docker bridge 网络中可能受限。**强烈建议使用 `--network host` 模式**以获得完整功能支持。
200
+
201
+ **更多 Docker 配置选项**,请参见下方的 [Docker 部署详细说明](#-docker-部署详细说明)。
202
+
203
+ ---
204
+
214
205
  启动后,在浏览器中打开 http://localhost:8000 即可开始使用!
215
206
 
207
+ ### 🎯 模型服务配置
208
+
209
+ AutoGLM-GUI 只需要一个 OpenAI 兼容的模型服务。你可以:
210
+
211
+ - 使用官方已托管的第三方服务
212
+ - 智谱 BigModel:`--base-url https://open.bigmodel.cn/api/paas/v4`,`--model autoglm-phone`,`--apikey <你的 API Key>`
213
+ - ModelScope:`--base-url https://api-inference.modelscope.cn/v1`,`--model ZhipuAI/AutoGLM-Phone-9B`,`--apikey <你的 API Key>`
214
+ - 或自建服务:参考上游项目的[部署文档](https://github.com/zai-org/Open-AutoGLM/blob/main/README.md)用 vLLM/SGLang 部署 `zai-org/AutoGLM-Phone-9B`,启动 OpenAI 兼容端口后将 `--base-url` 指向你的服务。
215
+
216
+ 示例:
217
+
218
+ ```bash
219
+ # 使用智谱 BigModel
220
+ pip install autoglm-gui
221
+ autoglm-gui \
222
+ --base-url https://open.bigmodel.cn/api/paas/v4 \
223
+ --model autoglm-phone \
224
+ --apikey sk-xxxxx
225
+
226
+ # 使用 ModelScope
227
+ pip install autoglm-gui
228
+ autoglm-gui \
229
+ --base-url https://api-inference.modelscope.cn/v1 \
230
+ --model ZhipuAI/AutoGLM-Phone-9B \
231
+ --apikey sk-xxxxx
232
+
233
+ # 指向你自建的 vLLM/SGLang 服务
234
+ pip install autoglm-gui
235
+ autoglm-gui --base-url http://localhost:8000/v1 --model autoglm-phone-9b
236
+ ```
237
+
216
238
  ## 🔄 升级指南
217
239
 
218
240
  ### 检查当前版本
@@ -282,29 +304,31 @@ AutoGLM-GUI 支持同时控制多个 Android 设备:
282
304
  4. **对话** - 描述你想要做什么(例如:"去美团点一杯霸王茶姬的伯牙绝弦")
283
305
  5. **观察** - Agent 会逐步执行操作,每一步的思考过程和动作都会实时显示
284
306
 
285
- <a id="mode-classic"></a>
286
- ### 🌿 普通模式(单模型 / Open AutoGLM)
287
-
288
- 这是**开源 AutoGLM-Phone 的“原生形态”**:由一个视觉模型直接完成「理解任务 → 规划步骤 → 观察屏幕 → 执行动作」的完整闭环。
307
+ ### 🤖 选择 Agent 类型
289
308
 
290
- - **优点**:配置最简单,上手最快
291
- - **适用场景**:目标明确、步骤较少的任务(例如打开应用、简单导航)
309
+ 在初始化设备时,可以选择不同的 Agent 类型(默认:GLM Agent):
292
310
 
293
- <a id="mode-dual"></a>
294
- ### 🧠 双模型协作模式(增强)
311
+ - **GLM Agent**:基于 GLM 模型优化,成熟稳定,适合大多数任务
312
+ - **MAI Agent**:**内部实现**的 Mobile Agent,支持多张历史截图上下文,适合复杂任务
313
+ - 🆕 **现已完全内部化**:移除 ~1200 行第三方依赖,性能优化,中文适配
314
+ - 🔄 **向后兼容**:需要使用旧版本可选择 `mai_legacy` 类型
295
315
 
296
- 双模型模式通过**决策大模型(负责规划/纠错)** + **视觉小模型(负责观察/操作)**协作,提升复杂任务的稳定性与可控性。
316
+ MAI Agent 可配置参数:
317
+ - `history_n`:历史截图数量(1-10,默认:3)
297
318
 
298
- #### 工作模式(Thinking Mode)
319
+ **MAI Agent 增强特性**(v1.5.0+):
320
+ - ✅ 流式思考输出(实时显示推理过程)
321
+ - ✅ 中文优化 Prompt(针对国内应用场景)
322
+ - ✅ 性能监控(LLM 耗时、动作执行统计)
323
+ - ✅ 详细的操作指南和错误避免提示
299
324
 
300
- - **🚀 TURBO(推荐)**:大模型先生成“操作序列”,视觉模型批量执行;仅在异常时触发重规划(通常 1-2 次大模型调用)
301
- - **🎯 DEEP**:每一步都调用大模型做决策与分析,最稳但成本/耗时更高
302
- - **⚡ FAST**:同样逐步决策,但提示词更短、响应更快,适合轻量任务
325
+ <a id="mode-classic"></a>
326
+ ### 🌿 普通模式(单模型 / Open AutoGLM)
303
327
 
304
- #### 配置要点
328
+ 这是**开源 AutoGLM-Phone 的“原生形态”**:由一个视觉模型直接完成「理解任务 → 规划步骤 → 观察屏幕 → 执行动作」的完整闭环。
305
329
 
306
- - **决策大模型**:建议使用推理/规划能力较强的模型(如 GLM-4.7、GPT-4、Claude 等)
307
- - **视觉小模型**:建议使用具备 GUI 观察与操作能力的模型(如 AutoGLM-Phone-9B / `autoglm-phone`)
330
+ - **优点**:配置最简单,上手最快
331
+ - **适用场景**:目标明确、步骤较少的任务(例如打开应用、简单导航)
308
332
 
309
333
  <a id="mode-layered"></a>
310
334
  ### 🧩 分层代理模式(Layered Agent,增强 / 实验性)
@@ -316,21 +340,16 @@ AutoGLM-GUI 支持同时控制多个 Android 设备:
316
340
  - **适用场景**:需要多轮推理、需要“边看边问边改计划”的复杂任务(例如浏览/筛选/对比、多轮表单填写等)
317
341
  - **重要限制**:执行层不负责“记笔记/保存中间信息/直接提取文本变量”;规划层需要信息时必须通过提问让执行层把屏幕内容“念出来”
318
342
 
319
- ### 🎭 三种工作模式对比
343
+ ### 🎭 两种工作模式对比
320
344
 
321
- AutoGLM-GUI 提供了三种不同的代理工作模式,适用于不同的使用场景:
345
+ AutoGLM-GUI 提供了两种不同的代理工作模式,适用于不同的使用场景:
322
346
 
323
347
  #### 1️⃣ 经典模式(Classic Mode)
324
348
  - **架构**:单一 `autoglm-phone` 视觉模型直接处理(即普通 Open AutoGLM 的体验)
325
349
  - **适用场景**:简单、明确的任务
326
350
  - **特点**:配置简单,适合快速上手
327
351
 
328
- #### 2️⃣ 双模型协作(Dual Model
329
- - **架构**:决策大模型(GLM-4.7/GPT-4)+ 视觉小模型(autoglm-phone)
330
- - **适用场景**:需要智能规划的中高复杂度任务
331
- - **特点**:支持 TURBO/DEEP/FAST 三种思考模式,在成本、速度与稳定性之间做权衡
332
-
333
- #### 3️⃣ 分层代理(Layered Agent)🆕 实验性功能
352
+ #### 2️⃣ 分层代理(Layered Agent
334
353
  - **架构**:基于 Agent SDK 的分层任务执行系统
335
354
  - **规划层**:决策模型作为高级智能中枢,负责任务拆解和多轮推理
336
355
  - **执行层**:autoglm-phone 作为执行者,只负责观察和操作
@@ -338,13 +357,9 @@ AutoGLM-GUI 提供了三种不同的代理工作模式,适用于不同的使
338
357
  - **特点**:规划层通过工具调用驱动执行层,过程更透明、更便于调试与迭代策略
339
358
 
340
359
  **选择建议**:
341
- - 🚀 **常规任务(订外卖、打车)**:双模型 TURBO 模式
342
- - 🎯 **复杂任务(浏览并评论帖子)**:双模型 DEEP 模式
360
+ - 🚀 **常规任务(订外卖、打车)**:经典模式
343
361
  - 🏗️ **需要多轮推理的任务**:分层代理模式
344
362
 
345
- > 💬 **我们需要你的反馈!**
346
- > 不同的任务场景适合不同的模式,我们正在持续优化这些模式的性能和易用性。如果你在使用过程中有任何建议、遇到问题或发现某个模式特别好用/不好用,欢迎通过 [GitHub Issues](https://github.com/suyiiyii/AutoGLM-GUI/issues) 或 [QQ 交流群](https://qm.qq.com/q/J5eAs9tn0W) 告诉我们。你的反馈将帮助我们改进产品!
347
-
348
363
  ### 手动控制模式
349
364
 
350
365
  除了 AI 自动化,你也可以直接在实时画面上操控手机:
@@ -394,6 +409,25 @@ AutoGLM-GUI 提供了三种不同的代理工作模式,适用于不同的使
394
409
 
395
410
  ## 🛠️ 开发指南
396
411
 
412
+ ### 源码安装
413
+
414
+ 如果你需要从源码进行开发或定制,可以按照以下步骤:
415
+
416
+ ```bash
417
+ # 1. 克隆仓库
418
+ git clone https://github.com/suyiiyii/AutoGLM-GUI.git
419
+ cd AutoGLM-GUI
420
+
421
+ # 2. 安装依赖
422
+ uv sync
423
+
424
+ # 3. 构建前端(必须)
425
+ uv run python scripts/build.py
426
+
427
+ # 4. 启动服务
428
+ uv run autoglm-gui --base-url http://localhost:8080/v1
429
+ ```
430
+
397
431
  ### 快速开发
398
432
 
399
433
  ```bash
@@ -402,6 +436,7 @@ uv run autoglm-gui --base-url http://localhost:8080/v1 --reload
402
436
 
403
437
  # 前端开发服务器(热重载)
404
438
  cd frontend && pnpm dev
439
+ ```
405
440
 
406
441
  ### 构建和打包
407
442
 
@@ -413,6 +448,57 @@ uv run python scripts/build.py
413
448
  uv run python scripts/build.py --pack
414
449
  ```
415
450
 
451
+ ## 🐳 Docker 部署详细说明
452
+
453
+ > 💡 **提示**:Docker 部署已整合到 [快速开始](#-快速开始) 部分,推荐直接查看上方的"方式二:Docker 部署"说明。
454
+
455
+ 本节提供更多 Docker 配置选项和高级用法。
456
+
457
+ ### 指定监听端口
458
+
459
+ 如果使用 host 网络模式且需要修改默认端口(8000),可以通过 `command` 参数指定:
460
+
461
+ ```bash
462
+ # 监听 9000 端口
463
+ docker run -d --network host \
464
+ -v autoglm_config:/root/.config/autoglm \
465
+ -v autoglm_logs:/app/logs \
466
+ ghcr.io/suyiiyii/autoglm-gui:main \
467
+ autoglm-gui --host 0.0.0.0 --port 9000 --no-browser
468
+ ```
469
+
470
+ 如果使用 bridge 网络模式,则使用 `-p` 参数映射端口:
471
+
472
+ ```bash
473
+ # 映射主机 9000 端口到容器 8000 端口
474
+ docker run -d -p 9000:8000 \
475
+ -v autoglm_config:/root/.config/autoglm \
476
+ -v autoglm_logs:/app/logs \
477
+ ghcr.io/suyiiyii/autoglm-gui:main
478
+ ```
479
+
480
+ ### 镜像标签
481
+
482
+ | 标签 | 说明 |
483
+ |------|------|
484
+ | `main` | 跟随 main 分支最新代码,推荐使用 |
485
+ | `<commit-sha>` | 特定 commit 的镜像(如 `abc1234`),用于锁定版本 |
486
+
487
+ ### 环境变量
488
+
489
+ | 变量 | 说明 | 默认值 |
490
+ |------|------|--------|
491
+ | `AUTOGLM_BASE_URL` | 模型 API 地址 | (必填) |
492
+ | `AUTOGLM_MODEL_NAME` | 模型名称 | `autoglm-phone` |
493
+ | `AUTOGLM_API_KEY` | API 密钥 | (必填) |
494
+
495
+ ### 健康检查
496
+
497
+ ```bash
498
+ # 检查服务状态
499
+ curl http://localhost:8000/api/health
500
+ ```
501
+
416
502
  ## 📝 开源协议
417
503
 
418
504
  Apache License 2.0