dsh-composer-plus 1.23.0 → 1.24.1
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.de.md +12 -5
- package/README.es.md +12 -5
- package/README.fr.md +12 -5
- package/README.hi.md +12 -5
- package/README.id.md +12 -5
- package/README.ja.md +12 -5
- package/README.ko.md +12 -5
- package/README.md +12 -5
- package/README.pt-BR.md +12 -5
- package/README.ru.md +12 -5
- package/README.tr.md +12 -5
- package/README.vi.md +12 -5
- package/README.zh.md +12 -5
- package/assets/features/assistant.webp +0 -0
- package/client.js +147 -47
- package/index.js +335 -1
- package/package.json +2 -2
- package/release-notes.json +14 -14
- package/tether/gateway/server.mjs +17 -7
|
@@ -51,7 +51,7 @@ export const PLUS = new Map([
|
|
|
51
51
|
['queue-move', ['POST']], ['queue-edit', ['POST']], ['branches', ['GET']], ['predict', ['POST']], ['complete', ['POST']], ['improve', ['POST']], ['unread', ['GET', 'POST']],
|
|
52
52
|
['worktrees', ['GET', 'POST']], ['new-session-workspace', ['POST']], ['memory-edit', ['GET', 'POST']], ['memory-history', ['GET', 'POST']], ['memory-export', ['POST']], ['memory-copy', ['GET', 'POST']], ['memory-stale', ['GET']], ['memory-chat', ['GET', 'POST']], ['memory-suggest', ['POST']], ['handoff', ['POST']], ['context', ['GET']],
|
|
53
53
|
['board-chats', ['GET', 'POST']], ['board-progress', ['GET']], ['secret-answer', ['GET', 'POST']], ['side-chat', ['GET', 'POST']],
|
|
54
|
-
['issue-report', ['POST']],
|
|
54
|
+
['issue-report', ['POST']], ['assistant', ['GET']],
|
|
55
55
|
])
|
|
56
56
|
/** Allow for this chat: an Auto Review ask (`approval/request` with this reason) for a tool that the chat granted. */
|
|
57
57
|
export const AUTO_REVIEW_ASK = 'Auto review denied tool '
|
|
@@ -668,6 +668,8 @@ export function createGateway(opts = {}) {
|
|
|
668
668
|
if (devices.length !== before) saveDevices()
|
|
669
669
|
for (const s of devSockets.get(id) ?? []) s.destroy()
|
|
670
670
|
devSockets.delete(id)
|
|
671
|
+
// No paired phone is left to answer the questions that wait for one: they go back to dsh's desktop.
|
|
672
|
+
if (devices.length === 0) for (const e of [...pendingEv.keys()]) dropPending(e, { kind: 'next' })
|
|
671
673
|
return devices.length !== before
|
|
672
674
|
}
|
|
673
675
|
function notify(msg) {
|
|
@@ -755,11 +757,13 @@ export function createGateway(opts = {}) {
|
|
|
755
757
|
if (v.type === 'cancel' && dropPending(v.eventId)) return toPhones({ type: 'cancel', eventId: v.eventId })
|
|
756
758
|
if (v.type !== 'waterfall') return
|
|
757
759
|
if (v.event === 'approval/request') return grantedOrAsk(v)
|
|
758
|
-
if (!EVENTS.has(v.event) ||
|
|
760
|
+
if (!EVENTS.has(v.event) || devices.length === 0) return answer(v.eventId, { kind: 'next' }).catch(() => {})
|
|
759
761
|
askPhones(v)
|
|
760
762
|
}
|
|
761
|
-
/** The gateway keeps an
|
|
762
|
-
* and Tether gets the ask when it connects. dsh's desktop can answer it at the same time.
|
|
763
|
+
/** The gateway keeps an approval for the phones while one is connected, or while a phone gets pushes: the push opens
|
|
764
|
+
* Tether, and Tether gets the ask when it connects. dsh's desktop can answer it at the same time. A question
|
|
765
|
+
* (`ask_user_question`) waits for a paired phone also while Tether is closed: dsh's "next" would leave it on the desktop
|
|
766
|
+
* only, and the phone that opens later could not answer it. The question still shows on the desktop meanwhile. */
|
|
763
767
|
const holds = () => evSubs.size > 0 || pushTo().length > 0
|
|
764
768
|
/** Allow for this chat, also with no dsh window open: the gateway allows a granted tool itself (the grants that the
|
|
765
769
|
* desktop and the phone save in dsh-composer-plus). Any other approval goes to the phones. */
|
|
@@ -776,8 +780,10 @@ export function createGateway(opts = {}) {
|
|
|
776
780
|
const frame = { type: 'waterfall', event: v.event, eventId: v.eventId, agentId: v.agentId, request: v.request }
|
|
777
781
|
if (v.event === 'approval/request') pushAll('Approval needed', v.request?.toolName, v.agentId)
|
|
778
782
|
else pushAll('DSH has a question', v.request?.questions?.[0]?.question, v.agentId)
|
|
779
|
-
// shortcut: unanswered
|
|
780
|
-
|
|
783
|
+
// shortcut: an unanswered approval falls back to 'next' (DSH desktop still decides) after a fixed timeout; make it configurable if users want longer.
|
|
784
|
+
// A question has no timeout: dsh waits for its answer, and the phone that opens hours later must still get it.
|
|
785
|
+
const timer = v.event === 'approval/request'
|
|
786
|
+
? setTimeout(() => { if (dropPending(v.eventId, { kind: 'next' })) toPhones({ type: 'cancel', eventId: v.eventId }) }, waterfallTtl) : undefined
|
|
781
787
|
pendingEv.set(v.eventId, { frame, timer })
|
|
782
788
|
toPhones(frame)
|
|
783
789
|
}
|
|
@@ -911,7 +917,11 @@ export function createGateway(opts = {}) {
|
|
|
911
917
|
// A failed connect (DSH restarting) is forgotten so the next stream open retries instead of failing forever.
|
|
912
918
|
const getUp = () => upP ??= upstream.mux().then(u => { up = u; u.onText = t => ws.send(t); u.onClose = () => ws.close(1011); return u }, e => { upP = null; throw e })
|
|
913
919
|
const err = (streamId, message) => ws.send(JSON.stringify({ type: 'error', streamId, error: { code: 'mobile/forbidden', message } }))
|
|
914
|
-
|
|
920
|
+
// The last phone left: its approvals go back to dsh's desktop; its questions keep waiting for the phone (askPhones).
|
|
921
|
+
const unsub = id => {
|
|
922
|
+
const s = subs.get(id); if (!s) return; subs.delete(id); evSubs.delete(s)
|
|
923
|
+
if (!holds()) for (const [e, p] of [...pendingEv]) if (p.frame.event === 'approval/request') dropPending(e, { kind: 'next' })
|
|
924
|
+
}
|
|
915
925
|
ws.onText = async text => {
|
|
916
926
|
let f
|
|
917
927
|
try { f = JSON.parse(text) } catch { return ws.close(1007) }
|