feat: sidebar_open tool gates model-driven sidebar opens behind a global setting
New global Side card setting `agentOpenTools` (default off, 常规 group): when enabled, one `sidebar_open` tool is injected into the model so it can actively open a local file, a local folder (tree rooted there), or an HTTP(S) page in the calling session's sidebar. - host: AgentOpenRegistry + registerOpenTool (src/agent-opens.ts); the tool classifies http(s) URLs / stat-driven file/folder paths, refuses other schemes, resolves relative paths against the session cwd, and reports target-tab-disabled instead of silently no-oping. Gated like agentTerminalTools (register/drain on settings watch). - delivery: /sidebar/ws/agent-opens push (consume-on-send queue, replay on attach); the tool result reports `delivered` so queued opens for non-active sessions are honest. - client: Sidebar subscribes and routes pushes to editor (file), folder window (meta.dir, tree rooted at the folder — EditorHost), or browser (URL) tabs; settings row in 常规 + 20 locale dictionaries. - tests: agent-opens registry/tool spec, smoke gating + WS route list, prefs/plugin-shape defaults, editor-host folder window, side-card rows. - docs: design doc, AGENTS.md key lists + reference, README feature bullets.
This commit is contained in:
@@ -293,4 +293,31 @@ describe('EditorHost (files window)', () => {
|
||||
unmount()
|
||||
}
|
||||
})
|
||||
|
||||
it('a folder tab (meta.dir) renders the tree rooted at the folder, no editor chrome', () => {
|
||||
const { store, ctx } = setup()
|
||||
ctx.betterSidebar!.openTab({
|
||||
type: 'editor',
|
||||
title: 'src',
|
||||
path: '/work/src',
|
||||
id: 'editor:/work/src',
|
||||
meta: { dir: true },
|
||||
}, { sessionId: 'editor-home-session' })
|
||||
const dirTab = (): SidebarTab =>
|
||||
allLeaves(store.getSnapshot().state!.splits).flatMap(leaf => leaf.tabs)
|
||||
.find(tab => tab.path === '/work/src')!
|
||||
const { container, unmount } = mountHost(ctx, store, dirTab)
|
||||
try {
|
||||
const html = container.innerHTML
|
||||
// The folder window is the full tree surface: the folder basename is
|
||||
// the tree root row and the search box is present; the editor empty
|
||||
// hint and the file path input are NOT.
|
||||
expect(html).toContain('src')
|
||||
expect(html).toContain('Search files by name…')
|
||||
expect(html).not.toContain('Pick a file from the tree panel')
|
||||
expect(html).not.toContain('File path (relative')
|
||||
} finally {
|
||||
unmount()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user