You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
QwenPaw 2.0.1b1, reproduced from source near commit 8c2cceff.
Description
Task tracking and same-session concurrency behave differently depending on
the execution entry point. Some paths serialize work, some attach to an
existing run while silently ignoring the new payload, and others allow
concurrent execution without registering the real task in TaskTracker.
This makes chat status, cancellation, graceful workspace reload, and session
state safety depend on how the run was started rather than on a documented
policy.
Examples:
External channel messages with the same (channel, session, priority) are
serialized by UnifiedQueueManager, while different priorities may run
concurrently for the same session.
A second /api/console/chat request for an active chat attaches to the
existing tracked run. Its new payload is not executed, and the API does not
report a conflict or queued status.
/api/console/chat/task bypasses both UnifiedQueueManager and TaskTracker, so multiple background tasks using the same session can run
concurrently.
Cron agent runs create a ChatSpec, but max_concurrency can permit
multiple executions that reuse the same job session.
Heartbeat runs use the shared main session and can be triggered manually
in addition to scheduled execution, but they do not explicitly create a ChatSpec or register the real execution in TaskTracker.
ACP maintains its own session registry and cancellation events. Concurrent
prompts for one ACP session are not explicitly rejected or serialized, and
a later prompt can replace the earlier _cancel_events[session_id] entry.
Security considerations: No direct data-exposure issue is known. However,
concurrent writes and incomplete cancellation can make tool execution and
session state harder to reason about.
Python version (if applicable): Python 3.12, conda environment
Steps to Reproduce
Submit two POST /api/console/chat/task requests with the same session_id before either task completes.
Observe that both tasks receive distinct task IDs and execute concurrently.
Query the chat list while they run. The chat can exist, but its status is
not backed by the actual background tasks in TaskTracker.
Submit two regular POST /api/console/chat requests for the same active
chat.
Observe that the second request attaches to the first run instead of
executing, queueing, or returning an explicit conflict.
Trigger /api/config/heartbeat/run while another main session run is
active, or trigger it repeatedly, and observe that no common per-session
concurrency policy is applied.
Actual vs Expected
Actual: Execution identity is sometimes a chat ID, sometimes an opaque
task ID, and sometimes absent from TaskTracker. Same-session work may be
serialized, merged, silently ignored, attached, or run concurrently based
on the entry point. request_stop() cannot cancel tasks that were never
registered with their actual asyncio.Task.
Expected: All execution paths should follow an explicit and testable
same-session concurrency policy. Every running operation should have a
unique execution ID, an optional chat association, accurate aggregate chat
status, and cancellation tied to the real task.
Logs / Screenshots
Relevant code paths:
src/qwenpaw/app/channels/unified_queue_manager.py
QueueKey = (channel_id, session_id, priority_level)
src/qwenpaw/app/channels/base.py
TaskTracker.attach_or_start(chat.id, ...)
Logs "Message ignored (task already running)" for an existing run.
src/qwenpaw/app/routers/console.py
/console/chat uses TaskTracker.attach_or_start(chat.id, ...)
/console/chat/task creates an independent asyncio task outside TaskTracker.
src/qwenpaw/app/crons/executor.py
Cron agent runs create or reuse a ChatSpec.
src/qwenpaw/app/crons/heartbeat.py
Heartbeat runs use session_id="main" and call workspace.stream_query().
src/qwenpaw/agents/acp/server.py
ACP prompt stores one cancel event per session ID and calls
workspace.stream_query() directly.
Additional Notes
Suggested design direction:
Give every execution a unique run_id or task_id.
Associate executions with an optional chat_id instead of using chat_id as the only TaskTracker key.
Allow TaskTracker to aggregate multiple running executions for one chat.
Register the real asyncio.Task so stop and shutdown operations cancel or
await the actual execution.
Define one policy for duplicate same-session work: queue, reject with an
explicit conflict, merge under documented rules, or allow controlled
concurrency. Avoid silently dropping the new payload.
Apply the policy consistently to Console streaming, background chat tasks,
external channels, cron, heartbeat, and ACP.
Suggested acceptance criteria:
Two runs for the same session have deterministic behavior documented by the
selected policy.
Chat status remains running until all associated executions finish.
Stop/cancel targets real executions and does not only update proxy state.
Workspace reload waits for or cancels all registered executions.
QwenPaw Version
QwenPaw 2.0.1b1, reproduced from source near commit
8c2cceff.Description
Task tracking and same-session concurrency behave differently depending on
the execution entry point. Some paths serialize work, some attach to an
existing run while silently ignoring the new payload, and others allow
concurrent execution without registering the real task in
TaskTracker.This makes chat status, cancellation, graceful workspace reload, and session
state safety depend on how the run was started rather than on a documented
policy.
Examples:
(channel, session, priority)areserialized by
UnifiedQueueManager, while different priorities may runconcurrently for the same session.
/api/console/chatrequest for an active chat attaches to theexisting tracked run. Its new payload is not executed, and the API does not
report a conflict or queued status.
/api/console/chat/taskbypasses bothUnifiedQueueManagerandTaskTracker, so multiple background tasks using the same session can runconcurrently.
ChatSpec, butmax_concurrencycan permitmultiple executions that reuse the same job session.
mainsession and can be triggered manuallyin addition to scheduled execution, but they do not explicitly create a
ChatSpecor register the real execution inTaskTracker.prompts for one ACP session are not explicitly rejected or serialized, and
a later prompt can replace the earlier
_cancel_events[session_id]entry.Related PR(s): #6272
Security considerations: No direct data-exposure issue is known. However,
concurrent writes and incomplete cancellation can make tool execution and
session state harder to reason about.
Component(s) Affected
Environment
8c2cceffSteps to Reproduce
POST /api/console/chat/taskrequests with the samesession_idbefore either task completes.not backed by the actual background tasks in
TaskTracker.POST /api/console/chatrequests for the same activechat.
executing, queueing, or returning an explicit conflict.
/api/config/heartbeat/runwhile anothermainsession run isactive, or trigger it repeatedly, and observe that no common per-session
concurrency policy is applied.
Actual vs Expected
task ID, and sometimes absent from
TaskTracker. Same-session work may beserialized, merged, silently ignored, attached, or run concurrently based
on the entry point.
request_stop()cannot cancel tasks that were neverregistered with their actual
asyncio.Task.same-session concurrency policy. Every running operation should have a
unique execution ID, an optional chat association, accurate aggregate chat
status, and cancellation tied to the real task.
Logs / Screenshots
Relevant code paths:
Additional Notes
Suggested design direction:
run_idortask_id.chat_idinstead of usingchat_idas the only TaskTracker key.asyncio.Taskso stop and shutdown operations cancel orawait the actual execution.
explicit conflict, merge under documented rules, or allow controlled
concurrency. Avoid silently dropping the new payload.
external channels, cron, heartbeat, and ACP.
Suggested acceptance criteria:
selected policy.
runninguntil all associated executions finish.cross-priority channel messages, heartbeat, cron concurrency, and ACP
prompts.