Skip to content

feat(hooks): follow Qwen Code per-hook fields#2094

Merged
dyoshikawa merged 2 commits into
mainfrom
resolve-issue-2069-qwencode-hook-fields
Jun 30, 2026
Merged

feat(hooks): follow Qwen Code per-hook fields#2094
dyoshikawa merged 2 commits into
mainfrom
resolve-issue-2069-qwencode-hook-fields

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Follow-up for Qwen Code upstream updates (#2069). Qwen Code's HTTP/Function/Async hooks (QwenLM/qwen-code#2827) added per-hook fields that rulesync's qwencode adapter dropped on generation. This adds them to the canonical hook schema and round-trips them through the qwencode adapter, type-gated by hook type.

Changes

  • src/types/hooks.ts: added async, env, shell, statusMessage, headers, allowedEnvVars, once to the canonical HookDefinitionSchema (modeling approach: extend the canonical looseObject schema, matching how existing per-hook fields like url/timeout/sequential are modeled; env/headers/allowedEnvVars are also shared with Copilot CLI, not qwencode-only).
  • src/features/hooks/qwencode-hooks.ts: emit (type-gated) in canonicalToQwencodeHooks and parse in qwencodeMatcherEntryToCanonical. Command-only fields (async/env/shell/statusMessage) never appear on http hooks and vice-versa for http-only fields (headers/allowedEnvVars/once); statusMessage applies to both per the docs.
  • src/features/hooks/copilotcli-hooks.ts: since env/headers/allowedEnvVars became canonical, copilotcli (which previously relied on non-canonical passthrough) now emits these natively-supported fields explicitly — no behavior regression.

Tests & docs

  • 6 round-trip tests (generate + import; command/http; cross-type leak checks).
  • Updated docs/reference/file-formats.md (+ synced skill copy).

Verification

pnpm cicheck fully green: 295 test files, 6601 tests; lint/typecheck, sync-skill-docs, gitignore, supported-tools, cspell, secretlint all pass.

References

Closes #2069

cm-dyoshikawa and others added 2 commits June 30, 2026 11:07
…Message/headers/allowedEnvVars/once)

Qwen Code PR #2827 added per-hook fields that rulesync's qwencode hooks adapter dropped on generation: command hooks gained async/env/shell/statusMessage and http hooks gained headers/allowedEnvVars/once (statusMessage applies to both).

Add these fields to the canonical HookDefinitionSchema (following the existing precedent of url/failClosed/sequential being modeled as canonical per-hook fields) and emit/parse them in canonicalToQwencodeHooks and qwencodeMatcherEntryToCanonical. Command-only fields are emitted only on command hooks and http-only fields only on http hooks, matching upstream.

Because copilotcli's hooks adapter passes through non-canonical keys by filtering out HookDefinitionSchema.shape, promoting env/headers/allowedEnvVars to canonical required copilotcli to emit those natively-supported fields explicitly; do so to keep its round-trip intact.

Both project and global scope are covered (the converter is scope-agnostic). Adds round-trip tests for each field and updates the file-formats docs.

Resolves #2069

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pact helper

Address PR review: gate command-only fields (async/env/shell) on the command hook type explicitly instead of not-http (so prompt/function hooks don't get them), apply safeString to env/headers values and shell to block control-character injection into generated env vars/HTTP headers, and extract the duplicated undefined/null-stripping helper into src/utils/object.ts (compact) used by both qwencode and copilotcli adapters.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dyoshikawa
dyoshikawa merged commit 8f56c63 into main Jun 30, 2026
8 checks passed
@dyoshikawa
dyoshikawa deleted the resolve-issue-2069-qwencode-hook-fields branch June 30, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Follow up Qwen Code upstream updates: hooks per-hook fields (async/env/shell/statusMessage/headers/allowedEnvVars/once)

2 participants