Star Office UI 多龙虾访客系统:Join Key 复用、并发控制、状态区域映射与动画渲染全解析
发布时间:2026/9/28 2:16:12来源:尧图网络
前端后端AI 应用数据可视化【免费下载链接】Star-Office-UIA pixel office for your OpenClaw: turn invisible work states into a cozy little space with characters, daily notes, and guest agents. Code under MIT; art assets for non-commercial learning only.项目地址https://gitcode.com/gh_mirrors/st/Star-Office-UI点击查看免费下载Star Office UI 是一个像素风办公空间项目将 OpenClaw 等 Agent 不可见的工作状态映射为办公室里可见的角色行为——写代码的角色会走到办公桌、待命的角色会躺到休息区沙发、出错的角色会出现在 Bug 区。本文基于 docs/FEATURES_NEW_2026-03-01.md 的能力清单结合仓库源码完整讲解本阶段实现的 8 项新增功能多访客接入、Join Key 复用、并发控制、状态区域映射、动画资源、气泡锚点、移动端适配与远端推送联调。读完你将掌握这套系统的完整链路从 Key 发放、并发准入、状态归一化、区域落位到前端角色动画与气泡渲染以及如何用推送脚本让任意 OpenClaw 在办公室里拥有一个实时工位。1. 多龙虾访客系统一室多客的接入模型多龙虾访客系统的核心目标是多个远端 OpenClaw 可以同时加入同一个办公室各自拥有独立身份与实时状态。这里的“龙虾”指的是使用 OpenClaw 驱动的 Agent 角色它们以访客身份出现在办公室看板上。从源码看后端用agents-state.json统一保存所有在场 Agent含主角色与访客每个访客记录以下字段见 backend/app.py 的DEFAULT_AGENTS与join_agent()实现字段含义agentId全局唯一 ID形如agent_毫秒时间戳_4位随机串避免并发加入时碰撞name访客显示名字isMain是否主角色办公室主人starstate/detail当前状态词与一句话说明area由状态映射出的办公室区域source固定为remote-openclaw标识远端来源joinKey该访客使用的接入密钥authStatuspending/approved/offline/rejectedauthExpiresAt授权到期时间默认 24 小时lastPushAt最近一次推送状态的时间参与在线判定avatar从guest_role_1~guest_role_6随机分配前端通过GET /agents轮询这份列表见 backend/app.py 的get_agents()并做两类自动清理pending超过authExpiresAt的申请自动 leaveapproved但 5 分钟无lastPushAt更新的访客自动标记offline。也就是说访客的在线不是一个静态开关而是由心跳状态推送动态维持的。2. Join Key 机制升级从一次性到固定可复用本阶段把 Join Key 从“一次性 key用过即废”升级为“固定可复用 key”同一个 key 可以被多个 Agent 反复使用、长期使用不再因被使用过就被拒绝。默认 key 为ocj_starteam01~ocj_starteam08。key 的结构见仓库中的样例配置 join-keys.sample.json{ keys: [ { key: ocj_example_team_01, used: false, reusable: true, maxConcurrent: 3, usedBy: null, usedByAgentId: null, usedAt: null } ] }运行时 key 文件为join-keys.json由后端在启动时初始化如果文件不存在会尝试从join-keys.sample.json拷贝生成否则初始化为空{keys: []}见 backend/app.py 启动初始化逻辑。各字段含义字段说明key接入密钥字符串格式ocj_xxxreusable是否可复用本阶段统一置为truemaxConcurrent该 key 的同时在线并发上限默认 3used/usedBy/usedByAgentId/usedAt最近一次使用信息仅用于追踪不再作为准入判据后端join_agent()中明确去掉了“usedtrue 就拒绝”的旧逻辑源码注释# key 可复用不再因为 usedtrue 拒绝并保留 key 级过期校验expiresAt——若配置了该字段且已过期会返回 403 并提示“活动已结束”。3. 并发控制修复 join 竞态第 4 个并发被正确拒绝并发控制是本阶段的重点修复项。旧实现中多个并发 join 请求可能基于同一份旧快照同时通过校验造成超限放行。修复后用threading.Lock()包裹 join 关键区见 backend/app.py 的join_lock在锁内重新读取join-keys.json与agents-state.json避免“先校验后写入”的窗口期并发计数只统计“同时在线”的访客authStatus approved且lastPushAt/updated_at在 5 分钟内超过 5 分钟视为 offline不计入并发当同 key 在线数达到maxConcurrent默认 3时第 4 个并发 join 返回HTTP 429提示“该接入密钥当前并发已达上限3请稍后或换另一个 key”。关键判定逻辑位于 backend/app.py 的join_agent()max_concurrent int(key_item.get(maxConcurrent, 3)) active_count 0 for a in agents: # 只统计同 key、已批准、5 分钟内有心跳的在线访客 ... if active_count max_concurrent: return jsonify({ok: False, msg: f该接入密钥当前并发已达上限{max_concurrent}请稍后或换另一个 key}), 429这个在线判定与get_agents()的 5 分钟自动离线逻辑一致保证“掉线访客释放额度、恢复推送自动回approved”见agent_push()中offline - approved的自动提升逻辑从而在“防超限”与“可恢复”之间取得平衡。4. 访客状态映射与区域渲染4.1 六种标准状态后端定义了唯一的合法状态集合backend/app.pyVALID_AGENT_STATES frozenset({idle, writing, researching, executing, syncing, error})4.2 状态 → 区域映射状态到办公室区域的映射由STATE_TO_AREA_MAP统一定义状态区域说明idlebreakroom休息区沙发writingwriting工作区办公桌researchingwriting工作区executingwriting工作区syncingwriting工作区errorerrorBug 区后端通过state_to_area(state)输出区域写入访客的area字段并返回给推送方前端在 frontend/index.html 中按agent.area把角色放进对应区域矩形breakroom: {x1,y1,x2,y2}等坐标常量同时维护各区域的排布索引把同一区域的多个访客错位摆放避免叠在一起。4.3 状态别名归一化推送方与后端各自做了别名归一化保证不同来源的状态词能被统一识别后端normalize_agent_state()working/busy/write - writingrun/running/execute/exec - executingsync - syncingresearch/search - researching未知值一律回落idle推送脚本normalize_state()map_detail_to_state()除了别名映射还会从 detail 文本关键词推断状态如“报错/error/bug”判error“同步/sync/备份”判syncing使“只有描述文字、没有状态词”的状态源也能正确落区。这解释了为什么本阶段修复后“访客气泡文案与状态不再错位”前端展示的气泡文案取自agent.detail区域由agent.area决定而detail与state/area由同一份推送数据来源同步写入不会再出现“文案说在写代码、角色却站在休息区”的割裂。5. 访客动画与资源优化访客从静态图升级为像素风动画精灵。仓库frontend/下提供动画序列guest_anim_1.webp~guest_anim_6.webp128×64 分帧的精灵图静态备用形象guest_role_1.png~guest_role_6.png128×64作为切换缓冲或降级兜底。后端join_agent()为每个新访客随机分配一个静态形象作为avatar前端角色动画播放guest_anim_*。资源说明见 frontend/index.html 的资产清单guest_anim_1~6为“32×32 分帧”的像素风动画序列建议轮廓清晰、与主角风格统一guest_role_1~6为对应静态备用图建议与对应动画角色设定一致避免切换割裂。使用 webp 版本的核心收益是体积webp 相比原始 png 在同等画质下显著减小加载体积配合后端/static的长期缓存策略Cache-Control: public, max-age31536000, immutable见 backend/app.py 的add_no_cache_headers()多访客同时播放动画时首屏与滚动加载压力都更小。6. 名字与气泡显示优化锚点基于名字定位旧实现中访客气泡直接以角色精灵为锚点非 demo 访客会出现名字/气泡被角色遮挡的问题。本阶段的修复策略是非 demo 访客名字与气泡整体上移名字位于角色上方约 120px 处避免与角色 body 重叠气泡锚点改为基于名字定位气泡 y 坐标取nameText.y - nameH/2 - 22见 frontend/index.html 中showGuestBubble/maybeShowGuestBubble附近逻辑从“气泡在角色上方”变为“气泡在名字上方”文字与角色的层级关系稳定不再错位demo 访客demo_nika/demo_mercury保留较低偏移-90px因为 demo 角色尺寸更小无需大幅上移。7. 移动端展示页面已支持手机端直接访问与展示frontend/index.html 设置了响应式 viewportmeta nameviewport contentwidthdevice-width, initial-scale1.0布局完成基础移动端适配页面、看板与角色渲染在手机尺寸下可正常浏览。需要说明的是本阶段移动端的目标是“满足演示场景”即能打开、能看到访客与状态变化属于基础适配而非全面触控交互优化。验收时可参考 docs/UPDATE_REPORT_2026-03-04_P0_P1.md 中的建议项首页进入速度、状态切换、回复结束回待命区等逐项在移动端过一遍。8. 远端推送脚本联调状态源诊断与 AGENT_NAME 时序修复8.1 从状态文件读取并推送远端 Agent 通过 office-agent-push.py 将本地状态推送到办公室。脚本只需配置 3 个变量JOIN_KEY ocj_starteam02 # 接入密钥必填 AGENT_NAME 小明的龙虾 # 在办公室里显示的名字必填 OFFICE_URL https://office.hyacinth.im # 办公室地址一般不用改脚本流程首次运行先POST /join-agent加入自动批准、无需等待随后每15 秒读取一次本地状态并POST /agent-push按CtrlC退出并自动离线。完整接入步骤见仓库内 frontend/join-office-skill.md。8.2 本地状态读取优先级脚本按以下优先级自动发现状态源无需手动配置state.json本机 OpenClaw 工作区自动发现多个候选路径按序探测http://127.0.0.1:19000/status本地 HTTP 接口可用OFFICE_LOCAL_STATUS_TOKEN携带鉴权默认 fallbackidle待命中。若状态文件路径特殊可用环境变量显式指定OFFICE_LOCAL_STATE_FILE/你的/state.json python3 office-agent-push.py脚本启动时会打印当前实际使用的状态文件路径与本地状态 URL[status-source:file] path...这就是“状态来源诊断日志”——当你疑惑“为什么一直显示 idle”时先看启动日志确认它到底读了哪个文件。8.3 防“假工作中”与 detail 纠偏脚本内置两重保护避免角色“卡在工位假工作”stale 回退本地状态文件的updated_at超过OFFICE_STALE_STATE_TTL默认 600 秒未更新时自动视为idledetail 关键词纠偏即使state字段缺失或过时map_detail_to_state()也会从detail文本推断真实状态如包含“报错”则判error保证文案与区域一致。8.4 AGENT_NAME 环境变量覆盖时序修复旧版本中AGENT_NAME环境变量可能在脚本读取默认配置之后才生效导致“名字没换成”。修复后的逻辑是load_local_state()从本地缓存文件office-agent-state.json读取上次 join 的agentNamejoin 时以“本地缓存 脚本默认值”的优先级取名字同时do_push()每次都会携带当前name同步给后端保证改名后办公室里的显示同步更新。9. 联调验证链路与常见排障结合 docs/UPDATE_REPORT_2026-03-04_P0_P1.md 与本阶段功能建议按以下链路验证并发控制用同一 key 同时发起 4 个 join 请求前 3 个成功200第 4 个返回 HTTP 429Key 复用同一 key 在访客离线后再次 join 应成功不受usedtrue影响状态落区分别推送idle / writing / researching / executing / syncing / error观察角色走向休息区 / 办公桌 / Bug 区气泡文案与区域一致自动离线停止推送超过 5 分钟/agents列表中该访客变为offline推送诊断启动office-agent-push.py时观察[status-source:*]日志确认状态源路径符合预期排查“一直 idle”问题移动端手机浏览器打开办公室页面确认访客、动画与气泡正常展示。常见返回码对照返回码含义处置403key 无效 / 已过期 / agent 未授权检查 key 与授权或重新 join404agent 未注册或已被移出重新 join脚本会自动停止推送429同 key 并发达上限默认 3等待在线访客离线或换另一个 key401本地本地/status需要鉴权设置OFFICE_LOCAL_STATUS_TOKEN10. 小结一套完整的“状态 → 行为”闭环本阶段新增功能覆盖了从接入到呈现的完整闭环接入层Join Key 复用 maxConcurrent并发控制 竞态修复让多个远端 OpenClaw 稳定入驻数据层六状态归一化 STATE_TO_AREA_MAP区域映射 5 分钟心跳离线判定保证数据单一事实来源呈现层动画精灵资源 名字锚点气泡 移动端 viewport 适配让状态变化可见、可读、不遮挡联动层推送脚本的状态源自动发现、stale 回退、诊断日志与AGENT_NAME时序修复让远端 Agent 从本地状态文件一路推送到办公室看板。如果你计划把某个 OpenClaw 接入办公室推荐按 frontend/join-office-skill.md 的 Quick Start 操作确认授权 → 下载office-agent-push.py→ 填 3 个变量运行脚本会自动完成 join 与 15 秒周期推送你的龙虾随即出现在办公室看板上并根据状态自动走到不同区域。赞分享前端后端AI 应用数据可视化【免费下载链接】Star-Office-UIA pixel office for your OpenClaw: turn invisible work states into a cozy little space with characters, daily notes, and guest agents. Code under MIT; art assets for non-commercial learning only.项目地址https://gitcode.com/gh_mirrors/st/Star-Office-UI点击查看免费下载相关推荐OpenClaw Control UI 侧边栏龙虾访客全解析机制、交互与源码实现OpenClaw Control UI 侧边栏龙虾访客全解析机制、交互与源码实现 OpenClaw 的 Control UI 中潜伏着一位特殊的居民——一AI 应用AI Agent交互助手后端即时通讯网关从像素到掩码MaskFormer如何用Transformer实现高效语义分割从像素到掩码MaskFormer如何用Transformer实现高效语义分割 MaskFormer是由Facebook Research开发的创新语义分割框架Terraform状态锁定多用户并发访问控制完全指南Terraform状态锁定多用户并发访问控制完全指南 引言基础设施即代码的并发困境 你是否曾在团队协作中遭遇过Terraform状态文件State FilIaCCLI基础设施云原生DevOps上一篇GreasyFork-Scripts: 自定义网页脚本的宝库下一篇推荐一个前端利器Next.js 集成 Apollo 的智能解决方案 - next-with-apollo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网