feat: add deepseek-harness workbench plugin and console diagnosis API
- console: GET /api/workflows/{id}, /runs/{run_id}, /runs/{run_id}/diagnosis
(journal trace + sanitized bounded log tails, workflow/run pairing enforced)
- workbench/: dsh 宿主插件(7 个工作流工具、中文系统提示词、失败监控器、
本机回环桥接服务)+ 侧边栏面板客户端包(sidebar.footer.action 与
shell.overlay 追加插槽)+ 降级独立面板 + 一键启动脚本
- adapters/browser: 收敛 looks_like_login_url 到共享层,修复
jd_main_image_collector 对 gyxx_flow.accounts 的越层导入
- tests: 新端点覆盖;replay_policy 断言对齐已迁移的 catalog(repeatable)
This commit is contained in:
1 parent
b124d757b0
commit
01218b2907
26 files changed
+4347
-8
No files matched your search
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* GYXX 工作台客户端插件入口。
|
||||
* 由 esbuild 打包为 CJS 并通过 window.__ModuleLoader__ 注册(见 scripts/build-client.mjs)。
|
||||
* 运行时只依赖 dsh 平台共享模块表中的 react。
|
||||
*/
|
||||
|
||||
import { createElement, useSyncExternalStore } from 'react'
|
||||
import { WorkflowPanel, refreshWorkflows } from './Panel.jsx'
|
||||
import { Toasts } from './Toasts.jsx'
|
||||
import { getState, subscribe, update } from './store.js'
|
||||
import stylesText from './styles.css'
|
||||
|
||||
export const inject = ['slots']
|
||||
|
||||
function useWorkbench() {
|
||||
return useSyncExternalStore(subscribe, getState)
|
||||
}
|
||||
|
||||
function injectStyles() {
|
||||
if (typeof document === 'undefined') return
|
||||
if (document.getElementById('gyxxwb-styles')) return
|
||||
const style = document.createElement('style')
|
||||
style.id = 'gyxxwb-styles'
|
||||
style.textContent = stylesText
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
|
||||
/** 侧边栏底部动作:工作流面板开关 + 聚合状态点。 */
|
||||
function WorkbenchFooterAction() {
|
||||
const s = useWorkbench()
|
||||
const failed = s.workflows.filter((w) => !w.active_run && w.last_run?.status === 'failed').length
|
||||
const running = s.workflows.filter((w) => w.active_run).length
|
||||
const tone = failed > 0 ? 'failed' : running > 0 ? 'running' : 'success'
|
||||
return createElement(
|
||||
'button',
|
||||
{
|
||||
type: 'button',
|
||||
className: `gyxxwb-footer-btn${s.open ? ' gyxxwb-footer-btn-active' : ''}`,
|
||||
title: 'GYXX 工作流工作台',
|
||||
onClick: () => {
|
||||
const next = !getState().open
|
||||
update({ open: next })
|
||||
if (next) refreshWorkflows()
|
||||
},
|
||||
},
|
||||
createElement('span', { className: `gyxxwb-dot gyxxwb-dot-${tone}` }),
|
||||
createElement('span', null, '工作流'),
|
||||
)
|
||||
}
|
||||
|
||||
/** 覆盖层根:左侧抽屉面板 + 失败 toast。 */
|
||||
function WorkbenchOverlay() {
|
||||
return createElement(
|
||||
'div',
|
||||
{ className: 'gyxxwb-overlay' },
|
||||
createElement(WorkflowPanel, null),
|
||||
createElement(Toasts, null),
|
||||
)
|
||||
}
|
||||
|
||||
export function apply(ctx) {
|
||||
injectStyles()
|
||||
ctx.effect(
|
||||
() => ctx.slots.register({ name: 'sidebar.footer.action' }, WorkbenchFooterAction),
|
||||
'gyxx-workbench: footer action',
|
||||
)
|
||||
ctx.effect(
|
||||
() => ctx.slots.register({ name: 'shell.overlay' }, WorkbenchOverlay),
|
||||
'gyxx-workbench: overlay',
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user