Skip to content

sync: taiji 定制版同步最新基线 8d810b99e(LegionCard 样式统一 + 群聊 P0 修复) - #2262

Open
1688mengdie wants to merge 555 commits into
GCWing:mainfrom
BitFun-SIG:custom/taiji-unofficial
Open

sync: taiji 定制版同步最新基线 8d810b99e(LegionCard 样式统一 + 群聊 P0 修复)#2262
1688mengdie wants to merge 555 commits into
GCWing:mainfrom
BitFun-SIG:custom/taiji-unofficial

Conversation

@1688mengdie

Copy link
Copy Markdown

同步内容

taiji 定制版(custom/taiji-unofficial)同步最新基线 \8d810b99e\(相对上次合并基线 aa98261 前进,含上游合流 9b05dd0)。

本 PR 新增关键提交

  • \8d810b99e\ feat(UI): unify LegionCard style with CoreAgentCard surface
  • \2ba9a7ecd\ fix(P0): group chat auto-creates Claw session for missing member
  • \5b9999431\ fix(CI): gate local_download_name_key test import to platforms that use it
  • 上游合流 9b05dd0(centralize default feature ownership)+ dmg branding + harmonyos fixes

验证

  • 前端 type-check:web → 0 error
  • 前端 vitest → 3381 tests 全绿
  • cargo check bitfun-core/cli/desktop(--jobs 4)→ 0 error
  • cargo test bitfun-core → 144 passed 0 failed

t added 30 commits August 17, 2026 09:58
R-WF-24 fix A: persisted list branch overlays live in-memory state for
sessions owned by this process (realizes the R-WF-11 comment at
session_manager.rs:554-556 that was never implemented). Out-of-process
sessions keep the disk-snapshot projection unchanged.

fix B: project busy/processing for an otherwise-idle summary while the
scheduler still tracks background activity (async outcome window).
apply_scheduler_busy_projection is a pure function injected with the
busy predicate; the list port wires get_global_scheduler() ->
is_session_busy_or_queued (active_turns).
… (batch 1)

- CompressionThresholds.trigger_percent (Option<u8>, serde default None):
  input_limit = min(legacy fixed-token, window x percent%), round semantics
  (1M x 85% = 891,290); 0 = legal special value; invalid (101+) -> None
  (zero behavior change)
- AiThresholdsConfig new domains: insights(8), file_read, session_title,
  persistence, user_questions, session_control + compression background
  follow-up limit + memories stage-one/phase1/slug + tool_timeout browser
  timeouts; all serde default mirrors of legacy constants
- Batch-1 tests: 5-scenario trigger percent matrix + batch-2 domain
  round-trip (defaults / overrides / empty config)
…(batch 2)

13 items (14th already configured: debug_log ingest_port), each via the
AiThresholdsConfig serde-default mirror pattern:
- insights 8 constants: collector transcript/message/tail/activity-gap +
  prompt_context summaries/friction/instructions + service facet concurrency
- compression.background_follow_up_text_limit: coordinator/scheduler/task
  follow-up + injection truncation (16_000)
- memories: stage_one_max_tokens(8192) / phase1_extraction_max_attempts(3) /
  rollout_slug_max_len(60) consumers
- tool_timeout.browser_*: browser wait / condition timeout consumers
- file_read.max_total_chars(64_000): Read tool local/remote/document paths
- session_title.truncate_user_message_chars(200): title generation
- persistence.session_reference_transcript_char_limit(60_000)
- user_questions.header_max_chars(20): AskUserQuestion validation
- session_control.short_name_max_chars(60): short-name boundary 60 pass / 61 reject
Frontend: ThresholdsConfig render + i18n en/zh-CN/zh-TW + settings search index.
Tests: batch-2 round-trip, short-name boundary, frontend render.
Recover the agent team gallery/editor (AgentTeamCard, AgentTeamComposer,
AgentTeamTabBar, AgentGallery, CapabilityBar) from the deleted upstream
agents UI. Team state (AgentTeam/AgentTeamMember/actions) merged back into
agentsStore with HEAD fields preserved; mock teams reference real builtin
agent ids; the editor shares the same useAgentsList data (no mock-only
data path). Capability categories normalized to coding/docs/analysis/
testing/creative/ops via existing enrichCapabilities mapping.
Recover ReviewTeamPage (team overview, live policy snapshot, member list +
detail) against the current reviewTeamService contract (worker/judge core
roles). reviewTeamService itself stays as-is in HEAD; only the page shell,
scss, appearance descriptor and registry wiring are re-added. Locale
blocks (default/detail/strategy) merged into all three locales from the
deleted upstream copy, keeping current members.* keys intact.
Add the agent-teams zone (gallery grid + create entry + detail modal) and
the review-team route/entry to AgentsScene, plus the AgentTeamEditorView
(gallery + composer + capability bar) backed by the shared useAgentsList
data. Locale blocks for the recovered team UI (teamsZone/composer/gallery/
tabbar/home/teamCard/formation/capability) added in three locales with
zh-TW traditional rendering; gallery-grid count assertion updated for the
new teams zone.
…locale

Address CQO review (88/100, P1 x1 + P2 x3):

P1: convert 11 remaining simplified-chinese spots in the recovered
A-suite zh-TW locale (阵型->陣型, 执行->執行, 顺序->順序, 独立->獨立,
详情->詳情, 按钮->按鈕). Verified zero simplified-only residue in the
A-suite blocks via the zh-CN/zh-TW data-diff character set.

P2-1: extend i18n:audit l10nQualityCandidates to catch partial-conversion
residue (zh-TW strings that differ from zh-CN but still carry
simplified-only script variants). The upgrade surfaced 3 pre-existing
partial-conversion entries (remoteConnect / alertDemo / processing-hints)
which are tracked in i18n-governance-baseline.json (maxTotal 0->3);
i18n-contract.test updated to expect the tracked baseline.

P2-2: extend reviewTeamLocaleCompleteness.test with a recovered A-suite
locale block test that asserts every block exists and that no zh-TW string
in those blocks contains simplified-only forms (regression lock for the
11 residue spots).

P2-3: note in agentsStore that MOCK_AGENT_TEAMS is frontend mock data to
be replaced by the R-WF-17 team backend.
R-ASYNC-01:
- Remove 3-layer queued coalescing (round-boundary / buffer 5s dedup /
  queue-submit dedup) so notifications are never dropped
- Suppress auto-reply for urgent injected turns (Completed included)
- Align Session reply truncation with BACKGROUND_FOLLOW_UP_TEXT_LIMIT
upstream 同步(cdb6909d3,11 commits CLI 重构)后 cli 编译遗留 2 warning + 1 error,
本次适配修复(上游同步适配):

1. startup.rs: unused import ModelMutation(上游重构引入,本地无 usage)-> 删除
2. runtime_client.rs: AgentSessionSummary 构造点缺本地定制 4 字段
   (parent_session_id/status/display_state/is_daemon)-> 补全(照抄同文件构造点)
3. runtime/mod.rs: agent_event_source() dead_code(上游保留但本地 -D warnings 拦截,
   全仓无调用者,embedded_app_server.rs 已被上游重构移除)-> 删除 + 清理 import

验证:cargo check -p bitfun-cli --tests --jobs 4 0e0w / cargo check --workspace
--features product-full --jobs 4 0e0w / cargo test -p bitfun-cli 0 failed /
type-check + i18n:audit 0
t and others added 30 commits August 30, 2026 10:58
…-0830)

The P0-8 best-effort 800ms drain budget raced the previous turn's spawn
tail: SessionState flips to Idle before SessionExecutionGuard::drop, so
warn-and-continue admitted same-session concurrent dialog turns (T3,
duplicate full-price context replays).

Admission now reuses the strict maintenance barrier
(ensure_session_execution_drained, 30s) already used by the recovery
chain: wait for the active-turn counter to reach zero, fail the
admission with a timeout error otherwise.

Zero-loss handling on the scheduler side: a drain timeout error
requeues the queued turn (requeue_front) and arms a delayed redispatch
(31s > 30s drain bound) so AgentSession/ScheduledJob follow-ups are
delivered after the drain completes; interactive callers simply
resubmit.

Hardening: wait_session_drained now builds its deadline with
checked_add (Duration::MAX + Instant::now() overflowed and panicked;
would wrap to a past deadline in release).
…BILLING-F1-0830)

Pre-existing lib-test debts uncovered while running the full suite for
the drain-wait gate:

- missing_max_rounds asserted the upstream 0=unlimited default; the
  local baseline pins DEFAULT_MAX_ROUNDS=50 (P0 spend guard), so assert
  against the constant.
- plan_compression_for_turn gained a max_retained_user_tokens parameter;
  its 6 call-site tests still used the old 5-arg shape.
- PersistedSessionStateFile initializer in legacy_minimal restore test
  missed the R-WF-11 display lifecycle fields.
- validate_rename duplicate test copies (E0428) removed; kept the
  strict-message variants.
- execution_engine tests double-imported ExecutionEngineConfig (E0252).
- create_test_command carries allow(dead_code) (referenced only by
  integration-style tests compiled under other targets).
- rustfmt formatting fallout in unrelated test blocks (statistics.rs,
  session_manager.rs).
Empty user/system/assistant text messages were converted to fabricated
tokens in the Text arm ("(empty message)", "You are a helpful assistant.",
" "). The model treats these as real user utterances or system directives,
and the fabricated value also bypasses the downstream converters'
empty-content filtering. Return None for empty text, matching the Mixed arm
precedent and the empty-reminder early return, so no synthetic token reaches
the provider.

Test: added 4 behavioral cases; message.rs tests pass (cargo check/test with
--features agent-runtime,external-sources; 2 unrelated pre-existing tests
fail on the clean baseline).
AI: generated with review; verified with the above commands.
The Multimodal arm built content starting from the text value and only
appended image markers when images were present, then always wrapped the
result in Some(content). A message with empty text and no images produced
Some("") — a bare empty string sent to the provider, where a strict API
rejects it and a permissive gateway silently bills an empty round. The Text
and Mixed arms both guard empty content, so guard the Multimodal arm too:
return None after building content when it trims to empty. Image-only
messages keep their markers and are unaffected.

Test: added 4 behavioral cases; message.rs tests pass (cargo check/test with
--features agent-runtime,external-sources).
AI: generated with review; verified with the above commands.
The retry loop in execute_sse_request_with_raw_body continued on any non-2xx
response and on a TTFT timeout, re-sending the same request_body. A
deterministic 4xx fails identically on retry (wasted budget), and a TTFT
timeout fires after the request body was already sent to the server, so
re-sending it is double-billing. Add an is_transient_http_status predicate
(5xx/429/408/504 are transient; deterministic 4xx are terminal), and treat
both a TTFT timeout and a terminal status as terminal: break out of the loop
instead of continuing. Transient statuses still retry with the existing
backoff, and the transport/success paths are unchanged.

Test: added is_transient_http_status and ttft_timeout_is_terminal coverage,
reversed bad_requests coverage to assert terminal 400; sse tests pass
(cargo check/test with --jobs 4).
AI: generated with review; verified with the above commands.
The Response non-2xx branch computed the retry delay and slept for
transient statuses (5xx/429/408), then unconditionally fell through to
break. Because the sleep was inside an if that did not jump back to the
top of the loop, every non-2xx response exited the retry loop -- even
transient server errors. This regressed the intended "only retry
transient statuses" semantics (review fix P1-1) and silently removed
automatic retries for 5xx/429/408 on the aggregation/compression chains.

After sleeping for a transient status, continue the retry loop so the
next attempt can succeed; only deterministic 4xx (and the no-retries-
remaining case) fall through to the terminal break. The TTFT branch, the
transport branch, and the successful-response path are untouched.

Test: added transient_server_errors_are_retried coverage using a mock that
returns 503 then 200 and asserts the fixture is called more than once
(attempts > 1); existing terminal assertions (4xx and TTFT timeout) still
pass; cargo test -p bitfun-ai-adapters --jobs 4 sse::tests passes (16
passed; 0 failed).
AI: generated with review; verified with the above commands; not pushed.
cargo fmt --check reported two pre-existing formatting deviations in the
message.rs test module (import ordering and an over-long expect line).
Normalize them so the format gate passes before the retry-category and
tool-loop work lands.

No behavior change: test-only formatting.

Test: cargo fmt --check
AI: lightly tested
Mirror the upstream retry-category fix onto the taiji round executor. The
retry ladder replayed deterministic request errors (4xx,
context_length_exceeded) up to the configured budget purely on a count gate,
so it reused the now-public is_retryable_category to decide retry admission:
transient categories (Network/RateLimit/Timeout/ProviderUnavailable) keep
retrying, deterministic categories become an immediate terminal error.
ContextOverflow stays on the RecoverableContextOverflow path so the overflow
recovery chain is preserved. C2/C3/C4 keep their original budget semantics.

The taiji-specific max_attempts config is preserved (the gate is layered on
top of it, never reverting to a constant). The is_transient_network_error
text fallback keeps only the "retry budget exhausted" signal; the
"failed after N attempts:" sentence is no longer treated as exhausted
because the main-dialog chain runs one SSE attempt so that sentence is
always present and would wrongly mark every error non-retryable.

Test: cargo test -p bitfun-core --features agent-runtime --jobs 4
AI: lightly tested
Mirror the upstream successful-tool convergence onto the taiji execution
engine. A model that keeps calling the same non-read-only tool with
identical arguments is not making progress even though each call succeeds,
so track a consecutive successful-signature count (reusing the existing
tool_call_signature / repeated_tool_signature_count facilities), exempt
legitimate read/poll tools via is_legitimate_poll_tool, inject a
LoopRecovery convergence reminder once the effective loop threshold is
crossed, and finalize without tools once the recovery cap is reached.

Wire the lay-3 R-MR-03 field: the convergence threshold now comes from
ai.thresholds.execution.duplicate_tool_calls (projected into
max_consecutive_same_tool in from_ai_config), which previously defined the
field but had no Rust consumer. The taiji max_rounds=50 default and the
R-MR-10/11 read/search duplicate gates are preserved.

Test: cargo test -p bitfun-core --features "agent-runtime,external-sources" --jobs 4
AI: lightly tested
`successful_tool_signature_count` was initialized to 0 at the top of the
execution loop, but that initial value is never read: every read is reached
through the tool_call_signature if-let chain that re-assigns it on all three
branches. This is an unused_assignments warning in rustc.

Additionally, the reset `successful_tool_signature_count = 0;` inside the
convergence-reminder branch is never read: the preceding
`recent_tool_signatures.clear();` already forces the next iteration to
recompute the count from the emptied vector. Both assignments are dead and
can be dropped without changing behavior.

Test: cargo check -p bitfun-core --features agent-runtime (0 warnings for
bitfun-core).
AI: light-tested (cargo check; dead-code removal only)
…oom parent chain

GROUP zan-pi (SYNC-4Z-0831): MainNav / CreateGroupChatDialog / GroupChatsSection / SessionsSection / AgentsScene / CreateLegionPage / GroupChatView / sessionOrdering / PresetPicker / NodePalette / WorkflowDiagram + web-ui i18n (common/agents) + group_room_tools.rs BE-J1 hou-duan fu-lian.

Gate: GROUP = CQO pass + tsc 0 err (pnpm type-check EXIT=0).
…holds

THRESH zan-pi (SYNC-4Z-0831): StreamOptions adopts model_retry thresholds (max_attempts / base_delay_ms / rate_limit_base_delay_ms / max_exponential_delay_ms / max_rate_limit_delay_ms / max_exponent_shift) + stream_connect_timeout_secs; ai-adapters client.rs/client/http.rs + config types.rs + infrastructure/ai/mod.rs + AIModelConfig / ThresholdsConfig + ai-model.json / thresholds.json 3 locales.

Gate: THRESH = V3-R1 pass (cargo check bitfun-ai-adapters/bitfun-core EXIT=0; pnpm type-check EXIT=0).
TODO-FIX (SYNC-4Z-0831): todo_write_tool.rs is_readonly true (align upstream permission_intents semantics), sync test assertion.

Gate: TODO-FIX = V1 pass (cargo check bitfun-core EXIT=0).
…831 four-zone sync batch (GROUP/THRESH/TODO-FIX + dev loop/agentic/codebuddy fixes)

Brings the taiji dev main line (full-baseline, 202a53b..2423bc1, 14 commits) into the stable custom branch. Upstream main (a39d03c) already merged (no-op). Intersection check: 3 both-modified files (execution_engine.rs / session_control_tool.rs / AgentsScene.test.tsx) all auto-resolve clean per merge-tree (5712dad) - no conflicts.
PresetPicker / NodePalette / WorkflowDiagram gain data-bf-component /
data-bf-part markers, register surfaces in defaultAppearanceRegistry,
and ship matching .appearance.ts descriptors. Closes the appearance
contract audit gap for the reworked GROUP frontend.
…P-CONTRACT GROUP front-end appearance contract fix
- Detect CodeBuddy model by provider/base_url in save_new_model
- Call list_models() to fetch dynamic catalog when adding CodeBuddy
- Register all dynamic models to runtime_ai_models
- Fallback to single model if dynamic fetch fails
- After successful CodeBuddy PAT login, call list_models() to get dynamic catalog
- Register all dynamic models to runtime_ai_models
- Fallback gracefully if dynamic fetch fails or returns empty
Evidence: app.log:264 parse codebuddy /v3/config response -> empty model list.
Parsing contract is data.models.data (V3ConfigData/V3ModelsData) but the CLI
side uses data.data.models. Capture the live shape (truncated 800 chars, no
credentials) before changing the parser, per the 0830 no-sample-no-fix rule.

Not a fix: evidence-gathering only.
Root cause: app.log:264 'parse codebuddy /v3/config response' -> empty list.
The parser only accepted data.models.data, but the gateway also serves
data.data.models, so a valid authenticated response failed to deserialize and
fell through to an empty catalog.

- V3ConfigData accepts models.data and data.models; documented shape wins
- model_entries() resolves either shape, unauthenticated -> empty (no error)
- parse failures keep a truncated credential-free body sample for diagnosis
- tests: legacy shape, shape precedence, unauthenticated resolution

Verified: cargo check + 25 codebuddy unit tests pass (EXITCODE=0).
Evidence: app.log:298 real response is {data:{agents:[{models:[hy4-preview,...]}]}}.
The gateway serves model IDs as a string array, not CodeBuddyModelEntry objects.

- V3ConfigData accepts models.data (CodeBuddyModelEntry[]) and agents[].models (String[])
- model_entries() prefers documented shape, falls back to string ID conversion
- parse failures keep a truncated credential-free body sample for diagnosis
- tests: agents.models shape, shape precedence, unauthenticated resolution

Verified: cargo test → 5 parse_v3_config tests pass
… KB)

Knowledge base ground truth (CW3-SEC-0828/执行-CB-MODELS-FULL-0830.md:45):
CLI reads ed?.data?.data ?? {} -> ep.models (top-level array), so the live
/v3/config shape is data.data.models = String[].

- V3ConfigData accepts models.data (CodeBuddyModelEntry[]) and data.models (String[])
- model_entries() prefers documented shape, falls back to string ID conversion
- tests: live shape, precedence, unauthenticated resolution

Verified: cargo test -> 25 codebuddy tests pass (EXITCODE=0).
The gateway has changed the model-list shape over time: documented
data.models.data (object entries), data.data.models (string IDs), and
data.agents[].models (string IDs, observed live 2026-09-01). Fixed struct
deserialization kept failing whenever the shape drifted, silently emptying
the catalog.

Replace struct-based parsing with lenient serde_json::Value extraction that
accepts every known shape, deduplicates IDs, and prefers object entries for
fidelity. Unknown/absent shapes resolve to an empty list instead of an error.

Network-dependent tests (no_enterprise_id_dynamic_failure_returns_empty_list,
enterprise_id_missing_logs_warning) assumed the gateway is unreachable; on a
network-enabled machine the live gateway now responds with real models, so
they are marked #[ignore] with the parse-level empty-list path covered by
unit tests instead.

Tests: 25 pass / 0 fail / 2 ignored (network-dependent).
…cial

# Conflicts:
#	src/crates/execution/tool-contracts/src/lib.rs
…te path

CI repo-hygiene rejects machine-specific absolute paths
(C:/Users/...); the qoder-wasm-extract default bundle path was the only
violation. Resolve the global install via npm root -g (ComSpec on
Windows) with QODER_BUNDLE / --bundle overrides, and fail with a clear
message when the package is not installed.

Verified: node --check, real extraction run, check-repo-hygiene passed.
…-0187)

Cargo Deny advisories fail on lopdf 0.41.0 (stack overflow via deeply
nested PDF objects, fixed in 0.42.0). Mirrors upstream PR GCWing#2588:
cargo update -p pdf-inspector. Verified: cargo deny check advisories ok,
cargo check -p tool-runtime ok.
…ates

Upstream main moved session_control_tool behind tools-git and stopped
enabling local git from agent-runtime (core-boundaries CI contract).
Custom code kept unconditional references, breaking the agent-runtime build.

- agent-runtime: drop both local git feature hacks (services-core worktree
  is reachable via tools-git at product level, matching upstream)
- session_control_tool: gate git/worktree deps behind feature=git; keep
  session auth helpers (R-26 orphan/authorization gates) unconditional so
  security checks stay on in all builds
- session_message_tool / coordinator: gate worktree paths behind git;
  authorization calls remain unconditional
- materialization: SessionControl registration behind tools-git (upstream)
- coordinator: emit standalone pub use DialogTriggerSource (contract)

Verified: check-core-boundaries passed, cargo check agent-runtime and
agent-runtime+git+tools-git (0e0w), cargo test -p bitfun-core --lib 165 pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants