fix(office-ui): native progress parity, ui_state lock hardening, approval-card idempotency
Native agent progress panel (company mode): - ws_handler: filter runtime bookkeeping noise (turn/status/member_inbox_updated), keep tool_completed as tool_call, thinking summary previews content, preserve raw thinking_delta fragments (no strip; skip whitespace-only) - frontend progressLog: summarize thinking by content preview; merge thinking by detail only so the 'Thinking' label never splices into text - AgentProgressBlock: add bottom "Show more (N earlier steps)" toggle ui_state.db "database is locked" hardening: - ws_handler: isolate engine progress/kanban/runtime-event callbacks so UI persistence failures never crash work items - chat_store: busy_timeout, _retry_locked backoff, idempotent insert_message (INSERT OR REPLACE), create_channel read-before-write to stop poll writes - server: flock single-instance guard for `opc ui` per OPC home Approval card duplicate-click bug: - EscalationPanel: disable buttons on click with Submitting state and 30s reconnect fallback - ws_handler: stale-escalation branch checks real card status (new chat_store.get_checkpoint_message); already-resolved cards get an accurate "already handled (decision: X)" reply without being re-marked stale; dedup identical helper messages within 120s to stop reply spam Company mode prompt: - add soft guidance that the runtime monitors state and re-activates roles, so leaders need not poll work items after delegation/review Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,9 +28,41 @@ for (const [seq, detail] of [
|
||||
}
|
||||
|
||||
assert.equal(log.length, 1)
|
||||
assert.equal(log[0]?.summary, 'Thinking')
|
||||
assert.equal(log[0]?.summary, '我先联网抓取')
|
||||
assert.equal(log[0]?.detail, '我先联网抓取')
|
||||
|
||||
// Token-sized streaming fragments keep their whitespace when merged, and
|
||||
// entries without detail never splice their summary label into the text.
|
||||
let spacedLog = appendProgressEntry([], {
|
||||
timestamp: 100,
|
||||
type: 'thinking',
|
||||
summary: 'The user',
|
||||
detail: 'The user',
|
||||
turnId: 'rt-2:1',
|
||||
itemId: 'rt-2:1:thinking',
|
||||
seq: 1,
|
||||
})
|
||||
spacedLog = appendProgressEntry(spacedLog, {
|
||||
timestamp: 101,
|
||||
type: 'thinking',
|
||||
summary: 'wants to',
|
||||
detail: ' wants to',
|
||||
turnId: 'rt-2:1',
|
||||
itemId: 'rt-2:1:thinking',
|
||||
seq: 2,
|
||||
})
|
||||
spacedLog = appendProgressEntry(spacedLog, {
|
||||
timestamp: 102,
|
||||
type: 'thinking',
|
||||
summary: 'Thinking',
|
||||
turnId: 'rt-2:1',
|
||||
itemId: 'rt-2:1:thinking',
|
||||
seq: 3,
|
||||
})
|
||||
assert.equal(spacedLog.length, 1)
|
||||
assert.equal(spacedLog[0]?.detail, 'The user wants to')
|
||||
assert.equal(spacedLog[0]?.summary, 'The user wants to')
|
||||
|
||||
const unchanged = appendProgressEntry(log, {
|
||||
timestamp: 5,
|
||||
type: 'thinking',
|
||||
|
||||
Reference in New Issue
Block a user