feat: agent ability to focus a page in the editor (PRD-7183)#385
Merged
Conversation
* docs(spec): PRD-7183 agent ability to focus a page in the editor Rationalize how the OK editor is exposed to agents for "focus page N" across hosts. Two worlds: pane/browser agent apps (Cursor, Codex Desktop, Claude Code Desktop) focus in-app via their own host tool + preview_url; no-pane hosts (Claude CLI, OK Desktop built-in terminal) focus the OK Desktop window via ok open. Surviving scope: reliable window foreground (app.focus steal), ok open -> world-aware selector reusing existing IPC, per-host SKILL.md guidance. Zero new MCP tools. CC1 focus channel cut to Future Work (auto-follow). Grounded + cold-reader audited. * feat(desktop): reliably foreground the editor window on agent focus (PRD-7183) When an agent focuses a page and the project window already exists, OK only called BrowserWindow.focus() — which on macOS reorders within the app but does not pull a backgrounded app to the front (electron/electron#19920). So an agent-driven "focus this page" silently left OpenKnowledge behind the user's current app unless the focus happened to ride the openknowledge:// + LaunchServices path (which activates the bundle as a side effect). Add a single bringToFront() recipe — restore -> show -> moveTop -> focus + app.focus({steal:true}) — used by every focus-an-existing-window path (deep-link warm path + createProjectWindow + ephemeral dedup). Skip the app-level steal when the window is already frontmost (e.g. the OK Desktop built-in terminal focusing a doc in its own active window). app.focus is injected via WindowManagerDeps.activateApp (macOS-guarded in index.ts) so the manager stays Electron-free for tests. SKILL.md: note that ok open from the OK Desktop built-in terminal re-targets the same window. Per-host focus guidance (W1 in-app, W2 ok open) was already present. Spec: specs/2026-06-26-agent-editor-page-focus. Zero new MCP tools; CC1 focus channel deferred to Future Work (auto-follow). Window foreground is unit-tested; true OS foreground is a packaged-build smoke check (OQ7). * feat(desktop+skill): make CLI agents reliably ok-open into the app (PRD-7183) Two seams from real OK Desktop built-in-terminal usage: 1. The embedded terminal gave an agent no signal it was running inside OK Desktop, so it guessed preview_url (the browser path) and had to be corrected repeatedly. Fix: buildShellEnv now exports OK_DESKTOP_TERMINAL=1 so the agent can detect it and `ok open <doc>` re-targets the same window. 2. Skill guidance under-named the CLI track. Reframe it around capability, not vendor: ANY CLI with no in-app browser (Claude Code CLI, Codex CLI, Cursor CLI, any pure shell agent) uses `ok open <doc>`, never a preview URL. Apps with a pane/browser (Claude Code Desktop, Cursor, Codex desktop) navigate their own. Stated up-front in the core TL;DR and in references/preview.md so the agent leads with the right path. No code beyond the one env marker; the rest is skill clarity. Tests: pty-host marker assertions; skill bundles recompose clean. * feat(cli): ok open works for docs, folders, and skills — no --folder needed (PRD-7183) Make `ok open <name>` consistent across content types and deep-link them all into OK Desktop (browser-UI fallback), instead of docs-to-app / folders-to-browser. - Auto-detect doc vs folder by stat'ing <name> against the project (directory → folder, else doc), so `--folder` is no longer required (kept as an explicit override for a not-yet-created folder). - Folders now deep-link to the app: openknowledge://open gains a `folder=` param. parseOpenKnowledgeUrl returns a {kind:'doc'|'folder'} discriminator (same traversal/null-byte validation for both); routeUrl threads parsed.kind to the existing kind-aware deep-link payload + pendingDeepLinkTarget. Renderer + check-target-exists already handled 'folder' (share flow), so no renderer change. - Skills: `ok open <name> --skill [--scope project|global]` opens the skill editor. A skill rides the existing doc= param as the synthetic __skill__/<scope>/<name> docName (resolves via docNameFromHash as an editor tab) — zero new scheme plumbing. Assets deliberately excluded: split-brained target (viewer route vs OS shell-open) with a disproportionate desktop delta. - export encodeSkillRoute from the server package index (single source of truth). - Skill guidance + `ok open --help` updated to be explicit: doc/folder auto-detected, --skill for skills, all deep-link into the app. Tests: open.test (auto-detect, folder deep-link, skill desktop+browser, bad scope); url-scheme parser folder= cases + both/neither rejection + traversal. * feat(mcp): preview_url steers to `ok open` when in the OK Desktop terminal (PRD-7183) Skill prose alone wasn't getting agents in OK Desktop's built-in terminal to use `ok open` — they kept reaching for preview_url + a browser. Add a runtime nudge that fires at the wrong call: when preview_url runs in the OK Desktop terminal, its response leads with `run \`ok open <target>\` … don't navigate the URL`. Detection needs no carrier: `ok mcp` (bare, no --port) runs in global-server mode (server.ts → registerAllTools), so preview_url executes IN the `ok mcp` process — which inherited `OK_DESKTOP_TERMINAL=1` from the terminal pty. server.ts passes `isDesktopTerminal: process.env.OK_DESKTOP_TERMINAL === '1'` into registerAllTools → preview_url. The shared collab server (`ok start`) never has the marker, so it passes false and is unaffected; Cursor/Codex/plain-CLI processes don't have it either, so they're unchanged (they correctly drive their own browser/pane). Steer only fires for an in-project doc/folder/skill target (root + the off-cwd `file` branch are untouched). Tests cover doc/folder/skill-global steers, the no-target no-steer case, and the not-a-desktop-terminal regression. * fix(cli): address PR #2269 review — skill name validation + steer test/structured gaps - Move the `isUnsafeName` traversal guard ABOVE the `--skill` branch so skill names get the same `..`/leading-slash/backslash rejection as docs and folders (pullfrog + claude: the skill branch returned before the check). Defense-in- depth — the desktop parser already rejects `..` — but keeps CLI-layer validation symmetric and avoids a false-success. - Surface the steer command as `okOpenCommand` in preview_url's structuredContent (nullable/optional; non-null only in the OK Desktop terminal with a target) so agents can consume it programmatically, not just parse the text body. - Tests: skill no-target → error (symmetry with doc/folder); skill traversal rejection; default-scope skill steer (`ok open <name> --skill`, no --scope); okOpenCommand assertions incl. the not-a-terminal null case. * fix: address PR #2269 re-review — shell-quote steer, dedupe scopes, fill steer tests - okOpenCommand now shell-quotes doc/folder paths containing spaces/specials (`shellQuoteArg`); clean slug paths pass through unquoted; skill names are already [a-z0-9-] so they're untouched. The field is documented "the exact command to run", so it must be shell-safe. - Replace local SKILL_SCOPES with core's canonical MANAGED_ARTIFACT_SCOPES (single source of truth; cli already deps on core). - Tests: folder steer asserts structuredContent.okOpenCommand; desktop-terminal + no-UI keeps the steer + okOpenCommand (ok open doesn't need the UI); space-containing doc → quoted okOpenCommand. * fix: address PR #2269 3rd review — narrow stat catches + edge-case steer tests - classifyName (open.ts) + isFileishTarget (single-file-dispatch.ts): narrow the bare statSync catch — ENOENT/ENOTDIR is the expected "doesn't resolve" case (silent fallthrough); any other code (EACCES/ELOOP/…) logs to stderr so a misclassification is diagnosable, mirroring the isServerLive pattern. - Tests: shellQuoteArg embedded single-quote POSIX escape (`what's new` → `'…what'\''s new'`); no-UI + folder + desktop-terminal okOpenCommand. --------- GitOrigin-RevId: c73dfbf00ceead6b09979cbbadf07c568191ee7c
Contributor
There was a problem hiding this comment.
Automated approval from agents-private public-mirror-sync (run: https://github.com/inkeep/agents-private/actions/runs/28413855696). Source of truth is the monorepo; direct edits on inkeep/open-knowledge are overwritten on next sync.
|
|
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.