fix: await queue mutations and repair editing actions

This commit is contained in:
Agent committed 2026-10-13 12:09:42 +00:00
1 parent c9856f7096
commit 6a8764c464
2 files changed
+4 -4

No files matched your search

+3 -3
View File
@@ -60,14 +60,14 @@ window.__ModuleLoader__.load({
const move = (id, target) => { setAssign((v) => ({...v, [id]: target})); setTab(target); }; const move = (id, target) => { setAssign((v) => ({...v, [id]: target})); setTab(target); };
const startEdit = (row) => setEditing({ id: row.id, value: drafts[row.id] ?? rowText(row) }); const startEdit = (row) => setEditing({ id: row.id, value: drafts[row.id] ?? rowText(row) });
const cancelEdit = () => { if (editing) setDrafts((v) => ({...v, [editing.id]: editing.value})); setEditing(null); }; const cancelEdit = () => { if (editing) setDrafts((v) => ({...v, [editing.id]: editing.value})); setEditing(null); };
const saveEdit = async () => { if (!editing || !editing.value.trim()) return; setBusy(editing.id); try { await updateQueue(editing.id, {kind:'edit', content:[{type:'text', text:editing.value}]}); setDrafts((v) => { const n={...v}; delete n[editing.id]; return n; }); setEditing(null); } catch { notify('error', 'Queue edit failed'); } finally { setBusy(null); } }; const saveEdit = async () => { if (!editing || !editing.value.trim()) return false; const id = editing.id; const value = editing.value; setBusy(id); try { await Promise.resolve(updateQueue(id, {kind:'edit', content:[{type:'text', text:value}]})); setDrafts((v) => { const n={...v}; delete n[id]; return n; }); setEditing(null); return true; } catch { notify('error', 'Queue edit failed'); return false; } finally { setBusy(null); } };
const action = async (id, value) => { setBusy(id); try { await updateQueue(id, value); setDrafts((v) => { const n={...v}; delete n[id]; return n; }); } catch { notify('error', 'Queue action failed'); } finally { setBusy(null); } }; const action = async (id, value) => { setBusy(id); try { await Promise.resolve(updateQueue(id, value)); setDrafts((v) => { const n={...v}; delete n[id]; return n; }); } catch { notify('error', 'Queue action failed'); } finally { setBusy(null); } };
const drop = (targetId) => { if (!drag || drag.id === targetId) return; const ids = sorted.map((r) => r.id).filter((id) => id !== drag.id); const at = ids.indexOf(targetId); ids.splice(Math.max(0, at), 0, drag.id); setOrder(ids); if (drag.list !== tab) move(drag.id, tab); setDrag(null); }; const drop = (targetId) => { if (!drag || drag.id === targetId) return; const ids = sorted.map((r) => r.id).filter((id) => id !== drag.id); const at = ids.indexOf(targetId); ids.splice(Math.max(0, at), 0, drag.id); setOrder(ids); if (drag.list !== tab) move(drag.id, tab); setDrag(null); };
if (!rows.length) return null; if (!rows.length) return null;
const Item = ({ row }) => { const isEdit = editing?.id === row.id; const draft = drafts[row.id]; return h('li', { className: `dqs-row${isEdit?' editing':''}${drag?.over===row.id?' over':''}`, draggable: !isEdit, onDragStart: () => setDrag({id:row.id,list:tab}), onDragOver: (e) => { e.preventDefault(); setDrag((v) => v && ({...v, over:row.id})); }, onDrop: () => drop(row.id), onDragEnd: () => setDrag(null) }, h('span',{className:'dqs-grip','aria-hidden':true},'⋮⋮'), isEdit ? h('textarea',{className:'dqs-editor',autoFocus:true,value:editing.value,onChange:(e)=>setEditing({...editing,value:e.target.value}),onKeyDown:(e)=>{if(e.key==='Escape')cancelEdit();if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();saveEdit();}}}) : h('span',{className:'dqs-preview'}, draft || rowText(row)), draft && !isEdit && h('small',{className:'dqs-draft'},'draft'), h('span',{className:'dqs-actions'}, isEdit ? [h('button',{key:'save',className:'dqs-action',disabled:!!busy,onClick:saveEdit},icon('IconCheckOutlineRegular','✓')),h('button',{key:'cancel',className:'dqs-action',disabled:!!busy,onClick:cancelEdit},icon('IconCloseOutlineRegular','×'))] : [h('button',{key:'edit',className:'dqs-action',disabled:!!busy,onClick:()=>startEdit(row)},icon('IconEditOutlineRegular','✎')),h('button',{key:'move',className:'dqs-action',disabled:!!busy,onClick:()=>move(row.id,tab==='batch'?'sequential':'batch')},tab==='batch'?'⇢':'⇠'),h('button',{key:'steer',className:'dqs-action',disabled:!!busy||!running,onClick:()=>action(row.id,{kind:'steer'})},icon('IconSendOutlineRegular','➤')),h('button',{key:'remove',className:'dqs-action',disabled:!!busy,onClick:()=>action(row.id,{kind:'remove'})},icon('IconTrashOutlineRegular','×'))])); }; const Item = ({ row }) => { const isEdit = editing?.id === row.id; const draft = drafts[row.id]; return h('li', { className: `dqs-row${isEdit?' editing':''}${drag?.over===row.id?' over':''}`, draggable: !isEdit, onDragStart: () => setDrag({id:row.id,list:tab}), onDragOver: (e) => { e.preventDefault(); setDrag((v) => v && ({...v, over:row.id})); }, onDrop: () => drop(row.id), onDragEnd: () => setDrag(null) }, h('span',{className:'dqs-grip','aria-hidden':true},'⋮⋮'), isEdit ? h('textarea',{className:'dqs-editor',autoFocus:true,value:editing.value,onChange:(e)=>setEditing({...editing,value:e.target.value}),onKeyDown:(e)=>{if(e.key==='Escape')cancelEdit();if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();saveEdit();}}}) : h('span',{className:'dqs-preview'}, draft || rowText(row)), draft && !isEdit && h('small',{className:'dqs-draft'},'draft'), h('span',{className:'dqs-actions'}, isEdit ? [h('button',{key:'save',className:'dqs-action',disabled:!!busy,onClick:saveEdit},icon('IconCheckOutlineRegular','✓')),h('button',{key:'cancel',className:'dqs-action',disabled:!!busy,onClick:cancelEdit},icon('IconCloseOutlineRegular','×'))] : [h('button',{key:'edit',className:'dqs-action',disabled:!!busy,onClick:()=>startEdit(row)},icon('IconEditOutlineRegular','✎')),h('button',{key:'move',className:'dqs-action',disabled:!!busy,onClick:()=>move(row.id,tab==='batch'?'sequential':'batch')},tab==='batch'?'⇢':'⇠'),h('button',{key:'steer',className:'dqs-action',disabled:!!busy||!running,onClick:()=>action(row.id,{kind:'steer'})},icon('IconSendOutlineRegular','➤')),h('button',{key:'remove',className:'dqs-action',disabled:!!busy,onClick:()=>action(row.id,{kind:'remove'})},icon('IconTrashOutlineRegular','×'))])); };
return h('div',{className:'dqs-dock','data-queue-dock':'dsh-queue-steer'},h('div',{className:'dqs-panel'},h('button',{className:'dqs-header',onClick:()=>setOpen(!open)},icon('IconQueueOutlineRegular','☷'),h('span',{className:'dqs-count'},`Queue & Steering (${rows.length})`),h('span',null,open?'⌃':'⌄')),open && h(React.Fragment,null,h('div',{className:'dqs-tabs'},h('button',{className:`dqs-tab ${tab==='batch'?'active':''}`,onClick:()=>{setTab('batch');write(`${sessionId}:tab`,'batch')}},`List 1 · all at once (${sorted.filter((r)=>listOf(r)==='batch').length})`),h('button',{className:`dqs-tab ${tab==='sequential'?'active':''}`,onClick:()=>{setTab('sequential');write(`${sessionId}:tab`,'sequential')}},`List 2 · one at a time (${sorted.filter((r)=>listOf(r)==='sequential').length})`)),visible.length?h('ul',{className:'dqs-list'},visible.map((r)=>h(Item,{key:r.id,row:r}))):h('div',{className:'dqs-empty'},'No entries in this list')))); return h('div',{className:'dqs-dock','data-queue-dock':'dsh-queue-steer'},h('div',{className:'dqs-panel'},h('button',{className:'dqs-header',onClick:()=>setOpen(!open)},icon('IconQueueOutlineRegular','☷'),h('span',{className:'dqs-count'},`Queue & Steering (${rows.length})`),h('span',null,open?'⌃':'⌄')),open && h(React.Fragment,null,h('div',{className:'dqs-tabs'},h('button',{className:`dqs-tab ${tab==='batch'?'active':''}`,onClick:()=>{setTab('batch');write(`${sessionId}:tab`,'batch')}},`List 1 · all at once (${sorted.filter((r)=>listOf(r)==='batch').length})`),h('button',{className:`dqs-tab ${tab==='sequential'?'active':''}`,onClick:()=>{setTab('sequential');write(`${sessionId}:tab`,'sequential')}},`List 2 · one at a time (${sorted.filter((r)=>listOf(r)==='sequential').length})`)),visible.length?h('ul',{className:'dqs-list'},visible.map((r)=>h(Item,{key:r.id,row:r}))):h('div',{className:'dqs-empty'},'No entries in this list'))));
} }
return { inject: ['slots', 'conversation'], apply(ctx) { installCss(); ctx.slots.inject('settings.section', () => ctx.slots.register({name:'settings.section', id:'dsh-queue-steer', order:170, label:'Queue & Steering'}, SettingsPanel)); ctx.slots.inject('conversation.input.dock', () => ctx.slots.register({name:'conversation.input.dock', id:'queue', priority:-1, order:20, inject:(sessionId)=>({updateQueue:(id,a)=>ctx.conversation.updateQueue(id,a), notify:(level,msg)=>ctx.conversation.input.for(ctx.sessions.scope(sessionId)).notify(level,msg)})}, QueueDock)); } }; return { inject: ['slots', 'conversation', 'sessions'], apply(ctx) { installCss(); ctx.slots.inject('settings.section', () => ctx.slots.register({name:'settings.section', id:'dsh-queue-steer', order:170, label:'Queue & Steering'}, SettingsPanel)); ctx.slots.inject('conversation.input.dock', () => ctx.slots.register({name:'conversation.input.dock', id:'queue', priority:-1, order:20, inject:(sessionId)=>{ const actx = ctx.sessions.scope(sessionId); const conversation = actx.get('conversation'); return { updateQueue:(id,a)=>conversation.updateQueue(id,a), notify:(level,msg)=>conversation.input.for(actx).notify(level,msg) }; }}, QueueDock)); } };
} }
}); });
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@local/dsh-queue-steer", "name": "@local/dsh-queue-steer",
"version": "0.2.0", "version": "0.2.1",
"description": "Custom queue and steering logic, settings page, /queue and /steer commands, and two-list queue widget for DeepSeek Harness.", "description": "Custom queue and steering logic, settings page, /queue and /steer commands, and two-list queue widget for DeepSeek Harness.",
"type": "module", "type": "module",
"main": "index.js", "main": "index.js",