Skip to content

fix(cli): repair search and status commands - #69

Merged
Dwsy merged 2 commits into
Dwsy:mainfrom
Batchputz:fix/cli-search-and-status
Sep 29, 2026
Merged

Dwsy merged 2 commits into
Dwsy:mainfrom
Batchputz:fix/cli-search-and-status

Conversation

@Batchputz

Copy link
Copy Markdown
Contributor

Summary

pi-session-cli cannot run two of its commands against the current server (reproduced on the v0.8.6 release binaries and on main = a09ae455, which is the same commit the tag points at):

command result
pi-session-cli search <query> Command failed: 命令 'search_sessions_fts' 失败: Failed to prepare FTS5 statement: no such table: sessions_fts
pi-session-cli status Command failed: 服务端返回了非 JSON 响应 (http://localhost:52131/health) — 可能服务端版本不匹配

Two independent causes, one commit each.

1. search — the legacy sessions_fts table is gone

src-tauri-cli/src/run.rs calls the app command search_sessions_fts, which resolves to data/sqlite/legacy_fts.rs::search_fts5():

SELECT path FROM sessions_fts WHERE sessions_fts MATCH ?

Since message-level FTS became the primary search path, data/sqlite/bootstrap.rs only builds ensure_message_fts_schema() and notes "Legacy session-level FTS remains disabled regardless of config"; init_fts5() — the only caller of full_rebuild_fts() — has no callers left, so sessions_fts is never created and the command always fails.

This is the bug reported in #62. That issue is closed as "Fixed by 208190a4: CLI session search now uses the current message_fts index instead of the removed sessions_fts table", but that commit does not exist in this repository, and the failure still reproduces on main/v0.8.6:

$ gh api repos/Dwsy/pi-session-manager/commits/208190a4
gh: No commit found for SHA: 208190a4 (HTTP 422)

$ gh api repos/Dwsy/pi-session-manager/commits/main --jq '.sha'
a09ae455595e90c79776f4f8821aee5cb54c8d2b
$ gh api repos/Dwsy/pi-session-manager/git/ref/tags/v0.8.6 --jq '.object.sha'
a09ae455595e90c79776f4f8821aee5cb54c8d2b   # tag == main

$ gh api "repos/Dwsy/pi-session-manager/contents/src-tauri-cli/src/run.rs?ref=main" \
    --jq '.content' | base64 -d | sed -n '490p'
            let data = request_command(&client, &base_url, "search_sessions_fts", json!({ "query": query })).await?;

This PR does what that closing comment describes — the CLI now uses the current message_fts index, via the existing full_text_search command (same one the UI's search uses):

request_command(&client, &base_url, "full_text_search",
    json!({ "query": query, "role_filter": "all", "page": 0, "page_size": 20 }))

Result: scored message hits with content snippets, session_path and timestamps (previously the command returned up to 50 SessionInfo rows; message-level hits are what the maintained index can serve).

2. status — there is no /health route to probe

request_status() requests GET {base_url}/health. The router in src/server/http/mod.rs registers /api, /api/events, /v1/*, /ws and /metrics — no /health, so the request falls through to the embedded-SPA handler, which answers with index.html, and resp.json() fails on the HTML.

The fix keeps /health as the first probe (for deployments that do expose it) and falls back to /v1/observability/summary, which is served in desktop and headless mode and reports exactly what status is for:

$ pi-session-cli status
{
  "data": {
    "capabilities": { "analytics_overview": true, "memory_recall": true, ... },
    "endpoints": [ "/v1/sessions", "/v1/memory/recall", ... ]

Testing

Built with cargo build --release -p pi-session-cli (feature cli, no Tauri/WebKit needed) and run against a running 0.8.6 desktop app with a schema-v19 database (~/.pi/agent/sessions/sessions.db), which is the environment from #62:

# before (stock 0.8.6 release binary)
$ pi-session-cli search waybar
ERROR 命令 'search_sessions_fts' 失败: Failed to prepare FTS5 statement: no such table: sessions_fts
$ pi-session-cli status
ERROR 服务端返回了非 JSON 响应 (http://localhost:52131/health) — 可能服务端版本不匹配

# after
$ pi-session-cli search waybar
{
  "has_more": true,
  "hits": [
    {
      "content": "restart waybar",
      "entry_id": "63b4db64",
      "match_reason": "content",
      "role": "user",
      "score": 14.397594451904297,
      "session_id": "019f6366-2abc-70bf-886c-5fd1640bf41a",
      "session_path": "/home/user/.pi/agent/sessions/---/2026-07-15T01-31-07-836Z_019f6366-....jsonl",
      "source_type": "user",
      "timestamp": "2026-07-15T02:47:55.604Z"
    },
    ...
  ]
}
$ pi-session-cli status
{ "data": { "capabilities": { "analytics_overview": true, ... } } }

session list, session get, tag, model etc. are untouched and still work.

Alternatives considered

  • Make the server-side search_sessions_fts fall back to the message index, so existing CLI builds keep working too. That changes the command's return shape (Vec<SessionInfo> → hits), so it is a behavioural change on a public command — happy to implement it instead if you prefer that direction.
  • Add a /health route server-side rather than adjusting the client. Also fine by me if you would rather have the conventional endpoint.

Both commits are independent — happy to split them into separate PRs if that is easier to review.

…s_fts table

`pi-session-cli search` called the app command `search_sessions_fts`, which runs
`SELECT path FROM sessions_fts WHERE sessions_fts MATCH ?`. Since message-level
FTS became the primary search path, the schema no longer creates `sessions_fts`
(see `ensure_message_fts_schema` in data/sqlite/bootstrap.rs, which is now the
only index built; `init_fts5`, the only caller of `full_rebuild_fts`, is unused),
so the command always failed with:

    Command failed: 命令 'search_sessions_fts' 失败:
    Failed to prepare FTS5 statement: no such table: sessions_fts

Route the CLI at `full_text_search` instead, which queries the maintained
message-level index and returns scored hits with content snippets.

Refs Dwsy#62
`pi-session-cli status` requested `GET /health`, but the axum router in
src/server/http/mod.rs registers no `/health` route, so the request fell through
to the SPA handler and the CLI reported:

    服务端返回了非 JSON 响应 (http://localhost:52131/health) — 可能服务端版本不匹配

Probe `/health` first (kept for deployments that do expose it) and fall back to
`/v1/observability/summary`, which reports the supported capabilities and
endpoints and is served in both desktop and headless modes.
@Dwsy
Dwsy merged commit 37a682e into Dwsy:main Sep 29, 2026
4 of 5 checks passed
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