openqj
c2f82da5e0
Merge pull request #92 from openqj/feat-sub2api-hotfix
...
fix: docker 默认 runner 支持 env + 并发开通竞态复用
2026-10-27 18:10:50 +08:00
host
4936db3c47
fix: docker 默认 runner 支持 env + 并发开通竞态复用
...
翻转实弹暴露的两个 #88 缺口:
- _docker_default_runner 不接受 env,_call_runner 遇 env 即 loud fail,
导致 sub2api 路径下所有 docker 任务失败(xcmapi 路径不传 env,
此前未暴露)。默认 runner 现接受 env 并与进程环境合并后传给
docker CLI 子进程(-e <名> 由此解析,值绝不进 argv)。
- 同一用户两任务并发开通时建号撞 email 已存在:现轮询复用
胜出者入库的行,等不到再原错抛出。
测试:sub2api 16、docker 沙箱 29;全量 cloud 789(4 跳过)、
host 65、deploy 19 全绿。
2026-10-27 17:59:04 +08:00
openqj
99efa93bd3
Merge pull request #88 from openqj/feat-sub2api
...
sub2api 网关接入:每用户独立账号 + 任务注入 + 网关可配置
2026-10-27 17:30:14 +08:00
host
dbfa026a4e
sub2api 开通授初始余额:余额为 0 的 key 在网关侧直接 403
2026-10-27 17:22:54 +08:00
host
ec47328d3c
sub2api 网关接入:每用户独立账号 + 任务注入 + 网关可配置
...
- cloud/sub2api.py:管理 API 客户端(管理员登录/token 刷新/
建用户/以用户发 key/删用户/查组/网关模型目录)+ 幂等开通
ensure_user_gateway_key(入库失败尽力清理孤儿 key 与账号)
- worker:网关门(sub2api 时按 created_by 幂等开通,失败任务
直接 failed;协调员子任务跟父任务属主)+ 默认模型走网关
目录首个;三条执行路径(Local popen/同步、Docker 同步)注
入任务级 env 与 --model-provider;NO_PROXY 追加网关 host
- host.py:--model-provider,sub2api 时以 -c 注入 provider 表
(不改租户 config.toml);未配 SUB2API_BASE_URL 时 loud fail
- sandbox:Local/Docker 执行器传 --model-provider 与任务 env;
docker 密钥只传名(-e SUB2API_API_KEY),值由 CLI 子进程
环境提供,绝不进 argv;runner 不支持 env 时 loud fail
- server:OAuth 建号 best-effort 开通;/relay/models 走调用者
自己的网关模型目录;init_db 补 user_gateway_keys 表
- 测试:新单测 11 个;全量 cloud 679(4 跳过)、host 65、
deploy 19 全过
- 诚实边界:真模型调用实弹需上游账号挂组后才做;切流前
xcmapi 保持现网
2026-10-27 17:22:54 +08:00
openqj
437684902a
Merge pull request #86 from openqj/feat-multiuser-hardening
...
多用户生产级缺口批:sweep 鉴权、默认配额、默认 executor、 无价 token 上限
2026-10-27 17:22:40 +08:00
host
89c8fb1a79
Key 修法:agent shell 不再继承密钥类环境变量
...
- 实弹证实:默认配置下 agent shell 继承 server 进程 env,local 与
docker 两路都能拿到共享 relay key(v3 标记文件法双路 PRESENT)。
- 修法用 codex 原生 shell_environment_policy.exclude:server 自己
的中转调用走进程 env(env_key),不受 shell 策略影响,两者可
分开;inherit 保持默认 all,PATH、代理变量等不动;gh 用文件
登录不用 env,故不排 *_TOKEN。
- host.py Server._start 经 _server_command 统一加 -c 旗标,local
与 docker 共用一处,覆盖两路;-c 语法已用本机二进制实测
(合法值启动正常,非法值立即报 invalid shell environment
policy 退出)。
- 测试:新增 _server_command 断言;全量 host 65、cloud 668
(4 跳过)、deploy 19 全过
2026-10-27 17:15:09 +08:00
host
7e081211db
多用户生产级缺口批:sweep 鉴权、默认配额、默认 executor、 无价 token 上限
...
- POST /admin/sweep 改走任一项目 maintainer+ 门槛(与备份管理同口径),否则 403,记 admin_sweep 审计;threshold 下限钳 60 秒
- OAuth 建号 created=True 时写默认配额行(默认 $10/月,CLOUD_DEFAULT_QUOTA_USD_MICROS 可调,INSERT OR IGNORE 幂等);老用户无配额行不受影响
- 建任务未指定且无环境继承时默认 executor=docker(分支继承为空时同理);CLOUD_DEFAULT_EXECUTOR 可覆盖,空字符串恢复旧行为;命令台下拉默认改为 docker
- 无价模型 token 上限:价目表外模型(默认 terra)成本 usd 为 NULL,USD 配额永不生效;有配额行的用户当月无价 token 达 CLOUD_QUOTA_UNPRICED_TOKEN_CAP(默认 2000 万/月)即停,服务端 402、worker 认领/重试/后续消息同口径;报表仍记 unpriced,不折假美元
- 测试:新增 test_multiuser_gaps 11 个 + test_worker_quota 3 个;全量 cloud 668、host 64、deploy 19 全过
2026-10-27 17:15:09 +08:00
openqj
c1f9313c10
Merge pull request #87 from openqj/feat-coordinator
...
feat: 协调员任务(并行子任务、等齐、合流汇总)
2026-10-27 16:25:32 +08:00
openqj
e786e1f85d
Merge pull request #89 from openqj/feat-p1
...
P1 补齐:自动评审队列、自动化+分诊、并发 caps、运行时审批队列
2026-10-27 16:00:53 +08:00
host
e0cecd70aa
feat: P1 补齐(自动评审队列、自动化+分诊、并发 caps、运行时审批队列)
2026-10-27 15:53:50 +08:00
host
7c46ac8e5b
feat: 协调员任务(并行子任务、等齐、合流汇总)
...
建任务时传 coordinator_parts(分工列表,1-20 项,分工名唯一)即为协调员任务:本身不跑模型回合,worker 认领后一次建齐子任务(普通任务,并行被各 worker 认领),等全部终态后合流成汇总报告写回。子任务带 parent_task_id 与 coordinator_part,控制台可用 parent_task_id 查到;协调员重跑按分工名复用已完成子任务、失败/中断的回 queued 重跑;取消与超时尽力取消未终态子任务。子任务的配额/key/执行器门照常生效,不构成绕过。协调员任务拒绝与 goal/plan/验收命令同用。控制台:任务列表 [协调]/[协调子任务] 标记、详情分工与子任务区、新建表单子任务 JSON 输入。新单测 26 个。
2026-10-27 15:45:17 +08:00
openqj
29efc6c61f
Merge pull request #85 from openqj/feat-task-turn-ids
...
feat: 任务列表显示 turn_id 与 root_turn_id
2026-10-27 15:44:33 +08:00
host
dbcc8e641a
feat: 任务列表显示 turn_id 与 root_turn_id
...
host.py dispatch 打印补 turn_id/root_turn_id;执行器解析(local/Docker)透传;worker 写回 tasks 新列(新值非空才覆盖);server 迁移与接口字段;控制台任务列表新增 turn/root turn 两列(短显+悬停全文);新单测 9 个。
2026-10-27 14:52:00 +08:00
openqj
559a7dcb9f
Merge pull request #84 from openqj/feat-peer-messages
...
feat: 任务间互发消息(API + agent 标记块,不中断任务)
2026-10-27 14:30:14 +08:00
host
ef30558f7c
feat: 任务间互发消息(API + agent 标记块,不中断任务)
...
同项目任务互发消息、对方做完可回消息:API POST /tasks/<目标>/messages
(from_task_id,目标项目 create_task + 发送项目 read 鉴权)与 agent
回合输出标记块(worker 回合后解析投递,不用联网、不用凭证,本地
与 Docker 都通)。投递不中断任务:对方运行中/排队中排成后续消息
(轮次边界执行,direct 优先);对方终态则续跑复活(resume_message +
queued),A→B→A 往返不受回合时序影响。拒绝项:自己、跨项目、goal
目标、已合并、复活位被占;每轮最多 5 块,仅 completed 轮次投递;
目标执行时配额门照常生效。控制台后续消息列显示发送方,新增给
其他任务发消息框(落已代理的 /tasks 下,不用改 nginx)。
测试:新增 test_peer_messages(15)、test_peer_messages_server(8)、
test_worker_peer(4);全量 cloud 654、host 64、deploy 19 全过(cloud 4 跳过)。
2026-10-27 14:12:28 +08:00
openqj
4901a1090b
Merge pull request #83 from openqj/feat-tenant-trace
...
fix: 租户 Docker 任务链路可见(租户目录优先、共享目录兜底)
2026-10-27 13:01:35 +08:00
host
a2863b2b10
fix: 租户 Docker 任务链路可见(租户目录优先、共享目录兜底)
...
此前服务端只读共享链路目录,租户隔离的 Docker 任务链路文件落在 tenants/<项目>/work/host-traces/,/trace 与 /agents 会误报为空。改后按任务解析目录列表(租户优先、共享兜底),父链路与子链路文件多目录合并读;直接发送的续写跟到已有链路文件所在的目录,不把一条任务的链路拆成两处。
2026-10-27 12:58:24 +08:00
openqj
79a1d56856
Merge pull request #82 from openqj/feat-subagent-chain
...
feat: 命令台子代理链路(主任务/模型子代理/委派子任务 + 过程调用实时同步)
2026-10-27 11:54:41 +08:00
host
c4d3ec9bff
feat: 命令台子代理链路(主任务/模型子代理/委派子任务 + 过程调用实时同步)
...
host:链路条目带 thread 归属;delegate 向父链路文件写 agent-start/done 标记。服务端:GET /tasks/{id}/agents 聚合父链路 + 子链路文件成代理链(状态口径:委派以结束标记为准、无标记即进行中;模型子代理无结束信号时父任务运行中为进行中、否则未知)。命令台:新增子代理链路区,随 SSE 流防抖刷新;扁平链路也渲染 agent 标记。
2026-10-27 11:51:11 +08:00
openqj
34cd0eeba7
Merge pull request #81 from openqj/feat-orphan-worker
...
fix: worker 代码变化自退 + 部署时清孤儿 worker
2026-10-27 11:26:47 +08:00
host
57f8852634
fix: worker 代码变化自退 + 部署时清孤儿 worker
...
2026-10-27 暂存清理实弹:05:51 的旧 docker worker 成孤儿后
继续用旧代码抢任务、按老路失败且不删暂存;autoscaler 用
start_new_session=True 拉 worker、部署重启杀不到非 unit 进程。
两层修:
1. worker 常驻循环每轮边界比对 worker.py 文件签名
(mtime_ns + size),部署换目录后必变,变了就以 75
(EX_TEMPFAIL,失败类)退出——检查点在轮次边界,绝不
中断在跑任务。退出后:unit 托管的由 systemd on-failure
重拉新版,autoscaler 托管的由 reconcile 重拉,孤儿直接
消失。附带好处:以后部署不用再手动重启本地 worker。
2. host_deploy.sh 换目录后、启动服务前清孤儿:按 cgroup
过滤杀非 .service 的 cloud.worker 进程(桥接修补前就存
在的孤儿),先 TERM(跑完当前任务再退),30 秒未退的
再 KILL;unit 托管的(如 host-1)不动。pgrep 用
[c]loud.worker 写法,避免检查命令自匹配。
测试:test_worker.py 新增 2 个(签名变了则 75 退出且不认领、
签名不变则跑到 max_seconds);反向验证:撤掉 worker 修复
时正好前者变红。清扫过滤器主机干跑:两个现役 worker 均
为 unit cgroup,全 KEEP,杀 0 个。全量 deploy 19、host
62、cloud 619 全过。
2026-10-27 11:23:49 +08:00
openqj
c007fafcc7
Merge pull request #78 from openqj/feat-quota-hardening
...
worker: enforce quotas during execution
2026-10-27 11:13:49 +08:00
host
ad014393ee
worker: enforce quotas during execution (claim/retry/fallback/followup/poll kill)
...
- claim-time gate: queued task whose quota was spent while waiting is
marked interrupted with a quota reason, no cost row, resume kept
- retry/fallback boundaries and every followup round check DB month
usage plus this run's accumulated usage (priced via cost table)
- local popen poll loop kills the process group on quota (30s throttle);
Docker/sync paths get boundary checks only (documented)
- quota stops finalize as interrupted + quota_exceeded error, keep the
actual cost row, no push, followups restored to pending
2026-10-27 11:06:40 +08:00
openqj
c189df4a20
Merge pull request #76 from openqj/fix-handler-500
...
fix: 请求处理未捕获异常回 500 JSON,不再断连变 nginx 502
2026-10-27 11:01:31 +08:00
openqj
ad8bf280d0
Merge pull request #77 from openqj/feat-staging-cleanup
...
fix: 提前失败路也清附件暂存
2026-10-27 11:00:27 +08:00
host
99de5c77f8
fix: 提前失败路也清附件暂存(仓库解析失败/缺 key 不再残留 bundle)
...
2026-10-27 附件实弹:仓库解析失败的任务不走正常终局清理,
bundle 目录永久残留(首个失败任务的暂存目录须手动删)。
根因:run_one 里缺 key 门与仓库解析失败两路提前返回,够不
到正常终局后的暂存清理;只有走完 _run_attempt 的任务才删。
修法:把终局清理抽成 _cleanup_task_seed 唯一入口,三路(正
常终局、缺 key 门、仓库解析失败)都走它;取消仍走 server
侧删,互不冲突;删失败不影响任务结果本身。
测试:test_worker.py 新增 2 个(仓库解析失败、缺 key 时
bundle 目录都被删);反向验证:撤掉 worker 修复时正好这
2 个变红,有修复时全绿。全量 deploy 19、host 62、cloud
610 全过。
2026-10-27 10:57:22 +08:00
host
df8c493281
fix: 请求处理未捕获异常回 500 JSON,不再断连变 nginx 502
...
2026-10-27 死锁事件的次生问题:_dispatch 里未捕获异常逃出
handle_one_request 后连接无响应,前端只看到 nginx 502、拿不到
任何可读错误;死锁本身修掉后,同类内部异常仍会以 502 露出来。
兜底(_dispatch_safe,四个 do_* 方法统一走它):
- 任何异常先记 _server_log.exception(堆栈进服务端日志),
再回固定 {"error": "internal_error"},不泄漏堆栈给客户端;
- _send_json/_send_html/SSE 发头后即标记已响应,之后异常
只记日志、不二次发送(响应一旦开始不能再发状态行);
- _responded 每请求重置,同一连接 keep-alive 复用不串请求。
单测:异常请求得 500 JSON(非断连)+ 服务端记日志;
同一连接上 500 之后再请求仍 200。
2026-10-27 10:56:08 +08:00
openqj
b0772d0eac
Merge pull request #75 from openqj/feat-deploy-key
...
feat: deploy 无密码时走密钥直连
2026-10-27 05:50:52 +08:00
openqj
0a862c11f7
Merge pull request #74 from openqj/feat-repo-picker2
...
GitHub 仓库选择菜单:安装仓库列表 + PATCH 补仓库 + 控制台下拉
2026-10-27 05:48:08 +08:00
host
420a7fecfd
feat: deploy 无密码时走密钥直连(收进 main,替代丢失的工作区补丁)
...
背景:2026-10-27 另一条线给 deploy.py 打的密钥补丁只放在
env-console 工作区未提交,切分支后丢失;部署一度只能靠它 +
--allow-dirty。本批把逻辑收进 main,并加一处加固。
分发:有 SSH_PASSWORD 时走 helper(pty 喂密码,实测最稳的一
路);无密码时 helper 不可用(会卡在密码提示),改走密钥直连:
ProxyCommand 显式环境变量优先、其次 helper 目录的
proxy_tunnel.py(存在才用),密钥按 CODEX_DEPLOY_KEY →
/root/.ssh/id_codex_deploy → ~/.ssh/id_codex_deploy 顺序显式传
-i——不能只依赖 /root/.ssh/config 的 Host 条目,那个目录会在
VM 回收时被清空(2026-10-27 05:04 实测),而 ~/.ssh 的那份
持久。两处都没有时不硬编造,靠 ssh 配置或 agent。
测试:deploy/tests 新增 TestSshScpCmd 5 个(有密码走 helper、
无密码绝不用 helper、无 helper 无代理时直连、显式代理优先、
显式密钥优先);全量 deploy 19、host 62、cloud 598 全过。
2026-10-27 05:47:33 +08:00
openqj
d91e5134f5
Merge pull request #73 from openqj/fix-rate-limit-deadlock
...
fix: 限流清理移出请求路径,根治 rate_limit_hits 死锁
2026-10-27 05:45:18 +08:00
host
6ba671e051
GitHub 仓库选择菜单:安装仓库列表 + PATCH 补仓库 + 控制台下拉
2026-10-27 05:43:56 +08:00
host
8bda29eac3
fix: 限流清理移出请求路径,根治 rate_limit_hits 死锁
...
allow() 原先每请求在同一事务里 DELETE 旧行 + INSERT + COUNT,
控制台并发加载 + 双 server 下两个事务在 rate_limit_hits 表上
死锁,未捕获异常直接断连、nginx 报 502(2026-10-27 实测,
环境与链路两区同时 502 均源于此,与各自端点逻辑无关)。
结构修复:
- allow() 只做 INSERT + 窗口内 COUNT(COUNT 按 ts > now-window
过滤,过期行残留不影响计数正确性);建表/索引每实例只做一次。
- 过期行改由后台线程 sweep_rate_limit_hits() 每 60 秒清一次;
Postgres 下拿事务级 advisory lock,另一台 server 正在清时
直接跳过,清理者之间也不死锁;清理失败只记 warning。
- main() 里对 DbRateLimiter 起 sweeper 线程(内存版不需要)。
单测:allow 不再删旧行、窗口计数忽略过期行、sweep 只删过期
行、空库 sweep 不炸。
2026-10-27 05:40:30 +08:00
openqj
5ba4d35839
Merge pull request #72 from openqj/feat-goal-marker
...
fix: goal 宣告检测容忍行尾句号
2026-10-27 05:32:11 +08:00
host
49dfb7c458
fix: goal 宣告检测容忍行尾句号,修提示与检测自矛盾致空转
...
_llm_declared_done 此前要求回合文本里单独一行恰好等于
目标已达成,但 run_goal_loop 三处提示都让模型输出
目标已达成。(带句号);模型照做后检测永不触发,实弹
goal 任务空转 292 轮才被手动取消。改成比对前去行尾空白
与句末标点(。!?;,、. 等),提示不动、单独一行要求
不动,行内带其它文字仍不算。
回归测试 test_goal_marker_trailing_punctuation_counts:裸标记、
句号、感叹号、句号前空格、行尾空格算达成;前缀文字、逗号
后续、反问、空串不算。
2026-10-27 05:28:59 +08:00
openqj
43748804d3
Merge pull request #71 from openqj/feat-quotas
...
租户配额与计费:按用户月度 USD 上限 + 建任务/分支/重试准入 402
2026-10-27 05:28:25 +08:00
host
970b181bab
租户配额与计费:按用户月度 USD 上限 + 建任务/分支/重试准入 402 + 管理/自查端点 + 控制台展示
2026-10-27 05:18:37 +08:00
openqj
2a7cdd582f
Merge pull request #70 from openqj/feat-continue
...
feat: 旧任务继续会话——终端任务带新消息 + 全部选项同一会话续跑
2026-10-27 04:46:06 +08:00
host
f9be9205ab
fix: goal_resume_task 只在 LocalExecutor 上调,其余回落 goal_task
...
与附件分支同款隐患:CloudExecutor 基类与假执行器没有
goal_resume_task,直接调会 AttributeError;回落到 goal_task 让
它们按原语义失败(CloudExecutor 即“不支持 goal”)。
2026-10-27 04:40:34 +08:00
host
3a4997d346
feat: 旧任务继续会话——终端任务带新消息 + 全部选项同一会话续跑
...
server:POST /tasks/{id}/continue(终端非 merged 任务重排队,
resume_message 列存本轮消息,不传选项沿用原值,plan/goal 冲突
与新建一致,goal_mode=1 时转新 goal 语义;CAS 防并发改状态,
审计 task_continued);tasks.resume_message 三处迁移 + PG 建表。
worker:认领后本轮 prompt 换成续跑消息(只换内存副本),
goal 续跑走 goal-resume 而不是 goal,跑完清 resume_message
(进程被杀时不清,下次认领重跑同一条消息)。
host:goal-resume --goal-text(旧任务接续 goal 模式:跳过状态
与记录守卫,旧线程上从第 1 轮开新目标循环,新语义不限轮次;
无线程时拒绝)。
sandbox:Local/Docker goal_resume_task + popen goal-resume kind;
附带 popen goal 命令改成新语义(无验收不传 --verify,轮次 0
原样传,此前 goal 任务到本地 worker 会直接报错)。
console:详情页终端非 merged 任务出继续会话表单(消息 +
模型/强度/权限/计划/goal,模型下拉复用中转列表)。
测试:新增 test_task_continue.py 11 个 + test_host_continue.py 2 个。
2026-10-27 04:40:11 +08:00
openqj
cf293914d9
Merge pull request #69 from openqj/feat-attachments
...
feat: 任务附件——文件/文件夹/图片进任务工作区
2026-10-27 04:39:05 +08:00
host
9306c957f3
fix: seed 参数只传给 LocalExecutor,假执行器/CloudExecutor 旧签名不再炸
...
worker 曾无条件给同步路径的 goal_task/dispatch_task 传 seed_dir,
CloudExecutor 基类与测试假执行器只有 (task) 一个参数,直接
TypeError,炸掉 test_project_repo 2 个 + test_cloud_executor_goal_unsupported
1 个(后者本应报“不支持 goal”)。改成 isinstance(LocalExecutor)
才传 seed_dir,其余走原签名;Docker 路径已有 is_docker 守卫。
2026-10-27 04:30:43 +08:00
host
7c444a688b
feat: 任务附件——server/worker/console 链路打通(+ popen goal 新语义补漏)
...
server:POST /uploads(multipart,413 预检、路径/数量/大小校验、
24h 过期包、used 防一包多用)+ 建任务绑定(同事务写附件行 +
包置 used,cloud 执行器 400)+ 列表/详情带 attachments +
取消删暂存 + 分支带走附件清单;db.py PG 建表 + init_db 补表。
worker:_task_seed_dir(无附件/目录已删静默 None)+ dispatch/
goal 三路(同步本地、popen、Docker 只读挂载 /tmp/codex-seed)
+ cloud 执行器兜底失败 + 终局删暂存。
console:文件/文件夹/图片三路输入,先上传拿 upload_id 再建任务,
列表 [附件×n]、详情列附件路径。
附带:popen 的 goal 命令此前强制要求 verify_command,goal 新语义
任务到本地 worker(走 popen)会直接报错,改成与同步 goal_task
一致(无验收不传 --verify,轮次 0 原样传)。
测试:新增 test_task_attachments.py 15 个。
2026-10-27 04:30:43 +08:00
host
9537e6f0d2
WIP: 任务附件——host seed-dir 与上传模块(未完,server/worker/console 待续)
2026-10-27 04:29:40 +08:00
openqj
c102327040
Merge pull request #68 from openqj/env-console
...
feat: 命令台云端环境——选、建、管 + 任务绑定环境
2026-10-27 04:13:11 +08:00
host
3d45edc8b4
feat: 命令台云端环境——选、建、管 + 任务绑定环境
...
环境是项目仓库的命名基准检出(项目 + 仓库快照 + 分支 + 执行器),
不是官方 Codex 云端环境(无公开调用口,不宣称能建它)。
- DB:environments 表(creating/ready/failed/archived,部分唯一索引
保证同项目未归档名唯一、归档名可重用)+ tasks.environment_id,
server/worker/db 三处迁移同步(含 #67 的 goal_mode,不丢新语义)。
- API:POST/GET /environments、GET /environments/{id}、
POST /environments/{id}/archive;任务创建选环境须本项目已 ready、
执行器一致或继承、cloud 执行器拒绝。
- Worker:run_all 每轮开头准备 creating 环境(真实 git clone +
checkout 分支,幂等、无 preparing 卡死态,准备期归档 CAS 不覆盖);
环境任务派发时 task[repo] 指到环境检出(租户 Docker 容器内路径 +
envs 整目录挂载),任务仍一任务一 worktree。
- Console:环境卡(列表/新建/归档,未 ready 置灰)+ 新建任务环境下拉
+ 任务列表 [环境] 标记;公网 nginx 须同批代理 /environments。
- 单测:新增 test_task_environments.py 14 个;本地实弹(真实 git
clone octocat/Hello-World,不跑模型)项目→环境→任务→归档全通。
2026-10-27 04:07:54 +08:00
openqj and host
c86b450851
feat: goal 模式新语义——prompt 即目标,无验收命令,不限轮次,模型宣告完成 ( #67 )
...
console 打勾 goal 模式时不再有专用 goal 文本、验收命令、轮次
三个输入(已移除,换成说明行),只发 goal_mode=1;server 侧
goal_mode=1 时 goal 存 prompt、验收命令空、轮次存 0,带验收
命令或与计划模式同用时 400,旧的带验收命令任务照原样可用。
host.py goal 循环:verify 为空时不跑验测,轮次提示里写明
标记约定;模型在完整跑完的回合末尾单独一行输出“目标已
达成”即达标(超时回合的部分文本含标记也不算);--max-rounds
0 为不限轮次,goal-resume 续跑按 0 处理(不用 or 兜底成 3)。
刹车只有取消与预算耗尽(后者记 interrupted、可续跑)。
迁移与 worker:tasks 加 goal_mode 列(server 迁移、worker 列
补齐、PG schema 三处同步);worker 按 goal_mode 或
verify_command 判定 goal 路径,重试与后续消息排空对新语义
同样只跑一次/不排空;Local/Docker goal_task 的 --verify 可选、
--max-rounds 0 原样传。
Co-authored-by: host <host@test.local >
2026-10-27 03:54:48 +08:00
openqj and host
4179fb1a0a
fix: 命令台初始化有 key 即加载模型列表 ( #66 )
...
回访用户 key 已在 localStorage 里:此前模型列表只在点“保存”
时加载一次,重开页面下拉永远只有默认项(2026-10-27 实测)。
初始化序列补 if (getKey()) loadRelayModels();单测补初始化
序列含该调用的标记断言。
另:公网 /relay/models 曾因 nginx 缺 /relay/ 代理返回 404,
与本修无关,nginx 侧另行补 location。
Co-authored-by: host <host@test.local >
2026-10-27 03:33:35 +08:00
openqj and host
f4443dca4f
feat: 计划模式 + 后续消息 + 会话分支接云端 ( #65 )
...
- 计划模式:tasks 加 plan 列;plan 与 approval=full / goal 冲突时
400;执行器在 approval 参数后追加 --sandbox read-only(本地
dispatch/run/goal/popen 与 Docker 内层命令全覆盖),host 任务
存下 sandbox 后续轮次自动继承只读。
- 后续消息:新表 task_followups;POST/GET /tasks/{id}/followups
(仅 queued/running 的非 goal 任务;direct 立即往链路追加
phase=followup-direct 条目,本轮跑完后优先于排队执行;排队
按 direct 优先、队内先来先服务逐条再跑一轮,同一 thread;
一条失败即停、剩余 pending 留给重试入口;取消时回 pending)。
- 会话分支:POST /tasks/{id}/fork(仅终态任务;继承 executor/
模型/强度/权限/计划,goal 字段置空);worker 先 fork 再跑首轮,
首轮失败不自动重试、不重复分叉,失败后走重试入口重跑首轮。
- 修任务级模型被覆盖:worker 此前无条件写成主模型,控制台
选的模型实际不生效;现为任务级 > worker 主模型 > 配置。
- Docker 租户准备抽成 _docker_task_context,供普通尝试与 fork 共用。
- console:新建任务计划勾选(含冲突拦截)、详情计划徽标与
分支来源、分支按钮与表单、后续消息区、列表 [计划]/[分支] 标记。
- 测试:cloud/tests/test_task_links.py 17 个(server 校验与继承、
worker 模型优先、只读命令、排空顺序与停排、goal 不排空、
fork 单次性);全量 cloud 542、host 49、deploy 14。
Co-authored-by: host <host@test.local >
2026-10-27 03:17:51 +08:00