Skip to content

feat(desktop): enable fuzzy @-search with directory support in Composer#3835

Closed
SuMuxi66 wants to merge 64 commits into
esengine:main-v2from
SuMuxi66:fix/fuzzy-at-search
Closed

feat(desktop): enable fuzzy @-search with directory support in Composer#3835
SuMuxi66 wants to merge 64 commits into
esengine:main-v2from
SuMuxi66:fix/fuzzy-at-search

Conversation

@SuMuxi66

Copy link
Copy Markdown
Contributor

Summary

Restore the v1-style fuzzy @file search behavior in the Composer so that
an intermediate directory segment in a query (e.g. @planind) surfaces
nested matches such as src/planind/index.tsx, and directory names like
assets/ are selectable from the @-menu.

Previously the backend matched only on d.Name() (basename), the frontend
filter reduced searchEntries to basename-only, and SearchFileRefs
hardcoded IsDir: false for all results — so deep paths and directories
were invisible to the @-menu.

Closes #3769.

What changed

  • internal/fileref/search.go

    • Search now returns []SearchResult (with Path and IsDir) instead of
      []string.
    • Matches are collected into three tiers: basename hits (preferred), path-
      segment hits (fallback), and directory-name hits (lowest). A dirQuota
      of 5 ensures directories are never fully crowded out by file matches.
    • pathSegmentContains(relSlash, queryLower) checks any slash-separated
      path segment for a match.
    • Noise directories (.git, node_modules, build, dist, ...) are
      still skipped. The public API signature is unchanged.
  • desktop/app.go

    • SearchFileRefs now propagates r.IsDir from SearchResult to
      DirEntry.IsDir, fixing a pre-existing bug where all results were
      hardcoded IsDir: false.
  • internal/cli/complete.go

    • Adapted to the new []SearchResult return type (CLI only uses Path).
  • desktop/frontend/src/lib/atMatches.ts (new)

    • Pure helper filterAtMatches(entries, searchEntries, atFrag) that
      matches against the full slash-normalized relative path and de-duplicates
      by e.name with the local list taking precedence.
  • desktop/frontend/src/__tests__/at-matches.test.ts (new)

    • 5 cases covering nested-path surfacing, basename match, de-duplication,
      local-before-fuzzy ordering, and the empty-fragment legacy behavior.
  • desktop/frontend/src/components/Composer.tsx

    • The atMatches useMemo now delegates to filterAtMatches. The rest
      of the @-menu logic, the atDir !== "" guard, and the directory
      navigation UX are intentionally untouched.
  • internal/fileref/search_test.go (new)

    • 6 cases covering path-segment match, basename match, directory match
      with IsDir=true, sort order between tiers, and noise-directory skip.

Test results

  • go test ./internal/fileref -count=1 — 6/6 PASS
  • pnpm exec tsx src/__tests__/at-matches.test.ts — 5/5 PASS
  • go build ./... — clean
  • Manual Wails dev test — directories and files both surface correctly

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) tui Terminal UI / CLI (internal/cli, internal/control) labels Jun 10, 2026
taibai and others added 25 commits June 10, 2026 19:36
TestACPFactoryLoadsSessionCwdProjectConfig builds a full controller via
boot.Build with the default config, which starts the codegraph serve
daemon when the binary is installed. The daemon opens
<workspaceRoot>/.codegraph/codegraph.db and on Windows holds the handle
past Close, so t.TempDir cleanup fails with "being used by another
process". The test only exercises ACP project-command loading, so turn
codegraph off — matching the boot tests' convention.

Co-authored-by: reasonix <reasonix@deepseek.com>
The desktop release dropped Debian/Ubuntu packaging in the v2 rewrite —
Linux only shipped a bare-binary tar.gz (discussion esengine#3627). Add a .deb
built with goreleaser/nfpm in desktop-build.sh's linux branch.

- desktop/build/linux/nfpm.yaml + reasonix.desktop describe the package:
  binary to /usr/bin, .desktop entry, icon to /usr/share/pixmaps, and
  libgtk-3-0 + libwebkit2gtk-4.1-0 runtime deps apt resolves on install.
- The .deb is a human-download artifact only (like the macOS .dmg); the
  Linux updater channel stays the tar.gz, so cmd/sign's manifest skips
  .deb files. A test locks the linux-amd64 key to the tarball.
- release-desktop.yml installs nfpm (pinned v2.46.3) on the Linux runner.

The existing sign / upload / release / R2-mirror steps already glob dist/*,
so the .deb is signed, attached to the GitHub release, and mirrored with no
further workflow changes.

Co-authored-by: reasonix <reasonix@deepseek.com>
…suffix-scan CanCode (esengine#3438) (esengine#3672)

* fix(control): fail conversation rewind loudly past a compacted boundary

A turn's conversation-rewind boundary is the message-log index at turn
start. Compaction shrinks the log without rewriting boundaries, so for a
turn compacted away the boundary now exceeds len(Messages). Rewind tested
`boundary <= len` and, when false, skipped the truncation but still emitted
a "rewound conversation" success — code restored, conversation silently not.
Return a clear failure instead, and only report success when the log was
actually truncated.

Closes esengine#3598

* fix(desktop): mark a turn code-rewindable when a later turn changed files

RestoreCode(turn) reverts every file touched in that turn or any later one,
so a turn that changed no files of its own can still rewind code when a
later turn did. CanCode only checked the turn's own paths, disabling the
code/both rewind buttons for such turns. Propagate CanCode backwards over
the oldest-first checkpoint list so the UI matches the backend's capability.

Refs esengine#3438

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
)

* chore(ci): add Dependabot config and CodeQL code scanning

Enable Dependabot version updates (gomod for the root and desktop
modules; npm for desktop/frontend, site, and npm/reasonix; github-actions)
with grouped minor/patch PRs to keep noise down, and add a CodeQL workflow
(go, javascript-typescript, actions; build-mode none so the multi-module
repo needs no build step) on push/PR to main-v2 plus a weekly scan.

* chore(ci): use codeql-action v4 (v3 deprecates Dec 2026)

* fix(ci): CodeQL Go requires a build — use autobuild, not none

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
)

Bumps the go group in /desktop with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [fyne.io/systray](https://github.com/fyne-io/systray) | `1.12.1` | `1.12.2` |
| [github.com/wailsapp/wails/v2](https://github.com/wailsapp/wails) | `2.11.0` | `2.12.0` |
| [golang.org/x/mod](https://github.com/golang/mod) | `0.36.0` | `0.37.0` |
| [golang.org/x/sys](https://github.com/golang/sys) | `0.45.0` | `0.46.0` |
| [golang.org/x/text](https://github.com/golang/text) | `0.37.0` | `0.38.0` |


Updates `fyne.io/systray` from 1.12.1 to 1.12.2
- [Changelog](https://github.com/fyne-io/systray/blob/master/CHANGELOG.md)
- [Commits](fyne-io/systray@v1.12.1...v1.12.2)

Updates `github.com/wailsapp/wails/v2` from 2.11.0 to 2.12.0
- [Release notes](https://github.com/wailsapp/wails/releases)
- [Commits](wailsapp/wails@v2.11.0...v2.12.0)

Updates `golang.org/x/mod` from 0.36.0 to 0.37.0
- [Commits](golang/mod@v0.36.0...v0.37.0)

Updates `golang.org/x/sys` from 0.45.0 to 0.46.0
- [Commits](golang/sys@v0.45.0...v0.46.0)

Updates `golang.org/x/text` from 0.37.0 to 0.38.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](golang/text@v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: fyne.io/systray
  dependency-version: 1.12.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go
- dependency-name: github.com/wailsapp/wails/v2
  dependency-version: 2.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: golang.org/x/mod
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: golang.org/x/sys
  dependency-version: 0.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: golang.org/x/text
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…gine#3687)

Bumps [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) from 4.7.0 to 5.2.0.
- [Release notes](https://github.com/vitejs/vite-plugin-react/releases)
- [Changelog](https://github.com/vitejs/vite-plugin-react/blob/plugin-react@5.2.0/packages/plugin-react/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@5.2.0/packages/plugin-react)

---
updated-dependencies:
- dependency-name: "@vitejs/plugin-react"
  dependency-version: 5.2.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [astro](https://github.com/withastro/astro/tree/HEAD/packages/astro) from 5.18.2 to 6.4.4.
- [Release notes](https://github.com/withastro/astro/releases)
- [Changelog](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG.md)
- [Commits](https://github.com/withastro/astro/commits/astro@6.4.4/packages/astro)

---
updated-dependencies:
- dependency-name: astro
  dependency-version: 6.4.4
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
/npm/reasonix only declares this project's own @reasonix/cli-* platform
binaries as optionalDependencies — versioned by the release pipeline, not
third-party deps. Dependabot was opening useless 0.0.0->1.0.0 self-bump PRs
for them; remove the ecosystem entry.

Co-authored-by: reasonix <reasonix@deepseek.com>
esengine#3688)

Bumps the actions group with 13 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `4` | `6` |
| [actions/setup-go](https://github.com/actions/setup-go) | `5` | `6` |
| [pnpm/action-setup](https://github.com/pnpm/action-setup) | `4` | `6` |
| [actions/setup-node](https://github.com/actions/setup-node) | `4` | `6` |
| [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) | `7` | `9` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `7` |
| [actions/github-script](https://github.com/actions/github-script) | `7` | `9` |
| [actions/setup-python](https://github.com/actions/setup-python) | `5` | `6` |
| [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) | `3` | `5` |
| [actions/deploy-pages](https://github.com/actions/deploy-pages) | `4` | `5` |
| [actions/labeler](https://github.com/actions/labeler) | `5` | `6` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `4` | `8` |
| [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) | `6` | `7` |



Updates `actions/checkout` from 4 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v6)

Updates `actions/setup-go` from 5 to 6
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](actions/setup-go@v5...v6)

Updates `pnpm/action-setup` from 4 to 6
- [Release notes](https://github.com/pnpm/action-setup/releases)
- [Commits](pnpm/action-setup@v4...v6)

Updates `actions/setup-node` from 4 to 6
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v4...v6)

Updates `golangci/golangci-lint-action` from 7 to 9
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](golangci/golangci-lint-action@v7...v9)

Updates `actions/upload-artifact` from 4 to 7
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

Updates `actions/github-script` from 7 to 9
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@v7...v9)

Updates `actions/setup-python` from 5 to 6
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v5...v6)

Updates `actions/upload-pages-artifact` from 3 to 5
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](actions/upload-pages-artifact@v3...v5)

Updates `actions/deploy-pages` from 4 to 5
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](actions/deploy-pages@v4...v5)

Updates `actions/labeler` from 5 to 6
- [Release notes](https://github.com/actions/labeler/releases)
- [Commits](actions/labeler@v5...v6)

Updates `actions/download-artifact` from 4 to 8
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](actions/download-artifact@v4...v8)

Updates `goreleaser/goreleaser-action` from 6 to 7
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](goreleaser/goreleaser-action@v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/deploy-pages
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/labeler
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-pages-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: golangci/golangci-lint-action
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: goreleaser/goreleaser-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pnpm/action-setup
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [react-markdown](https://github.com/remarkjs/react-markdown) from 9.1.0 to 10.1.0.
- [Release notes](https://github.com/remarkjs/react-markdown/releases)
- [Changelog](https://github.com/remarkjs/react-markdown/blob/main/changelog.md)
- [Commits](remarkjs/react-markdown@9.1.0...10.1.0)

---
updated-dependencies:
- dependency-name: react-markdown
  dependency-version: 10.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) from 0.460.0 to 1.17.0.
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.17.0/packages/lucide-react)

---
updated-dependencies:
- dependency-name: lucide-react
  dependency-version: 1.17.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ngine#3678)

Bumps the go group with 3 updates in the / directory: [golang.org/x/sys](https://github.com/golang/sys), [golang.org/x/term](https://github.com/golang/term) and [golang.org/x/text](https://github.com/golang/text).


Updates `golang.org/x/sys` from 0.45.0 to 0.46.0
- [Commits](golang/sys@v0.45.0...v0.46.0)

Updates `golang.org/x/term` from 0.43.0 to 0.44.0
- [Commits](golang/term@v0.43.0...v0.44.0)

Updates `golang.org/x/text` from 0.37.0 to 0.38.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](golang/text@v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: golang.org/x/term
  dependency-version: 0.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
- dependency-name: golang.org/x/text
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
esengine#3706)

The release golangci-lint v2.12.2 binary CI runs flags SA5011 (possible nil
pointer dereference) on two `if x == nil { t.Fatal(...) }`-guarded derefs,
even though they are correct (Fatal stops the test). The finding was masked by
the golangci-lint-action cache until esengine#3678 changed go.sum and invalidated it,
then surfaced on main-v2 and every open PR. A locally-built golangci-lint does
not reproduce it, so this is a staticcheck quirk in the pinned binary, not a
real defect.

Restructure both sites with flow-based guards (else-if / switch) the analyzer
always respects — no behaviour change, no unreachable `return` (which a
Fatal-aware analyzer would flag locally).

Co-authored-by: reasonix <reasonix@deepseek.com>
… layout breakage (esengine#3700)

The 'Allow for session' and 'Always allow' buttons in the approval modal
displayed the full bash command as inline code (e.g. Bash(cd ...)), which
stretched the button elements and broke the card layout.

The command is already visible in the card header meta area and the
expandable Details section, so showing it again inside the action buttons
is redundant. Removed the RuleActionLabel component, the rule-formatting
helpers (approvalSessionRule, approvalPersistentRule, truncateSubject),
and the unused CSS classes.

Fixes esengine#3677

Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
) (esengine#3712)

* fix(control): don't auto-answer the ask tool in YOLO mode

Controller.Ask checked bypassEnabled() and silently returned the first option
of every question, so in YOLO mode the `ask` tool got a fake answer and the
user never saw the prompt. Bypass is meant to skip tool-approval gates, not to
answer the user's genuine questions. Remove both bypass checks (and the now
unused recommendedAskAnswers helper); Ask always emits an AskRequest and waits
for AnswerQuestion, even under bypass.

Combines the minimal fix from esengine#3709 (CVEngineer66) with the behavior tests
from esengine#3638 (warvyvr), dropping that PR's unrelated files.

Closes esengine#3624

Co-authored-by: CVEngineer66 <CVEngineer66@users.noreply.github.com>
Co-authored-by: warvyvr <warvyvr@users.noreply.github.com>

* fix(control): drop now-unused bypassEnabled helper

Removing the bypass checks from Ask left bypassEnabled with no callers
(staticcheck unused).

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
Co-authored-by: CVEngineer66 <CVEngineer66@users.noreply.github.com>
Co-authored-by: warvyvr <warvyvr@users.noreply.github.com>
…sengine#3713)

run_skill is ReadOnly()=false because subagent skills can spawn writer tool
calls, so plan mode (read-only) blocks ALL skill use — including inline skills,
which only render a body and have no side effects. That made it impossible to
consult a playbook while planning (esengine#3491).

Add read_skill: a read-only counterpart that renders an inline skill body and
rejects subagent skills (pointing the model at run_skill). Being ReadOnly it
stays available in plan mode. Added to SubagentMetaTools so spawned agents
don't inherit it.

Closes esengine#3491

Co-authored-by: reasonix <reasonix@deepseek.com>
…esengine#3635) (esengine#3714)

* fix(config): honor an explicit proxy for no_proxy providers (mimo)

The built-in mimo presets carry no_proxy=true so their domestic endpoint
stays off an auto-detected (GFW-circumvention) system proxy. But that bypass
was applied in every mode, so behind a mandatory corporate proxy
(proxy_mode = "custom") mimo tried a direct connection the firewall blocks —
making mimo unusable on enterprise networks (esengine#3635).

Apply the provider-level no_proxy bypass only for auto/env proxies. An explicit
custom proxy means "route everything through this", so honor it for every
provider; a custom-proxy user who still wants a host direct uses
network.no_proxy.

Closes esengine#3635

* test(config): structurally guard nil-deref (staticcheck SA5011)

The release golangci-lint binary CI runs flags SA5011 on guarded t.Fatal
derefs in backfill_test.go and migrate_test.go (same cache-masked false
positive as esengine#3706); this PR touches the config package so a cold lint run
surfaces them. Guard with else-if; no behavior change.

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
…ne#3715)

The pinned golangci-lint binary's staticcheck reports SA5011 (possible nil
pointer dereference) on `if x == nil { t.Fatal(...) }`-guarded derefs in tests
— it doesn't model t.Fatal as terminating. The same code is clean under a
locally-built golangci-lint, and the finding is masked by the action cache
until a go.sum change cold-busts it, so it surfaces per-package and has failed
lint on otherwise-correct PRs (handled ad hoc in esengine#3706, esengine#3714).

Scope a test-only SA5011 exclusion so it stops blocking PRs while SA5011 keeps
guarding production code.

Co-authored-by: reasonix <reasonix@deepseek.com>
…3716)

* fix: always allow (persist) now grants all tools for the session

When user clicks 'Always allow' (Allow Persistently) on a tool approval
prompt, the current code only remembers the grant for that specific tool
(e.g. write_file). Later in the same session, other tools like bash still
trigger permission prompts, confusing the user.

This fix makes 'Always allow' set a wildcard session grant (c.granted['*'])
so all writer tools are auto-allowed for the rest of the session without
further prompting. The actual on-disk config rule is still written as before
via OnRemember for cross-session persistence.

The normal 'Allow for this session' remains tool-specific as before.

* Revert "fix: always allow (persist) now grants all tools for the session"

This reverts commit f90ba6f.

* fix: reload persist rule into in-memory Policy immediately

After OnRemember writes an 'always allow' rule to the on-disk config,
also append the parsed rule to the Gate's in-memory Policy.Allow slice
so it takes effect in the current session without requiring a restart.

Previously, clicking 'Always allow' on a tool (e.g. write_file) would:
1. Write the rule to reasonix.toml ✅
2. Set c.granted['write_file'] = true for the Approver path ✅
3. BUT: the Gate's Policy was not updated in memory ❌
   → Any code path consulting Policy.Decide() directly would still see
     the old policy and not match the new allow rule

This fix adds the parsed rule to g.Policy.Allow after writing to disk,
so the in-memory Policy stays consistent with the persisted config.

Ref: esengine#3607

---------

Co-authored-by: HorusJiang <horusjiang@users.noreply.github.com>
SivanCola and others added 22 commits June 10, 2026 19:36
… loop (esengine#3752)

Lands three changes from esengine#3752:

- Desktop: graphite UI redesign with slate/carbon/nocturne/amber theme
  directions (light+dark), Cmd-K command palette, and a status bar /
  composer / sidebar refresh. Default desktop appearance is now light.
- Controller: separate tool approvals from business asks and plan
  approval. Posture is ask/auto/yolo; deny rules still block upstream,
  auto keeps explicit ask rules while auto-approving the writer fallback,
  and plan approval plus the ask tool stay user decisions in every mode.
- Controller: opt-in /goal autonomous loop that self-continues up to 50
  turns, driven by [goal:complete|blocked|continue] markers, bounded and
  cancellable, with a repeated-block stop.
…sengine#3773)

CodeQL go/allocation-size-overflow (high) flagged `n + m` flowing into
`make([]int, 2*maxD+1)`: a pathological line count could overflow the
addition before the downstream clamp. The result was already safe (the
clamp caught a wrapped-negative maxD), but the addition itself still
tripped the query. Restructure to maxD = min(n+m, maxDiffEdits) with the
sum taken only when n and m are within the cap — no overflow at the
operation, identical bound.

Co-authored-by: reasonix <reasonix@deepseek.com>
…tion (esengine#3775)

Follow-up to esengine#3773: that cleared the n+m addition alert, but CodeQL still
flagged the 2*maxD allocation (go/allocation-size-overflow) because it
doesn't propagate maxD's bound through the guarded sum. Clamp each line
count to maxDiffEdits before summing, so the sum and the 2*maxD allocation
both have constant-bounded operands. maxD stays min(n+m, maxDiffEdits).

Co-authored-by: reasonix <reasonix@deepseek.com>
)

Lands the bot gateway as its own feature, extracted from esengine#3752: gateway/session plumbing plus Feishu, Weixin, and QQ adapters, CLI/config support, and the desktop Settings UI for bot channel configuration and guided setup.

Co-authored-by trailers preserved from the source branch.
esengine#3779)

Follow-up to esengine#3763.

- Feishu webhook mode is the default, and verificationTokenValid accepts
  any caller when no token is configured, so an empty verification_token
  exposed an unauthenticated event endpoint. Refuse to start webhook mode
  without a token (fail closed).
- Move the weixin account-persistence and QR-login block to
  weixin_login.go, bringing weixin.go under the 800-line ceiling (811->587).

Co-authored-by: reasonix <reasonix@deepseek.com>
esengine#3711)

Background auto-refresh calls FetchProviderModels for every configured
provider and merges the result via mergedFetchedProviderModels().
When the user left the models list empty (common for custom providers),
preserveCurated: true had no effect because saved.length === 0,
causing every model from the API to be written into the config.

Now the background refresh skips providers whose models list is empty,
preventing silent pollution of the model dropdown. Users can still
manually fetch models via the 'Refresh Models' button.

Fixes esengine#3705

Co-authored-by: wufengfan <wufengfan@wufengfandeMacBook-Air.local>
…port to top/bottom (esengine#3723)

Co-authored-by: 广东移动系统集成揭阳公司-黄韵学 <13413986135@139.com>
…end (esengine#3690)

Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react), [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). These dependencies needed to be updated together.

Updates `react` from 18.3.1 to 19.2.7
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.7/packages/react)

Updates `react-dom` from 18.3.1 to 19.2.7
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v19.2.7/packages/react-dom)

Updates `@types/react` from 18.3.29 to 19.2.17
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-version: 19.2.17
  dependency-type: direct:development
  update-type: version-update:semver-major
- dependency-name: react
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-major
- dependency-name: react-dom
  dependency-version: 19.2.7
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ine#3618)

* feat(control): extract text from PDF attachments

* fix(control): bound PDF extractor subprocess output
…ps (esengine#3787)

* fix(proc): reap codegraph's process tree off Windows via process groups

KillTree off Windows only signalled the direct child, so a launcher whose
sub-daemon outlives it (codegraph's bundled node runtime) left orphan
grandchildren after exit — the Unix counterpart of the Windows Job Object
reaping. StartTracked now starts the child in its own process group
(Setpgid) and KillTree kills the whole group with a negative-pid signal;
SetProcessGroupKill exposes the same for one-shot children (codegraph init).
No-op on Windows, where the Job Object already covers the tree.

Co-authored-by: ttmouse <ttmouseg@gmail.com>

* test(proc): lift the reap-poll break into the loop condition (QF1006)

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
Co-authored-by: ttmouse <ttmouseg@gmail.com>
…e#3791)

@types/react 19 (bumped in esengine#3690) tightened ref nullability and dropped the
global JSX namespace, which TypeScript 6 enforces. Type the shared ref props
as RefObject<T | null> (matching what useRef(null) returns), import the JSX
namespace from react, and give the debounce useRef an explicit initial value.
No behavior change; unblocks the typescript@6 bump (esengine#3691).

Co-authored-by: reasonix <reasonix@deepseek.com>
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 6.0.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](microsoft/TypeScript@v5.9.3...v6.0.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 6.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…sengine#3793)

* chore(deps-dev): bump @types/react-dom to 19 to match @types/react

esengine#3690 bumped @types/react to 19 but left @types/react-dom at 18, whose types
pin the @types/react peer to ^18 — an ERESOLVE conflict that npm ci tolerated
only on older npm. Bump @types/react-dom to 19.2.3 so the two react type
packages agree: npm ci now resolves without --legacy-peer-deps and the
frontend typechecks unchanged.

* chore(deps-dev): sync pnpm-lock.yaml for the @types/react-dom 19 bump

---------

Co-authored-by: reasonix <reasonix@deepseek.com>
…#3752 合并后的桌面 UI 修复 (esengine#3795)

* fix(desktop): preserve curated provider models on refresh

* fix(desktop): clarify composer collaboration entry

* fix(desktop): keep draft goal mode visible

* fix(desktop): allow approval mode changes while running
…d names (esengine#3628, esengine#3629) (esengine#3647)

- Add max-height and overflow-y: auto to model dropdown menu
- Add title attribute to model name and provider for full text tooltip
- Fixes long model names being truncated without way to see full name
- Fixes model list not being scrollable when there are many models

Co-authored-by: Li-Charles-One <Li-Charles-One@users.noreply.github.com>
…sengine#3539) (esengine#3583)

- Add 'Show in file manager' option to file tree right-click menu
- Call app.RevealWorkspacePath to open file in system file manager
- Split context menu height constants to avoid selection menu offset issue
- Add locale strings for en/zh

Co-authored-by: Li-Charles-One <Li-Charles-One@users.noreply.github.com>
…ngine#3802)

The goal-draft decision was inlined at seven App.tsx call sites (active
tab, tab list, controller sync, model switch). Move it into
src/lib/goalDraftMode.ts so the rule lives in one place and is unit
tested; no behavior change from the inline form merged in esengine#3795.

Co-authored-by: reasonix <reasonix@deepseek.com>
Co-authored-by: SivanCola <32437197+SivanCola@users.noreply.github.com>
The v2 @-menu search matched only on the basename of each file, so an
input like "@planind" never surfaced a deeply-nested match such as
"src/planind/index.tsx" whose basename is "index.tsx".

* internal/fileref/search.go: split matches into a basename tier and a
  path-segment tier; basename hits still win, but the segment tier now
  fills the remaining capacity using pathSegmentContains(rel, query).
  Noise directories (node_modules, build, dist, .git, ...) are still
  skipped before the matching switch.
* internal/fileref/search_test.go: cover path-segment match, basename
  match, sort order between tiers, and noise-directory skip list.
* desktop/frontend/src/lib/atMatches.ts: extract the Composer @-menu
  filter into a pure helper so it can be unit-tested without React.
* desktop/frontend/src/__tests__/at-matches.test.ts: regression tests
  for nested path surfacing, basename match, and stable de-duplication.
* desktop/frontend/src/components/Composer.tsx: delegate the filter
  to the helper. The atDir !== "" guard for sub-path search is
  intentionally left unchanged for this fix.
@SuMuxi66 SuMuxi66 force-pushed the fix/fuzzy-at-search branch from 77409bc to 4e46b37 Compare June 10, 2026 11:37
@github-actions github-actions Bot added skills Skill system (internal/skill, internal/tool) agent Core agent loop (internal/agent, internal/control) mcp MCP servers / plugins (internal/plugin, codegraph) config Configuration & setup (internal/config) updater Auto-update / installer / release packaging provider Model providers & selection (internal/provider) labels Jun 10, 2026
@SuMuxi66 SuMuxi66 closed this Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) mcp MCP servers / plugins (internal/plugin, codegraph) provider Model providers & selection (internal/provider) skills Skill system (internal/skill, internal/tool) tui Terminal UI / CLI (internal/cli, internal/control) updater Auto-update / installer / release packaging v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: @选择上下文无法模糊搜索的问题