v0.4.0: tasks running-task view + apps center
This commit is contained in:
+150
-8
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user