Commit Graph
299 Commits
Author SHA1 Message Date
host ce85043a24 trace: 标注被截断的链路消息,避免误读为模型未写完
2026-10-29 实弹:468 字 final_answer 在链路里只剩前 300 字、
断在 fu 后,控制台照原样当助手回复展示,用户误以为模型
没写完。截断本身是设计(防链路文件写爆),缺的是标记。

- host.py _summarize_trace_item:agentMessage 超 300 字时
  条目带 truncated=True,短消息不带,完整回复仍在任务
  result_text 里,不在链路条目里。
- 控制台:TraceEntry 加 truncated 字段,mapTrace 与
  traceLineText 在被截断的消息后标注“链路摘要已截断至
  300 字,完整回复见右侧任务结果”,console.html 为构建产物同步。
- 单测:tests/test_host_trace.py 新增截断标记用例(468 字
  截 300 字且带标记、短消息不带标记)。

验证:host 10 项、cloud test_task_trace 14 项全过;
React tsc+vite 构建通过,产物 322151 字节、含截断标注、
含 #150 的 total_tokens/首字/总耗时,无回退。
2026-10-30 01:01:50 +08:00
openqj fd9fe5f254 Merge pull request #153 from openqj/feat-auth-unknown-role
fix(auth): unknown project role denies instead of KeyError 500
2026-10-30 00:55:54 +08:00
openqj 284e821d0c Merge pull request #152 from openqj/feat-console-task-detail-meta
console: 任务详情显示首字、总耗时、token 与自动成本明细
2026-10-30 00:50:08 +08:00
host c823e32336 fix(auth): unknown project role denies instead of KeyError 500
check_permission now returns False for roles not in _ROLE_LEVEL
(e.g. a directly-written 'member' row, which set_member itself
rejects but legacy/direct DB rows can still carry), so the failure
mode is PermissionError/403, never an unhandled 500. Regression test
test_unknown_role_denied_not_500 fails with KeyError on old code.
2026-10-30 00:49:03 +08:00
host 994c4ea5d1 console: 任务详情自动显示成本明细
打开详情就自动拉 GET /tasks/{id}/cost(不再只靠
“查成本”按钮出 JSON),详情顶部新一行:美元、总
token(实际/估算、缓存、无价单列)、轮数、fallback
次数;美元小于 1 美分时用 4 位小数,避免小任务
显示成 $0.00 误导成免费;加载中/失败有各自的
弱化文案,成本拉失败不影响详情其它内容;原
“查成本”按钮不动,仍可手动拉原始 JSON。
服务端不用改:成本接口与 _get_task 的 token 聚合
都已在 #150 / 详情 meta 那单里就位。
2026-10-30 00:39:13 +08:00
host 0f7162934b console: 任务详情也显示首字、总耗时、token
列表行与详情共用同一口径:新抽 api/taskMeta.ts(首字/
总耗时/token 计算),TaskListSection 改 import 它(逻辑
原样不动),TaskDetailPanel 在状态行下方加一行:首字
方块 + 耗时 + token,title 里写口径。
详情的数据缺口一并补上:单任务接口 _get_task 此前走
_task_to_dict 默认 total_tokens=None,详情 token 只能
显示占位;现与列表一样用 _task_tokens_map 一次聚合
(单任务只多一条查询),详情直接出真数。
types.ts 里过期的“列表不回 token”注释同步更新。
新测试:单任务 GET /tasks/{id} 聚合回 total_tokens。
2026-10-30 00:39:13 +08:00
openqj 3696dad7c8 Merge pull request #146 from openqj/feat-task-files-tenant
fix: task files endpoint resolves tenant docker worktrees
2026-10-30 00:04:37 +08:00
host 4cbdc41e20 fix: task files endpoint resolves tenant docker worktrees
GET /tasks/{id}/files previously returned 409 for all docker tasks
on the grounds that tenant docker shares /app/work per project.
Production inspection shows the worker creates a per-task
host-worktrees/<task-id> subdirectory under the tenant work dir
(62 such dirs under the wwww tenant), so per-task reads are
attributable after all: the endpoint now resolves tenant docker
tasks via tenants/<project>/work/host-worktrees/<task-id> (local
worktree as fallback), never serves the shared /app/work mount
itself, and still 409s cloud/cross-host tasks. Docs and the
harness2_tasks boundary notes are updated to match.
2026-10-29 23:16:01 +08:00
openqj d4a517fc7e Merge pull request #150 from openqj/feat-console-task-meta
console: 任务列表行显示首字、总耗时、token(服务端列表补 total_tokens)
2026-10-29 18:38:36 +08:00
host 9eedee5a3d server: 任务列表一次聚合回 total_tokens
_list_tasks 在取附件的同时用 _task_tokens_map 一次查
cost_records 按 task_id 求和(GROUP BY),一屏只多一条
查询,不按任务逐个调成本接口。无记录计 0、表不存在时
全计 0 且列表不失败;_task_to_dict 新增 total_tokens
参数,默认 None(非列表调用方不把“未算”写成 0)。
前端 TaskListSection 的 token 栏位此前已接好 total_tokens,
补上后列表行直接显示真数,不再显示 token —;前端注释
与占位文案同步更新。
新测试 test_task_list_tokens.py 3 项:HTTP 列表聚合
(actual+estimated 加总、无记录为 0)、缺表不炸、
_task_to_dict 默认 None。
2026-10-29 18:27:53 +08:00
host 65a875ada9 console: 任务列表行显示首字、总耗时、token 栏位
任务列表每一行新增三项(筛选、搜索、选中高亮、状态点不动):
- 首字:行前小方块,prompt 第一个非空白字符(按码点取),
  无 prompt 时用任务 id 首字符兜底;原 prompt 文案不动。
- 总耗时:只用列表已回时间戳算。终态用 finished_at -
  started_at(与服务端 avg_duration_seconds 同口径);running
  显示“进行中 + 已用时长”,随列表刷新更新;无 started_at
  时用 created_at 兜底(含排队,title 注明口径)。格式:
  3分12秒、1小时5分、1天1小时。
- token:栏位已接好,total_tokens 优先,actual +
  estimated 分项加总次之;但列表接口 _task_to_dict 目前
  不回任何 token 字段,单任务真数只在 GET /tasks/{id}/cost
  里,所以当前显示“token —”,不编造、不逐个调 /cost
  拖慢列表。服务端在列表里补 total_tokens 后本行自动出真数。

诚实边界:worker 每次认领重写 started_at,多轮续跑任务
的耗时是末次认领时长,不是历次之和;严格累计需服务端
保留首次 started_at 或累加各轮时长。token 的服务端缺口:
需在 _task_to_dict / 列表查询里按 task_id 聚合 cost_records
的 total_tokens,不需要新端点。
构建:npm run build(tsc + vite singlefile)0 退出,
dist/index.html 原样拷到 cloud/console.html,产物含
issue-first、耗时、token —,未动其它确认框。
2026-10-29 18:24:07 +08:00
openqj e5bf361c6d Merge pull request #149 from openqj/feat-no-full-confirm
console: 新建任务选完全访问不再弹确认框
2026-10-29 18:17:16 +08:00
host 6d9cd24553 console: 新建任务选完全访问不再弹确认框
DispatchSection 提交时删掉 full 的 window.confirm:下拉里
选 full 本身就是显式选择,提交直接送 approval,不再二次
确认。计划模式与 full 互斥的拦截不动,其它确认框(取消/
合并/提 PR 等)不动。
构建产物 cloud/console.html 由 npm run build(tsc + vite
singlefile)重新生成,产物里已无“确认提交吗”,仅剩下拉
选项本身的“完全访问”文案。
2026-10-29 18:06:18 +08:00
openqj baf330f112 Merge pull request #148 from openqj/feat-console-goal-invincible
console: 增加 goal 模式无敌版勾选
2026-10-29 18:05:19 +08:00
host 7d400afa37 console: add goal-mode invincible option
DispatchSection gains a 'goal 模式无敌版' checkbox next to 'goal 模式':
checking it sends goal_mode=1 plus no_time_limit=1 (server already
accepts the field; the console just never exposed it). Plain goal
checkbox behavior is unchanged; invincible wins when both are
checked. Plan/coordinator mutual exclusion now covers invincible
too (it is a goal variant). TaskDetailPanel shows
'goal 模式无敌版(不限时)' when a task carries no_time_limit.
Help text states the honest boundary: worker/docker total timeouts
are lifted, the 600s single-turn host guard stays. Built with
npm run build (tsc+vite pass); console.html synced verbatim from
dist/index.html.
2026-10-29 17:58:50 +08:00
openqj 9961a251d1 Merge pull request #147 from openqj/feat-prestart-goal-logs
worker: 补漏:goal 路径的 docker 分段日志 + 审计任务 id
2026-10-29 17:52:30 +08:00
host 6f0eec71b6 worker: cover goal docker paths with prestart stage logging
PR #145 added docker_run_* lines only to _run_in_container, but
goal/goal-resume/goal-resume-breakpoint call _call_runner directly
(to keep full stdout for goal conclusions), so the production live
test (a goal task) produced zero docker_run_ lines. Extract a
_docker_call_staged helper and route all four task paths through it;
error lines log the class name then re-raise so each caller's
kill+failed handling is unchanged.

Also fix audit attribution: audit_log has no task_id column, and
worker_exec_done/error details carried no task id, so per-task
queries missed them (the rows existed). All three exec details now
start with task_id=. Tests: 2 new goal-path stage cases + a done
detail task-id assertion (8 total in test_prestart_stages).
2026-10-29 17:46:12 +08:00
openqj a17f0c7412 Merge pull request #145 from openqj/feat-prestart-logs
worker: 启动前分段日志(派发卡死可定位)
2026-10-29 17:33:05 +08:00
host 9d90d97046 worker: prestart stage logging for dispatch stalls
Claim-to-dispatch stalls (cf. 2026-10-29 task A: 61s to interrupted
with zero detail) were invisible because docker run blocks with
captured output and watchdog kills were silent. Add three layers:
- worker_exec_start/done/error audit rows in _run_attempt (PG,
  survives --rm), start/done pairing shows whether an attempt died
  inside the executor call;
- docker_run_start/done/error log lines in DockerExecutor (container
  + image only, never the inner command/prompt);
- stdout tail (last 2000 chars) to the worker log on failed or
  interrupted results, and a log line on both watchdog kill paths.
Tests: cloud/tests/test_prestart_stages.py, 6 cases incl. a
no-prompt-in-logs assertion.
2026-10-29 17:07:53 +08:00
openqj 0129b0149a Merge pull request #144 from openqj/feat-neverstart-fresh
worker: 从未启动的任务自动续跑回落全新跑
2026-10-29 16:51:42 +08:00
host e74f20608b worker: auto-resume falls back to fresh goal for never-started tasks
2026-10-29 live test: task A was interrupted 61s after claim but had
never written anything (no host-state entry, no worktree, no trace,
no checkpoint); auto-resume ran goal-resume, which host rightly
refused, and the task failed. Refusal only makes sense for tasks
with progress but a lost breakpoint (those go through the P0
checkpoint rebuild); for a never-started task the only meaningful
outcome is a fresh run, identical to its first attempt (same task
id, same goal, worktree does not exist yet so nothing is
overwritten).

Change (claim path only, via _resolve_breakpoint_resume):
- rebuild from checkpoint first, unchanged;
- if rebuild fails AND _task_never_started holds (state entry,
  checkpoint row, worktree dir, trace file all absent), clear the
  breakpoint flag so the run takes the fresh goal path, with a
  worker_fresh_restart audit event;
- any evidence of prior execution, or any check failure,
  keeps the old refusal path (fail-closed); the auto-resume
  count cap and no-progress stall guard still bound retries.

Tests: cloud/tests/test_neverstart_fresh.py, 10 items (fallback
holds, entry/checkpoint/worktree/trace presence each block it,
corrupt state blocks it, rebuild still wins when a checkpoint
exists); test_goal_resume's breakpoint-routing test now sets up
a task with a checkpoint so it still exercises goal-resume.
Full suites: cloud 1178 (skipped 4), host 104, deploy 39, green.
2026-10-29 16:45:07 +08:00
openqj a4586cbebc Merge pull request #143 from openqj/feat-harness2-followups
harness2: per-role models, sweep batch, task file assets endpoint
2026-10-29 16:39:48 +08:00
host c20192bce8 harness2: per-role models, sweep batch, task file assets endpoint
- Role models: run_improvement_via_tasks gains role_models
  (probe/editor/selector/reflector) plus --model-<role> CLI flags;
  missing/empty falls back to shared --model, both empty means
  server default, so default behavior is unchanged.
- Sweep: run_sweep + examples/harness2_sweep.py manifest CLI with
  shared library_root (library restore), per-run failure isolation
  and sweep-report.json summary; preflight gates task creation.
- Deliverable assets: GET /tasks/{id}/files for local-executor
  tasks (safe path resolution, UTF-8 text <=256KB, listing <=200;
  docker/cloud/cross-host 409 with explicit reason, since tenant
  Docker shares one /app/work per project and per-task attribution
  would misattribute); probe rollout deliverable_files from the
  endpoint plus DELIVERABLE FILE reply blocks (endpoint wins on
  collision, bad blocks dropped), surfaced in
  deliverables/<label>/files/ context and full_result summary.
- Docs: harness2.md comparison table updated for all three items.
2026-10-29 16:32:58 +08:00
openqj 9e444eca38 Merge pull request #142 from openqj/feat-state-lock
host: 修复断点丢失(tmp 碰撞 + 跨容器 flock 失效)
2026-10-29 16:04:12 +08:00
host 9ea0a05fb1 host: fix state-loss from tmp collision and cross-container flock failure
2026-10-29 task 2 lost its host-state entry (version 390 -> single
digits) while running under Docker/gVisor. Root cause, proven live:
- save_state tmp name contained only pid, and every containerized
  host.py runs as pid 1, so concurrent writers shared one tmp file
  and interleaved writes produced corrupt JSON;
- fcntl.flock does not exclude across runsc containers sharing a
  bind-mounted lock file (both entered at 0.0s in a live probe);
- _read_state_file silently treated corrupt JSON as empty state, so
  the next save legitimately rewrote the file with only the
  surviving writer's tasks.

Fix:
- tmp name now hostname + pid + thread + uuid4 (backup tmp same);
- mkdir atomic lock replaces flock (atomic on the host fs, holds
  across bind mounts/gofer), with stale-lock recovery after 120s
  and a loud timeout instead of unlocked writes; reads need no lock
  because publication is tmp + os.replace;
- save path uses a strict disk read: corrupt JSON, non-object top
  level, or wrong-shaped tasks/automations now raise instead of
  overwriting (recovery stays with restore_state + .bak).

Tests: tests/test_host_state_lock.py, 7 items (tmp uniqueness in
process and across processes, 8-process concurrent saves all
survive with version 8, stale lock recovery, fresh lock timeout
raises, corrupt/wrong-shaped disk refuses to overwrite).
Full suites: cloud 1168 (skipped 4), host 104, deploy 39, all green.
2026-10-29 15:57:46 +08:00
openqj 7425f2e778 Merge pull request #141 from openqj/feat-harness2-gaps
harness2: upstream gap fill — trivial fix, session budget, tag validation, preflight
2026-10-29 15:40:09 +08:00
openqj 4d16d63313 Merge pull request #140 from openqj/feat-longtask-p0-three
断点镜像状态标签回落:host-state 条目写 status 不是 goal_status
2026-10-29 15:37:51 +08:00
host 4ed1479d7a harness2: upstream gap fill — trivial selection fix, session budget, run_tag validation, preflight check
- select_final trivial condition now k==1 and single-candidate pool,
  regardless of whether a selector is provided (previously gated on
  selector is None, so wired runs always paid for a useless selector
  task at k=1)
- Budget gains max_sessions gate (probe + stage-attempt sessions;
  fmt2 corrections and selector/reflector sessions exempt), the
  backstop for unpriced models where the USD gate never binds
- validate_run_tag (charset, no leading '-', no s<N> seed prefix)
  enforced at run_improvement_via_tasks and the CLI
- CLI --check preflight (base harness, source dir, prompt, tag,
  control-plane /health probe) without creating tasks
- ModeResult.to_dict now includes rollout summaries so a lost probe
  is visible in full_result instead of only on the server
- CLI plan counts the selector only when k>1
2026-10-29 15:31:58 +08:00
host 8c719c7e62 断点镜像状态标签回落:host-state 条目写 status 不是 goal_status
生产实弹:极小 goal 任务的 timeline 里 checkpoint goal_status 为
None——host.py 的任务条目只有 status(goal-running/goal-met),
没有 goal_status 键,镜像原样读 goal_status 永远是空。修法:
entry.get('goal_status') or entry.get('status')。轮次、thread_id、
state_sha 等关键字段不受影响(熔断只看轮次),纯标签 fidelity
修复;单测加 status-only 条目镜像断言。
2026-10-29 15:31:07 +08:00
openqj 3d60f32bd3 Merge pull request #139 from openqj/feat-longtask-p0-three
长任务 P0 三件:断点进库、错误分类+熔断、Run/Step 时间线
2026-10-29 15:19:43 +08:00
host 585242fc8f 长任务 P0 三件:断点进库、错误分类+熔断、Run/Step 时间线
断点进库:task_checkpoints 表(PG 新库 + 老库幂等补表 + 迁移清单
对齐);worker 在 goal 任务执行期间每 30 秒把磁盘 host-state 断点
镜像进库,终局再补一次;断点续跑认领前,若 host-state 条目丢失
但库里有断点,先按库断点重建最小条目再跑,库里也没有断点时不
造假、走原有拒绝路径。

错误分类+熔断:sandbox 四处解析加永久错误分支(KeyError、配置
缺失等无结论异常退出判 failed 死信,不再判 interrupted;host 已
明言 interrupted 的不受影响,未知错误不分类);worker 自动恢复
加退避(10 秒起指数退避、封顶 300 秒)与无进展熔断(库断点轮次
连续 3 次不变即标 auto_resume_stalled 等人工)。

时间线:task_steps 表 + host 每轮写 host-steps 步骤文件 + worker
导入;GET /tasks/{id}/timeline 一次返回 steps 与 checkpoints;
认领、暂停、自动恢复、终局都记步骤。旧任务返回空数组,不编造。

单测:cloud/tests/test_p0_three.py 14 项(分类、熔断、镜像重建、
步骤导入去重、timeline 接口)。
2026-10-29 15:13:01 +08:00
openqj d56bd3a99e Merge pull request #138 from openqj/feat-harness2
harness2: recursive harness optimization wired to real codex tasks
2026-10-29 14:28:44 +08:00
openqj b34812f605 Merge pull request #137 from openqj/feat-longtask-resume-guard
fix: 断点丢失时 goal-resume 拒绝成 failed,阻断自动恢复空转
2026-10-29 14:24:44 +08:00
host 42abe3cc5b harness2: recursive harness optimization wired to real codex tasks
Port Google Research's Harness^2 method layer (model weights frozen,
only the surrounding harness is optimized): Propose-Probe-Compose with
INV/DOM/AGG editors, parallel/sequential modes, per-domain experience
library, anonymous-product selection, k<=3 hard cap and budget gate.
Execution goes only through the existing control-plane API (upload ->
task with idempotency key -> poll -> trace/cost -> cancel on timeout);
no new server endpoints, no codex flags composed, tasks inherit the
normal executor/sandbox/quota/audit path.

Wiring lessons from four real rounds against production (project
wwww, ledger task): HttpTaskClient retries transient disconnects and
502/503/429 (3 attempts); editors get a worked file-block example, an
explicit <no-change> marker and one feedback retry (.fmt2) instead of
silently accepting notes-only replies; run_task unwraps the server's
result_text JSON envelope (text field holds the real reply) — without
this, line-anchored file-block parsing could never see blocks the
agents were actually emitting. Final round (real4) fully green:
all stages landed, selection non-fallback, experience入库, probe
delivers the correct signed total 85.15.

Tests: 35 harness tests (17 method + 18 wiring incl. fake-control-plane
full round, idempotent replay, retry, format retry, envelope round).
Deliberate deviations from upstream are documented in docs/harness2.md
(no network-unrestricted/sandbox-disabled defaults, auto_apply off,
no benchmark/scorer, probe deliverable = final reply text).
2026-10-29 14:21:18 +08:00
host a5f2e4e091 fix: 断点丢失时 goal-resume 拒绝成 failed,阻断自动恢复空转
2026-10-29 长任务实弹:Docker goal 断点续跑在 host-state 里找
不到任务时抛 KeyError,worker 把无结论异常退出判 interrupted,
自动恢复再排队、再 KeyError,12 秒一轮空转 49 次(人工暂停
拦下,第 50 次人工续跑又烧掉),文件 32 章原样未动。
修法:host.py goal-resume 先查任务在不在 state 里,不在就打印
拒绝行、正常退出;sandbox 三处解析(本地、Docker resume、
Docker 断点)见拒绝行即判 failed 终态,不进自动恢复循环。
单测:host 缺任务拒绝不炸 + 三处解析拒绝判 failed。
2026-10-29 14:14:13 +08:00
openqj e48b756f96 Merge pull request #136 from openqj/feat-longtask-invincible
无敌补齐:连续失败上限 + worker退出审计 + 配额恢复自动续跑
2026-10-29 13:16:49 +08:00
host ae3aff8602 feat: 长任务无敌补齐三件:连续失败上限 + worker退出审计 + 配额恢复自动续跑
1. host goal 循环连续失败护栏:3 轮连续失败即中断出口,
   任务记 interrupted、可断点续跑,不再无限空转
   (2026-10-29 实弹:断点后 274 轮全失败)。
2. worker 退出杀残留路径补审计 worker_shutdown_interrupted,
   detail 为任务 id,与 sweep_interrupted 同口径。
3. 配额中断自动恢复:每轮现查配额,仍超限/查不到时留
   在 interrupted 不重排队,下轮再查;现查为 None 时
   (新月份/额度上调/无价上限重置)才 CAS 回 queued。

单测:配额仍超限不动、配额恢复续跑、连续 3 轮失败停转。
2026-10-29 13:07:57 +08:00
openqj 88fcfeebd3 Merge pull request #135 from openqj/feat-console-keys-ui
CI verify pass. Deploy follows separately via deploy.py.
2026-10-29 12:57:18 +08:00
host a68b63e0f1 console: API Key 区补生成/列表/撤销(调现有自助接口) 2026-10-29 12:51:00 +08:00
openqj 49f3ff7cb6 Merge pull request #134 from openqj/feat-longtask-docker-resume-env
修法:Docker 断点续跑透传密钥环境(SUB2API_API_KEY 缺失空转)
2026-10-29 12:48:12 +08:00
host 5b2bdc9bbf fix: Docker 断点续跑透传密钥环境(SUB2API_API_KEY 缺失空转修法)
Docker goal_resume_breakpoint_task 是唯一漏传
env=self._docker_cli_env(extra_env) 的 goal 方法:密钥只按名
进 docker run,值靠 CLI 环境带;漏传导致容器内 key 为空,
断点后每轮瞬间报 Missing SUB2API_API_KEY、无限空转
(2026-10-29 长任务实弹:274 轮全失败)。

单测:断言断点方法调用 runner 时 CLI 环境含密钥值,
命令里密钥只按名出现不带值。
2026-10-29 12:42:19 +08:00
openqj c757810097 Merge pull request #133 from openqj/feat-longtask-auto-resume
长任务中断自动恢复:仅用户暂停才暂停,不限时
2026-10-29 11:48:22 +08:00
host c9cfe22a36 feat: 长任务中断自动恢复,仅用户暂停才暂停,不限时
- 新增 tasks 列 paused_by_user/interrupted_reason/auto_resume_count/no_time_limit(幂等迁移,server+worker 双侧)
- POST /tasks/{id}/pause:用户暂停标 interrupted + paused_by_user=1;/cancel 同款标记;人工 /retry、/goal-resume 清标记
- sweep 标 sweep、配额标 quota、协调员孤儿标 coordinator_orphan、worker 退出标 worker_shutdown
- worker.run_loop 每轮后 auto_resume_interrupted:只接系统中断的 goal 任务,CAS 回 queued + goal_resume_pending=1(G10 断点续跑),用户暂停/配额/孤儿/非 goal 不接,上限 50 次防无限烧额度
- no_time_limit=1 的任务 worker/Docker 级不限时(其它任务仍默认 1800 秒;host 单轮 600 秒仍是单轮护栏)
- 前置 cherry-pick:G10 断点续跑透传 model_provider(否则 Docker 断点续跑在 sub2api 下必死,自动恢复无法实证;本 PR  supersedes #127,勿另行合并 #127)
2026-10-29 11:37:06 +08:00
host a19b1567bb fix: G10 断点续跑透传 model_provider(sub2api 续跑失败修法)
断点续跑容器不带 --model-provider 时 Server 的 provider 表里
没有 sub2api,thread/resume 报 provider not found(probe15 实弹)。
Docker/Local 断点方法加可选 model_provider 并转发,worker 两处
调用点传 gateway_provider;补单测断言断点命令含
--model-provider sub2api(旧代码下两新测试 1 失败 1 报错)。
2026-10-29 11:28:39 +08:00
openqj 0ef896c317 Merge pull request #132 from openqj/feat-console-gapfix
console: 分栏改独立容器,修模块间空白间距
2026-10-29 11:04:22 +08:00
host e5aa5c2acb console: 分栏改独立容器,修模块间空白间距
PR #130 的共享网格行是根因:一行高度由该行最高模块决定,
任务列表撑高第 2 行后,对话(第 3 行)只能从任务列表底下开始,
派发/环境等短模块下面空出一大截;align-items:start 只让盒子
不拉伸,拉不上来下一行。

修法:App.tsx 把模块包进三个独立 .dash-col(左:任务+项目,
中:派发+对话,右:环境+Workers+技能+自动化+分诊+管理区+
API Key),栏内 flex 纵向紧贴;中屏两栏(左+中上右下)、宽屏
三栏并排;窄屏用 display:contents + 每模块 order 恢复原单列
顺序。构建产物 316093 字节,sha 与构建输出一致。
2026-10-29 10:56:36 +08:00
openqj e7f7edf5c2 Merge pull request #131 from openqj/feat-readme-update
docs: README 对齐生产现状(main 93c25a9,补 PR #130 自适应分栏)
2026-10-29 10:48:52 +08:00
host b27d98e642 docs: README 基线跟进到 main 93c25a9,补 PR #130 自适应分栏 2026-10-29 10:43:01 +08:00
host da0c7d453e docs: README 对齐生产现状(main 4c3420a)
- 顶部新增项目现状:生产 Postgres + api.diante.me + React 命令台 GitHub 风格
- 新增云端控制面一节:状态机、worker/扩容、配额成本、记忆搜索、继续/计划/followup/fork、部署链路
- 纠正过期表述:云端不再是演示、PR/CI 本仓已走通(旧无远端/无登录已过期)、多机同步走中心库
- 新增诚实边界:内层 bwrap、40 人暂搁置、单机 HA 模拟、PR #127 未合并
2026-10-29 10:42:27 +08:00
openqj 93c25a92bc Merge pull request #130 from openqj/feat-console-adaptive
console: 按宽度自适应分栏(一栏/两栏/三栏)
2026-10-29 10:35:54 +08:00