dsh-monkeyai-sessions 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-monkeyai-sessions",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "在 DeepSeek Harness 中读取和继续 MonkeyAI 会话:查看完整对话历史、下发新指令,无缝接续之前在 MonkeyAI 客户端上的工作",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -28,12 +28,19 @@ const t = {
28
28
  }
29
29
 
30
30
  const style = {
31
- page: { display: 'grid', gap: 12, maxWidth: 1080, margin: '0 auto', padding: '16px 18px 24px', color: t.text, height: '100%', minHeight: 0, overflowY: 'auto', boxSizing: 'border-box', alignContent: 'start', fontSize: 13, lineHeight: 1.5 },
31
+ page: { display: 'grid', gap: 14, maxWidth: 1320, margin: '0 auto', padding: '18px 20px 24px', color: t.text, background: '#f7f8fb', height: '100%', minHeight: 0, overflowY: 'auto', boxSizing: 'border-box', alignContent: 'start', fontSize: 13, lineHeight: 1.5 },
32
32
  header: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, paddingBottom: 2 },
33
- title: { margin: 0, fontSize: 15, fontWeight: 650, letterSpacing: '-0.01em', color: t.text },
33
+ title: { margin: 0, fontSize: 18, fontWeight: 700, letterSpacing: '-0.025em', color: '#182230' },
34
+ eyebrow: { margin: 0, fontSize: 10.5, fontWeight: 700, letterSpacing: '0.1em', color: t.text3, textTransform: 'uppercase' },
34
35
  subtitle: { margin: 0, fontSize: 12, color: t.text3 },
35
36
  sectionTitle: { margin: 0, fontSize: 12, fontWeight: 650, color: t.text2, textTransform: 'uppercase', letterSpacing: '0.04em' },
36
- card: { display: 'grid', gap: 10, padding: 14, border: `1px solid ${t.border}`, borderRadius: t.radiusLg, background: t.surface },
37
+ card: { display: 'grid', gap: 10, padding: 14, border: `1px solid ${t.border}`, borderRadius: 12, background: t.surface, boxShadow: '0 2px 8px rgba(16,24,40,0.035)' },
38
+ toolbarCard: { display: 'grid', gap: 10, padding: '13px 15px', border: `1px solid ${t.border}`, borderRadius: 12, background: t.surface, boxShadow: '0 2px 8px rgba(16,24,40,0.035)' },
39
+ workspace: { display: 'grid', gridTemplateColumns: 'minmax(248px, 292px) minmax(0, 1fr)', gap: 12, minWidth: 0, alignItems: 'stretch' },
40
+ sessionSidebar: { display: 'grid', gridTemplateRows: 'auto minmax(0, 1fr) auto', gap: 10, minWidth: 0, padding: 12, border: `1px solid ${t.border}`, borderRadius: 12, background: t.surface, boxShadow: '0 2px 8px rgba(16,24,40,0.035)' },
41
+ sessionList: { display: 'grid', gridTemplateColumns: '1fr', alignContent: 'start', gap: 6, minHeight: 0, overflowY: 'auto', padding: '1px 3px 2px 1px' },
42
+ thread: { display: 'grid', gridTemplateRows: 'auto minmax(0, 1fr) auto', gap: 10, minWidth: 0, height: 'min(70vh, 720px)', minHeight: 440, overflow: 'hidden', padding: 12 },
43
+ emptyThread: { display: 'grid', placeContent: 'center', justifyItems: 'center', gap: 9, minWidth: 0, minHeight: 'min(70vh, 720px)', padding: 28, border: `1px dashed ${t.border2}`, borderRadius: 12, background: 'linear-gradient(145deg, #ffffff 0%, #f8faff 100%)', textAlign: 'center' },
37
44
  row: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' },
38
45
  label: { display: 'grid', gap: 4, flex: 1, minWidth: 180, fontSize: 12, fontWeight: 600, color: t.text2 },
39
46
  input: { width: '100%', boxSizing: 'border-box', padding: '7px 10px', borderRadius: t.radius, border: `1px solid ${t.border2}`, background: t.surface, color: t.text, outline: 'none', fontSize: 13, transition: 'border-color .15s, box-shadow .15s' },
@@ -52,13 +59,13 @@ const style = {
52
59
  sessionTitle: { fontSize: 13, fontWeight: 650, lineHeight: 1.35, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
53
60
  sessionMeta: { fontSize: 11.5, color: t.text3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
54
61
  chip: { display: 'inline-flex', alignItems: 'center', gap: 5, padding: '2px 8px', borderRadius: 999, border: `1px solid ${t.border}`, background: t.surfaceAlt, fontSize: 11.5 },
55
- events: { display: 'flex', flexDirection: 'column', gap: 8, height: '56vh', minHeight: 200, overflowY: 'auto', padding: '4px 6px 4px 2px' },
62
+ events: { display: 'flex', flexDirection: 'column', gap: 10, height: 'auto', minHeight: 0, overflowY: 'auto', padding: '6px 8px 8px 4px', overscrollBehavior: 'contain' },
56
63
  event: { padding: '8px 11px', borderRadius: t.radius, background: t.surfaceAlt, border: `1px solid ${t.border}`, overflowWrap: 'anywhere', color: t.text },
57
64
  bubbleWrap: { display: 'flex', gap: 8, alignItems: 'flex-start', width: '100%' },
58
65
  bubbleWrapUser: { display: 'flex', gap: 8, alignItems: 'flex-start', justifyContent: 'flex-end', width: '100%' },
59
66
  avatar: { width: 24, height: 24, borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700, color: '#ffffff', flexShrink: 0, marginTop: 2 },
60
- bubble: { maxWidth: '88%', minWidth: 0, flex: '0 1 auto', width: 'fit-content', borderRadius: t.radiusLg, padding: '8px 13px', background: t.surfaceAlt, border: `1px solid ${t.border}`, lineHeight: 1.55, fontSize: 13 },
61
- bubbleUser: { maxWidth: '88%', minWidth: 0, flex: '0 1 auto', width: 'fit-content', borderRadius: t.radiusLg, padding: '8px 13px', background: t.accent, color: '#ffffff', lineHeight: 1.55, fontSize: 13 },
67
+ bubble: { maxWidth: '88%', minWidth: 0, flex: '0 1 auto', width: 'fit-content', borderRadius: 12, padding: '9px 13px', background: t.surface, border: `1px solid ${t.border}`, boxShadow: '0 1px 2px rgba(16,24,40,0.04)', lineHeight: 1.6, fontSize: 13 },
68
+ bubbleUser: { maxWidth: '88%', minWidth: 0, flex: '0 1 auto', width: 'fit-content', borderRadius: 12, padding: '9px 13px', background: '#315fe8', color: '#ffffff', boxShadow: '0 2px 5px rgba(49,95,232,0.18)', lineHeight: 1.6, fontSize: 13 },
62
69
  thought: { maxWidth: '88%', borderRadius: t.radiusLg, padding: '7px 11px', background: '#faf7fd', border: `1px solid #e8ddf5`, lineHeight: 1.5, fontSize: 12.5, color: '#5b4a72' },
63
70
  thoughtSummary: { cursor: 'pointer', color: '#6b4fa0', fontWeight: 650, fontSize: 10.5, letterSpacing: '0.05em', textTransform: 'uppercase', userSelect: 'none' },
64
71
  approval: { padding: '11px 13px', borderRadius: t.radiusLg, border: `1px solid #f0d98c`, background: '#fffbeb', display: 'grid', gap: 8 },
@@ -82,6 +89,36 @@ const PANEL_CSS = `
82
89
  .mai-panel [data-events]::-webkit-scrollbar-thumb:hover { background: #b8c2cf; }
83
90
  .mai-panel .mai-card-hover { transition: border-color .15s, background .15s; }
84
91
  .mai-panel .mai-card-hover:not(:disabled):hover { border-color: #b9cdf3 !important; background: #f7faff !important; }
92
+ .mai-panel .mai-toolbar { position: relative; overflow: hidden; }
93
+ .mai-panel .mai-toolbar::before { content: ''; position: absolute; inset: 0 0 auto; height: 3px; background: linear-gradient(90deg, #3568e8 0%, #8baaf4 46%, #e7edfc 100%); }
94
+ .mai-panel .mai-workspace { display: grid; grid-template-columns: minmax(248px, 292px) minmax(0, 1fr); gap: 12px; min-width: 0; align-items: stretch; }
95
+ .mai-panel .mai-session-sidebar { min-height: min(70vh, 720px); }
96
+ .mai-panel .mai-session-list { scrollbar-gutter: stable; }
97
+ .mai-panel .mai-session-card { position: relative; }
98
+ .mai-panel .mai-session-card[aria-current='true']::before { content: ''; position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px; border-radius: 0 3px 3px 0; background: #3568e8; }
99
+ .mai-panel .mai-thread { height: min(70vh, 720px); min-height: 440px; }
100
+ .mai-panel .mai-thread-events { height: auto !important; min-height: 0 !important; }
101
+ .mai-panel .mai-empty-thread { min-height: min(70vh, 720px); }
102
+ .mai-panel .mai-empty-mark { display: grid; place-items: center; width: 54px; height: 54px; border-radius: 17px; background: #edf2ff; color: #315fe8; box-shadow: inset 0 0 0 1px #dce6ff; }
103
+ .mai-panel .mai-session-meta { overflow-wrap: anywhere; }
104
+ @media (max-width: 900px) {
105
+ .mai-panel .mai-workspace { grid-template-columns: minmax(0, 1fr); }
106
+ .mai-panel .mai-session-sidebar { min-height: 0; grid-template-rows: auto minmax(0, auto) auto; }
107
+ .mai-panel .mai-session-list { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); max-height: 235px; }
108
+ .mai-panel .mai-thread { height: 68vh; min-height: 390px; }
109
+ .mai-panel .mai-empty-thread { min-height: 330px; }
110
+ }
111
+ @media (max-width: 560px) {
112
+ .mai-panel .mai-page-title { font-size: 16px !important; }
113
+ .mai-panel .mai-toolbar-controls { align-items: stretch; }
114
+ .mai-panel .mai-toolbar-controls select { flex-basis: 100% !important; }
115
+ .mai-panel .mai-session-list { grid-template-columns: 1fr !important; max-height: 210px; }
116
+ .mai-panel .mai-thread { height: 68vh; min-height: 360px; padding: 10px; }
117
+ .mai-panel .mai-thread-header { gap: 6px !important; }
118
+ .mai-panel .mai-thread-header strong { min-width: 100px; }
119
+ .mai-panel .mai-thread-header select { flex-basis: 100% !important; }
120
+ .mai-panel .mai-events { gap: 7px; }
121
+ }
85
122
  @keyframes mai-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
86
123
  .mai-panel .mai-pulse { animation: mai-pulse 1.2s ease-in-out infinite; }
87
124
  .mai-panel .mai-md > div:first-child > :first-child { margin-top: 0; }
@@ -901,9 +938,11 @@ function RemoteSessionPage({ api }) {
901
938
  return h('main', { style: style.page, className: 'mai-panel' },
902
939
  h('style', { dangerouslySetInnerHTML: { __html: PANEL_CSS } }),
903
940
  h('header', { style: style.header },
904
- h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
905
- h(MonkeyIcon, { size: 22 }),
906
- h('h1', { style: style.title }, 'MonkeyAI 会话')),
941
+ h('div', { style: { display: 'grid', gap: 1 } },
942
+ h('p', { style: style.eyebrow }, '远程工作区'),
943
+ h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
944
+ h(MonkeyIcon, { size: 22 }),
945
+ h('h1', { style: style.title, className: 'mai-page-title' }, 'MonkeyAI 会话'))),
907
946
  h(StatusBadge, { status, live: isLive })),
908
947
  error ? h('div', { role: 'alert', style: style.error },
909
948
  h('span', { style: { flex: 1 } }, error),
@@ -987,11 +1026,13 @@ function RemoteSessionPage({ api }) {
987
1026
  h('p', { style: { margin: 0, fontSize: 12, color: t.text3 } }, '浏览器授权需要回调能访问到本机 Host。手机上请改用上方账号登录。'))),
988
1027
  accounts.length > 0 ? h('p', { style: { margin: 0, fontSize: 12, color: t.text3 } }, '已连接的账号会出现在设备列表上方的账号选择器中。') : null))
989
1028
  : null,
990
- currentAccount ? h('section', { style: style.card },
991
- h('div', { style: style.row },
992
- h('h2', { style: { ...style.sectionTitle, flex: 1 } }, '远程会话'),
993
- h('span', { style: { fontSize: 11, color: t.text3 } }, currentAccount.scopes.filter(s => s !== 'device:connect').join(' · '))),
994
- h('div', { style: style.row },
1029
+ currentAccount ? h('section', { style: style.toolbarCard, className: 'mai-toolbar' },
1030
+ h('div', { style: style.row, className: 'mai-toolbar-heading' },
1031
+ h('div', { style: { display: 'grid', gap: 1, flex: 1, minWidth: 0 } },
1032
+ h('h2', { style: style.sectionTitle }, '远程会话'),
1033
+ h('p', { style: style.subtitle }, '选择设备,继续处理 MonkeyAI 会话')),
1034
+ h('span', { style: style.chip }, currentAccount.scopes.filter(s => s !== 'device:connect').join(' · '))),
1035
+ h('div', { style: style.row, className: 'mai-toolbar-controls' },
995
1036
  h('select', { style: { ...style.input, flex: '1 1 200px' }, value: accountId, onChange: event => setAccountId(event.target.value), 'aria-label': '已授权账号' },
996
1037
  accounts.map(account => h('option', { key: account.accountId, value: account.accountId }, account.serverOrigin))),
997
1038
  h('button', { type: 'button', style: { ...style.button, flex: '0 0 auto', padding: '6px 10px', fontWeight: 700 }, disabled: loading || addingServer, onClick: () => { setAddingServer(true); setServerAddress(''); setAuthorizationRequestId(''); setAuthorizationUrl(''); setAuthorizationMode(''); setCallbackUrl(''); setStatus('请输入 MonkeyAI 服务器地址') }, title: '授权另一个 MonkeyAI 服务器' }, '+ 添加服务器'),
@@ -1053,27 +1094,38 @@ function RemoteSessionPage({ api }) {
1053
1094
  type: 'button', style: style.primaryButton, flex: '0 0 auto',
1054
1095
  disabled: loading || !machineId || !newSessionCwd.trim() || newSessionBusy,
1055
1096
  onClick: createRemoteSession,
1056
- }, newSessionBusy ? '创建中…' : '创建')))),
1057
- sessionOptions.length > 0
1058
- ? h('div', { style: style.sessions }, sessionOptions.map(session => {
1059
- const flag = session.stale ? '已过期' : session.deviceStatus && session.deviceStatus !== 'online' ? (session.deviceStatus === 'offline' ? '离线' : session.deviceStatus) : ''
1060
- return h('button', {
1061
- style: { ...style.session, ...(session.id === sessionId ? style.selected : {}) },
1062
- className: 'mai-card-hover',
1063
- key: session.id,
1064
- type: 'button',
1065
- disabled: !session.cwd,
1066
- onClick: () => openSession(session),
1067
- title: session.cwd ? `打开 ${session.cwd}` : 'ACP 会话列表未提供工作目录',
1068
- },
1069
- h('span', { style: style.sessionTitle }, session.title || session.id),
1070
- h('span', { style: style.sessionMeta }, session.cwd || '加载历史需要 runtime 提供工作目录'),
1071
- flag !== '' ? h('span', { style: { fontSize: 10.5, fontWeight: 650, color: session.stale ? t.text3 : '#8a6d1d', textTransform: 'uppercase', letterSpacing: '0.04em' } }, flag) : null)
1072
- }))
1073
- : h('p', { style: style.subtitle }, machineId ? '该设备暂无会话。可在上方新建,或点击刷新。' : '请选择设备以列出其会话。'))
1097
+ }, newSessionBusy ? '创建中…' : '创建')))))
1074
1098
  : null,
1075
- sessionId ? h('section', { style: style.card },
1076
- h('div', { style: style.row },
1099
+ currentAccount ? h('div', { className: 'mai-workspace' },
1100
+ h('aside', { style: style.sessionSidebar, className: 'mai-session-sidebar' },
1101
+ h('div', { style: { ...style.row, justifyContent: 'space-between' } },
1102
+ h('h2', { style: style.sectionTitle }, '会话列表'),
1103
+ h('span', { style: style.chip }, String(sessionOptions.length))),
1104
+ sessionOptions.length > 0
1105
+ ? h('div', { style: style.sessions, className: 'mai-session-list' }, sessionOptions.map(session => {
1106
+ const flag = session.stale ? '已过期' : session.deviceStatus && session.deviceStatus !== 'online' ? (session.deviceStatus === 'offline' ? '离线' : session.deviceStatus) : ''
1107
+ return h('button', {
1108
+ style: { ...style.session, ...(session.id === sessionId ? style.selected : {}) },
1109
+ className: 'mai-card-hover mai-session-card',
1110
+ 'aria-current': session.id === sessionId ? 'true' : undefined,
1111
+ key: session.id,
1112
+ type: 'button',
1113
+ disabled: !session.cwd,
1114
+ onClick: () => openSession(session),
1115
+ title: session.cwd ? `打开 ${session.cwd}` : 'ACP 会话列表未提供工作目录',
1116
+ },
1117
+ h('span', { style: style.sessionTitle }, session.title || session.id),
1118
+ h('span', { style: style.sessionMeta, className: 'mai-session-meta' }, session.cwd || '加载历史需要 runtime 提供工作目录'),
1119
+ flag !== '' ? h('span', { style: { fontSize: 10.5, fontWeight: 650, color: session.stale ? t.text3 : '#8a6d1d', textTransform: 'uppercase', letterSpacing: '0.04em' } }, flag) : null)
1120
+ }))
1121
+ : h('div', { style: { display: 'grid', justifyItems: 'center', gap: 7, padding: '22px 12px', textAlign: 'center' } },
1122
+ h('span', { style: { ...style.avatar, width: 34, height: 34, background: t.surfaceAlt, color: t.text3, fontSize: 17 } }, '·'),
1123
+ h('span', { style: { fontSize: 12, fontWeight: 600, color: t.text2 } }, machineId ? '这里还没有会话' : '请选择远程设备'),
1124
+ h('span', { style: { fontSize: 11, color: t.text3 } }, machineId ? '刷新会话或创建一个新会话' : '会话列表会显示在这里')),
1125
+ h('div', { style: { borderTop: `1px solid ${t.border}`, paddingTop: 8 } },
1126
+ h('p', { style: { margin: 0, fontSize: 10.5, color: t.text3 } }, machineId ? '会话来自所选设备的 runtime' : '连接设备后查看会话'))),
1127
+ sessionId ? h('section', { style: { ...style.card, ...style.thread }, className: 'mai-thread' },
1128
+ h('div', { style: style.row, className: 'mai-thread-header' },
1077
1129
  h('button', {
1078
1130
  type: 'button', style: { ...style.button, flexShrink: 0 }, title: '关闭会话并返回列表',
1079
1131
  onClick: () => { streamGenerationRef.current += 1; streamRef.current?.dispose(); streamRef.current = null; setSessionId(''); setTurnActive(false); setStopping(false); setSessionStatus(''); setStatus('远程会话已关闭') },
@@ -1105,7 +1157,7 @@ function RemoteSessionPage({ api }) {
1105
1157
  ? h('option', { value: currentModel }, currentModel.slice(0, 24))
1106
1158
  : null,
1107
1159
  models.map(m => h('option', { key: m.id, value: m.id }, `${m.displayName} (${Math.round(m.contextWindowTokens / 1000)}k)`)))),
1108
- h('div', { style: style.events, 'aria-live': 'polite', 'data-events': '', ref: eventsRef,
1160
+ h('div', { style: style.events, className: 'mai-thread-events mai-events', 'aria-live': 'polite', 'data-events': '', ref: eventsRef,
1109
1161
  onScroll: event => {
1110
1162
  const el = event.currentTarget
1111
1163
  if (el.scrollTop < 60 && visibleCount < displayEntries.length) {
@@ -1209,7 +1261,12 @@ function RemoteSessionPage({ api }) {
1209
1261
  lastDelivery || turnActive ? h('div', { style: { fontSize: 11.5, color: turnActive ? t.accent : lastDelivery?.accepted ? t.success : lastDelivery?.frame === 'pending' ? t.text3 : t.danger, textAlign: 'right', display: 'flex', alignItems: 'center', justifyContent: 'flex-end', gap: 6 } },
1210
1262
  turnActive ? h('span', { className: 'mai-pulse', style: { ...style.dot, background: t.accent } }) : null,
1211
1263
  turnActive ? (stopping ? '正在停止当前回合…' : 'MonkeyAI 正在处理…') : lastDelivery?.accepted ? '回合已结束' : lastDelivery?.frame === 'pending' ? '等待投递' : '投递被拒绝') : null)
1212
- : null)
1264
+ : h('section', { style: style.emptyThread, className: 'mai-empty-thread' },
1265
+ h('div', { className: 'mai-empty-mark' }, h(MonkeyIcon, { size: 26 })),
1266
+ h('p', { style: style.eyebrow }, '远程会话'),
1267
+ h('h2', { style: { margin: 0, fontSize: 18, fontWeight: 650, color: '#182230' } }, '选择一个会话'),
1268
+ h('p', { style: { ...style.subtitle, maxWidth: 300 } }, sessionOptions.length > 0 ? '从左侧选择会话,在此继续对话。' : machineId ? '当前设备还没有会话。可在上方新建或刷新。' : '先选择一个远程设备。'))
1269
+ ) : null)
1213
1270
  }
1214
1271
 
1215
1272
  function MonkeyIcon({ size = 18 }) {