@wenbin_wb/dsh-bridge 2.2.6 → 2.2.7
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.en.md +278 -0
- package/README.md +143 -142
- package/lib/platform/conversation-bridge.js +120 -70
- package/lib/wechat/node.js +1 -1
- package/package.json +2 -2
- package/README.zh-CN.md +0 -277
|
@@ -326,9 +326,11 @@ export class ConversationBridge {
|
|
|
326
326
|
source: { kind: 'user' },
|
|
327
327
|
}))
|
|
328
328
|
}
|
|
329
|
-
|
|
329
|
+
const wsDetail = cwdOverride ? `\n- **工作区**:\`${cwdOverride}\`` : ''
|
|
330
|
+
const hint = prompt ? '' : '\n\n> 💡 发送任意消息即可直接与 Agent 对话。'
|
|
331
|
+
await this.sendText(`✓ **已创建新会话**\n- **会话 ID**:\`${fmtSessionId(handle.agent.session.id)}\`${wsDetail}${hint}`)
|
|
330
332
|
} catch (error) {
|
|
331
|
-
await this.sendText(
|
|
333
|
+
await this.sendText(`❌ **创建会话失败**:${error instanceof Error ? error.message : String(error)}`)
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
336
|
|
|
@@ -510,11 +512,11 @@ export class ConversationBridge {
|
|
|
510
512
|
this.logger?.warn?.(`[dsh-bridge ${this.platform.id}] failed to re-attach agent: ${reason}`)
|
|
511
513
|
// 清除失效的 activeSessionId,避免用户误以为还在旧会话中
|
|
512
514
|
this.activeSessionId = null
|
|
513
|
-
await this.sendText(
|
|
515
|
+
await this.sendText(`❌ **恢复会话失败**:${reason}\n\n> 发送 \`/new <提示词>\` 可新建一个会话。`)
|
|
514
516
|
}
|
|
515
517
|
}
|
|
516
518
|
if (!agent) {
|
|
517
|
-
await this.sendText(
|
|
519
|
+
await this.sendText(`> 💤 **当前没有活动会话**\n> 发送 \`/new <提示词>\` 开始新会话,或发送 \`/sessions\` 查看已有会话。`)
|
|
518
520
|
return 'routed'
|
|
519
521
|
}
|
|
520
522
|
|
|
@@ -603,11 +605,11 @@ export class ConversationBridge {
|
|
|
603
605
|
if (this.peerId) this.sendTyping(2).catch(() => {})
|
|
604
606
|
const reason = event.data.reason
|
|
605
607
|
if (reason.kind === 'error') {
|
|
606
|
-
void this.sendText(
|
|
608
|
+
void this.sendText(`❌ **处理出错**:${summarizeError(reason.error)}`)
|
|
607
609
|
} else if (reason.kind === 'aborted') {
|
|
608
|
-
void this.sendText(
|
|
610
|
+
void this.sendText(`⏹ **任务已停止**`)
|
|
609
611
|
} else if (reason.kind === 'max-tokens') {
|
|
610
|
-
void this.sendText(
|
|
612
|
+
void this.sendText(`⚠️ **达到模型单轮输出上限,本轮内容已截断**`)
|
|
611
613
|
}
|
|
612
614
|
return
|
|
613
615
|
}
|
|
@@ -630,12 +632,16 @@ export class ConversationBridge {
|
|
|
630
632
|
|
|
631
633
|
const number = this.nextApprovalNumber()
|
|
632
634
|
const timeoutSec = this.config.approvalTimeoutSec
|
|
635
|
+
const timeoutMin = Math.max(1, Math.round(timeoutSec / 60))
|
|
633
636
|
const prompt = [
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
637
|
+
`### ⚠️ 操作权限确认 (#${number})`,
|
|
638
|
+
'',
|
|
639
|
+
`- **调用工具**:\`${req.toolName}\``,
|
|
640
|
+
...(req.reason ? [`- **申请原因**:${req.reason}`] : []),
|
|
641
|
+
`- **等待超时**:${timeoutMin} 分钟内未回复将自动拒绝`,
|
|
642
|
+
'',
|
|
643
|
+
`> 回复 \`/yes\`(或 \`1\`)批准执行`,
|
|
644
|
+
`> 回复 \`/no\`(或 \`2\`)拒绝执行`,
|
|
639
645
|
].join('\n')
|
|
640
646
|
|
|
641
647
|
void this.sendText(prompt)
|
|
@@ -653,7 +659,7 @@ export class ConversationBridge {
|
|
|
653
659
|
|
|
654
660
|
// 仅在非超时路径发送确认消息(超时时 resolve 已经发生在 timer 回调)
|
|
655
661
|
if (!timeoutFired) {
|
|
656
|
-
const label = outcome === 'allowed-once' ?
|
|
662
|
+
const label = outcome === 'allowed-once' ? '✓ **已批准执行**' : outcome === 'rejected' ? '❌ **已拒绝执行**' : `**[${outcome}]**`
|
|
657
663
|
void this.sendText(`${label}(#${number})`)
|
|
658
664
|
}
|
|
659
665
|
return outcome
|
|
@@ -676,10 +682,10 @@ function sessionLabel(session) {
|
|
|
676
682
|
.map((block) => block.text ?? '')
|
|
677
683
|
.join(' ')
|
|
678
684
|
.trim()
|
|
679
|
-
if (text) return text.length >
|
|
685
|
+
if (text) return text.length > 28 ? `${text.slice(0, 28)}…` : text
|
|
680
686
|
}
|
|
681
687
|
}
|
|
682
|
-
return '(
|
|
688
|
+
return '新会话 (待输入)'
|
|
683
689
|
}
|
|
684
690
|
|
|
685
691
|
// 校验工作区路径(防止路径遍历攻击)
|
|
@@ -689,13 +695,11 @@ async function validateWorkspacePath(node, sel) {
|
|
|
689
695
|
const allowedPaths = workspaces.map(w => normalize(resolve(w.path)))
|
|
690
696
|
|
|
691
697
|
if (!allowedPaths.includes(normalized)) {
|
|
692
|
-
const wsDisplay = allowedPaths.slice(0, 5).join('\n
|
|
693
|
-
const more = allowedPaths.length > 5 ? `\n
|
|
698
|
+
const wsDisplay = allowedPaths.slice(0, 5).map((p, i) => `- \`[${i + 1}]\` \`${p}\``).join('\n')
|
|
699
|
+
const more = allowedPaths.length > 5 ? `\n- *…等共 ${allowedPaths.length} 个工作区*` : ''
|
|
694
700
|
return {
|
|
695
701
|
valid: false,
|
|
696
|
-
error:
|
|
697
|
-
`可用工作区:\n ${wsDisplay}${more}\n\n` +
|
|
698
|
-
`提示:使用 /workspaces 查看完整列表`
|
|
702
|
+
error: `❌ **路径不在已注册工作区列表中**:\`${normalized}\`\n\n**可用工作区:**\n${wsDisplay}${more}\n\n> 提示:发送 \`/workspaces\` 查看完整列表`
|
|
699
703
|
}
|
|
700
704
|
}
|
|
701
705
|
|
|
@@ -705,7 +709,7 @@ async function validateWorkspacePath(node, sel) {
|
|
|
705
709
|
if (!ok) {
|
|
706
710
|
return {
|
|
707
711
|
valid: false,
|
|
708
|
-
error:
|
|
712
|
+
error: `❌ **工作区目录不存在**:\`${normalized}\``
|
|
709
713
|
}
|
|
710
714
|
}
|
|
711
715
|
|
|
@@ -778,6 +782,13 @@ async function listWorkspaces(node) {
|
|
|
778
782
|
}
|
|
779
783
|
}
|
|
780
784
|
|
|
785
|
+
function getWorkspaceBasename(cwd) {
|
|
786
|
+
if (!cwd || cwd === '(未指定)') return '(未指定)'
|
|
787
|
+
const norm = normalize(cwd).replace(/[\\/]+$/, '')
|
|
788
|
+
const parts = norm.split(/[\\/]/)
|
|
789
|
+
return parts[parts.length - 1] || cwd
|
|
790
|
+
}
|
|
791
|
+
|
|
781
792
|
async function routeCommand(node, text) {
|
|
782
793
|
const trimmed = text.trim()
|
|
783
794
|
if (!trimmed.startsWith('/')) return false
|
|
@@ -800,25 +811,27 @@ async function routeCommand(node, text) {
|
|
|
800
811
|
const index = Number(rest[0])
|
|
801
812
|
const sessions = sessionsInDisplayOrder(await listSessions(node))
|
|
802
813
|
if (!Number.isInteger(index) || index < 1 || index > sessions.length) {
|
|
803
|
-
await node.sendText(
|
|
814
|
+
await node.sendText(`❌ **无效会话编号**:\`${rest[0] ?? ''}\`\n\n> 可用编号范围:\`1 – ${sessions.length}\`(发送 \`/sessions\` 查看会话列表)`)
|
|
804
815
|
return true
|
|
805
816
|
}
|
|
806
817
|
const session = sessions[index - 1]
|
|
807
818
|
node.setActiveSessionById(session.id)
|
|
808
|
-
|
|
819
|
+
const title = session.title || (session.events ? sessionLabel(session) : '')
|
|
820
|
+
const titleLine = title ? `\n- **标题**:${title}` : ''
|
|
821
|
+
await node.sendText(`✓ **已切换到会话 #${index}**${titleLine}\n- **会话 ID**:\`${fmtSessionId(session.id)}\``)
|
|
809
822
|
return true
|
|
810
823
|
}
|
|
811
824
|
case 'workspaces': {
|
|
812
825
|
const workspaces = await listWorkspaces(node)
|
|
813
826
|
if (workspaces.length === 0) {
|
|
814
|
-
await node.sendText(
|
|
827
|
+
await node.sendText(`### 🗂️ 可用工作区\n\n> ℹ️ 当前没有已注册的工作区。可使用 \`/new <提示词> @<路径>\` 指定项目目录。`)
|
|
815
828
|
return true
|
|
816
829
|
}
|
|
817
830
|
const lines = workspaces.map((w, i) => {
|
|
818
|
-
const
|
|
819
|
-
return
|
|
831
|
+
const titleStr = w.title && w.title !== w.path ? `**${w.title}**` : `**${getWorkspaceBasename(w.path)}**`
|
|
832
|
+
return `- **[${i + 1}]** ${titleStr}\n \`${w.path}\``
|
|
820
833
|
})
|
|
821
|
-
await node.sendText(
|
|
834
|
+
await node.sendText(`### 🗂️ 可用工作区 (共 ${workspaces.length} 个)\n> 新建会话:发送 \`/new <提示词> @序号\`\n\n${lines.join('\n')}`)
|
|
822
835
|
return true
|
|
823
836
|
}
|
|
824
837
|
case 'new': {
|
|
@@ -835,7 +848,10 @@ async function routeCommand(node, text) {
|
|
|
835
848
|
const idx = Number(sel)
|
|
836
849
|
const ws = workspaces[idx - 1]
|
|
837
850
|
if (ws) cwd = ws.path
|
|
838
|
-
else {
|
|
851
|
+
else {
|
|
852
|
+
await node.sendText(`❌ **无效工作区编号**:\`${sel}\`\n\n> 请发送 \`/workspaces\` 查看可用工作区列表与编号。`)
|
|
853
|
+
return true
|
|
854
|
+
}
|
|
839
855
|
} else {
|
|
840
856
|
// 直接指定路径时,规范化并校验(必须完全匹配已注册工作区)
|
|
841
857
|
const validation = await validateWorkspacePath(node, sel)
|
|
@@ -852,60 +868,71 @@ async function routeCommand(node, text) {
|
|
|
852
868
|
case 'stop': {
|
|
853
869
|
const agent = node.activeAgent()
|
|
854
870
|
if (!agent) {
|
|
855
|
-
await node.sendText(
|
|
871
|
+
await node.sendText(`ℹ️ **当前没有正在运行的 Agent 任务**`)
|
|
856
872
|
} else {
|
|
857
873
|
agent.cancel({ kind: 'user' })
|
|
858
|
-
await node.sendText(
|
|
874
|
+
await node.sendText(`⏹ **已请求停止当前任务**`)
|
|
859
875
|
}
|
|
860
876
|
return true
|
|
861
877
|
}
|
|
862
878
|
case 'end': {
|
|
863
|
-
// 结束当前会话:停止 agent 并清除活动会话(进入"
|
|
879
|
+
// 结束当前会话:停止 agent 并清除活动会话(进入"没有活动会话"状态)
|
|
864
880
|
const agent = node.activeAgent()
|
|
865
881
|
if (agent) agent.cancel({ kind: 'user' })
|
|
866
882
|
node.activeSessionId = null
|
|
867
883
|
await node.onActiveSessionChange?.(null)
|
|
868
|
-
|
|
869
|
-
await node.sendText(`${node.mark.ok} 已结束当前会话(没有活动会话)。\n\n发送以下任一命令开始:\n/new <提示词> — 新建会话\n/sessions — 查看已有会话\n/help — 命令帮助`)
|
|
884
|
+
await node.sendText(`✓ **已结束当前会话**(没有活动会话)。\n\n> **后续操作**:\n> - \`/new <提示词>\` — 新建会话并开始\n> - \`/sessions\` — 查看历史会话列表\n> - \`/help\` — 查看常用指令帮助`)
|
|
870
885
|
return true
|
|
871
886
|
}
|
|
872
887
|
case 'status': {
|
|
873
888
|
const agent = node.activeAgent()
|
|
874
889
|
const session = node.activeSession()
|
|
875
890
|
if (!session) {
|
|
876
|
-
await node.sendText(
|
|
891
|
+
await node.sendText(`### 📊 Agent 状态看板\n\n> ℹ️ **当前没有活动会话**。\n> 发送 \`/new <提示词>\` 开始新任务,或发送 \`/sessions\` 查看已有会话。`)
|
|
877
892
|
return true
|
|
878
893
|
}
|
|
879
|
-
const
|
|
894
|
+
const statusMap = {
|
|
895
|
+
idle: '空闲 (idle)',
|
|
896
|
+
running: '运行中 (running)',
|
|
897
|
+
paused: '已暂停 (paused)',
|
|
898
|
+
error: '异常 (error)',
|
|
899
|
+
}
|
|
900
|
+
const status = statusMap[agent?.status] || (agent?.status ?? '空闲 (idle)')
|
|
880
901
|
const lastTurn = [...(session.events ?? [])].reverse().find((e) => e.type === 'turn/end')
|
|
881
902
|
const reason = lastTurn ? describeTurnEnd(lastTurn.data.reason) : '尚未运行'
|
|
882
|
-
|
|
903
|
+
const title = session.title || (session.events ? sessionLabel(session) : '')
|
|
904
|
+
const titleLine = title ? `\n- **会话标题**:${title}` : ''
|
|
905
|
+
const cwdLine = session.header?.cwd ? `\n- **工作区**:\`${session.header.cwd}\`` : ''
|
|
906
|
+
|
|
907
|
+
await node.sendText(`### 📊 Agent 状态看板\n\n- **会话 ID**:\`${session.id}\`${titleLine}${cwdLine}\n- **Agent 状态**:${status}\n- **累计事件**:${session.seq ?? 0} 条\n- **最近执行**:${reason}`)
|
|
883
908
|
return true
|
|
884
909
|
}
|
|
885
910
|
case 'start': // 别名:首次扫码自动开始一个会话
|
|
886
911
|
await node.createSession('')
|
|
887
912
|
return true
|
|
888
913
|
default:
|
|
889
|
-
await node.sendText(
|
|
914
|
+
await node.sendText(`❌ **未知指令**:\`/${command}\`\n\n${helpText()}`)
|
|
890
915
|
return true
|
|
891
916
|
}
|
|
892
917
|
}
|
|
893
918
|
|
|
894
919
|
function describeTurnEnd(reason) {
|
|
895
920
|
switch (reason.kind) {
|
|
896
|
-
case 'completed': return '
|
|
897
|
-
case 'error': return '
|
|
898
|
-
case 'aborted': return '
|
|
899
|
-
case 'blocked': return '
|
|
900
|
-
case 'max-tokens': return '
|
|
901
|
-
case 'interrupted': return '
|
|
902
|
-
default: return reason.kind
|
|
921
|
+
case 'completed': return '✓ 已完成'
|
|
922
|
+
case 'error': return '❌ 出错'
|
|
923
|
+
case 'aborted': return '⏹ 已停止'
|
|
924
|
+
case 'blocked': return '⚠️ 已阻塞'
|
|
925
|
+
case 'max-tokens': return '⚠️ 输出截断'
|
|
926
|
+
case 'interrupted': return '⚡ 已中断'
|
|
927
|
+
default: return `[${reason.kind}]`
|
|
903
928
|
}
|
|
904
929
|
}
|
|
905
930
|
|
|
906
931
|
async function renderSessions(node) {
|
|
907
932
|
const all = await listSessions(node)
|
|
908
|
-
if (all.length === 0)
|
|
933
|
+
if (all.length === 0) {
|
|
934
|
+
return `### 📋 会话列表\n\n> ℹ️ 暂无历史会话。发送 \`/new <提示词>\` 开始新会话。`
|
|
935
|
+
}
|
|
909
936
|
// 按工作区(真实 cwd)分组;无 cwd 的归入 '(未指定)'
|
|
910
937
|
const groups = new Map()
|
|
911
938
|
for (const s of all) {
|
|
@@ -914,23 +941,34 @@ async function renderSessions(node) {
|
|
|
914
941
|
groups.get(key).push(s)
|
|
915
942
|
}
|
|
916
943
|
const sortedGroups = [...groups.entries()].sort((a, b) => String(a[0]).localeCompare(String(b[0])))
|
|
917
|
-
const parts = [
|
|
944
|
+
const parts = [
|
|
945
|
+
`### 📋 会话列表 (共 ${all.length} 个)`,
|
|
946
|
+
`> 切换会话:发送 \`/use 编号\` 或 \`/resume 编号\``,
|
|
947
|
+
'',
|
|
948
|
+
]
|
|
918
949
|
let idx = 0
|
|
919
950
|
for (const [cwd, sessions] of sortedGroups) {
|
|
920
|
-
|
|
951
|
+
const groupName = cwd === '(未指定)' ? '📁 未指定工作区' : `📁 **${getWorkspaceBasename(cwd)}**`
|
|
952
|
+
const pathDetail = cwd === '(未指定)' ? '' : ` \`${cwd}\``
|
|
953
|
+
parts.push(`${groupName}${pathDetail}`)
|
|
921
954
|
for (const session of sessions.slice(0, 20)) {
|
|
922
955
|
idx += 1
|
|
923
|
-
const
|
|
956
|
+
const isActive = session.id === node.activeSessionId
|
|
957
|
+
const activeTag = isActive ? ' `[当前]`' : ''
|
|
924
958
|
const title = session.title || (session.events ? sessionLabel(session) : '')
|
|
925
959
|
const label = title || fmtSessionId(session.id)
|
|
926
960
|
const when = session.createdAt ? fmtTime(session.createdAt) : ''
|
|
927
|
-
|
|
928
|
-
parts.push(
|
|
961
|
+
const timeStr = when ? ` · ${when}` : ''
|
|
962
|
+
parts.push(`- **#${idx}** ${label}${activeTag}`)
|
|
963
|
+
parts.push(` \`${fmtSessionId(session.id)}\`${timeStr}`)
|
|
964
|
+
}
|
|
965
|
+
if (sessions.length > 20) {
|
|
966
|
+
parts.push(` *…该工作区共 ${sessions.length} 个会话*`)
|
|
929
967
|
}
|
|
930
|
-
|
|
968
|
+
parts.push('')
|
|
931
969
|
}
|
|
932
|
-
if (all.length > 50) parts.push(
|
|
933
|
-
return
|
|
970
|
+
if (all.length > 50) parts.push(`*…共 ${all.length} 个会话,仅显示前 50 个*`)
|
|
971
|
+
return parts.join('\n').trim()
|
|
934
972
|
}
|
|
935
973
|
|
|
936
974
|
// 与 renderSessions 完全一致的显示顺序:按工作区字母序分组、组内保持 listSessions 顺序。
|
|
@@ -946,35 +984,47 @@ function sessionsInDisplayOrder(all) {
|
|
|
946
984
|
return sortedGroups.flatMap(([, sessions]) => sessions)
|
|
947
985
|
}
|
|
948
986
|
|
|
949
|
-
// 时间戳 →
|
|
987
|
+
// 时间戳 → 简洁可读时间 (MM-DD HH:mm 或 YYYY-MM-DD HH:mm)
|
|
950
988
|
function fmtTime(ms) {
|
|
951
989
|
try {
|
|
952
990
|
const d = new Date(ms)
|
|
991
|
+
if (isNaN(d.getTime())) return ''
|
|
953
992
|
const p = (n) => String(n).padStart(2, '0')
|
|
954
|
-
|
|
993
|
+
const now = new Date()
|
|
994
|
+
const isSameYear = d.getFullYear() === now.getFullYear()
|
|
995
|
+
const datePart = isSameYear ? `${p(d.getMonth() + 1)}-${p(d.getDate())}` : `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
|
996
|
+
return `${datePart} ${p(d.getHours())}:${p(d.getMinutes())}`
|
|
955
997
|
} catch { return '' }
|
|
956
998
|
}
|
|
957
999
|
|
|
958
|
-
//
|
|
1000
|
+
// 提取精简会话短 ID(去除冗余 session- 前缀,保留 8 位短标识)
|
|
959
1001
|
function fmtSessionId(id) {
|
|
960
|
-
|
|
961
|
-
|
|
1002
|
+
if (!id) return ''
|
|
1003
|
+
const clean = String(id).replace(/^session-/, '')
|
|
1004
|
+
return clean.length > 8 ? clean.slice(0, 8) : clean
|
|
962
1005
|
}
|
|
963
1006
|
|
|
964
1007
|
function helpText() {
|
|
965
1008
|
return [
|
|
966
|
-
|
|
967
|
-
'
|
|
968
|
-
'
|
|
969
|
-
'
|
|
970
|
-
'
|
|
971
|
-
'
|
|
972
|
-
'
|
|
973
|
-
'
|
|
974
|
-
'
|
|
975
|
-
'
|
|
976
|
-
'
|
|
977
|
-
'
|
|
1009
|
+
'### 🤖 常用指令帮助',
|
|
1010
|
+
'',
|
|
1011
|
+
'**💬 会话控制**',
|
|
1012
|
+
'- `/sessions` (或 `/list`) — 查看所有会话列表',
|
|
1013
|
+
'- `/use <编号>` (或 `/resume <编号>`) — 切换到指定编号会话',
|
|
1014
|
+
'- `/new <提示词>` — 在当前工作区创建新会话并开始',
|
|
1015
|
+
'- `/new <提示词> @序号` — 在指定工作区创建新会话(/workspaces)',
|
|
1016
|
+
'- `/new <提示词> @路径` — 在指定目录路径创建新会话',
|
|
1017
|
+
'- `/end` — 结束当前会话(回到无活动会话状态)',
|
|
1018
|
+
'- `/stop` — 中断停止当前正在执行的任务',
|
|
1019
|
+
'',
|
|
1020
|
+
'**📁 环境与状态**',
|
|
1021
|
+
'- `/workspaces` — 查看已注册的工作区列表',
|
|
1022
|
+
'- `/status` — 查看 Agent 运行状态与事件摘要',
|
|
1023
|
+
'- `/help` — 查看此帮助菜单',
|
|
1024
|
+
'',
|
|
1025
|
+
'**🔐 权限确认**',
|
|
1026
|
+
'- `/yes` (或 `1`) — 批准当前工具执行请求',
|
|
1027
|
+
'- `/no` (或 `2`) — 拒绝当前工具执行请求',
|
|
978
1028
|
].join('\n')
|
|
979
1029
|
}
|
|
980
1030
|
|
package/lib/wechat/node.js
CHANGED
|
@@ -108,7 +108,7 @@ export class WechatConversationNode extends ConversationBridge {
|
|
|
108
108
|
if (debugInfo.length > 0) {
|
|
109
109
|
errMsg += `\n调试信息:\n${debugInfo.join('\n')}`
|
|
110
110
|
}
|
|
111
|
-
await this.sendText(
|
|
111
|
+
await this.sendText(`❌ **${errMsg}**`)
|
|
112
112
|
return
|
|
113
113
|
}
|
|
114
114
|
this.logger?.info?.(`[dsh-bridge wechat] ignore empty message from ${sender}`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wenbin_wb/dsh-bridge",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.7",
|
|
4
4
|
"description": "手机扫码即可在移动端/公网继续用 DeepSeek Harness,人不在电脑前也能接着干。一键局域网二维码、Cloudflare 公网隧道、自建隧道与微信 Bot(多工作区/会话持久化/媒体/审批),无需自己搭公网服务器。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"client",
|
|
17
17
|
"cordis.patch.yml",
|
|
18
18
|
"README.md",
|
|
19
|
-
"README.
|
|
19
|
+
"README.en.md",
|
|
20
20
|
"LICENSE",
|
|
21
21
|
"docs/banner.jpg",
|
|
22
22
|
"docs/custom-tunnel.md",
|