dsh-thoughtdag 0.4.16 → 0.4.17
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/dist-app/assets/{canonical-ChxvAi6N.js → canonical-D4SquoNo.js} +2 -2
- package/dist-app/assets/{canvas-record-Be2aKIf8.js → canvas-record--EHyNDCM.js} +1 -1
- package/dist-app/assets/{claude-code-session-B51keZPd.js → claude-code-session-CJTZw-s-.js} +1 -1
- package/dist-app/assets/{codex-session-BR_x_Fzf.js → codex-session-kzdkETJK.js} +1 -1
- package/dist-app/assets/{dsh-session-D0yZa0_o.js → dsh-session-DrnTTQ3v.js} +1 -1
- package/dist-app/assets/{experiment-loop-pAs6MwPV.js → experiment-loop-BysOJBTB.js} +1 -1
- package/dist-app/assets/{index-JMt9ljo3.js → index-C1uc774A.js} +11 -11
- package/dist-app/assets/{index-DvBTIsHr.js → index-DE_CLHc3.js} +1 -1
- package/dist-app/assets/{index-_B6z8_Ff.js → index-DMEJ2pfg.js} +3 -3
- package/dist-app/assets/{index-962V9CYS.js → index-k_sPEfl2.js} +1 -1
- package/dist-app/assets/{live-mirror-C9sTXAvv.js → live-mirror-CkSO5X2s.js} +2 -2
- package/dist-app/assets/{pi-session-B7frsRRp.js → pi-session-CIlDUNBG.js} +1 -1
- package/dist-app/assets/{sensitive-scan-Cwg4RAEk.js → sensitive-scan-OXO0A60C.js} +1 -1
- package/dist-app/assets/{session-handoff-BXosSY-e.js → session-handoff-DF4fnjEz.js} +2 -2
- package/dist-app/assets/{shared-L3KzXorg.js → shared-ClPLXGBi.js} +1 -1
- package/dist-app/assets/{turndown-plugin-gfm.cjs-pG4f1F8S.js → turndown-plugin-gfm.cjs-DeGwvSez.js} +1 -1
- package/dist-app/assets/{update-check-lHz7ROW6.js → update-check-CNsM71E0.js} +1 -1
- package/dist-app/index.html +1 -1
- package/lib/index.js +34 -6
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -639,6 +639,9 @@ function installApprovalAnswerer(ctx) {
|
|
|
639
639
|
ctx.on('approval/request', async function (req, next) {
|
|
640
640
|
const entry = canvasTurns.get(req?.agent?.id)
|
|
641
641
|
if (!entry) return next()
|
|
642
|
+
// an approval raised by another turn of the same session (the person's
|
|
643
|
+
// own tool call, running before or after ours) stays with the harness UI
|
|
644
|
+
if (entry.turn === null || entry.current() !== entry.turn) return next()
|
|
642
645
|
const id = 'td-' + randomUUID()
|
|
643
646
|
const call = req.callId !== undefined ? entry.calls.get(req.callId) : undefined
|
|
644
647
|
const name = call?.name ?? req.toolName
|
|
@@ -698,7 +701,9 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
698
701
|
emit({ harnessSession: sessionId, continued: sessionId === continueId, ...(forkedFrom ? { forkedFrom } : {}) })
|
|
699
702
|
// a streaming caller can show and answer approvals; a one-shot caller
|
|
700
703
|
// (/claude) cannot, so its requests fall through to the harness's own panel
|
|
701
|
-
|
|
704
|
+
// turn/current are filled once our message enters the session: the approval
|
|
705
|
+
// answerer uses them to take only the approvals our turn raises
|
|
706
|
+
const turnEntry = { emit, isClosed, calls: new Map(), turn: null, current: () => null }
|
|
702
707
|
if (answerApprovals) canvasTurns.set(sessionId, turnEntry)
|
|
703
708
|
const hasImages = Array.isArray(body?.images) && body.images.length > 0
|
|
704
709
|
if (hasImages) {
|
|
@@ -714,17 +719,40 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
714
719
|
let fullText = ''
|
|
715
720
|
let done
|
|
716
721
|
const finished = new Promise(resolve => { done = resolve })
|
|
722
|
+
// The session is shared with the person chatting in the harness: their
|
|
723
|
+
// turns may run before, after or around ours (ours is queued behind
|
|
724
|
+
// whatever is running). Everything below is scoped to OUR turn. dsh stamps
|
|
725
|
+
// the prompt's requestId on the user message it creates (source.rpcId), so
|
|
726
|
+
// that message is recognised exactly; it names our turn, and only that
|
|
727
|
+
// turn's text, tool calls, approvals and end belong to this node (#42).
|
|
728
|
+
const requestId = 'td-' + randomUUID()
|
|
717
729
|
let currentTurn = null
|
|
730
|
+
let ourTurn = null
|
|
731
|
+
let ourMessagePending = false
|
|
732
|
+
const claimTurn = (turn) => { ourTurn = turn; turnEntry.turn = turn }
|
|
733
|
+
const isOurs = (event) => ourTurn !== null && (typeof event.data?.turn === 'number' ? event.data.turn === ourTurn : currentTurn === ourTurn)
|
|
734
|
+
turnEntry.current = () => currentTurn
|
|
718
735
|
const off = ctx.on('session/event', (session, event) => {
|
|
719
736
|
if (session?.id !== sessionId || !event) return
|
|
720
|
-
if (event.type === 'turn/start') {
|
|
737
|
+
if (event.type === 'turn/start') {
|
|
738
|
+
currentTurn = event.data?.turn ?? null
|
|
739
|
+
if (ourMessagePending && currentTurn !== null) { ourMessagePending = false; claimTurn(currentTurn) }
|
|
740
|
+
return
|
|
741
|
+
}
|
|
721
742
|
// the person's question entering the surface: THIS is the turn the
|
|
722
743
|
// canvas node stands for — with its id the canvas marks the node as the
|
|
723
|
-
// mirror of that turn, and the live mirror does not append it a second
|
|
724
|
-
|
|
725
|
-
|
|
744
|
+
// mirror of that turn, and the live mirror does not append it a second
|
|
745
|
+
// time. Only our own message counts; a message the person typed in the
|
|
746
|
+
// chat meanwhile belongs to their turn, not to this node.
|
|
747
|
+
if (event.type === 'user/message') {
|
|
748
|
+
const source = event.data?.source
|
|
749
|
+
if (ourTurn === null && !ourMessagePending && (source?.kind ?? 'user') === 'user' && source?.rpcId === requestId) {
|
|
750
|
+
if (currentTurn === null) ourMessagePending = true; else claimTurn(currentTurn)
|
|
751
|
+
emit({ harnessTurn: { session: sessionId, turn: currentTurn, userMessageId: event.data?.id ?? null, seq: event.seq ?? null } })
|
|
752
|
+
}
|
|
726
753
|
return
|
|
727
754
|
}
|
|
755
|
+
if (!isOurs(event)) return
|
|
728
756
|
if (event.type === 'assistant/chunk') {
|
|
729
757
|
const c = event.data?.chunk
|
|
730
758
|
if (c?.type === 'text-delta' && c.text) { sawChunk = true; fullText += c.text; emit({ text: c.text }) }
|
|
@@ -748,7 +776,7 @@ async function runAgentTurn(ctx, body, emit, isClosed, { answerApprovals = true
|
|
|
748
776
|
for (const img of Array.isArray(body?.images) ? body.images : []) {
|
|
749
777
|
if (img && typeof img.data === 'string' && IMAGE_MEDIA.has(img.mimeType)) promptContent.push({ type: 'image', mediaType: img.mimeType, data: img.data })
|
|
750
778
|
}
|
|
751
|
-
await ctx.sessionController.prompt({ requestId
|
|
779
|
+
await ctx.sessionController.prompt({ requestId, sessionId, mode: 'queue', content: promptContent }, AbortSignal.timeout(30000))
|
|
752
780
|
const timeout = new Promise(resolve => setTimeout(resolve, 20 * 60 * 1000))
|
|
753
781
|
const closed = new Promise(resolve => { const t = setInterval(() => { if (isClosed()) { clearInterval(t); resolve() } }, 500); finished.then(() => clearInterval(t)) })
|
|
754
782
|
await Promise.race([finished, agent.whenIdle().then(() => finished), timeout, closed])
|
package/package.json
CHANGED