{"record":{"id":"1858e414914fb822","repo":"moeru-ai/airi","slug":"toolkit-requires-a-host-tool-registry-runtime","errorCode":null,"errorMessage":"toolKit requires a host tool registry runtime.","messagePattern":"toolKit requires a host tool registry runtime\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk-tamagotchi/src/tools/index.ts","lineNumber":296,"sourceCode":" *\n * Expects:\n * - The host provides tool registry APIs when creating the kit client\n *\n * Returns:\n * - A client that registers LLM tools without depending on domain-specific kits\n */\nexport const toolKit = defineKit<ToolKitClient>({\n  id: 'kit.tool',\n  version: '1.0.0',\n  allowedExposePolicies: ['local-only', 'remote-observable'],\n  defaultExposePolicy: 'local-only',\n  createClient(runtime) {\n    const toolRuntime = runtime as ToolKitRuntime\n\n    return {\n      async registerTool(definition) {\n        if (!toolRuntime.tools) {\n          throw new Error('toolKit requires a host tool registry runtime.')\n        }\n\n        const isAvailable = definition.isAvailable\n\n        await toolRuntime.tools.register({\n          tool: {\n            id: definition.id,\n            title: definition.title,\n            description: definition.description,\n            activation: {\n              keywords: definition.activation?.keywords ?? [],\n              patterns: (definition.activation?.patterns ?? []).map(pattern => pattern.source),\n            },\n            parameters: await serializeToolParameters(definition.inputSchema),\n          },\n          availability: isAvailable,\n          execute: definition.execute,\n        })","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/plugin-sdk-tamagotchi/src/tools/index.ts#L278-L314","documentation":"toolKit (kit.tool in plugin-sdk-tamagotchi) expects the host to supply a tool registry runtime when it instantiates the kit client; registerTool checks runtime.tools and throws this error when it is absent. The registry is what actually stores tool metadata (id, title, activation keywords/patterns, serialized parameters) and wires execute callbacks for later invocation. Without it there is nowhere to register, so the kit fails fast instead of silently dropping tools.","triggerScenarios":"Calling module.kits.use(toolKit) then registerTool(...) in a unit test with a minimal mock runtime, in a bare plugin-sdk host that never attached a tools registry, or in a host integration where tool support is not implemented. Also when kit clients are created for a runtime shape that was cast (as ToolKitRuntime) but not actually populated with tools.","commonSituations":"Extension authors running vitest against their module's registration code with a hand-rolled runtime; new hosts embedding plugin-sdk-tamagotchi piecemeal; regression after a host refactor stopped passing tools into kit creation.","solutions":["Run the registration inside the real tamagotchi host, which provides runtime.tools when creating kit clients.","If you control the host, implement/attach the tool registry (register({ tool, availability, execute })) to the runtime you hand to the kit.","In tests, inject a fake registry: { tools: { register: async () => {}, registerToolsetPrompt: async () => {} } }.","Feature-detect before registering when the same extension must run on hosts with and without tool support."],"exampleFix":"// before\nconst tools = await module.kits.use(toolKit)\nawait tools.registerTool(definition) // throws: mock runtime has no .tools\n\n// after (test)\nconst tools = await module.kits.use(toolKit, {\n  tools: { register: vi.fn(async () => {}), registerToolsetPrompt: vi.fn(async () => {}) },\n})\nawait tools.registerTool(definition)","handlingStrategy":"validation","validationCode":"const tools = await module.kits.use(toolKit)\n// only register when the host actually provides a tool registry\nif (hostRuntime?.tools) {\n  await tools.registerTool(definition)\n}","typeGuard":"interface ToolRuntimeLike { tools?: { register(input: unknown): Promise<void> } }\nfunction hasToolRegistry(runtime: ToolRuntimeLike): runtime is ToolRuntimeLike & { tools: NonNullable<ToolRuntimeLike['tools']> } {\n  return typeof runtime.tools?.register === 'function'\n}","tryCatchPattern":"try {\n  await tools.registerTool(definition)\n} catch (error) {\n  if (errorMessageFrom(error).includes('requires a host tool registry runtime')) {\n    // host without tool support: skip registration, log once\n  } else throw error\n}","preventionTips":["In unit tests, always inject a stub registry: { tools: { register: async () => {}, registerToolsetPrompt: async () => {} } }.","Feature-detect the tool capability at module setup instead of letting the first registerTool crash the extension session.","Keep registration inside the live session window — after stop/dispose the host runtime is torn down."],"tags":["plugin-sdk","tamagotchi","tools","host-runtime","registration"],"backgroundTag":"host-runtime-capability-missing","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}