Skip to content

feat(kap-server): add session-less POST /workspace/fs:search route - #2437

Merged
sailist merged 6 commits into
MoonshotAI:mainfrom
sailist:feat/fs-search-workspace-ref
Jul 31, 2026
Merged

feat(kap-server): add session-less POST /workspace/fs:search route#2437
sailist merged 6 commits into
MoonshotAI:mainfrom
sailist:feat/fs-search-workspace-ref

Conversation

@sailist

@sailist sailist commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problems are explained per theme below.

Problem

kimi-web's @ file mention must search files before a session exists (the new-session draft), but the only search endpoint was POST /sessions/{id}/fs:search, forcing the client to abuse the {session_id} slot to carry a workspace reference, and to keep a session id around for ordinary searches. This branch makes session-less workspace search first-class and carries the stacked engine work it builds on:

  1. There was no POST /api/v1/workspace/fs:search; draft @ mentions had to borrow the session route's {session_id} slot, and kimi-web could not search files without a session id.
  2. workspaceHandler was misnamed: the Workspace-scope service owns session create/resume/fork/close, so sessionLifecycle matches its role (reviving the name of the deleted App-scope domain).
  3. minidb text-index rebuilds hard-blocked the host process on large indexes.
  4. An unbound main agent reported the wire model's zero thinking value (off) instead of an empty level, so new sessions briefly showed a stale thinking level (e.g. Max).

What changed

1. Session-less workspace file search (7cfa0692a, 848713317)

  • New route POST /api/v1/workspace/fs:search: the request body is the engine's fs-search request plus a workspace field (registered workspace id or absolute root, registered on the spot), resolved to the same Workspace-scope fs service a session would resolve to. Unknown refs map to 40410 workspace.not_found; the response shape matches the session route's fs:search.
  • kimi-web's @ mention now always calls this route with the workspace ref — the active session's workspace, or the draft's active workspace — so no session id is involved anywhere.
  • The session route's draft fallback (workspace ref in the {session_id} slot, introduced in 7cfa0692a) stays for wire compatibility.
  • Tests: route coverage in packages/kap-server/test/fs.test.ts (registered id, absolute root, empty query listing, unknown ref, missing field), the API-surface snapshot gains the route, and the file's temp-dir cleanup follows the repo's retry pattern for the async query-store shard writer.

2. refactor(agent-core-v2): rename workspaceHandler → sessionLifecycle (7c0a93b0c)

  • Pure rename of the Workspace-scope session-lifecycle domain and its service (IWorkspaceHandlerServiceISessionLifecycleService) across the engine, kap-server, klient, kimi-inspect, kimi-code, and the agent-dev docs/skills. No behavior change.

3. perf(minidb): async, non-blocking text index rebuilds (91e133b88)

  • TextIndex.build() yields to the event loop during tokenization and batches postings writes; writes landing mid-build are queued and replayed onto the new base at swap time; open-time compaction runs in the background; the postings rebuild is skipped when the write buffer is clean.
  • Known issue: the now-async shard writes can outlive test teardown in kap-server's suite, surfacing as flaky ENOTEMPTY temp-dir cleanup errors (pre-existing on this branch, unrelated to theme 1).

4. fix(agent-core-v2): empty thinking level for unbound main agent (ff57f5fa0)

  • sessionLegacyService.status returns an empty thinking_level when the main agent has no bound model, so clients fall back to the catalog default; ships web changesets for the draft @ mention and the new-session thinking level.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

…sions

- fs:search accepts a workspace id or absolute root in the session_id slot
  so the @ file mention works before the session exists
- kimi-web searchFiles falls back to the active workspace id in draft state
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 8ee2a8f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 31, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@8ee2a8f
npx https://pkg.pr.new/@moonshot-ai/kimi-code@8ee2a8f

commit: 8ee2a8f

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7cfa0692a8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

async function searchFiles(query: string): Promise<Array<{ path: string; name: string }>> {
const sid = rawState.activeSessionId;
if (!sid) return [];
const id = rawState.activeSessionId ?? rawState.activeWorkspaceId;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use resolved active workspace for draft file search

In the no-session draft path, the UI uses client.activeWorkspaceId.value, whose computed fallback returns the first visible workspace when rawState.activeWorkspaceId is unset or stale. This line reads only the raw field, so after loading a registered workspace with no persisted selection/session (or after a stale persisted id), the composer can submit to a workspace but @ autocomplete still returns [] or queries the wrong id. Please pass the same resolved active workspace into this composable or fall back to workspacesView.value[0]?.id.

Useful? React with 👍 / 👎.

Comment on lines +203 to +205
const workspaceFs =
session === undefined && fsAction === 'search'
? await resolveWorkspaceFs(core, session_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Map workspace-resolution failures for draft search

For fs:search with a registered workspace id whose root was removed or became unreadable, handlerFor can throw while materializing the workspace through createOrTouch. Because this fallback resolution runs before the switch's try/catch, those errors bypass sendMappedError and hit the global handler as 50001 instead of the declared filesystem/session envelope, turning a stale workspace entry into an internal-error response. Move this resolution inside the mapped-error try or catch it here.

Useful? React with 👍 / 👎.

sailist added 4 commits July 31, 2026 10:49
- sessionLegacyService.status returns thinking_level '' when the main
  agent has no bound model (mirroring model: undefined), so clients
  fall back to the catalog default instead of folding in the wire
  model's 'off' zero value
- add regression test for a never-bound main agent status
- add web changesets: draft @ file mention, new-session thinking level
- TextIndex.build() yields to the event loop during tokenization and
  batches postings writes (~1 MiB), so large rebuilds no longer
  hard-block the host process
- writes landing mid-build are queued and replayed onto the new base at
  swap time, keeping the rebuilt index exact
- PostingsFile.rebuildSync renamed to async rebuild with a synchronous
  commit section (beforeRename hook + atomic rename)
- onCompacted hook is now awaited (sync or async); open-time compaction
  runs in the background so open() returns without blocking on the
  snapshot rewrite and postings rebuild
- compaction skips the postings rebuild when the index's write buffer is
  clean (needsRebuild)
- createTextIndex registers before building so concurrent writes feed
  the build queue; dropTextIndex throws while a build is in flight
- rename IWorkspaceHandlerService to ISessionLifecycleService and move
  src/workspace/workspaceHandler/ to src/workspace/sessionLifecycle/;
  update all consumers (gateway, sessionExport, sessionLegacy,
  sessionLookup, kap-server, klient, node-sdk, kimi-inspect, kimi-code)
- rename IStateService to IAppStateService and add the Workspace-scope
  IWorkspaceStateService, so the state domain spans all four scope tiers
- add cascading StateRegistry.inspect(): each tier injects the parent
  tier's registry and folds App to current scope into one StateInspection
  tree; check-domain-layers gains a Rule 2b exemption for state-on-state
  imports
Carry the workspace reference (registered id or absolute root) in the
request body and resolve it to the same Workspace-scope fs service the
session route uses, so clients no longer borrow the session route's
{session_id} slot. kimi-web's @ file mention now calls this route with
the workspace ref instead of a session id; the session-route fallback
stays for wire compatibility.
@sailist sailist changed the title feat(kap-server): let fs:search resolve a workspace ref for draft sessions feat(kap-server): add session-less POST /workspace/fs:search route Jul 31, 2026
…IWorkspaceStateService

- move workspaceDirs / workspaceInstructions / workspaceSkillCatalog / workspaceTrust
  runtime state from bare instance fields into the workspace state container
- extend gen-state-manifest.mts to scan app/workspace scopes, emitting
  AppStateSnapshot / WorkspaceStateSnapshot alongside Session/Agent
- regenerate docs/state-manifest.d.ts and update AGENTS.md + agent-core-dev skill
- update affected tests to register the state services and assert the new state keys
@sailist
sailist merged commit ed7a4cc into MoonshotAI:main Jul 31, 2026
14 checks passed
@github-actions github-actions Bot mentioned this pull request Jul 31, 2026
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.

1 participant