Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,22 @@ export const OverflowText = forwardRef<HTMLElement, OverflowTextProps>(
if (!element || !content) return;

const distance = Math.max(0, content.scrollWidth - element.clientWidth);
const isOverflowing = element.clientWidth > 0 && (distance > 0
|| (element.clientHeight > 0 && element.scrollHeight > element.clientHeight));
// A compact single-line label can have glyph ink extend slightly beyond
// its line box without any text being clipped. Only multiline clamps use
// vertical overflow as a truncation signal; single-line slots are clipped
// exclusively on the inline axis.
const hasVerticalClampOverflow = lines !== undefined
&& element.clientHeight > 0
&& element.scrollHeight > element.clientHeight;
const isOverflowing = element.clientWidth > 0
&& (distance > 0 || hasVerticalClampOverflow);
const current = measurementRef.current;
if (current.distance === distance && current.isOverflowing === isOverflowing) return;

const next = { distance, isOverflowing };
measurementRef.current = next;
setMeasurement(next);
}, []);
}, [lines]);

const prepareTooltip = useCallback(() => {
const element = elementRef.current;
Expand Down
1 change: 1 addition & 0 deletions design-system/packages/ui/tests/overflow-text.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ test("OverflowText measures real clipping for fade and marquee treatments", asyn
]);

assert.match(source, /content\.scrollWidth - element\.clientWidth/);
assert.match(source, /lines !== undefined\s*&& element\.clientHeight > 0\s*&& element\.scrollHeight > element\.clientHeight/s);
assert.match(source, /measurementRef\.current/);
assert.match(
source,
Expand Down
12 changes: 6 additions & 6 deletions docs/interactive-capabilities/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!-- generated by scripts/generate-interactive-capabilities.mjs; do not edit -->
# OpenBitFun 功能与设置目录 / OpenBitFun Features & Settings

OpenBitFun Playbook 当前包含 **22 个功能**和 **21 个设置页**,共 **43 个**用户可理解的条目、**321 项**有源码证据的子能力。每个条目有独立 Markdown,并直接服务于说明书网站、OpenBitFun 全局搜索和 `OpenBitFunControl` Agent 工具。
OpenBitFun Playbook 当前包含 **22 个功能**和 **21 个设置页**,共 **43 个**用户可理解的条目、**322 项**有源码证据的子能力。每个条目有独立 Markdown,并直接服务于说明书网站、OpenBitFun 全局搜索和 `OpenBitFunControl` Agent 工具。

OpenBitFun Playbook currently contains **22 features**, **21 settings pages**, and **321** source-backed sub-capabilities across **43** user-facing entries. Every entry has its own Markdown page and directly powers the website, in-app global search, and the `OpenBitFunControl` agent tool.
OpenBitFun Playbook currently contains **22 features**, **21 settings pages**, and **322** source-backed sub-capabilities across **43** user-facing entries. Every entry has its own Markdown page and directly powers the website, in-app global search, and the `OpenBitFunControl` agent tool.

## 唯一事实源 / Single source of truth

Expand Down Expand Up @@ -33,14 +33,14 @@ Docs, website, search, and agents see only features, settings, and documented su

## 控制边界 / Control boundary

- 每个子能力都明确标记为直接控制、委托给专用 Agent 工具、需交互打开或不支持;“打开页面”不会再被统计成“Agent 已控制”。当前覆盖:直接 **48**、委托 **61**、需交互 **212**、不支持 **0**。
- 每个子能力都明确标记为直接控制、委托给专用 Agent 工具、需交互打开或不支持;“打开页面”不会再被统计成“Agent 已控制”。当前覆盖:直接 **48**、委托 **61**、需交互 **213**、不支持 **0**。
- 稳定行为声明为带 JSON 输入契约的 `operations` 或 `options`,并绑定原生产品控制 Provider;Agent 不接触原始 Tauri Command。
- `OpenBitFunControl list` 和 `search` 都返回带 `nextCursor` 的精简分页结果;目录可持续增长,不靠固定总量上限。完整目录和 321 项子能力都不会写入 system prompt。
- `OpenBitFunControl list` 和 `search` 都返回带 `nextCursor` 的精简分页结果;目录可持续增长,不靠固定总量上限。完整目录和 322 项子能力都不会写入 system prompt。
- 目录发现与契约读取不依赖 React 或可见窗口。普通配置型 option 统一由 Product Assembly 的共享 ConfigService 执行器读、写并回读,因此 Desktop、CLI 与 Headless 表面走同一份实现;只有宿主原生 operation/provider option 和界面导航按表面注册适配器,缺失时必须明确返回不可用,禁止静默回退本机。只读 Agent 只能发现和读取目录。

- Every documented item is classified as direct control, delegated Agent control, interactive opening, or unsupported; opening a page is never counted as direct control. Current coverage is **48 direct**, **61 delegated**, **212 interactive**, and **0 unsupported**.
- Every documented item is classified as direct control, delegated Agent control, interactive opening, or unsupported; opening a page is never counted as direct control. Current coverage is **48 direct**, **61 delegated**, **213 interactive**, and **0 unsupported**.
- Stable behavior becomes a typed `operation` or `option` with a JSON input contract and a native product-control provider. Agents never receive raw Tauri commands.
- `OpenBitFunControl list` and `search` return compact pages with a `nextCursor`; the catalog can grow without a fixed total-size ceiling. Neither the full catalog nor its 321 documented items enters the system prompt.
- `OpenBitFunControl list` and `search` return compact pages with a `nextCursor`; the catalog can grow without a fixed total-size ceiling. Neither the full catalog nor its 322 documented items enters the system prompt.
- Discovery and contract lookup do not depend on React or a visible window. Ordinary config-backed options are read, written, and read back by one Product Assembly ConfigService executor shared by Desktop, CLI, and headless surfaces. Only host-native operations/provider options and presentation routes install surface adapters; missing adapters return explicit unavailability without local fallback. Read-only agents may only discover and inspect entries.

## 防腐化门禁 / Anti-drift gates
Expand Down
94 changes: 87 additions & 7 deletions docs/interactive-capabilities/capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"title": "OpenBitFun Playbook",
"origin": "https://playbook.openbitfun.com",
"source": "src/shared/interactive-capabilities/catalog.json",
"digest": "d7a7419ddd673eb733ae8bd33dbb3dcd3b4d1ce0acfc953067a3403fe26d6699",
"digest": "409e6dbef7ebceafccc11606e2855227b9a33fa1ed71f5b4608da04e8a23de7d",
"ownerDigest": "c0e5c187cf62bc6ed06196ce8520b3eb427bf268cf24659b72d2552fb1d99c54",
"searchAcceptance": [
{
Expand Down Expand Up @@ -138,11 +138,11 @@
"features": 22,
"settings": 21,
"userFacing": 43,
"documentedItems": 321,
"documentedItems": 322,
"controlCoverage": {
"direct": 48,
"delegated": 61,
"interactive": 212,
"interactive": 213,
"unsupported": 0
}
},
Expand Down Expand Up @@ -14816,6 +14816,7 @@
"id": "setting.workspace.session:query",
"capabilityId": "setting.workspace.session",
"itemIds": [
"default-agent-harness",
"automatic-titles",
"title-model",
"accelerated-search",
Expand Down Expand Up @@ -14949,6 +14950,52 @@
"pageId": "workspace.session"
}
},
{
"id": "setting.workspace.session:open:default-agent-harness",
"capabilityId": "setting.workspace.session",
"itemIds": [
"default-agent-harness"
],
"kind": "open",
"risk": "ui",
"executionHost": "presentationSurface",
"availability": {
"desktop": {
"available": true
},
"cli": {
"available": false,
"reason": "This delivery profile has no live presentation surface"
},
"peer": {
"available": true,
"requiredCapabilities": [
"product_control_v1",
"product_control_presentation_v1"
]
},
"remoteControl": {
"available": true
},
"detachedDispatch": {
"available": false,
"reason": "This delivery profile has no live presentation surface"
}
},
"inputSchema": {
"type": "object",
"additionalProperties": false
},
"outputSchema": {
"type": "object",
"additionalProperties": true
},
"openReason": "unstructuredInteraction",
"presentationTarget": {
"kind": "settings",
"pageId": "workspace.session"
}
},
{
"id": "setting.workspace.session:open:title-model",
"capabilityId": "setting.workspace.session",
Expand Down Expand Up @@ -27132,33 +27179,50 @@
"categoryId": "assistant",
"titleZh": "会话与工作区设置",
"titleEn": "Session & workspace settings",
"summaryZh": "控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。",
"summaryEn": "Control session-title generation, accelerated workspace search, and project-context behavior.",
"summaryZh": "控制默认 Agent Harness、会话标题生成、工作区加速搜索和与项目上下文相关的行为。",
"summaryEn": "Control the default Agent Harness, session-title generation, accelerated workspace search, and project-context behavior.",
"keywordsZh": [
"会话设置",
"工作区设置",
"默认 Harness",
"上次选择",
"标题生成",
"项目搜索",
"索引"
],
"keywordsEn": [
"session settings",
"workspace settings",
"default Harness",
"last selection",
"title generation",
"project search",
"index"
],
"highlightsZh": [
"跟随上次选择或固定默认 Harness",
"自动生成会话标题",
"本地工作区加速搜索",
"会话使用的标题模型"
],
"highlightsEn": [
"Follow the last selection or fix a default Harness",
"Automatic session titles",
"Accelerated local-workspace search",
"Model used for session titles"
],
"items": [
{
"id": "default-agent-harness",
"titleZh": "让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness",
"titleEn": "Make regular new sessions follow the last ChatInput selection or use a fixed Harness",
"control": {
"kind": "open",
"reasonCode": "unstructuredInteraction",
"reasonZh": "“让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness”由会话设置页中的关联控件共同管理,目前没有一个能确定完成整个流程的单一结构化 Command;Agent 会打开精确入口,并把选择保留在用户可见界面。",
"reasonEn": "“Make regular new sessions follow the last ChatInput selection or use a fixed Harness” is managed by related controls on the session settings page and currently has no single structured Command that can deterministically complete the whole workflow; the Agent opens the exact entry and keeps the selection visible to the user."
}
},
{
"id": "automatic-titles",
"titleZh": "启用或停用根据会话内容自动生成标题",
Expand Down Expand Up @@ -27224,18 +27288,22 @@
"stepsZh": [
"打开设置",
"进入“工作区 > 会话与工作区”",
"调整标题或搜索选项"
"调整默认 Harness、标题或搜索选项"
],
"stepsEn": [
"Open Settings",
"Go to Workspace > Session & Workspace",
"Tune title or search controls"
"Tune the default Harness, title, or search controls"
],
"agentExamplesZh": [
"让新会话跟随 ChatInput 上一次选择的 Harness",
"把新会话固定为 Ultimate Harness",
"关闭自动生成会话标题",
"启用工作区加速搜索"
],
"agentExamplesEn": [
"Make new sessions follow the last Harness selected in ChatInput",
"Fix Ultimate as the Harness for new sessions",
"Turn off automatic session titles",
"Enable accelerated workspace search"
],
Expand Down Expand Up @@ -27274,20 +27342,28 @@
"AI & collaboration",
"会话设置",
"工作区设置",
"默认 Harness",
"上次选择",
"标题生成",
"项目搜索",
"索引",
"session settings",
"workspace settings",
"default Harness",
"last selection",
"title generation",
"project search",
"index",
"跟随上次选择或固定默认 Harness",
"自动生成会话标题",
"本地工作区加速搜索",
"会话使用的标题模型",
"Follow the last selection or fix a default Harness",
"Automatic session titles",
"Accelerated local-workspace search",
"Model used for session titles",
"让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness",
"Make regular new sessions follow the last ChatInput selection or use a fixed Harness",
"启用或停用根据会话内容自动生成标题",
"Enable or disable automatic titles generated from session content",
"让标题模型继承主模型、快速模型或使用指定模型",
Expand All @@ -27298,8 +27374,12 @@
"Inspect index status and rebuild the workspace index when needed",
"远程工作区明确降级搜索实现,不把远程路径回退到本机",
"Use an explicit remote-workspace search path without silently falling back to local files",
"让新会话跟随 ChatInput 上一次选择的 Harness",
"把新会话固定为 Ultimate Harness",
"关闭自动生成会话标题",
"启用工作区加速搜索",
"Make new sessions follow the last Harness selected in ChatInput",
"Fix Ultimate as the Harness for new sessions",
"Turn off automatic session titles",
"Enable accelerated workspace search"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ title_en: "Session & workspace settings"

> 设置 / Setting

控制会话标题生成、工作区加速搜索和与项目上下文相关的行为。
控制默认 Agent Harness、会话标题生成、工作区加速搜索和与项目上下文相关的行为。

Control session-title generation, accelerated workspace search, and project-context behavior.
Control the default Agent Harness, session-title generation, accelerated workspace search, and project-context behavior.

## 完整功能清单 / Everything included

- **Agent 可定位入口,需交互完成 / Agent opens; interaction required** · 让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness
- Make regular new sessions follow the last ChatInput selection or use a fixed Harness
- **Agent 可直接控制 / Direct Agent control** · 启用或停用根据会话内容自动生成标题
- Enable or disable automatic titles generated from session content
- **Agent 可定位入口,需交互完成 / Agent opens; interaction required** · 让标题模型继承主模型、快速模型或使用指定模型
Expand All @@ -34,8 +36,8 @@ Control session-title generation, accelerated workspace search, and project-cont
Open Settings
2. 进入“工作区 > 会话与工作区”
Go to Workspace > Session & Workspace
3. 调整标题或搜索选项
Tune title or search controls
3. 调整默认 Harness、标题或搜索选项
Tune the default Harness, title, or search controls

入口 / Entry: OpenBitFun 设置

Expand All @@ -54,6 +56,10 @@ Control session-title generation, accelerated workspace search, and project-cont

## 可以直接对 Agent 说 / Try saying

- “让新会话跟随 ChatInput 上一次选择的 Harness”
- “Make new sessions follow the last Harness selected in ChatInput”
- “把新会话固定为 Ultimate Harness”
- “Fix Ultimate as the Harness for new sessions”
- “关闭自动生成会话标题”
- “Turn off automatic session titles”
- “启用工作区加速搜索”
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"schemaVersion": 1,
"generatedFrom": "src/shared/interactive-capabilities/catalog.json",
"catalogDigest": "d7a7419ddd673eb733ae8bd33dbb3dcd3b4d1ce0acfc953067a3403fe26d6699",
"count": 212,
"catalogDigest": "409e6dbef7ebceafccc11606e2855227b9a33fa1ed71f5b4608da04e8a23de7d",
"count": 213,
"reasonCounts": {
"externalAuth": 4,
"secretEntry": 5,
"unstructuredInteraction": 185,
"unstructuredInteraction": 186,
"visualSelection": 18
},
"entries": [
Expand Down Expand Up @@ -2891,6 +2891,23 @@
"command:reset_config"
]
},
{
"capabilityId": "setting.workspace.session",
"itemId": "default-agent-harness",
"titleZh": "让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness",
"titleEn": "Make regular new sessions follow the last ChatInput selection or use a fixed Harness",
"reasonCode": "unstructuredInteraction",
"reasonZh": "“让普通新会话跟随 ChatInput 上次选择,或固定使用指定 Harness”由会话设置页中的关联控件共同管理,目前没有一个能确定完成整个流程的单一结构化 Command;Agent 会打开精确入口,并把选择保留在用户可见界面。",
"reasonEn": "“Make regular new sessions follow the last ChatInput selection or use a fixed Harness” is managed by related controls on the session settings page and currently has no single structured Command that can deterministically complete the whole workflow; the Agent opens the exact entry and keeps the selection visible to the user.",
"presentationTarget": {
"kind": "settings",
"pageId": "workspace.session"
},
"evidence": [
"source:src/web-ui/src/infrastructure/config/components/DefaultHarnessConfig.tsx#DefaultHarnessConfig",
"source:src/web-ui/src/locales/zh-CN/settings/runtime.json#defaultHarness.title"
]
},
{
"capabilityId": "setting.workspace.session",
"itemId": "title-model",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 2,
"generatedFrom": "src/shared/interactive-capabilities/catalog.json",
"catalogDigest": "d7a7419ddd673eb733ae8bd33dbb3dcd3b4d1ce0acfc953067a3403fe26d6699",
"catalogDigest": "409e6dbef7ebceafccc11606e2855227b9a33fa1ed71f5b4608da04e8a23de7d",
"commandCount": 666,
"coverage": {
"commandCount": 666,
Expand Down
4 changes: 1 addition & 3 deletions src/apps/desktop/src/api/custom_agent_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,7 @@ pub async fn delete_custom_agent(
"",
|config: &mut openbitfun_core::service::config::GlobalConfig| {
config.ai.agent_profiles.remove(&agent_id);
if config.app.flow_chat.default_mode_id.as_deref() == Some(agent_id.as_str()) {
config.app.flow_chat.default_mode_id = None;
}
config.app.flow_chat.remove_mode_reference(&agent_id);
Ok(())
},
)
Expand Down
Loading
Loading