{"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":292,"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":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/packages/plugin-sdk-tamagotchi/src/tools/index.ts#L274-L310","documentation":"Thrown by toolKit.registerTool() when the ToolKitRuntime supplied by the host does not include a `tools` registry. The `tools` field is optional (`tools?: { register; registerToolsetPrompt }`), so a host that registered the toolKit API without providing a tool registry causes every registerTool call to fail at the runtime boundary.","triggerScenarios":"Calling module.kits.use(toolKit).registerTool(...) on a host where the kit client was created with a runtime object that has no `tools` property, or where the host contribution forgot to attach the TamagotchiToolRegistry-backed register function.","commonSituations":"A Tamagotchi host wires up the toolKit descriptor but does not pass a TamagotchiToolRegistry instance into the runtime. Common during host bootstrap, in tests that register the kit but skip the registry, or after refactoring the host contribution that owns tool registration.","solutions":["Ensure the host contribution creating the toolKit client passes a `tools` object with register() and registerToolsetPrompt() bound to a TamagotchiToolRegistry.","Verify the kit is registered via host.registerKitApi with the full ToolKitRuntime, not just the kit descriptor.","If tool registration is optional for your host, call tryUse(toolKit) and check availability before registerTool."],"exampleFix":"// before\nhost.registerKitApi({ id: 'kit.tool', createClient: rt => toolKit.createClient(rt) })\n\n// after\nconst registry = new TamagotchiToolRegistry()\nhost.registerKitApi({\n  id: 'kit.tool',\n  createClient: rt => toolKit.createClient({ ...rt, tools: {\n    register: rec => registry.register({ ownerSessionId: rt.sessionId, ownerExtensionId: rt.extensionId, ...rec }),\n    registerToolsetPrompt: rec => registry.registerToolsetPrompt({ ownerSessionId: rt.sessionId, ownerExtensionId: rt.extensionId, ...rec }),\n  } }),\n})","handlingStrategy":"validation","validationCode":"const result = await module.kits.tryUse(toolKit)\nif (!result.ok || !result.client) {\n  throw new Error('toolKit unavailable on this host')\n}\n// Only safe to call registerTool if the host advertised the tool registry;\n// otherwise the kit client's registerTool will throw at runtime boundary.","typeGuard":"import type { ToolKitRuntime } from './tools'\n\nfunction hostProvidesToolRegistry(rt: ToolKitRuntime): rt is ToolKitRuntime & { tools: NonNullable<ToolKitRuntime['tools']> } {\n  return rt.tools !== undefined\n}","tryCatchPattern":"try {\n  await client.registerTool(definition)\n} catch (error) {\n  if (error instanceof Error && /toolKit requires a host tool registry runtime/.test(error.message)) {\n    // host did not attach a TamagotchiToolRegistry; skip or queue registration\n  } else {\n    throw error\n  }\n}","preventionTips":["In the host contribution that creates the toolKit client, always pass a `tools` registry object backed by TamagotchiToolRegistry.","Use tryUse(toolKit) and inspect the result before registerTool when tool support is optional.","Add an integration test that registers a tool right after host bootstrap to catch a missing registry early."],"tags":["runtime","tool-registration","host-configuration","missing-dependency"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}