{"record":{"id":"49a29a515ccd9d78","repo":"siyuan-note/siyuan","slug":"injectagent-v","errorCode":null,"errorMessage":"injectAgent: %v","messagePattern":"injectAgent: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/plugin/api_agent.go","lineNumber":49,"sourceCode":"\n// pluginCapabilityModelName 构造内核插件能力向模型暴露的函数名。\nfunc pluginCapabilityModelName(pluginName, capabilityName string) string {\n\tname := fmt.Sprintf(\"plugin__%s__%s\", util.SanitizeName(pluginName), util.SanitizeName(capabilityName))\n\thash := sha256.Sum256([]byte(pluginName + \"\\x00\" + capabilityName))\n\tsuffix := fmt.Sprintf(\"__%x\", hash[:6])\n\tif len(name) > maxCapabilityModelNameLen-len(suffix) {\n\t\tname = name[:maxCapabilityModelNameLen-len(suffix)]\n\t}\n\treturn name + suffix\n}\n\nconst maxCapabilityModelNameLen = 64\n\n// injectAgent 将 siyuan.agent 注入插件 JS 沙箱。\nfunc injectAgent(p *KernelPlugin, rt *goja.Runtime, siyuan *goja.Object) (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"injectAgent: %v\", r)\n\t\t}\n\t}()\n\n\tagentAPI := rt.NewObject()\n\n\t// siyuan.agent.registerCapability(name, config, handler) 返回 Promise<IRegisteredCapability>。\n\tlo.Must0(agentAPI.Set(\"registerCapability\", rt.ToValue(func(call goja.FunctionCall, rt *goja.Runtime) goja.Value {\n\t\tpromise, resolve, reject := rt.NewPromise()\n\n\t\tvar name string\n\t\tvar title string\n\t\tvar description string\n\t\tvar effects *tools.ToolEffects\n\t\tvar actionEffects map[string]tools.ToolEffects\n\t\tvar inputSchema *tools.ToolSchema\n\t\tvar outputSchema *tools.ToolSchema\n\t\tvar handler goja.Callable\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/plugin/api_agent.go#L31-L67","documentation":"injectAgent injects the siyuan.agent API into a kernel plugin's goja JS sandbox. The whole injection is wrapped in a recover() so any panic inside goja (runtime mismatch, nil object, scripting engine error) is converted into this wrapped error instead of crashing the kernel.","triggerScenarios":"Plugin loading/initialization reaches injectAgent and a panic occurs while building the agent API object or registering registerCapability on the goja runtime — surfaced as \"injectAgent: <panic value>\".","commonSituations":"Buggy plugin runtime setup, goja runtime closed or used from the wrong goroutine, or an internal kernel regression while wiring the agent API during plugin startup.","solutions":["Read the wrapped %v payload to identify the underlying panic and fix the root cause.","Ensure the plugin worker's goja runtime is alive and only accessed from its own run loop when injection happens.","Retry plugin load after fixing; if reproducible with a minimal plugin, report it as a kernel bug since plugin JS cannot normally panic Go code."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Kernel-side recover already wraps the panic; consumers of plugin load should catch:\nif err := injectAgent(p, rt, siyuan); err != nil {\n  log.Fatalf(\"plugin %s agent injection failed: %v\", p.Name, err)\n}","preventionTips":["Only touch the goja runtime from its owning worker goroutine.","Keep goja and kernel versions in sync when rebuilding.","Report reproducible panics with a minimal plugin — they indicate kernel bugs."],"tags":["plugin","goja","panic-recovery","initialization"],"backgroundTag":"module-init-failed","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}