Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ macOS/Linux arm64 与 x64 缺少二进制时,OpenPI 会从官方 Release 下

Plan 模式下需先退出规划,再通过 `/openpi-setup` 修改配置。Web 设置页会禁用相关修改入口,并在会话空闲时提供退出按钮;退出仅切换状态,不调用模型或开始实施。Setup 在接收命令和投递排队请求时都检查当前 Session 的 Plan 状态。设置页依据实际工具回执反馈保存、设置未变化、失败或取消;回合结束或模型声称成功都不能替代保存回执。

工作区清理保护默认使用 `enforce`;可用 `/openpi-setup 不透明清理命令走确认` 切换为 `ask`,或选择 `off` 关闭。

Web 侧栏支持独立置顶会话分区。行内图钉可置顶或取消,置顶区菜单切换最近更新和手动排序;手动模式支持拖动以及会话菜单上移/下移。`ui.webPinnedSort` 默认为 `manual`,可选 `updated`,由 `/openpi-setup` 或置顶区菜单保存。置顶顺序保存在当前 Web 会话目录的工作区元数据中;归档暂时隐藏置顶,恢复后保留顺序。

会话行右侧只保留三种提示:执行中的转圈、已完成未读的小圆点、需要处理的提示。等待输入和失败共用需要处理标记,悬停或打开会话可查看具体原因;停止和未知结果恢复普通行。断线时收起执行动画,由页面连接状态统一提示,绝不当作完成。打开会话并在可见页面停留四秒后,完成圆点在当前浏览器标签页内记为已读;后台完成回执在当前 Host 生命周期内保留,不将已释放运行实例误报为空闲。
Expand All @@ -466,7 +468,7 @@ Web 侧栏宽度默认 280px(220–420px),工具面板宽度默认 520px

Web 常规设置提供 Subagent、Bash 和 Write/Edit 的完整/紧凑显示控件,直接保存已有 `ui.subagentResultDisplay`、`ui.bashToolDisplay`、`ui.fileMutationDisplay`,并用于 Web 的结果与执行过程默认展开。Pi 终端页脚开关和样式保存已有 `ui.customFooter` / `ui.footerStyle`,仅影响 Pi 终端页脚。能力发现、工作流上限、下一步建议及编辑后命令的控件通过 `/openpi-setup` 修改,以实际写入回执为准。

<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls childExecutions childExecutions.maxActive ui.webTheme ui.webChatWidth ui.webSidebarWidth ui.webAuxiliaryWidth ui.webChatFontSize ui.webExpandThinking ui.webPinnedSort ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
<!-- config-contract: workspaceCleanupGuard capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls childExecutions childExecutions.maxActive ui.webTheme ui.webChatWidth ui.webSidebarWidth ui.webAuxiliaryWidth ui.webChatFontSize ui.webExpandThinking ui.webPinnedSort ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->

Web 保存终端页脚偏好不会重新配置另一份已打开的 Pi 界面;该界面在下次 Session 启动或原生 setup 应用时更新页脚。

Expand Down Expand Up @@ -498,6 +500,7 @@ Footer 布局以 `footerLines` 作为唯一持久化格式。旧版 `footerItems

| 配置 | 默认值 |
| ---------------------------- | ---------------------------------------------- |
| Workspace cleanup guard | `enforce`;另有 `ask` / `off` |
| Capability discovery | `explicit`;`adaptive` 必须显式开启 |
| Next-action Suggestion | 关闭;启用时显式选择 Registry 模型与 reasoning |
| Workflow 并发 / 总调用 | 8 / 128;硬上限 64 / 1024 |
Expand Down
4 changes: 3 additions & 1 deletion SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Exit Plan mode before starting `/openpi-setup`, including from Web settings. The

## Configure this package

The workspace cleanup guard defaults to `enforce`: it blocks deletion commands whose targets OpenPI cannot verify. Set `workspace_cleanup_guard=ask` to confirm those opaque commands through Pi's existing confirmation UI, or `off` to disable this guard. Known pre-existing literal paths continue to use the existing deletion confirmation in both `enforce` and `ask` modes; change the mode with `/openpi-setup`.

Web appearance controls directly save only their presentation fields; their success status is based on the completed write. Other package-owned settings forms submit requests through `/openpi-setup`. Role/model choices, concurrency, skill and plugin configuration requests remain visible in that episode, including required confirmation and its final apply/closure receipt. A setup submission message is not proof of persistence. Pi-owned model definitions and credentials have separate direct forms backed by Pi's `models.json` and native login API; secrets never enter the setup prompt.

Web shows the original setup command and its results, including failed or unapplied requests, rather than hiding the configuration episode. Appearance controls wait for the current run to settle before accepting another change. Chat-width and font-size reset buttons request the existing defaults through the same setup entry point. The model tree selects the editable Pi definition and retains unsaved drafts within the same Session; narrow screens use a labeled settings-section selector.
Expand Down Expand Up @@ -103,7 +105,7 @@ Web pinned conversations have a separate collapsible section above Workspaces. U

Web sidebar width defaults to 280px (220–420px); tool pane width defaults to 520px (360–720px). Dragging or keyboard resizing saves `ui.webSidebarWidth` / `ui.webAuxiliaryWidth` through the shared appearance writer. Reload restores the preferred widths; a small viewport clamps only their visible sizes. `/openpi-setup` exposes the same choices as `ui_web_sidebar_width` and `ui_web_auxiliary_width`.

<!-- config-contract: capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls childExecutions childExecutions.maxActive ui.webTheme ui.webChatWidth ui.webSidebarWidth ui.webAuxiliaryWidth ui.webChatFontSize ui.webExpandThinking ui.webPinnedSort ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->
<!-- config-contract: workspaceCleanupGuard capabilities.discovery suggestions.enabled suggestions.model workflows.concurrency workflows.maxAgentCalls childExecutions childExecutions.maxActive ui.webTheme ui.webChatWidth ui.webSidebarWidth ui.webAuxiliaryWidth ui.webChatFontSize ui.webExpandThinking ui.webPinnedSort ui.showHeader ui.customFooter ui.footerStyle ui.footerLines ui.subagentResultDisplay ui.bashToolDisplay ui.fileMutationDisplay postEdit.command subagents.roleModels -->

Web model configuration can query an explicitly supplied provider connection, search its model catalog and add up to 100 selected models in one revision-checked native `models.json` write. Existing model metadata and credentials are preserved. Discovery uses Pi credentials only for the matching saved endpoint, or an optional temporary key that is not persisted. Catalog queries are bounded to ten seconds, 1 MiB and 500 models, reject redirects, and never send prompts. New models inherit the form's context/output and reasoning defaults; verify these in advanced parameters. Manual configuration remains available when the catalog is unsupported. No additional OpenPI preference is introduced.

Expand Down
22 changes: 18 additions & 4 deletions extensions/setup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
POST_EDIT_COMMAND_MAX_CHARS,
REASONING_LEVELS,
SETUP_CONFIG_CHANGED_CHANNEL,
type WorkspaceCleanupGuardMode,
WORKSPACE_CLEANUP_GUARD_MODES,
updateSetupConfig,
WEB_THEMES,
type WebTheme,
Expand Down Expand Up @@ -154,12 +156,12 @@ export function buildInteractiveSetupPrompt(options: {
}) {
const configurationState = options.savedConfigExists
? [
"This package has already been configured. Explain the current settings in the user's language, then ask whether they want to keep them or change Capability discovery, Next-action suggestions, Workflow limits, OpenPI Web appearance, UI/Footer, result detail display, Post-edit, Agent role models, or review everything.",
"This package has already been configured. Explain the current settings in the user's language, then ask whether they want to keep them or change Workspace cleanup guard, Capability discovery, Next-action suggestions, Workflow limits, OpenPI Web appearance, UI/Footer, result detail display, Post-edit, Agent role models, or review everything.",
"If the user keeps the current settings, do not call configure_my_pi_setup. If they choose a category, ask only the follow-up needed for that category.",
]
: [
"This is the first setup. Explain the available choices and their impact in the user's language, then collect the initial preferences.",
"Prefer one ask_user call with up to three independent questions covering Capability discovery plus Workflow limits, Next-action suggestions, and UI/Footer/result display. Explain that Post-edit defaults off; keep it off unless the user opts in, then ask only for the command. Explain that built-in Agent roles used by subagent_spawn and workflow agent_type inherit the parent model unless the user assigns an available model to a role.",
"Prefer one ask_user call with up to three independent questions covering Workspace cleanup guard plus Capability discovery, Workflow limits, Next-action suggestions, and UI/Footer/result display. Explain that Post-edit defaults off; keep it off unless the user opts in, then ask only for the command. Explain that built-in Agent roles used by subagent_spawn and workflow agent_type inherit the parent model unless the user assigns an available model to a role.",
];

return [
Expand All @@ -176,6 +178,7 @@ export function buildInteractiveSetupPrompt(options: {
...configurationState,
"",
"Before asking, briefly explain what can be configured and the practical impact:",
"- Workspace cleanup guard: enforce (default) blocks deletion commands whose targets OpenPI cannot verify; ask uses the existing confirmation for those opaque commands; off disables this guard. Known pre-existing literal paths still use the normal confirmation in enforce and ask modes.",
"- Capability discovery: explicit is the safe default and keeps OpenPI model tools absent until the user asks for a capability. adaptive is opt-in and keeps only the small openpi_load_tools gateway visible, allowing the model to load Subagents, Workflows, background terminals, structured search, or Session tracking when it judges them useful. Loaded groups remain session-stable, and normal permission, concurrency, and workflow limits still apply.",
"- Next-action suggestions: disabled, or model-generated after a fully settled main-agent run. A suggestion appears as dim inline text on the first row of an empty editor; reserved cells at the row end keep CJK IME preedit from overwriting it. Right accepts it without submitting, and any other editor input dismisses it. Enabling requires an available provider/model and reasoning level and adds one small model call per settled run.",
"- Workflow fan-out: concurrency controls simultaneous agents and resource pressure; max agent calls controls the total capacity of one workflow. Valid ranges are 1-64 and 1-1024.",
Expand All @@ -188,6 +191,7 @@ export function buildInteractiveSetupPrompt(options: {
"Natural-language configuration examples the user might ask for:",
'- "let the model discover OpenPI capabilities when useful" → capability_discovery=adaptive',
'- "only use OpenPI capabilities when I ask" → capability_discovery=explicit',
'- "ask before allowing opaque workspace cleanup" → workspace_cleanup_guard=ask',
'- "use dark theme in OpenPI Web" → ui_web_theme=dark',
'- "set OpenPI Web chat width to 960px" → ui_web_chat_width=960',
`- Web sidebar width defaults to ${DEFAULT_WEB_SIDEBAR_WIDTH}px (${MIN_WEB_SIDEBAR_WIDTH}-${MAX_WEB_SIDEBAR_WIDTH}); tool pane width defaults to ${DEFAULT_WEB_AUXILIARY_WIDTH}px (${MIN_WEB_AUXILIARY_WIDTH}-${MAX_WEB_AUXILIARY_WIDTH}). Dragging a pane saves the same canonical preferences; small viewports temporarily clamp the visible width.`,
Expand Down Expand Up @@ -458,8 +462,14 @@ export default function openPiSetup(pi: ExtensionAPI) {
name: "configure_my_pi_setup",
label: "Configure OpenPI",
description:
"Apply a user-requested configuration change for this Pi setup. Configures capability discovery (explicit or opt-in adaptive), next-action suggestions, workflow fan-out, canonical OpenPI Web appearance (theme, chat width, font size, thinking expansion), UI/Footer (presets, style, multi-line layout), result detail display, optional Post-edit, and built-in Agent-role model assignments shared by subagent_spawn and workflow agent_type. Role models must be available in the Pi registry; null clears a role back to parent-model inheritance. Footer examples: powerline preset, powerline-mono, compact, or custom ui_footer_lines with flex. Preserve current values for settings the user did not ask to change. Changes apply immediately to the capability gateway and active TUI footer; Web observes appearance changes through canonical snapshots.",
"Apply a user-requested configuration change for this Pi setup. Configures the workspace cleanup guard, capability discovery (explicit or opt-in adaptive), next-action suggestions, workflow fan-out, canonical OpenPI Web appearance (theme, chat width, font size, thinking expansion), UI/Footer (presets, style, multi-line layout), result detail display, optional Post-edit, and built-in Agent-role model assignments shared by subagent_spawn and workflow agent_type. Role models must be available in the Pi registry; null clears a role back to parent-model inheritance. Footer examples: powerline preset, powerline-mono, compact, or custom ui_footer_lines with flex. Preserve current values for settings the user did not ask to change. Changes apply immediately to the active session.",
parameters: Type.Object({
workspace_cleanup_guard: Type.Optional(
StringEnum(WORKSPACE_CLEANUP_GUARD_MODES, {
description:
"Workspace cleanup guard mode: enforce (default) blocks opaque deletion commands, ask opens confirmation for opaque commands, and off skips the guard. Known pre-existing literal paths still use the normal confirmation in enforce and ask. Omit to preserve the current value.",
}),
),
capability_discovery: Type.Optional(
StringEnum(CAPABILITY_DISCOVERY_MODES, {
description:
Expand Down Expand Up @@ -694,6 +704,10 @@ export default function openPiSetup(pi: ExtensionAPI) {
);

const config: MyPiSetupConfig = {
workspaceCleanupGuard:
(params.workspace_cleanup_guard as
| WorkspaceCleanupGuardMode
| undefined) ?? current.workspaceCleanupGuard,
capabilities: {
discovery:
(params.capability_discovery as
Expand Down Expand Up @@ -824,7 +838,7 @@ export default function openPiSetup(pi: ExtensionAPI) {
EXPLICIT_VALUE_GUIDANCE,
FOOTER_PRESET_GUIDANCE,
"",
"Capability discovery is explicit by default; adaptive is an opt-in that keeps only openpi_load_tools visible so the model may load useful groups. Footer tips: presets are powerline, powerline-mono, compact; style is plain/powerline/powerline-mono; custom layouts use ui_footer_lines (2D enum arrays with optional flex). Do not use ui_footer_items together with ui_footer_lines. Built-in Agent role models (explorer, implementer, reviewer, advisor) are shared by subagent_spawn and workflow agent_type; they inherit the parent unless assigned an available registry model, and clearing an assignment restores inheritance. Custom agent-type files still override built-in role definitions. A Nerd Font renders Footer Codicons and powerline seams as designed; text stays readable without it. Changes apply immediately in the active TUI session.",
"Workspace cleanup guard defaults to enforce; ask confirms opaque cleanup commands, and off disables the guard. Capability discovery is explicit by default; adaptive is an opt-in that keeps only openpi_load_tools visible so the model may load useful groups. Footer tips: presets are powerline, powerline-mono, compact; style is plain/powerline/powerline-mono; custom layouts use ui_footer_lines (2D enum arrays with optional flex). Do not use ui_footer_items together with ui_footer_lines. Built-in Agent role models (explorer, implementer, reviewer, advisor) are shared by subagent_spawn and workflow agent_type; they inherit the parent unless assigned an available registry model, and clearing an assignment restores inheritance. Custom agent-type files still override built-in role definitions. A Nerd Font renders Footer Codicons and powerline seams as designed; text stays readable without it. Changes apply immediately in the active TUI session.",
"",
"configure_my_pi_setup is available only for this setup run. If the run settles without a successful apply, the writer is hidden and a later change requires /openpi-setup <request>. Use configure_my_pi_setup to apply only the requested OpenPI-owned changes and preserve everything else. Interpret model names from the available Pi registry. Do not edit configuration files directly.",
SETUP_REQUEST_VALIDATION,
Expand Down
13 changes: 13 additions & 0 deletions extensions/shared/setup-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ export const CAPABILITY_DISCOVERY_MODES = ["explicit", "adaptive"] as const;
export type CapabilityDiscoveryMode =
(typeof CAPABILITY_DISCOVERY_MODES)[number];

export const WORKSPACE_CLEANUP_GUARD_MODES = ["enforce", "ask", "off"] as const;
export type WorkspaceCleanupGuardMode =
(typeof WORKSPACE_CLEANUP_GUARD_MODES)[number];

/** Canonical default layout: one-line plain footer with flex alignment. */
export const DEFAULT_FOOTER_LINES: FooterLines = [
["model", "context", "flex", "git", "pr", "cwd"],
Expand Down Expand Up @@ -165,6 +169,7 @@ export const POST_EDIT_COMMAND_MAX_CHARS = 500;
export const SETUP_CONFIG_CHANGED_CHANNEL = "my-pi-setup:config-changed";

export interface MyPiSetupConfig {
readonly workspaceCleanupGuard: WorkspaceCleanupGuardMode;
readonly capabilities: {
readonly discovery: CapabilityDiscoveryMode;
};
Expand Down Expand Up @@ -211,6 +216,7 @@ export interface MyPiSetupConfig {
}

export const DEFAULT_SETUP_CONFIG: MyPiSetupConfig = {
workspaceCleanupGuard: "enforce",
capabilities: { discovery: "explicit" },
suggestions: { enabled: false },
workflows: {
Expand Down Expand Up @@ -541,6 +547,11 @@ export function parseSetupConfig(value: unknown): MyPiSetupConfig {
const subagents = isRecord(value.subagents) ? value.subagents : {};
const footer = parseUiFooter(ui);
return {
workspaceCleanupGuard: WORKSPACE_CLEANUP_GUARD_MODES.includes(
value.workspaceCleanupGuard as WorkspaceCleanupGuardMode,
)
? (value.workspaceCleanupGuard as WorkspaceCleanupGuardMode)
: "enforce",
capabilities: {
discovery: isCapabilityDiscoveryMode(capabilities.discovery)
? capabilities.discovery
Expand Down Expand Up @@ -665,6 +676,7 @@ const modelShape = {
const suggestionShape = { enabled: booleanValue, model: modelShape };
const setupShape: ConfigShape = {
configVersion: (value) => value === SETUP_CONFIG_VERSION,
workspaceCleanupGuard: oneOf(WORKSPACE_CLEANUP_GUARD_MODES),
capabilities: { discovery: isCapabilityDiscoveryMode },
suggestions: suggestionShape,
summaries: suggestionShape,
Expand Down Expand Up @@ -1409,6 +1421,7 @@ export function formatSetupConfig(config = loadSetupConfig()) {
? `on · ${config.ui.footerStyle} · ${formatFooterLines(config.ui.footerLines)}`
: "off";
return [
`Workspace cleanup guard: ${config.workspaceCleanupGuard}`,
`Capability discovery: ${config.capabilities.discovery}`,
suggestions,
`Workflows: ${config.workflows.concurrency} concurrent agents · ${config.workflows.maxAgentCalls} total calls`,
Expand Down
Loading
Loading