{"_id":"@abdo12k/assistant-kit","_rev":"4-119171f10a0c9cc9e2d7e077f8c988cb","name":"@abdo12k/assistant-kit","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.0":{"name":"@abdo12k/assistant-kit","version":"0.1.0","_id":"@abdo12k/assistant-kit@0.1.0","maintainers":[{"name":"abdo12k","email":"Abdo12k@hotmail.com"}],"dist":{"shasum":"66cf6380ec9a7fb4c6b431df0ccff6eabea296b7","tarball":"https://registry.npmjs.org/@abdo12k/assistant-kit/-/assistant-kit-0.1.0.tgz","fileCount":67,"integrity":"sha512-fvEHWFCZDZeBTjeRDxiPsGD5ts7TyzbCyzvNKPJMT/34v7ClsUIMf4xvzcREd6NrC0i/XEf0SfAv/xWVuEo2xw==","signatures":[{"sig":"MEUCIG/C4nRvudD1KKdL23iDpwblwR7qtfeMfBDRts8oHVrKAiEAiqh73hXvl329yQBhLOaDyGLxjAq45xA+H7TQJ+ZTtG8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1759206},"type":"module","_from":"file:abdo12k-assistant-kit-0.1.0.tgz","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./core":{"types":"./dist/core/index.d.ts","import":"./dist/core/index.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"},"./browser":{"types":"./dist/browser/index.d.ts","import":"./dist/browser/index.js"},"./sprites":{"types":"./dist/sprites/index.d.ts","import":"./dist/sprites/index.js"},"./package.json":"./package.json","./assets/signal/manifest.json":"./assets/signal/manifest.json"},"scripts":{"build":"tsc -p tsconfig.build.json","typecheck":"tsc -p tsconfig.build.json --noEmit"},"_npmUser":{"name":"abdo12k","email":"Abdo12k@hotmail.com"},"_resolved":"C:\\Users\\ABDO\\AppData\\Local\\Temp\\8e5f6293cd913c61ef9f9099b87f213c\\abdo12k-assistant-kit-0.1.0.tgz","_integrity":"sha512-fvEHWFCZDZeBTjeRDxiPsGD5ts7TyzbCyzvNKPJMT/34v7ClsUIMf4xvzcREd6NrC0i/XEf0SfAv/xWVuEo2xw==","_npmVersion":"11.11.0","description":"Provider-neutral, installable AI assistant runtime, UI contracts, and sprite-pack support.","directories":{},"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"ai":">=7.0.0 <8","zod":">=4.1.8 <5","react":">=19.0.0 <20","react-dom":">=19.0.0 <20","@ai-sdk/react":">=4.0.0 <5"},"peerDependenciesMeta":{"react":{"optional":true},"react-dom":{"optional":true},"@ai-sdk/react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/assistant-kit_0.1.0_1785636343024_0.25157514322369945","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@abdo12k/assistant-kit","version":"0.2.0","_id":"@abdo12k/assistant-kit@0.2.0","maintainers":[{"name":"abdo12k","email":"Abdo12k@hotmail.com"}],"dist":{"shasum":"ac127098a8ec51295a4b5820d02b507fcdd81949","tarball":"https://registry.npmjs.org/@abdo12k/assistant-kit/-/assistant-kit-0.2.0.tgz","fileCount":83,"integrity":"sha512-uJyT/bcGm1TXHvUIuT6a8ZztNcyh3WiNm9pbfRp5B85gu9gVA9fX7OVyqGAG4eoULt9jS5BXgtI8a4IUefCt1g==","signatures":[{"sig":"MEYCIQDSrx6TNt2IPktme4LEyqg0upg83trETlOsHFCEaOFxXAIhALsNDQEPwWp5CN2Tta0BrLh4QpSM1yFZOWZrNgwHzseM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1866397},"type":"module","_from":"file:abdo12k-assistant-kit-0.2.0.tgz","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./ui":{"types":"./dist/ui/index.d.ts","import":"./dist/ui/index.js"},"./core":{"types":"./dist/core/index.d.ts","import":"./dist/core/index.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"},"./browser":{"types":"./dist/browser/index.d.ts","import":"./dist/browser/index.js"},"./sprites":{"types":"./dist/sprites/index.d.ts","import":"./dist/sprites/index.js"},"./package.json":"./package.json","./ui/styles.css":"./dist/ui/styles.css","./assets/signal/manifest.json":"./assets/signal/manifest.json"},"scripts":{"build":"tsc -p tsconfig.build.json && node scripts/copy-ui-assets.mjs","typecheck":"tsc -p tsconfig.build.json --noEmit"},"_npmUser":{"name":"abdo12k","email":"Abdo12k@hotmail.com"},"_resolved":"C:\\Users\\ABDO\\AppData\\Local\\Temp\\6abf877375760ab8154c96fb923462ea\\abdo12k-assistant-kit-0.2.0.tgz","_integrity":"sha512-uJyT/bcGm1TXHvUIuT6a8ZztNcyh3WiNm9pbfRp5B85gu9gVA9fX7OVyqGAG4eoULt9jS5BXgtI8a4IUefCt1g==","_npmVersion":"11.11.0","description":"Provider-neutral AI assistant runtime with an optional portfolio-matched UI and sprite-pack support.","directories":{},"_nodeVersion":"24.14.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"ai":">=7.0.0 <8","zod":">=4.1.8 <5","react":">=19.0.0 <20","motion":">=12.0.0 <13","react-dom":">=19.0.0 <20","streamdown":">=2.0.0 <3","lucide-react":">=0.468.0 <2","@ai-sdk/react":">=4.0.0 <5","@streamdown/cjk":">=1.0.0 <2","@streamdown/code":">=1.0.0 <2","@streamdown/math":">=1.0.0 <2","@streamdown/mermaid":">=1.0.0 <2"},"peerDependenciesMeta":{"react":{"optional":true},"motion":{"optional":true},"react-dom":{"optional":true},"streamdown":{"optional":true},"lucide-react":{"optional":true},"@ai-sdk/react":{"optional":true},"@streamdown/cjk":{"optional":true},"@streamdown/code":{"optional":true},"@streamdown/math":{"optional":true},"@streamdown/mermaid":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/assistant-kit_0.2.0_1785674146536_0.5202738161431668","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@abdo12k/assistant-kit","version":"0.2.1","_id":"@abdo12k/assistant-kit@0.2.1","maintainers":[{"name":"abdo12k","email":"Abdo12k@hotmail.com"}],"dist":{"shasum":"8bf4eb1344e4e25b4bcc27f440649f823a95be6d","tarball":"https://registry.npmjs.org/@abdo12k/assistant-kit/-/assistant-kit-0.2.1.tgz","fileCount":83,"integrity":"sha512-tYdeE6GTHuk0RHotqpMm/kr9htsruhxDlOqm7FejOeVQxEo1jcRJWIUPEiF6IuOY100SzZsEhSwgv3OulW7+ig==","signatures":[{"sig":"MEUCIBuQTUxDbP8xLXszqy8S9dHWa5IRsgg0yFkfQu8ZkpFzAiEA9iPq0+fwyQAgHxZ6O9z+xAQZfZN7IkTh0NJyiVFOHuw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1935422},"type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./ui":{"types":"./dist/ui/index.d.ts","import":"./dist/ui/index.js"},"./core":{"types":"./dist/core/index.d.ts","import":"./dist/core/index.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"},"./browser":{"types":"./dist/browser/index.d.ts","import":"./dist/browser/index.js"},"./sprites":{"types":"./dist/sprites/index.d.ts","import":"./dist/sprites/index.js"},"./package.json":"./package.json","./ui/styles.css":"./dist/ui/styles.css","./assets/signal/manifest.json":"./assets/signal/manifest.json"},"gitHead":"b3457292d6c282692d2cd5deaa2c948e8751ed65","scripts":{"build":"tsc -p tsconfig.build.json && node scripts/copy-ui-assets.mjs","prepack":"pnpm build","typecheck":"tsc -p tsconfig.build.json --noEmit"},"_npmUser":{"name":"abdo12k","email":"Abdo12k@hotmail.com"},"_npmVersion":"11.11.0","description":"Provider-neutral AI assistant runtime with an optional portfolio-matched UI and sprite-pack support.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"@fontsource/syne":"5.3.0","@fontsource/cairo":"5.3.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"ai":">=7.0.0 <8","zod":">=4.1.8 <5","react":">=19.0.0 <20","motion":">=12.0.0 <13","react-dom":">=19.0.0 <20","streamdown":">=2.0.0 <3","lucide-react":">=0.468.0 <2","@ai-sdk/react":">=4.0.0 <5","@streamdown/cjk":">=1.0.0 <2","@streamdown/code":">=1.0.0 <2","@streamdown/math":">=1.0.0 <2","@streamdown/mermaid":">=1.0.0 <2"},"peerDependenciesMeta":{"react":{"optional":true},"motion":{"optional":true},"react-dom":{"optional":true},"streamdown":{"optional":true},"lucide-react":{"optional":true},"@ai-sdk/react":{"optional":true},"@streamdown/cjk":{"optional":true},"@streamdown/code":{"optional":true},"@streamdown/math":{"optional":true},"@streamdown/mermaid":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/assistant-kit_0.2.1_1785717476766_0.0031844321383844854","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@abdo12k/assistant-kit","version":"0.2.2","description":"Provider-neutral AI assistant runtime with an optional portfolio-matched UI and sprite-pack support.","type":"module","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./core":{"types":"./dist/core/index.d.ts","import":"./dist/core/index.js"},"./browser":{"types":"./dist/browser/index.d.ts","import":"./dist/browser/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react/index.js"},"./ui":{"types":"./dist/ui/index.d.ts","import":"./dist/ui/index.js"},"./ui/styles.css":"./dist/ui/styles.css","./sprites":{"types":"./dist/sprites/index.d.ts","import":"./dist/sprites/index.js"},"./assets/signal/manifest.json":"./assets/signal/manifest.json","./package.json":"./package.json"},"scripts":{"build":"tsc -p tsconfig.build.json && node scripts/copy-ui-assets.mjs","prepack":"pnpm build","typecheck":"tsc -p tsconfig.build.json --noEmit"},"peerDependencies":{"@ai-sdk/react":">=4.0.0 <5","@streamdown/cjk":">=1.0.0 <2","@streamdown/code":">=1.0.0 <2","@streamdown/math":">=1.0.0 <2","@streamdown/mermaid":">=1.0.0 <2","ai":">=7.0.0 <8","lucide-react":">=0.468.0 <2","motion":">=12.0.0 <13","react":">=19.0.0 <20","react-dom":">=19.0.0 <20","streamdown":">=2.0.0 <3","zod":">=4.1.8 <5"},"peerDependenciesMeta":{"@ai-sdk/react":{"optional":true},"@streamdown/cjk":{"optional":true},"@streamdown/code":{"optional":true},"@streamdown/math":{"optional":true},"@streamdown/mermaid":{"optional":true},"lucide-react":{"optional":true},"motion":{"optional":true},"react":{"optional":true},"react-dom":{"optional":true},"streamdown":{"optional":true}},"publishConfig":{"access":"public"},"dependencies":{"@fontsource/cairo":"5.3.0","@fontsource/syne":"5.3.0"},"gitHead":"13654ea4cfb23aa175ae8a8a517836d91cd12396","_id":"@abdo12k/assistant-kit@0.2.2","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-lDcK3iC5yWtzH1TOn7X7xW6tmRIwswPz3HaI9bMOzb//o1DgbwOEfcRF4aWiIw2iUIgwGo7+mYyMzsIyn7sbUg==","shasum":"85ca2c2ff0f35fa393f2740dda6165f7b9d1dc3f","tarball":"https://registry.npmjs.org/@abdo12k/assistant-kit/-/assistant-kit-0.2.2.tgz","fileCount":83,"unpackedSize":1944628,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFb+vfE4eGsqrKTZyygriUFHNTHPYoeN7MbwqrruepotAiEAoGLshra+YW0ED7QHx0mnXXFm1pk3bXpdBgEmtJepXKY="}]},"_npmUser":{"name":"abdo12k","email":"Abdo12k@hotmail.com"},"directories":{},"maintainers":[{"name":"abdo12k","email":"Abdo12k@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/assistant-kit_0.2.2_1785763837593_0.9498317661739029"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-02T02:05:42.822Z","modified":"2026-08-03T13:30:37.940Z","0.1.0":"2026-08-02T02:05:43.187Z","0.2.0":"2026-08-02T12:35:46.750Z","0.2.1":"2026-08-03T00:37:56.958Z","0.2.2":"2026-08-03T13:30:37.790Z"},"description":"Provider-neutral AI assistant runtime with an optional portfolio-matched UI and sprite-pack support.","maintainers":[{"name":"abdo12k","email":"Abdo12k@hotmail.com"}],"readme":"# @abdo12k/assistant-kit\n\nReusable AI assistant infrastructure for projects that need a configurable model, prompt, trusted context, tools, canonical resources, optional mascot sprites, and an optional portfolio-matched UI.\n\nThe package is intentionally provider-neutral. The consuming application supplies the AI SDK model, project adapter, storage, and tools. The package does not import Google, OpenAI, Anthropic, database, or portfolio code.\n\n## Install in another project\n\nFrom a published package registry:\n\n```bash\npnpm add @abdo12k/assistant-kit @abdo12k/create-assistant ai zod\npnpm create @abdo12k/assistant init\n```\n\nThe base install is server-first and does not install the full visual shell. If the project uses the optional React client seam or mascot component, add its React peers:\n\n```bash\npnpm add @ai-sdk/react react react-dom\n```\n\nThe full branded UI is opt-in. It carries the canonical portfolio assistant shell into another project: floating sprite launcher and status bubble, tucked/dragged launcher controls, responsive conversation panel, header actions, starter prompts, browse cards, streaming states, history, resource drawer, keyboard shortcuts, reduced-motion behavior, portaled tooltips, focus restoration, animated history filters, and touch drawer dismissal. Install its optional peers only when you want that surface:\n\n```bash\npnpm add @ai-sdk/react lucide-react motion react react-dom streamdown @streamdown/cjk @streamdown/code @streamdown/math @streamdown/mermaid\n```\n\nImport the stylesheet once, then render `AssistantWidget`:\n\n```tsx\nimport \"@abdo12k/assistant-kit/ui/styles.css\";\n\nimport { AssistantWidget } from \"@abdo12k/assistant-kit/ui\";\nimport { defaultSignalSpritePack } from \"@abdo12k/assistant-kit\";\n\nexport function ProjectAssistant() {\n  return (\n    <AssistantWidget\n      api=\"/api/assistant\"\n      spritePack={defaultSignalSpritePack}\n      adapter={{\n        assistantName: \"Ask Abdo\",\n        ownerName: \"Abdo\",\n        subtitle: \"Portfolio assistant\",\n        infoDescription: \"Ask about the work, the systems behind it, or where to go next.\",\n        suggestions: [\n          \"What can you help me with?\",\n          \"Which project should I explore first?\",\n        ],\n        onContact: () => {\n          window.location.href = \"/contact\";\n        },\n      }}\n    />\n  );\n}\n```\n\n`AssistantWidget` and the explicitly named `PortfolioAssistantWidget` export\nuse the same canonical shell. The latter is useful in generated projects when\nyou want the intent to be obvious in the project adapter without changing the\nruntime or UI contract.\n\n`AssistantWidget` owns the reusable shell and creates the AI SDK chat transport. For a project that already owns the transport or calls `useAssistantChat` itself, use `AssistantSurface` instead:\n\n```tsx\nimport \"@abdo12k/assistant-kit/ui/styles.css\";\n\nimport { useMemo } from \"react\";\nimport { DefaultChatTransport } from \"ai\";\nimport { AssistantSurface } from \"@abdo12k/assistant-kit/ui\";\nimport { useAssistantChat } from \"@abdo12k/assistant-kit/react\";\n\nexport function ProjectAssistant() {\n  const transport = useMemo(\n    () => new DefaultChatTransport({ api: \"/api/assistant\" }),\n    [],\n  );\n  const chat = useAssistantChat({ transport });\n\n  return (\n    <AssistantSurface\n      chat={chat}\n      adapter={{\n        assistantName: \"Ask Project\",\n        ownerName: \"the team\",\n        onInternalLinkClick: (href) => {\n          window.location.assign(href);\n        },\n      }}\n    />\n  );\n}\n```\n\nThe `adapter` keeps project-specific content and behavior out of the shell. It can provide the assistant/owner copy, subtitle and info popover, starter prompts and browse areas, contact action, launcher presentation, message text or a custom message renderer, canonical resources or custom resource rows, per-answer resource projections, internal-link navigation, history namespace, and the project’s concurrency label. Use `spritePack` to supply the project’s own validated pack; the default Signal pack remains available when no custom pack is supplied. The UI is optional: projects that want only the runtime, server adapters, React hooks, or sprite component can keep using the base entry points without importing `@abdo12k/assistant-kit/ui` or its stylesheet.\n\nUser turns expose the same edit-and-resubmit interaction as the portfolio: hover or focus a user message, choose `Edit Message`, revise the text, and choose `Save & resubmit`. Historical edits ask for confirmation before descendants are removed. The built-in fallback uses AI SDK’s `sendMessage({ text, messageId })` replacement semantics, which is enough for a stateless consumer such as the generated starter. Projects that persist immutable message versions, tombstones, generation invalidation, or cross-device revisions should provide `adapter.onEditMessage` and perform that transaction in the host application before starting the replacement generation. The callback receives the canonical UI request and may return `generation-unavailable` after persistence succeeds so the shell can show the correct recovery copy.\n\nThe initializer writes a server route, model/tool/configuration stubs, a client-safe `sprites.ts` seam, and copies the default Signal sprite pack into `public/assistant/sprites/signal`. With `--ui`, it also writes a neutral `ui.ts` adapter and `AssistantWidget.tsx`; customize those project-owned files rather than changing the packaged shell. Existing files are preserved unless `--force` is supplied.\n\nTo install a project-owned sprite pack instead:\n\n```bash\npnpm create @abdo12k/assistant init --sprite-dir ./path/to/my-sprite-pack\n```\n\nThe custom directory must contain a version-1 `manifest.json` and the referenced assets. The initializer rejects missing local assets, platform path separators, and symbolic links; run `pnpm assistant:validate-sprite -- ./path/to/my-sprite-pack` in the source repository for atlas dimension and alpha-channel checks before deploying. The initializer does not enable runtime visitor uploads; projects that need user-uploaded mascots should add a separately authenticated upload/storage feature.\n\nThe generated adapter is the portability seam: replace `buildTrustedContext`, `buildInstructions`, `createTools`, and `getAssistantModel` for each project. Keep database clients, credentials, canonical resource materializers, rate limiting, and lifecycle persistence behind those project-owned ports. `lifecycle` hooks are available for a project's queue/lease/result store without coupling the kit to PostgreSQL, Redis, or a hosted job system.\n\nFrom this repository, `pnpm assistant:pack` creates the versioned kit and initializer tarballs in `.assistant-release/`. `pnpm assistant:verify-install` installs those archives into a clean temporary consumer, typechecks the generated route and optional UI wrapper, checks that rerunning the initializer preserves existing files, and verifies a custom sprite-pack install. Publish `@abdo12k/assistant-kit` before `@abdo12k/create-assistant`; the initializer package depends on the matching kit version.\n\nThe package exports the reusable client boundaries `useAssistantChat` and `useAssistantResourceUi` from `@abdo12k/assistant-kit/react`. The latter scopes per-group expansion/collapse state to a conversation while resource cards, route-aware visibility, animations, analytics, and drawer chrome remain project-owned so they can match the host application's product choices.\n\n## Conversation and history port\n\nThe kit exports `AssistantConversationDocument`, `AssistantConversationPersistence`, `AssistantConversationSyncChannel`, and `AssistantConversationStore` from the root package. These are contracts rather than a forced database choice:\n\n```ts\nimport type {\n  AssistantConversationPersistence,\n  AssistantConversationStore,\n} from \"@abdo12k/assistant-kit\";\n\ntype ProjectConversationDocument = unknown;\ntype ProjectConversationEvent = unknown;\n\nconst conversationStore: AssistantConversationStore<\n  ProjectConversationDocument,\n  ProjectConversationEvent\n> = {\n  persistence: {\n    read: async () => null,\n    write: async (document) => ({ document, status: \"written\" }),\n  } satisfies AssistantConversationPersistence<ProjectConversationDocument>,\n  codec: {\n    normalize: (value) => value as ProjectConversationDocument,\n    merge: (left) => left,\n  },\n};\n```\n\nThe consuming project owns message validation, schema migration, encryption, quota/eviction policy, local or remote storage, and cross-tab/device synchronization. The kit only standardizes the seam and the write result states (`written`, `degraded`, and `failed`).\n\nFor a browser project that wants the common local-storage mechanics, the optional browser entry point provides a synchronous adapter while leaving the document schema and migration policy in the project:\n\n```ts\nimport { createAssistantBrowserConversationStorage } from \"@abdo12k/assistant-kit/browser\";\n\nconst persistence = createAssistantBrowserConversationStorage({\n  key: \"my-assistant-history-v1\",\n  normalize: (value) => (isMyConversationDocument(value) ? value : null),\n});\n```\n\nIt safely handles unavailable storage, JSON serialization, legacy migration, quota-reduction retries, and best-effort clearing. The project still decides what is valid, what can be evicted, and how analytics are recorded.\n\n## Compatibility\n\nThe base runtime targets Node 22+, AI SDK 7, and Zod 4. The optional React entry targets React 19 and `@ai-sdk/react` 4.\n\n## Sprite packs\n\nThe default Signal asset is copied into the consuming application by the initializer. A project can replace it with a local sprite pack by supplying another validated manifest and base URL. Runtime visitor uploads are intentionally outside the v1 configuration surface.\n\n## Runtime strategy\n\nThe current advanced assistant uses the AI SDK `streamText` runtime because it needs custom presentation sidecars, manifest finalization, cancellation, and lifecycle persistence. A simpler `ToolLoopAgent` adapter can be added later without changing the domain contracts.\n\n`costBudgetUsd` is enforced only when the project supplies a `costEstimator`, because token pricing is provider/model-specific. Tool allowlists, step/call/result/timeout limits, same-origin/HTTPS asset checks, and canonical resource URL checks are provider-neutral safeguards included in the kit.\n\nFor assistants that need distributed Stop, refresh-safe terminal recovery, or a global active-generation limit, `@abdo12k/assistant-kit/server` also exports `AssistantGenerationAuthority` and `superviseAssistantGeneration`. They are ports, not storage implementations: the consuming project supplies its lease authority, terminal result store, executor, telemetry, and publication policy.\n\nRefresh-safe terminal adoption is also available as the provider-neutral `recoverAssistantGenerationTerminal` helper. It accepts a project-owned `AssistantTerminalResult` and a message adapter for generation matching, authoritative completed-message construction, terminal-reason mapping, and lifecycle metadata application. This keeps exact answer/resource envelopes and UI message formats in the consuming project.\n\nThe server entry point also exports `AssistantGenerationResultStore` and `resolveAssistantGenerationResult`. A project adapts its lease/result backend to the namespace-and-owner contract once; the helper then performs the race-safe result read, active snapshot read, and final result read used during refresh recovery.\n\nFor the mascot UI:\n\n```tsx\nimport { AssistantSprite } from \"@abdo12k/assistant-kit/react\";\nimport { defaultSignalSpritePack } from \"@abdo12k/assistant-kit\";\n\n<AssistantSprite pack={defaultSignalSpritePack} state=\"working\" size={72} />;\n```\n","readmeFilename":"README.md"}