v0.4.0: tasks running-task view + apps center

This commit is contained in:
2026-09-02 08:14:56 +08:00
parent dd5bc6f489
commit 89e752023c
+150 -8
View File
@@ -1,11 +1,14 @@
/**
* apes--sidebar — WorkBuddy/Tutti 风格右侧边栏增强(配置化主插件 v0.3.0)
* apes--sidebar — WorkBuddy/Tutti 风格右侧边栏增强(配置化主插件 v0.4.0)
*
* 单个 client bundle 注册三个可配置 Tab:
* 单个 client bundle 注册四个可配置 Tab:
* - 'wb:tasks' —— WorkBuddy 式任务导航:按工作区分组的会话列表、搜索、
* 运行中徽标、一键打开/新建会话、当前会话高亮。
* 运行中徽标;升级:含「运行中任务」区(子代理拓扑 +
* 实时计数角标),一键打开/新建会话、当前会话高亮。
* - 'wb:agents' —— Tutti 式 Agent 总览:子代理/后台 agent 列表、运行状态、
* 所属工作区、一键打开(不依赖 remote.commands)。
* - 'wb:apps' —— Tutti 式应用中心:已装应用网格(Design/PPT/Video 等),
* 点击在会话视图打开。
* - 'wb:profile' —— WorkBuddy 底部用户区:当前 provider/model、连接状态、
* 设置/帮助入口。
*
@@ -15,6 +18,7 @@
* 或用户任意自定义
* - enableTasks (bool, 默认 true) 显示 Tasks Tab
* - enableAgents (bool, 默认 true) 显示 Agents Tab
* - enableApps (bool, 默认 true) 显示 Apps Tab
* - enableProfile (bool, 默认 true) 显示 Profile Tab
* - tasks.showTime / tasks.showUngrouped Tasks 子设置
*
@@ -48,6 +52,7 @@ window.__ModuleLoader__.load({
var SETTINGS_NS = 'apes--sidebar';
var TASKS_TAB_ID = "wb:tasks";
var AGENTS_TAB_ID = "wb:agents";
var APPS_TAB_ID = "wb:apps";
var PROFILE_TAB_ID = "wb:profile";
var TASKS_STYLE_ID = "apes-sidebar-style";
var AGENTS_STYLE_ATTR = "data-apes-sidebar-agents-styles";
@@ -78,6 +83,12 @@ window.__ModuleLoader__.load({
"setting.enableAgentsDesc": "子代理/后台 agent 列表与运行状态",
"setting.enableProfile": "Profile Tab",
"setting.enableProfileDesc": "底部用户区:模型信息与设置/帮助入口",
"setting.enableApps": "应用中心 Tab",
"setting.enableAppsDesc": "已装应用网格(Design/PPT/Video),点击在会话视图打开",
"apps.title": "应用中心",
"apps.hint": "点击应用在会话视图打开;也可在会话顶栏视图切换",
"apps.open": "打开",
"apps.notFound": "未检测到该应用(可能未安装)",
"setting.showTime": "显示相对时间",
"setting.showTimeDesc": "会话行右侧显示最后活动时间",
"setting.showUngrouped": "显示未分组会话",
@@ -96,7 +107,7 @@ window.__ModuleLoader__.load({
"profile.model": "模型",
"profile.settings": "设置",
"profile.help": "帮助",
"profile.footer": "apes--sidebar 0.3.0 · WorkBuddy/Tutti 风格增强"
"profile.footer": "apes--sidebar 0.4.0 · WorkBuddy/Tutti 风格增强"
};
var en = {
"tab.tasks.title": "Tasks",
@@ -115,6 +126,12 @@ window.__ModuleLoader__.load({
"setting.enableAgentsDesc": "Subagent / background agent list and status",
"setting.enableProfile": "Profile tab",
"setting.enableProfileDesc": "Bottom user area: model info + settings/help",
"setting.enableApps": "Apps tab",
"setting.enableAppsDesc": "Installed app grid (Design/PPT/Video), click to open in conversation view",
"apps.title": "Apps",
"apps.hint": "Click an app to open it in the conversation view; also switchable in the view bar",
"apps.open": "Open",
"apps.notFound": "App not detected (maybe not installed)",
"setting.showTime": "Show relative time",
"setting.showTimeDesc": "Show last activity time on session rows",
"setting.showUngrouped": "Show ungrouped sessions",
@@ -133,7 +150,7 @@ window.__ModuleLoader__.load({
"profile.model": "Model",
"profile.settings": "Settings",
"profile.help": "Help",
"profile.footer": "apes--sidebar 0.3.0 · WorkBuddy/Tutti style enhancement"
"profile.footer": "apes--sidebar 0.4.0 · WorkBuddy/Tutti style enhancement"
};
function isZh() {
@@ -174,7 +191,7 @@ window.__ModuleLoader__.load({
// ====================================================================
/** 读取本插件的设置快照(防御性,读不到返回默认值)。 */
function readSettings(store) {
var defs = { displayName: DISPLAY_NAME_DEFAULT, enableTasks: true, enableAgents: true, enableProfile: true };
var defs = { displayName: DISPLAY_NAME_DEFAULT, enableTasks: true, enableAgents: true, enableApps: true, enableProfile: true };
try {
var raw = store && store.prefs && store.prefs.pluginSettings ? store.prefs.pluginSettings[SETTINGS_NS] : null;
if (raw && typeof raw === 'object') {
@@ -182,6 +199,7 @@ window.__ModuleLoader__.load({
displayName: typeof raw.displayName === 'string' && raw.displayName.trim() !== '' ? raw.displayName.trim() : DISPLAY_NAME_DEFAULT,
enableTasks: raw.enableTasks !== false,
enableAgents: raw.enableAgents !== false,
enableApps: raw.enableApps !== false,
enableProfile: raw.enableProfile !== false
};
}
@@ -228,7 +246,14 @@ window.__ModuleLoader__.load({
'@keyframes wb-pulse{0%,100%{opacity:1}50%{opacity:.35}}',
'#' + TASKS_STYLE_ID + '-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}',
'#' + TASKS_STYLE_ID + '-time{flex:0 0 auto;color:var(--dsw-alias-label-tertiary,#8f959e);font-size:11px}',
'#' + TASKS_STYLE_ID + '-badge{flex:0 0 auto;padding:1px 6px;border-radius:999px;background:rgba(34,197,94,.12);color:var(--dsw-alias-state-success-primary,#16a34a);font-size:10px;font-weight:600}'
'#' + TASKS_STYLE_ID + '-badge{flex:0 0 auto;padding:1px 6px;border-radius:999px;background:rgba(34,197,94,.12);color:var(--dsw-alias-state-success-primary,#16a34a);font-size:10px;font-weight:600}',
'#' + TASKS_STYLE_ID + '-tasks{flex:0 0 auto;margin:0 10px 2px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l2,rgba(31,35,41,.08));border-radius:8px;background:var(--dsw-alias-bg-layer-1,transparent)}',
'#' + TASKS_STYLE_ID + '-tasks-head{display:flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary,#5c6069);margin-bottom:6px}',
'#' + TASKS_STYLE_ID + '-tasks-count{margin-left:auto;padding:1px 7px;border-radius:999px;background:rgba(34,197,94,.12);color:var(--dsw-alias-state-success-primary,#16a34a);font-size:10px}',
'#' + TASKS_STYLE_ID + '-tasks-row{display:flex;align-items:center;gap:8px;padding:4px 2px;border-radius:6px;cursor:pointer;font-size:12px}',
'#' + TASKS_STYLE_ID + '-tasks-row:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}',
'#' + TASKS_STYLE_ID + '-tasks-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
'#' + TASKS_STYLE_ID + '-tasks-none{color:var(--dsw-alias-label-tertiary,#8f959e);font-size:11px;padding:2px 0}'
].join('\n');
function sessionsSnapshot(ctx) {
@@ -373,8 +398,37 @@ window.__ModuleLoader__.load({
}
}
// 「运行中任务」区:当前会话的子代理拓扑(运行中优先),实时计数
var runningChildren = [];
var allIds = Object.keys(byId || {});
for (var ri = 0; ri < allIds.length; ri++) {
var rid = allIds[ri];
var rentry = byId[rid];
if (!rentry) continue;
if (rid === currentId) continue;
var rp = rentry.parentSessionId || rentry.parentId || rentry.parent;
var isChild = (rp && rp === currentId) || (currentId && (rid.indexOf(currentId + ':') === 0 || rid.indexOf(currentId + '/') === 0));
if (!isChild) continue;
runningChildren.push({
id: rid,
title: sessionTitleOf(rentry) || rid,
running: rentry.running === true
});
}
runningChildren.sort(function (a, b) { return (a.running === b.running) ? 0 : (a.running ? -1 : 1); });
return e('div', { id: TASKS_STYLE_ID + '-root' },
e('div', { className: TASKS_STYLE_ID + '-search' },
runningChildren.length > 0 ? e('div', { className: TASKS_STYLE_ID + '-tasks' },
e('div', { className: TASKS_STYLE_ID + '-tasks-head' },
'运行中任务',
e('span', { className: TASKS_STYLE_ID + '-tasks-count' }, String(runningChildren.length))),
runningChildren.map(function (rc) {
return e('div', { key: rc.id, className: TASKS_STYLE_ID + '-tasks-row', title: rc.id,
onClick: function () { try { ctx.sessions.open(rc.id); } catch (err) {} } },
e('span', { className: TASKS_STYLE_ID + '-dot' + (rc.running ? ' is-running' : '') }),
e('span', { className: TASKS_STYLE_ID + '-tasks-name' }, rc.title));
})) : null,
e('div', { className: TASKS_STYLE_ID + '-search' },
e('span', { className: TASKS_STYLE_ID + '-search-icon' }, '⌕'),
e('input', { placeholder: t('search.placeholder'), value: query,
onChange: function (ev) { setQuery(ev.target.value); } }),
@@ -550,6 +604,90 @@ window.__ModuleLoader__.load({
};
}
// ====================================================================
// Apps Tab(Tutti 式应用中心)
// ====================================================================
/** 默认应用清单:deepseek 三件套(视图 id 与 slots 注册一致)。 */
var DEFAULT_APPS = [
{ id: 'ipollowork-design-studio', name: 'Design', desc: 'DeepSeek iDesign · 设计稿/UI', viewId: 'ipollowork-design-studio' },
{ id: 'ipollowork-ppt-studio', name: 'PPT', desc: 'DeepSeek iPPT · 演示文稿', viewId: 'ipollowork-ppt-studio' },
{ id: 'ipollowork-video-studio', name: 'Video', desc: 'DeepSeek iVideo · 视频创作', viewId: 'ipollowork-video-studio' }
];
var APPS_STYLE_ID = 'apes-sidebar-apps-style';
var APPS_CSS = [
'#' + APPS_STYLE_ID + '-root{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--dsw-alias-bg-base,transparent);color:var(--dsw-alias-label-primary,#1f2329);font-size:13px;line-height:1.5}',
'#' + APPS_STYLE_ID + '-root *{box-sizing:border-box}',
'#' + APPS_STYLE_ID + '-head{flex:0 0 auto;display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid var(--dsw-alias-border-l2,rgba(31,35,41,.08))}',
'#' + APPS_STYLE_ID + '-title{flex:1;font-weight:600;font-size:13px}',
'#' + APPS_STYLE_ID + '-grid{flex:1 1 auto;min-height:0;overflow-y:auto;padding:10px;display:grid;grid-template-columns:repeat(2,1fr);gap:10px;align-content:start}',
'#' + APPS_STYLE_ID + '-card{border:1px solid var(--dsw-alias-border-l2,rgba(31,35,41,.08));border-radius:10px;padding:12px;cursor:pointer;background:var(--dsw-alias-bg-layer-1,transparent);display:flex;flex-direction:column;gap:6px;transition:border-color .15s,background .15s}',
'#' + APPS_STYLE_ID + '-card:hover{border-color:var(--dsw-alias-brand-primary,#3370ff);background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.04))}',
'#' + APPS_STYLE_ID + '-card-icon{width:34px;height:34px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;color:#fff;background:linear-gradient(135deg,#3370ff,#7c3aed)}',
'#' + APPS_STYLE_ID + '-card-name{font-weight:600;font-size:13px}',
'#' + APPS_STYLE_ID + '-card-desc{color:var(--dsw-alias-label-tertiary,#8f959e);font-size:11px;line-height:1.4}',
'#' + APPS_STYLE_ID + '-card-open{margin-top:2px;font-size:11px;color:var(--dsw-alias-brand-primary,#3370ff)}',
'#' + APPS_STYLE_ID + '-hint{padding:14px;color:var(--dsw-alias-label-tertiary,#8f959e);font-size:12px;line-height:1.6}'
].join('\n');
/** 应用清单:配置里的 apps.list 覆盖默认(防御性合并)。 */
function appsList(store) {
try {
var raw = store && store.prefs && store.prefs.pluginSettings && store.prefs.pluginSettings[SETTINGS_NS] ? store.prefs.pluginSettings[SETTINGS_NS] : null;
var custom = raw && Array.isArray(raw.appsList) ? raw.appsList : null;
if (custom && custom.length > 0) return custom;
} catch (err) { /* ignore */ }
return DEFAULT_APPS;
}
/** 尝试在会话视图打开应用(viewId = conversation.view slot 的 id)。 */
function openAppView(ctx, app) {
var viewId = app.viewId || app.id;
try {
// 方式1:uiConversation 视图激活(若公开)
var uc = ctx.get ? ctx.get('uiConversation') : null;
if (uc && typeof uc.activateView === 'function') { uc.activateView(viewId); return true; }
if (uc && uc.views && typeof uc.views.activate === 'function') { uc.views.activate(viewId); return true; }
} catch (err) { /* ignore */ }
try {
// 方式2:slots 激活 conversation.view
var slots = ctx.get ? ctx.get('slots') : null;
if (slots && typeof slots.set === 'function') { slots.set('conversation.view', viewId); return true; }
} catch (err) { /* ignore */ }
// 降级:提示在会话视图顶栏手动切换
return false;
}
function AppsView(props) {
var ctx = props.ctx;
var apps = appsList(props.store);
return e('div', { id: APPS_STYLE_ID + '-root' },
e('div', { id: APPS_STYLE_ID + '-head' },
e('span', { id: APPS_STYLE_ID + '-title' }, t('apps.title'))),
e('div', { id: APPS_STYLE_ID + '-grid' },
apps.map(function (app) {
return e('div', { key: app.id || app.name, id: APPS_STYLE_ID + '-card',
title: app.desc || app.name,
onClick: function () { openAppView(ctx, app); } },
e('div', { id: APPS_STYLE_ID + '-card-icon' }, String(app.name || 'A').charAt(0).toUpperCase()),
e('div', { id: APPS_STYLE_ID + '-card-name' }, app.name || app.id),
app.desc ? e('div', { id: APPS_STYLE_ID + '-card-desc' }, app.desc) : null,
e('div', { id: APPS_STYLE_ID + '-card-open' }, t('apps.open')));
})),
e('div', { id: APPS_STYLE_ID + '-hint' }, t('apps.hint')));
}
function appsTabDescriptor(ctx) {
return {
id: APPS_TAB_ID,
title: function () { return t('apps.title'); },
icon: function (size) { return e(primitives.IconGridOutline16 || primitives.IconAppsOutline16, { size: size }); },
order: 90,
single: true,
component: function (props) { return e(AppsView, props); }
};
}
// ====================================================================
// Profile Tab(WorkBuddy 底部用户区)
// ====================================================================
@@ -644,6 +782,7 @@ window.__ModuleLoader__.load({
function apply(ctx) {
injectStyles(TASKS_STYLE_ID, TASKS_CSS);
injectStyles(AGENTS_STYLE_ATTR, AGENTS_CSS);
injectStyles(APPS_STYLE_ID, APPS_CSS);
injectStyles(PROFILE_STYLE_ID, PROFILE_CSS);
ctx.effect(function () {
@@ -653,11 +792,13 @@ window.__ModuleLoader__.load({
var settings = readSettings(ctx.get('betterSidebar') && ctx.get('betterSidebar').store ? ctx.get('betterSidebar').store : null);
if (settings.enableTasks) disposers.push(ctx.betterSidebar.registerTab(tasksTabDescriptor(ctx)));
if (settings.enableAgents) disposers.push(ctx.betterSidebar.registerTab(agentsTabDescriptor(ctx)));
if (settings.enableApps) disposers.push(ctx.betterSidebar.registerTab(appsTabDescriptor(ctx)));
if (settings.enableProfile) disposers.push(ctx.betterSidebar.registerTab(profileTabDescriptor(ctx)));
} catch (err) {
// 配置读取失败时注册全部(保守默认)
disposers.push(ctx.betterSidebar.registerTab(tasksTabDescriptor(ctx)));
disposers.push(ctx.betterSidebar.registerTab(agentsTabDescriptor(ctx)));
disposers.push(ctx.betterSidebar.registerTab(appsTabDescriptor(ctx)));
disposers.push(ctx.betterSidebar.registerTab(profileTabDescriptor(ctx)));
}
return function () {
@@ -669,6 +810,7 @@ window.__ModuleLoader__.load({
return function () {
disposeStyles(TASKS_STYLE_ID);
disposeStyles(AGENTS_STYLE_ATTR);
disposeStyles(APPS_STYLE_ID);
disposeStyles(PROFILE_STYLE_ID);
};
}, "apes--sidebar: dispose styles");