Files
qwen-code/integrations/external-context-mem0/examples/managed-auto-recall-user-settings-posix.json
qqqysandqwen-code-dev-bot f49dda1b2f fix(core)!: read command hook timeout in seconds (#11615)
* fix(core)!: read command hook timeout in seconds with a 600s default

Command hooks passed `timeout` to the timer as milliseconds, while HTTP
and prompt hooks read it as seconds, the settings schema described
seconds, and the hooks guide documented both. A command hook written
with `"timeout": 10` was killed after 10ms and failed open.

Command hook `timeout` is now read in seconds and defaults to 600s. A
value of 1000 or more is still read as milliseconds so existing settings
keep their meaning, and a debug-log warning names each such hook once.
Timeout errors report seconds. HTTP, prompt and function hooks are
unchanged. The schema description, generated JSON schema and every
command hook example in the guide now use seconds.

BREAKING CHANGE: a command hook `timeout` below 1000 is now seconds
rather than milliseconds.

Part of #11610

* fix(core): keep hook timeouts authoritative and surface legacy values

Review follow-up.

- Hook execution requests on the message bus no longer carry the bus's
  60-second default deadline, so a hook is bounded by its own timeout
  instead of being abandoned while it keeps running. Explicit caller
  timeouts and other request types are unchanged.
- Command hooks on MessageDisplay, StopFailure and SessionDelete, which
  outlive the CLI, default to 60 seconds instead of 600.
- Settings warnings now name each command hook whose timeout is still
  read as milliseconds; the advice never suggests a seconds value that
  would itself be read as milliseconds.
- The hooks guide scopes "seconds" to command, HTTP and prompt hooks and
  notes async slot usage; shipped external-context examples use seconds.
- Tests pin the async registration and supervisor deadlines, and reset
  the warning deduplication between cases.

Part of #11610

* docs(core): explain long command hook timeouts and blocking hold time

A command hook timeout of 1000 or more is still read as legacy
milliseconds, so a value meant as a long timeout in seconds, such as 1800
for 30 minutes, ends up as 1.8 seconds. The startup warning now also says
how to keep the value that was meant as seconds, and the hooks guide
explains that long timeouts stay in milliseconds. The guide also notes that
a synchronous hook on an event that waits for its result holds the turn
until it exits or times out, 600 seconds by default.

* fix(core): bound signal-less hook requests and cancel tool hooks on abort

The message bus now waives its default deadline only for hook execution
requests that carry an abort signal. Requests without one cannot be
cancelled, so they keep the 60-second deadline instead of waiting on the
hook's own timeout.

PreToolUse, PostToolUse and non-interrupt PostToolUseFailure hooks now
receive the tool's abort signal, in the payload and as the request signal,
so an abort stops the hook and releases the wait. Interrupt reports keep no
signal because it is already aborted there. The UserPromptSubmit hook gets
the send signal, and a send aborted during or right after that hook ends as
an abort instead of recording or sending the prompt.

MessageDisplay deliveries pass the turn signal to the request, warn when the
bus reports a failed hook execution, and stay quiet when the turn was
cancelled.

A command hook timeout written as a numeric string is read like the number
it holds instead of falling back to the default.

The startup warning for legacy millisecond timeouts is removed from this
change and tracked in #11675; the hooks guide now explains how to find such
hooks. Async hook timeout messages report seconds, the remaining first-party
millisecond values in integration fixtures and design docs are rewritten in
seconds, and the async hooks bullet names the 60-second default on events
whose hooks outlive the process.

* fix(core): keep the 60 second command hook default and drop hook bus signal threading

Raising the command hook default to 600 seconds forced two rounds of
reconciliation with the 60 second and 15 second bus deadlines: first by
waiving the deadline, then by threading abort signals through the tool
and prompt hook call sites. Each round produced new regressions (payload
vs request signal, already-aborted failure reports, unmigrated arity
assertions, orphaned hook children, cancels recorded as hook errors). The
default change and the cancellation work move to a follow-up issue, and
this change keeps only the unit.

- Command hook timeouts stay in seconds with a 60 second default, the
  same duration as before; values of 1000 or more keep their legacy
  millisecond meaning, and numeric strings are still coerced. The
  separate default for hooks that outlive the process is gone because it
  now equals the default.
- MessageBus, tool hook triggers, the scheduler, the UserPromptSubmit
  request, the MessageDisplay dispatcher and their tests are back to main.
- An unusable timeout such as "30s" is named in the debug log with the
  default it was replaced by, like a legacy millisecond value.
- Timeout warnings are recorded as sent only once debug logging can write
  them, and are deduplicated per session.
- Async hook timeout messages and a real spawned hook with timeout 1 now
  pin the seconds conversion.

---------

Co-authored-by: qwen-code-dev-bot <[email protected]>
2026-09-12 10:44:06 +00:00

20 lines
459 B
JSON

{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "exec '/absolute/path/to/node' '/administrator/path/to/external-context-mem0/dist/auto-recall.js'",
"timeout": 8,
"name": "external-context-mem0-auto-recall",
"statusMessage": "Retrieving external context"
}
]
}
]
},
"$version": 4
}