test pr on fork - #1
Open
sunagent wants to merge 51 commits into
Open
Conversation
added 30 commits
August 16, 2026 02:42
- Fix zh dictionary residue: trajectory toolbar, model selection, permission presets, settings models, Cordis panel - Extract hardcoded English to locale keys: trajectory view (105 keys with t() threading), Think row, Skill row, Cordis inspect, Session log header action - Sync tests, zh web goldens, and shipped preset.yml metadata; en dictionaries and en-locale fixtures stay byte-identical - Add LOCALIZATION_PLAN.zh.md / LOCALIZATION_HANDOVER.md
- PermissionSelect (composer), /permission popup options, and the settings PermissionRow now render the Full access preset label through the new permission.fullAccess locale key (zh 完全访问 / en Full access); settings-store data-layer labels are overridden at render - Sync zh e2e assertions (access-confirmation, settings-chrome) and input-bar unit assertions; en assertions and ui-commands mocks unchanged - Update handover: remove the Full access product-label row from the deliberate-English list
- knownPermissionLabel() renders all three known preset labels through permission.* locale keys (只读 / 工作区写入 / 完全访问 in zh; product names in en) - Composer PermissionSelect, /permission popup options, and the settings PermissionRow all translate; data-layer settings-store labels stay untranslated and are overridden at render - Sync zh unit/e2e assertions and the settings-chrome zh golden; en assertions (Access mode, current: ...) unchanged
- Group the read-only plugin list into 8 categories (core/tools/skills/goals/data/host/ui/other) with collapsible headers and per-group counts - Add one-line zh/en descriptions for all 129 shipped plugin entries via a language-neutral catalog (plugin-metadata.ts) keyed by Loader id or module short name; unknown/custom plugins fall back to the other category - Search now matches names, ids, and descriptions; card shows the description under the title - Update the settings-chrome plugins golden for the new description line
- Eight 16px linear category glyphs (chip/terminal/bolt/target/database/server/window/dots) shown on filter chips and category headings - Category filter chips with per-category counts; selection composes with search; All resets - Update the design notes (PLUGIN_INVENTORY_DESIGN.zh.md)
- Expanded card now opens with a full feature description (2-3 sentences: what it does, when to use it) for all 129 shipped plugins, zh/en - Metadata table gains a detail key per entry; summaries stay on the collapsed card - Update design notes
…graph_rag engine - New @deepseek-ai/dsh-codegraph package: codeGraph service (one persistent Python bridge per process, line-delimited JSON-RPC over stdio) + codegraph_search tool (symbol/call-graph + BM25, optional local embeddings) - python/bridge.py reuses the verified codegraph_rag engine verbatim; configuration points at a local venv via pythonPath/sourcePath (env-overridable in the web-app patch) - Integration tests run against the real bridge when DSH_CODEGRAPH_PYTHON/DSH_CODEGRAPH_SOURCE are set (5/5 green), skip otherwise - Register in the host aggregate and the web-app bundle
…d benchmark - Bridge patches the engine's ignore list with lib/dist/out/coverage (engine hardcodes VCS dirs only; without this compiled artifacts pollute every query) - README: measured graph+BM25 vs +local-vector characteristics on packages/core (213 files): 12s vs 679s index, vector rescues NL/cross-language queries
- The reused engine only routes vector-heavy weights (0.3/0.5/0.2) to strong issue/bug queries; plain NL falls into graph-first (vector 0.05), so semantic retrieval barely participates in everyday use - bridge.py now patches SearchEngine._get_dynamic_weights at import time (module-level, engine untouched): issue keeps 0.3/0.5/0.2, plain NL gets a middle tier 0.5/0.3/0.2, code/function-memory stays 0.9/0.05/0.05 - Verified via the full bridge protocol: 'retry and fallback logic for llm requests' now lands on agent-loop/src/agent.ts instead of a test file
…rd queries - Tests excluded from indexing by default (DSH_CODEGRAPH_INCLUDE_TESTS=1 to opt back in): end-to-end runs showed test files dominating NL query results - Multi-word queries split camelCase terms before search (sessionProjection -> session Projection); single identifiers stay untouched so exact-symbol lookup keeps its precision (executeToolCalls -> agent-loop/src/tool-calls.ts verified) - Verified on the whole packages/ tree: retry-and-fallback NL query now lands on llm-retry/src/index.ts
- embeddingProvider defaults to 'local' with the ModelScope-downloaded model path; DSH_CODEGRAPH_EMBEDDING / DSH_CODEGRAPH_MODEL override - Missing model degrades safely to graph+BM25 (provider factory returns None on failure)
… weights - who calls X / callers of X / what does X call now return actual relation owners via graph_engine.callers/callees (verified: who calls executeToolCalls -> agent.ts step), instead of ranking the definition first - camelCase augmentation keeps original identifiers so the graph channel still extracts symbols from relation queries - Plain-NL middle weight tier configurable via DSH_CODEGRAPH_NL_WEIGHTS
…ading value.hits
- Tool description now documents the exact relation phrases (callers of X / who calls X / what does X call) and advises querying callers before modifying a function
- Render previously read Array.isArray(value) while execute returns { hits }; relation results now get a RELATION HITS header
- NL middle weights already env-tunable (DSH_CODEGRAPH_NL_WEIGHTS)
…is stale - A failed str_replace now extracts identifier-ish words from the stale snippet and ranks current-file lines by overlap, appending 'Closest current lines: L10: ...' to the error - Ported from the DeerFlow IDE structured-edit matching approach; lets the model re-anchor on the actual symbol instead of guessing - New test: stale function-header old_str points at the real definition line
…s ported from DeerFlow guidance
… nodes; identifier fallback - Full packages/ GPU index: 320s (RTX 5060 Ti) vs 1h+ CPU; 1507 files / 38896 call edges - Relation routing resolves qualified graph nodes (module.symbol) so exact callers are returned without fuzzy misfires - Single-identifier queries retry with split terms when exact lookup returns nothing - 20-task evaluation: 73% strict / 95% relevance; real issues: cross-package same-name callee noise, self-index pollution (CODEGRAPH_REAL_TASK_REPORT.md)
…guard - The bridge's own package dir joins the index ignore list at runtime (self-reference pollution: sessionProjection used to hit bridge.py itself) - Callee answers are kept only when they share the queried symbol's package; all-cross-package results are treated as same-name graph noise and fall back to normal search (parseArguments no longer resolves to api/gateway parse)
…tion angle brackets; untrack stray pyc
…ings card Indexing now runs on a bridge background thread so the first (slow) full build reports live progress instead of blocking. New codegraph_index_status tool tells the model the state (idle/indexing/ready/error), per-file progress, and last-build coverage. A CodeGraphStatusGateway Typert remote plus a read-only settings card (ui-settings-plugins) surface the same state in the web GUI, polling while a build is in flight. Search/reindex during a build raise a clear retry error. The parallel session's codegraph_impact blast-radius tool lands with it (resolver hoisted to module scope, bare-name mapping, upstream assertion fixed).
… migration stats and new-features docs
added 21 commits
August 16, 2026 23:17
…ndows backslash vs init forward slash)
…manifest rows never suppress host registration
…status, and index view tab - bridge: file-level mtime snapshot skips unchanged files on rebuild; call edges persist to a bridge_calls table so the in-memory CallGraph is fully restored after a restart without re-parsing; stats read live from DB - status: expose embeddingProvider/modelName/alive/reindex counters and code+doc vector totals; ambient warm-start on any status read; gateway adopts the first live agent workspace so a cold process builds on open - UI: dedicated conversation view tab (chat | trajectory | index) with vectors, engine liveness, embedding config and incremental-rebuild rows; timer-service polling (2s indexing / 30s settled) with dotted remote inject - impact: drop the full-depth file list, keep totals and direct neighbors - tests: codegraph index view spec (17), gateway and skills smoke specs
… and align its spec with the 30s settled cadence
…r-session index routing - bridge: one WorkspaceEngine per workspace (state/progress/thread/stats isolated); all workspace methods carry a workspace param; embedding provider is a process-wide shared singleton (lock-serialized); engines LRU-capped at 4 - gateway: status(sessionId?) resolves the session's workspace from live agents, drives that workspace's engine, and attaches sessionWorkspace so the view can show a serve/session mismatch - client: one poll controller per session (lazy map), polls with its session id, and the index view shows an explicit mismatch notice - tests: controller and view specs updated (25 passing); multi-workspace bridge verified end to end (parallel builds, isolation, shared provider, LRU cap)
The codegraph index view injected the timer service's repeating interval directly as the controller's one-shot scheduler. Every refresh registered another live interval without cancelling the previous one, so the poll rate grew exponentially (1 -> 2 -> 4 -> ...) until the browser stalled on ERR_INSUFFICIENT_RESOURCES. Normalize the chain inside the controller (cancel the pending timer before registering the next, and self-cancel on first fire) and inject timer.timeout, whose one-shot semantics match the chain contract. The controller spec now fakes the real repeating interval and pins that the poll count stays linear.
The bridge reported progress under snake_case keys (files_done, files_total) while the Typert remote schema validates camelCase (filesDone, filesTotal), so every gateway status call failed boundary validation and the index view showed a permanent bridge unavailable error. Map the progress keys in the status snapshot. Also clear the service initedWorkspaces set when the bridge child exits: a respawned bridge starts with an empty engine table, and skipping init left status calls failing with bridge not initialized.
The index view worked, but the model never reached for codegraph_search: it did not know when the index was ready, and a not-ready search failed with an instruction to fall back to grep, so grep became the default. - Inject a system-prompt guidance line (systemPrompt.section, refreshed on a 30s cadence and after status reads) so every turn states the index is ready with coverage, and routes structural queries to codegraph_search/codegraph_impact vs plain string matching to grep. - When the semantic index is still building, codegraph_search now falls back to the grep tool internally, labels results TEXT FALLBACK, and still returns usable hits, so a call is never wasted and the first call starts the build. - Rewrite tool descriptions: drop the continue-with-grep escape hatch, make the structural-vs-string routing explicit, and mandate impact analysis before modifying a symbol. - Unit tests for the guidance renderer (ready/building/error/idle), the grep-to-hit conversion, and the fallback orchestration (12 tests).
…ines
Two consistency fixes surfaced by a delegated bug-fix task that edited
bridge.py and observed the semantic index losing and re-gaining the file:
- require_ready() gains an allow_unready escape hatch: idle state returns
instead of starting a build and raising, leaving the decision to the
caller; indexing/error still raise. Default behavior is unchanged
(the three dispatch branches keep raising as before).
- The tools/result reindex listener bypassed the indexer's ignored
directories: editing bridge.py (whose package self-isolates) wrote
ghost entries back into the DB that the next full build deleted again,
so search results for that file flickered in and out. bridge reindex
now checks _is_ignored_path (same directory rules as _discover_files)
and skips ignored files with {"skipped": true}.
Also document both behaviors in CODEGRAPH_FEATURE.md (known limits 7-8,
troubleshooting rows), including the rule that one index directory must
not be shared by two engine processes (a second engine's full rebuild
cleans the first one's incremental entries).
A fresh session whose workspace was still empty at first build indexed 0 files; every file added afterwards stayed invisible until edited (the reindex listener only covers edited files), and the status page kept showing 0 because engine.stats only updates on a full build. - WorkspaceEngine._maybe_discover_new_files(): on status, throttled to 60s, re-scan the workspace with the indexer's own discovery rules and reindex every file the DB does not know yet (skipping ignored dirs). A project cloned into an empty workspace now enters the index within the throttle window without any edit. - status_snapshot(): report live COUNTs from the index DB (files, chunks, symbols, calls) instead of the stale full-build snapshot, so incremental reindexes are reflected in the page immediately. - Verified isolated (temporary index dir: new file indexed after the throttle window, files 16->17) and live (new file in the F:\deepseek index within 65s; blackhole project indexed 14 files after its first build). - CODEGRAPH_FEATURE.md: known-limit 9 and a troubleshooting row.
Two concurrent full builds (one per workspace) were observed holding ~12GB resident after finishing, vs a ~2GB steady state for the same two engines when builds completed sequentially. Python/transformers memory pools can keep the embedding peak resident indefinitely; collect eagerly when a full build finishes so the engine RSS returns to the steady state while staying warm. Cosmetic and safe: gc.collect() has no semantic effect on engine state.
…orch threads Full rebuilds parse and embed every file; on a 6-core machine the indexing process could starve the interactive session (observed as system-wide lag during concurrent workspace builds). The embedding model already runs on the GPU (SentenceTransformer auto-selects cuda), so the CPU cost is parse/tokenize work — cap torch's CPU thread pool at 4 and set the bridge process to BELOW_NORMAL_PRIORITY_CLASS on Windows so rebuilds stay warm without stealing the desktop. The ctypes pseudo-handle needs pointer-sized restype/argtypes or SetPriorityClass silently fails.
The bridge held ~5.6GB VRAM after builds even though embedding peaks at ~0.65GB plus the ~1.7GB model: torch's caching allocator keeps freed blocks resident. Bound the process with torch.cuda.set_per_process_memory_fraction (default 0.4, tunable via DSH_CODEGRAPH_GPU_MEM_FRACTION) and let the allocator release cached blocks past garbage_collection_threshold, so idle residency drops to ~3.4GB and the rest of the card stays available for the user's other models. Verified: 5.6GB -> 3.4GB with search still working.
Leaves ~13GB of a 16GB card free for the user's other models; embedding peaks around 1.3GB plus the ~1.7GB model, so 0.2 (3.3GB cap) still has ample headroom. Verified earlier: 0.15 works at 2.4GB, 0.2 is the recommended safe floor.
…idance Two follow-ups from the second-project session: - The status gateway returned a blank idle snapshot whenever the requesting sessionId was not among the live agents (closed session, or the registry not exposing it). Fall through to the default workspace routing instead, so the index view keeps showing the engine it can reach and a status read still warms a cold engine into its first build. - System-prompt guidance was a single process-wide snapshot of the most recently touched workspace; a session in another project saw the wrong index's readiness and never reached for codegraph_search. Guidance is now per-workspace: the section provider reads the agent's own session cwd and serves that workspace's cached status (miss falls back to a neutral line and triggers a refresh). - Incremental discovery now diffs mtime/size against the persisted snapshot instead of only adding unknown files, so files edited outside the agent's edit tool (manual edits) get reindexed within the throttle window, and the snapshot is updated so a later full build skips them.
…irectory name Self-isolation added the package dir name to the engine _IGNORE_DIRS, which prunes by name at every path component, wrongly excluding any user dir named codegraph and making the package source unsearchable. Exclude by absolute path prefix instead, scoped to the bridge's own source dirs (python/, src/) so the fixtures sample workspace stays indexable: _PKG_ROOT + _is_self_excluded, applied in _tracked_discover and _is_ignored_path.
…rd-filtering The engine's active_file routing hard-filters every channel to the active file's language, zeroing out results when the query's natural matches are in another language. Stop passing activeFile to the engine; request a wider pool (topK*3) and apply a soft bias in _apply_active_file_bias (exact-file and same-directory boosts), then re-rank and truncate to topK.
The status test expected a fresh workspace to report idle, but the ambient warm-start (added in 70c8f80) kicks off the first build on any status read, so the first read reports indexing. Update the expectation and poll for ready instead of a single racy read.
…ped-component symbols The engine maps .tsx to the plain TypeScript grammar, which cannot parse JSX; a .tsx file with top-level JSX yields a parse error that swallows the declarations after it, so its symbols and call edges never enter the graph (GenericToolCard.tsx: chunked but 0 symbols, 0 calls). The bridge now re-parses .tsx/.jsx files with language_tsx and reuses the engine's generic extractors. It also extends _is_function_like_variable to recognize memo/forwardRef-wrapped components, and records a file's incremental signature only after a successful index so a failed file is retried instead of skipped forever.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.