Proposal visibility is already global; this change makes finish, stop,
and cancel shared queue-management actions so any user can unblock the
single worker and shared queue. Confirm, adjust, follow_up, and
start_next remain owner-only. Assistant/bootstrap copy, /help, /list,
and runtime checks now align with that split.
The unfinished-proposal board is now visible to every conversation,
with entries marked scope=own/scope=other (chat type only, no IDs), so
anyone can see what the single worker is busy with. All actions remain
owner-only, and pending reminders still target only the owner.
Non-owners now see the same real-time status card as the owner, marked
as another user's proposal, instead of a desensitized busy line. This
is a debugging-phase relaxation; restore owner-only visibility for
production.
While a worker turn is running, the assistant prompt for the working
proposal's owner includes a compact status card (elapsed time, last
tool activity category with age, per-category counts) built from the
ACP session/update stream the runtime already receives. Other users
still see only the desensitized busy state, and raw update content
never enters the assistant session.
When a conversation's assistant session has been idle longer than
runtime.acp.assistantSessionResetIdleMs (default 1h, 0 disables) and
its owner has no unfinished proposals, the next inbound message starts
a fresh session instead of resuming. Binding lastActiveAt is persisted
per turn so the decision survives restarts.
Models occasionally drop the closing tag of the result envelope while
the JSON itself is complete; the strict parser rejected these and one
repair attempt could not always recover, cascading into worker_error
and dropping valid attachments. The parser now falls back to
brace-balanced salvage when the closing tag is missing, and worker
lifecycle events (start, resume, invalid envelope, repair, settle,
worker_error) are logged.
Worker results may report image attachments stored inside the workspace;
the runtime validates them (containment, png/jpg magic, size) and
delivers them with the pending event. Assistants gain a send_image
action so users can ask for an image later. QQ uploads via /files with
base64 file_data and sends msg_type 7 rich media, sharing the same
msg_id/msg_seq counter as text replies; non-image adapters flatten
images to text.
Proposal semantics: worker results no longer distinguish success/fail;
only an explicit finish settles a pending proposal. Pending owner input
follows up by resuming the original worker session. Dirty pending blocks
start_next globally; clean pending only blocks its owner.
QQ adapter now downloads image attachments and passes them as ACP image
content blocks; video/file attachments degrade to link text.