Files
雷电芽衣 bc6983a62e chore(oss): audit the server package and resync the SDK mirrors
Split the 657-line operation service into eor, submit, and verify
modules, add the AGENT_REVOKED and KEY_RETIRED codes the Backend already
emits, and condense every multi-line comment. Mirror Node, Python, and
Go at 2.1.0 with the deep-health 503, non-idempotent retry, rotation
grace, and path-encoding fixes. Document which routes and response
fields the self-hosted server does not provide.

Claude-Session: https://claude.ai/code/session_01Agoc9bRVE9KL7mmWtey9Vq
2026-09-03 20:48:20 -04:00

123 lines
3.0 KiB
Go

package plugins
import "fmt"
// QwenPlugin manages Qwen Code native user hooks.
type QwenPlugin struct {
rename renameFunc
}
// ManagesGuardRuntime reports that Qwen commits its guard, audit runtime, and
// settings in one transaction.
func (p *QwenPlugin) ManagesGuardRuntime() bool {
return true
}
// PreflightInstall validates every effective source and runtime identity before
// the CLI writes any managed file.
func (p *QwenPlugin) PreflightInstall(config InstallConfig) error {
sources, err := readQwenSources()
if err != nil {
return err
}
_, _, err = preflightQwenInstallation(config, sources)
return err
}
func qwenInstalledGroups(
nodePath, guardPath, auditPath string,
) map[string]map[string]any {
return map[string]map[string]any{
"PreToolUse": buildQwenGroup(nodePath, guardPath, qwenGuardHookName),
"PostToolUse": buildQwenGroup(nodePath, auditPath, qwenAuditHookName),
"PostToolUseFailure": buildQwenGroup(
nodePath,
auditPath,
qwenAuditHookName,
),
}
}
func (p *QwenPlugin) Install(config InstallConfig) error {
sources, err := readQwenSources()
if err != nil {
return err
}
paths, nodePath, err := preflightQwenInstallation(config, sources)
if err != nil {
return err
}
rendered, err := renderQwenDocument(
sources.user,
"",
paths.runtimeRoot,
qwenInstalledGroups(nodePath, paths.guardPath, paths.auditPath),
)
if err != nil {
return err
}
prepared, err := prepareQwenInstallation(config, sources, rendered)
if err != nil {
return err
}
if err := commitQwenInstallation(prepared, p.rename); err != nil {
return err
}
fmt.Printf("Qwen Code hooks: %s\n", sources.user.filePath)
fmt.Println("Qwen Code verification: run /hooks.")
return nil
}
func (p *QwenPlugin) Uninstall(agentID string) error {
sources, err := readQwenSources()
if err != nil {
return err
}
runtimeRoot, err := AgentRuntimeRoot()
if err != nil {
return err
}
rendered, err := renderQwenDocument(
sources.user,
agentID,
runtimeRoot,
map[string]map[string]any{},
)
if err != nil {
return err
}
if !rendered.changed {
return nil
}
change, preconditions, err := prepareQwenUninstall(sources, rendered)
if err != nil {
return err
}
return commitQwenUninstall(change, preconditions, p.rename)
}
func (p *QwenPlugin) Status() (PluginStatus, error) {
entry := SupportedAgents[qwenAgentKey]
status := PluginStatus{AgentName: qwenAgentKey, DisplayName: entry.Name}
sources, err := readQwenSources()
if err != nil {
return status, err
}
status.ConfigPath = sources.user.filePath
runtimeRoot, err := AgentRuntimeRoot()
if err != nil {
return status, err
}
contracts := qwenRuntimeContracts(sources.user.hooks, runtimeRoot)
status.HookConfigured = !sources.disableControl.disabled && len(contracts) > 0
if !status.HookConfigured {
return status, nil
}
status.HookScriptExists, err = qwenRuntimeFilesExist(contracts)
if err != nil {
return status, err
}
status.Installed = status.HookScriptExists
return status, nil
}