{"_id":"@bawolf/inkwell-client","_rev":"2-7068719a36fb09217ff601edfce1b4e6","name":"@bawolf/inkwell-client","dist-tags":{"latest":"0.0.3"},"versions":{"0.0.1":{"name":"@bawolf/inkwell-client","version":"0.0.1","keywords":["inkwell","api","client","typescript","javascript","ai","generative","assets"],"author":{"name":"Inkwell Team"},"license":"MIT","_id":"@bawolf/inkwell-client@0.0.1","maintainers":[{"name":"bawolf","email":"bawolf@gmail.com"}],"homepage":"https://github.com/bawolf/inkwell-client-ts#readme","bugs":{"url":"https://github.com/bawolf/inkwell-client-ts/issues"},"dist":{"shasum":"ba3c66704cacda11cbc917a5049a704db76619fa","tarball":"https://registry.npmjs.org/@bawolf/inkwell-client/-/inkwell-client-0.0.1.tgz","fileCount":14,"integrity":"sha512-c4uk2jQHSUslDorP8d2By1Wc57p9kFu7OcQ44hrPNh3nDvkPXDPzOoHTCopyE+wPxw22mCTxrgiwKJqbGRBisg==","signatures":[{"sig":"MEUCIBPzRgKlh/xYKbvq2Cgyb+l0gQq7jcrtODoIJVC2XBwrAiEA6yn5gopAwC3dm7AJlDpz56FHXxBJ1lc6avFBdZBK2LA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":148126},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"a50175be1e3939c57aaad7211b1dcc299f08bbca","scripts":{"dev":"rollup -c -w","lint":"eslint src --ext .ts","test":"jest --config jest.config.cjs","build":"rollup -c","smoke":"npm run build && DEBUG=inkwell:client node scripts/smoke.mjs","format":"prettier --write src/**/*.ts","lint:fix":"eslint src --ext .ts --fix","test:watch":"jest --config jest.config.cjs --watch","prepublishOnly":"npm run build && npm run test"},"_npmUser":{"name":"bawolf","email":"bawolf@gmail.com"},"repository":{"url":"git+https://github.com/bawolf/inkwell-client-ts.git","type":"git"},"_npmVersion":"11.4.2","description":"Official Inkwell API client for JavaScript/TypeScript","directories":{},"_nodeVersion":"22.17.0","dependencies":{"zod":"^3.22.0","axios":"^1.6.0","debug":"^4.3.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.0.0","tslib":"^2.8.1","eslint":"^8.0.0","rollup":"^4.0.0","ts-jest":"^29.0.0","prettier":"^3.0.0","typescript":"^5.0.0","@types/jest":"^29.0.0","@types/node":"^20.0.0","@types/debug":"^4.1.12","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","@rollup/plugin-typescript":"^12.0.0","@typescript-eslint/parser":"^6.0.0","@typescript-eslint/eslint-plugin":"^6.0.0"},"_npmOperationalInternal":{"tmp":"tmp/inkwell-client_0.0.1_1759011275561_0.8691768568123057","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"@bawolf/inkwell-client","version":"0.0.3","description":"Official Inkwell API client for JavaScript/TypeScript","type":"module","main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"rollup -c","dev":"rollup -c -w","test":"jest --config jest.config.cjs","test:watch":"jest --config jest.config.cjs --watch","lint":"eslint src --ext .ts","lint:fix":"eslint src --ext .ts --fix","format":"prettier --write src/**/*.ts","prepublishOnly":"npm run build && npm run test","smoke":"npm run build && DEBUG=inkwell:client node scripts/smoke.mjs","live-check":"npm run build && DEBUG=inkwell:client node scripts/live-check.mjs"},"publishConfig":{"access":"public"},"keywords":["inkwell","api","client","typescript","javascript","ai","generative","assets"],"author":{"name":"Inkwell Team"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bawolf/inkwell-client-ts.git"},"bugs":{"url":"https://github.com/bawolf/inkwell-client-ts/issues"},"homepage":"https://github.com/bawolf/inkwell-client-ts#readme","dependencies":{"axios":"^1.6.0","debug":"^4.3.4","zod":"^3.22.0"},"devDependencies":{"@rollup/plugin-typescript":"^12.0.0","@types/debug":"^4.1.12","@types/jest":"^29.0.0","@types/node":"^20.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","eslint":"^8.0.0","eslint-config-prettier":"^9.0.0","eslint-plugin-prettier":"^5.0.0","jest":"^29.0.0","prettier":"^3.0.0","rollup":"^4.0.0","ts-jest":"^29.0.0","tslib":"^2.8.1","typescript":"^5.0.0"},"_id":"@bawolf/inkwell-client@0.0.3","gitHead":"8fbc7f421d0f959a409d705152d7a3dcc45c72ec","_nodeVersion":"22.17.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-kuHmqYMQAsX/hSY6am//AaP0vjlI9rPN1URp8WO7L3duK3NoIWUDwanoXdJU3nkfFdOp6FFgFwoD9YoE5IeGcw==","shasum":"1b4eef6f73e2dd35523edd576c098814ed3a2884","tarball":"https://registry.npmjs.org/@bawolf/inkwell-client/-/inkwell-client-0.0.3.tgz","fileCount":14,"unpackedSize":150036,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDu74H0e4v89/MiEoJR90EzHyoiro81WTw/B8ZQOuC6zAiEAsQg4dfi31yJ+Zq3mSc8KNpvg8ObsKvpWqaA4IE34Tvc="}]},"_npmUser":{"name":"bawolf","email":"bawolf@gmail.com"},"directories":{},"maintainers":[{"name":"bawolf","email":"bawolf@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/inkwell-client_0.0.3_1759014802595_0.8929163750084044"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-27T22:14:35.472Z","modified":"2025-09-27T23:13:23.012Z","0.0.1":"2025-09-27T22:14:35.743Z","0.0.3":"2025-09-27T23:13:22.805Z"},"bugs":{"url":"https://github.com/bawolf/inkwell-client-ts/issues"},"author":{"name":"Inkwell Team"},"license":"MIT","homepage":"https://github.com/bawolf/inkwell-client-ts#readme","keywords":["inkwell","api","client","typescript","javascript","ai","generative","assets"],"repository":{"type":"git","url":"git+https://github.com/bawolf/inkwell-client-ts.git"},"description":"Official Inkwell API client for JavaScript/TypeScript","maintainers":[{"name":"bawolf","email":"bawolf@gmail.com"}],"readme":"# @bawolf/inkwell-client\n\nOfficial Inkwell API client for JavaScript/TypeScript applications. This client provides a robust, type-safe interface to the Inkwell API with runtime validation and comprehensive error handling.\n\n## Features\n\n- 🚀 **Type-safe**: Full TypeScript support with runtime validation using Zod\n- 🛡️ **Error Handling**: Comprehensive error handling with custom error types\n- 📝 **Logging**: Built-in debug logging for development and troubleshooting\n- 🔧 **Configurable**: Flexible configuration options for different environments\n- 📦 **Framework Agnostic**: Works with any JavaScript/TypeScript framework\n- ✅ **Validated**: Runtime schema validation ensures data integrity\n\n## Installation\n\n```bash\nnpm install @bawolf/inkwell-client\n```\n\n## Quick Start\n\n```typescript\nimport { createInkwellClient } from '@bawolf/inkwell-client';\n\nconst client = createInkwellClient({\n  apiKey: 'your-api-key-here',\n});\n\n// Get a specific entity\nconst entity = await client.getEntity('entity-123');\nconsole.log(entity.type); // 'character', 'item', etc.\n\n// Get a random character\nconst randomCharacter = await client.getRandomEntity(['character']);\n\n// Find nearest matches (distances + entityIds, faithful to API)\nconst matches = await client.nearestByEmbedding({\n  embedding: [0.1, 0.2, 0.3],\n  types: ['character'],\n  top: 5,\n});\n// Or resolve to full entities via convenience method\nconst entities = await client.nearestByEmbeddingEntities({\n  embedding: [0.1, 0.2, 0.3],\n  types: ['character'],\n  top: 5,\n});\n```\n\n## Configuration\n\n```typescript\nimport { createInkwellClient } from '@bawolf/inkwell-client';\n\nconst client = createInkwellClient({\n  apiKey: 'your-api-key', // Required for authenticated requests\n  baseUrl: 'https://api.inkwell.ing/v1', // Optional: custom API endpoint\n  timeout: 30000, // Optional: request timeout (default: 30s)\n  axiosInstance: customAxios, // Optional: custom axios instance\n});\n```\n\n## API Reference\n\n### Client Methods\n\n#### `getEntity(id: string): Promise<InkwellEntity>`\n\nGet a specific entity by its ID.\n\n```typescript\nconst entity = await client.getEntity('character-123');\nif (entity.type === 'character') {\n  console.log(entity.facing); // 'left' or 'right'\n  console.log(entity.worldUrl); // Sprite sheet URL\n}\n```\n\n#### `getRandomEntity(types?: InkwellEntityType[]): Promise<InkwellEntity>`\n\nGet a random entity, optionally filtered by types.\n\n```typescript\n// Get any random entity\nconst anyEntity = await client.getRandomEntity();\n\n// Get a random character\nconst character = await client.getRandomEntity(['character']);\n\n// Get a random item or effect\nconst itemOrEffect = await client.getRandomEntity(['item', 'effect']);\n```\n\n#### `getEmbeddingByEntityId(entityId: string): Promise<{embedding: number[], entityId: string}>`\n\nGet the embedding vector for a specific entity.\n\n```typescript\nconst { embedding, entityId } =\n  await client.getEmbeddingByEntityId('entity-123');\nconsole.log(`Entity ${entityId} has ${embedding.length} dimensions`);\n```\n\n#### `nearestByEmbedding(req: InkwellNearestRequest): Promise<InkwellNearestMatchesPayload>`\n\nFind nearest matches to a given embedding vector. Returns distances and `entityId` references (API-faithful response).\n\n```typescript\nconst matches = await client.nearestByEmbedding({\n  embedding: [0.1, 0.2, 0.3 /* ... */],\n  types: ['character'],\n  top: 5,\n  metadata: {\n    scenery: {\n      width: 128,\n      height: 128,\n    },\n  },\n});\nconsole.log(matches.matches[0].distance);\n```\n\n#### `nearestByEmbeddingEntities(req: InkwellNearestRequest): Promise<InkwellEntity[]>`\n\nConvenience helper that resolves the match `entityId`s to full entities via `entitiesByIds`.\n\n```typescript\nconst entities = await client.nearestByEmbeddingEntities({\n  embedding: [0.1, 0.2, 0.3],\n  types: ['character'],\n  top: 5,\n});\n```\n\n#### `nearestFromEntityTransform(req: InkwellNearestFromEntityTransformRequest): Promise<InkwellEntity[]>`\n\nFind entities similar to a source entity but of a different type.\n\n```typescript\nconst items = await client.nearestFromEntityTransform({\n  entityId: 'character-123',\n  targetType: 'item',\n  count: 3,\n});\n```\n\n#### `entitiesByIds(req: InkwellEntitiesByIdsRequest): Promise<InkwellEntity[]>`\n\nGet multiple entities by their IDs in a single request.\n\n```typescript\nconst entities = await client.entitiesByIds({\n  ids: ['entity-1', 'entity-2', 'entity-3'],\n});\n```\n\n### Response Shapes (Canonical)\n\n- `nearestByEmbedding` returns an object payload with `matches` (API-faithful).\n- `entitiesByIds` returns an array of entities, parsed from a server object `{ items: InkwellEntity[] }`.\n- `nearestFromEntityTransform` returns an array of entities, parsed from a server object `{ items: InkwellEntity[] }`.\n\nNotes:\n\n- The server wraps some list responses in `{ items }`. The client normalizes those to plain arrays.\n- Arrays are not returned directly by the server for these endpoints; do not rely on raw array shapes.\n\n### Type Guards\n\nThe client includes type guard functions to help with type narrowing:\n\n```typescript\nimport { isCharacter, isItem, isEffect } from '@bawolf/inkwell-client';\n\nconst entity = await client.getRandomEntity();\n\nif (isCharacter(entity)) {\n  // TypeScript knows this is a InkwellCharacterEntity\n  console.log(entity.facing);\n  console.log(entity.worldUrl);\n} else if (isItem(entity)) {\n  // TypeScript knows this is a InkwellItemEntity\n  console.log(entity.inventoryUrl);\n} else if (isEffect(entity)) {\n  // TypeScript knows this is a InkwellEffectEntity\n  console.log(entity.effectUrl);\n}\n```\n\n### Error Handling\n\nThe client throws `InkwellError` instances for API errors:\n\n```typescript\nimport { InkwellError } from '@bawolf/inkwell-client';\n\ntry {\n  const entity = await client.getEntity('invalid-id');\n} catch (error) {\n  if (error instanceof InkwellError) {\n    console.error('API Error:', error.message);\n    console.error('Status:', error.status);\n    console.error('Response:', error.response);\n  }\n}\n```\n\n### Debug Logging\n\nEnable debug logging by setting the `DEBUG` environment variable:\n\n```bash\nDEBUG=inkwell:client node your-script.js\n```\n\nOr in your code:\n\n```typescript\nimport debug from 'debug';\ndebug.enabled('inkwell:client');\n```\n\n## Smoke testing against the live API\n\nYou can quickly verify your setup against the live API using the bundled smoke script.\n\nPrerequisites:\n\n- Set `INKWELL_API_KEY` (required)\n- Optional: `INKWELL_BASE_URL` to override the default endpoint\n- Optional: `INKWELL_ENTITY_ID` to fetch a specific entity by ID\n- Optional: filter random entity by type(s) using `INKWELL_TYPES` env var or `--types` CLI arg\n\nCommands:\n\n```bash\n# Random entity (no filter)\nINKWELL_API_KEY=your_key npm run smoke\n\n# Random entity filtered by types (comma-separated)\nINKWELL_API_KEY=your_key INKWELL_TYPES=character,tile npm run smoke\n\n# Or use a CLI argument for types\nINKWELL_API_KEY=your_key npm run smoke -- --types=character,tile\n\n# Specific entity by ID\nINKWELL_API_KEY=your_key INKWELL_ENTITY_ID=entity-123 npm run smoke\n\n# Custom base URL (if needed)\nINKWELL_API_KEY=your_key INKWELL_BASE_URL=https://api.inkwell.ing/v1 npm run smoke\n```\n\nWhat the smoke test does:\n\n- Builds the library\n- Creates an `InkwellClient` with your API key (and optional base URL)\n- If `INKWELL_ENTITY_ID` is set, fetches that entity; otherwise fetches a random entity\n- Fetches an embedding for the entity by ID, then fetches 3 nearest entities using `nearestByEmbeddingEntities`\n\n## Advanced Usage\n\n### Custom Axios Instance\n\nYou can provide a custom Axios instance for advanced configuration:\n\n```typescript\nimport axios from 'axios';\nimport { createInkwellClient } from '@bawolf/inkwell-client';\n\nconst customAxios = axios.create({\n  timeout: 10000,\n  headers: {\n    'User-Agent': 'MyApp/1.0',\n  },\n});\n\nconst client = createInkwellClient({\n  apiKey: 'your-key',\n  axiosInstance: customAxios,\n});\n```\n\n### Environment Variables\n\nYou can configure the client using environment variables:\n\n```bash\nINKWELL_API_KEY=your-api-key\nINKWELL_BASE_URL=https://api.inkwell.ing/v1\nDEBUG=inkwell:client\n```\n\n```typescript\nconst client = createInkwellClient({\n  apiKey: process.env.INKWELL_API_KEY,\n  baseUrl: process.env.INKWELL_BASE_URL,\n});\n```\n\n### React Integration\n\n```typescript\nimport { useEffect, useState } from 'react';\nimport { createInkwellClient, InkwellEntity } from '@inkwell/client';\n\nfunction EntityList() {\n  const [entities, setEntities] = useState<InkwellEntity[]>([]);\n  const [loading, setLoading] = useState(true);\n\n  useEffect(() => {\n    const client = createInkwellClient({\n      apiKey: process.env.REACT_APP_INKWELL_API_KEY\n    });\n\n    client.getRandomEntity(['character'])\n      .then(entity => setEntities([entity]))\n      .catch(console.error)\n      .finally(() => setLoading(false));\n  }, []);\n\n  if (loading) return <div>Loading...</div>;\n\n  return (\n    <div>\n      {entities.map(entity => (\n        <div key={entity.entityId}>\n          <h3>{entity.promptShort}</h3>\n          <p>Type: {entity.type}</p>\n        </div>\n      ))}\n    </div>\n  );\n}\n```\n\n## Contributing\n\nContributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\n- 🐛 [Issue Tracker](https://github.com/bawolf/inkwell-client-ts/issues)\n","readmeFilename":"README.md"}