Skip to content

feat(plugins): follow the selected session and reveal work-panel views - #1745

Merged
vastsa merged 3 commits into
mainfrom
feat/plugin-session-context
Oct 18, 2026
Merged

vastsa merged 3 commits into
mainfrom
feat/plugin-session-context

Conversation

@vastsa

@vastsa vastsa commented Oct 18, 2026

Copy link
Copy Markdown
Owner

背景

插件中心拒了 local.diff-view-1.4.16.piplug:renderer/index.mjs:466: dynamic or remote code execution: dynamic module loading。作者为了跟随当前会话、识别运行中任务、跳转右侧工作面板,只能动态 import 宿主内部模块。

宿主内部其实都有:渲染器掌握选中会话,主进程掌握 activeTurns,工作面板按会话维护标签页。缺的只是公开契约,session:activated 也一直停在规格的「计划中」。

变更

  • 新增 pi.session.getActive() 与 session:activated 事件,载荷 { sessionId, projectPath, activeTurn: { turnId, startedAt } | null },不需要新权限(与 workspace.get 同级)。
  • 快照由两方合成:渲染器推送选中项与项目路径,主进程用 recordTurnStart 这个已有接缝为回合打时间戳,并在发布前用 activeTurns 校验 turn id;没有收到结束通知的回合会自然过期,不会留下假的「运行中」。
  • 新增 pi.ui.revealView({ viewId?, location?, sessionId? })(ui.view),在指定会话的工作面板里打开插件自己的视图,复用既有 piViewOpen / view:open 位置通道;命名了一个已经离开的会话会以 INVALID_ARGUMENT 拒绝,而不是打开没人看的标签页。
  • 两个能力同时作为面板桥通道暴露,停靠视图读到同一份快照。
  • 未改动宿主协议、持久化数据、manifest schema 与权限列表。

复审后的修正

第一版提交留下的四个语义漏洞已修:项目级插件能读到/跳到别的项目的会话(现在走与视图 IPC 同一套 scope 校验);两次选中推送可能乱序落地并回退到已离开的会话(渲染器带序号,主进程拒绝倒退);独立 ui.panel 窗口收到了它并不属于的会话选中事件(改为只发插件进程与停靠视图);回合开始时间表随会话数无界增长(改为带上限)。

验证

  • tsc -p apps/desktop/tsconfig.json --noEmit 通过
  • packages/{shared,plugin-sdk,racp} vitest 全绿(1272 + 382 + 27)
  • apps/desktop node --test 全量:4102 项,4098 通过。2 项失败与本改动无关:一项缺 apps/desktop/out/renderer/index.html 构建产物;另一项 check-release-docs 在 main 上同样报 0.21.0-beta.3 changelog 缺失
  • 新增测试:apps/desktop/test/plugin-session-follow.test.mjs(快照合成、去重、过期回合/过期会话拒绝、作用域拒绝、ui.view 门禁、面板桥通道、时间表上限)+ main-wiring-contract.test.mjs 线束契约
  • scripts/check-architecture.mjs、check-style-tokens.mjs、check-agent-policy-sync.mjs 通过

文档

  • docs/spec/07-plugins/03-plugin-api.md(含 zh-CN):ui.revealView、会话跟随、事件、面板通道与审计
  • docs/spec/07-plugins/13-plugin-permissions-matrix.md(含 zh-CN)
  • docs/spec/06-delivery/04-e2e-test-plan.md 新增 E2E-267
  • 新增 ADR 0331

未覆盖

告警:交互式 Electron 场景(E2E-267)未在本机执行,verify:ui:* 未运行。

Plugins that follow the conversation had no public way to learn which session
the user is looking at or which turn it is running, so a published diff view
imported host internals from its renderer entry and the packaging check refused
it as dynamic module loading. The host already had every piece; only the
contract was missing.

`pi.session.getActive()` and the `session:activated` event now report the
selected session, its project path, and the live turn with the durable turn id
and its start time. The renderer pushes the selection because it owns it, and
the main process dates the turn from the same seam that records turn identity,
validating every id against the live turn map so a turn that ended without
notice ages out instead of pinning a stale "running" state.

`pi.ui.revealView()` shows one of the plugin's own contributed views in a
session's work panel, reusing the existing location transport, and refuses a
session the user has left instead of opening a tab nobody is watching. Both are
also panel bridge channels, so a docked view reads the same snapshot. No
permission, manifest, persisted-data or host-core protocol changes.
…ches

Review of the first commit found four ways the new surface could still tell a
plugin something the shell did not mean: a project-scoped plugin could read and
reveal the selection of a project it is inactive in, two selection pushes in
flight could land out of order and restore a session the user already left, a
detached panel window received a selection it does not belong to, and the map of
turn start times grew with every session that ever ran.

`session.getActive` and `ui.revealView` now consult the same activation-scope
lookup every view IPC uses, the renderer stamps each push with a counter that
the main process refuses to run backwards, `session:activated` is delivered to
plugin processes and docked views through one fan-out that knows which surfaces
are session-scoped, and the start-time map is capped instead of unbounded.
Copilot AI balanced review requested due to automatic review settings October 18, 2026 06:01

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

The new ADR pointed at two ADR filenames that do not exist, which fails the
VitePress dead-link check and therefore every docs-dependent CI job, and an
earlier edit dropped a stray `ui.revealView` table row into the panel-bridge
prose while removing the chrome-marker sentence beside it. Both are documentation
defects only; the API text is unchanged.
@vastsa
vastsa merged commit f1daa54 into main Oct 18, 2026
9 of 10 checks passed
vastsa pushed a commit that referenced this pull request Oct 20, 2026
…nside scope

Two defects in the #1745 follow feature:

- The out-of-order guard kept a main-side high-water mark over a counter
  the renderer owns in a useRef. A renderer reload (the automatic
  recovery for render-process-gone restarts the counter) left the mark
  stale, so every push afterwards was silently ignored and plugins saw
  the pre-reload session forever (#1753). Pushes now carry a per-load
  boot id; a changed boot id resets the mark, and the out-of-order guard
  still applies within a boot.
- session:activated fanned out to every loaded plugin process and docked
  view without the activation-scope check that session.getActive and
  ui.revealView enforce, so a project-scoped plugin received other
  projects' session identity its pull API refuses to give (#1754). The
  fan-out now scope-filters selection events per recipient, using the
  session's project from the live map and the workspace-relative check
  when the session has none.
@vastsa
vastsa deleted the feat/plugin-session-context branch November 6, 2026 04:24
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