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/README.md +1 -1
- package/README.zh.md +1 -1
- package/client.js +322 -241
- package/lib/client-runtime.cjs +322 -241
- package/package.json +1 -1
- package/src/client/index.js +93 -36
package/package.json
CHANGED
package/src/client/index.js
CHANGED
|
@@ -28,12 +28,19 @@ const t = {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const style = {
|
|
31
|
-
page: { display: 'grid', gap:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
61
|
-
bubbleUser: { maxWidth: '88%', minWidth: 0, flex: '0 1 auto', width: 'fit-content', borderRadius:
|
|
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: '
|
|
905
|
-
h(
|
|
906
|
-
h('
|
|
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.
|
|
991
|
-
h('div', { style: style.row },
|
|
992
|
-
h('
|
|
993
|
-
|
|
994
|
-
|
|
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
|
-
|
|
1076
|
-
h('
|
|
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
|
-
:
|
|
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 }) {
|