{"_id":"@aist-packages/aist-agent-sdk","_rev":"3-3f4298ad5ffdd026d9aa5667f62ec197","name":"@aist-packages/aist-agent-sdk","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@aist-packages/aist-agent-sdk","version":"0.1.0","keywords":["aist","agent","ai","llm","sdk","tasks","client-tools","typescript"],"author":{"name":"Ilya Ignatev"},"license":"MIT","_id":"@aist-packages/aist-agent-sdk@0.1.0","maintainers":[{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"}],"dist":{"shasum":"926b5d17b7b7f92902cd45d9d81b262e000821af","tarball":"https://registry.npmjs.org/@aist-packages/aist-agent-sdk/-/aist-agent-sdk-0.1.0.tgz","fileCount":9,"integrity":"sha512-7QAsMkPoB8DysDm+SiwKTaEd6GNJlVm2v3LdzG2sXLxBZhjTOpr3oP9R5bmgnWI9AEk4OpY+SNijr7y6uQe+Mw==","signatures":[{"sig":"MEUCIQC5OUQxsnd74JS5UXTDnJgihsL4G4pfUXYz/VyLUP0CYAIgE1H1JFV6jGMU8s+pRLwMmwO23mddG/CFvONZ1ye1Igk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":141751},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"dc0c2d52e923d16d921ef2e0e6d624e860e7aa09","scripts":{"test":"vitest run","build":"tsup","clean":"rimraf dist","test:watch":"vitest","type-check":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"},"overrides":{"esbuild":"^0.28.1"},"_npmVersion":"10.9.7","description":"TypeScript/JavaScript SDK for the Aist Agent gateway HTTP API (tasks, polling, client tools, file uploads).","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","rimraf":"^6.0.0","vitest":"^4.0.18","typescript":"^5.7.2","@types/node":"^22.10.2"},"_npmOperationalInternal":{"tmp":"tmp/aist-agent-sdk_0.1.0_1783518996136_0.9670864478791179","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aist-packages/aist-agent-sdk","version":"0.2.0","keywords":["aist","agent","ai","llm","sdk","tasks","client-tools","typescript"],"author":{"name":"Ilya Ignatev"},"license":"MIT","_id":"@aist-packages/aist-agent-sdk@0.2.0","maintainers":[{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"}],"dist":{"shasum":"d6b28e85b890712ffa68530ded4e82bb7f52bdf0","tarball":"https://registry.npmjs.org/@aist-packages/aist-agent-sdk/-/aist-agent-sdk-0.2.0.tgz","fileCount":9,"integrity":"sha512-DkOlOdDjZTVMwlf96Y955Ly+AnPRs6aQqO7b4/r5fjpXDg2IRME5ZOGIrxZRdv0Jjo4lphWbtMUb3Djc+2RZTQ==","signatures":[{"sig":"MEYCIQClh2KQm1mCQ5QPgwJv7h8efCTTxrdOEhPvStGkTNMAEwIhAJiRHhDt4jAg8p9DYUygf/DhmwiGtl4bsSJx1Geqs7NO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":172039},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"162fe5c4ef68c468810866012386ab0e59203525","scripts":{"test":"vitest run","build":"tsup","clean":"rimraf dist","test:watch":"vitest","type-check":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"},"overrides":{"esbuild":"^0.28.1"},"_npmVersion":"10.9.8","description":"TypeScript/JavaScript SDK for the Aist Agent gateway HTTP API (tasks, polling, client tools, file uploads).","directories":{},"sideEffects":false,"_nodeVersion":"22.23.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","rimraf":"^6.0.0","vitest":"^4.0.18","typescript":"^5.7.2","@types/node":"^22.10.2"},"_npmOperationalInternal":{"tmp":"tmp/aist-agent-sdk_0.2.0_1785996067499_0.4430730892767605","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@aist-packages/aist-agent-sdk","version":"0.3.0","description":"TypeScript/JavaScript SDK for the Aist Agent gateway HTTP API (tasks, polling, client tools, file uploads).","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"engines":{"node":">=18"},"scripts":{"build":"tsup","type-check":"tsc --noEmit","test":"vitest run","test:watch":"vitest","clean":"rimraf dist","prepublishOnly":"npm run build"},"keywords":["aist","agent","ai","llm","sdk","tasks","client-tools","typescript"],"author":{"name":"Ilya Ignatev"},"license":"MIT","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"overrides":{"esbuild":"^0.28.1"},"devDependencies":{"@types/node":"^22.10.2","rimraf":"^6.0.0","tsup":"^8.5.0","typescript":"^5.7.2","vitest":"^4.0.18"},"_id":"@aist-packages/aist-agent-sdk@0.3.0","gitHead":"279a2aa07e3109a0c43894e7e1f04656fd060f67","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-Nh71c45TVCxxgorrNA5rw5NAIjCNV30Cp0TSrG+4FB47lWe+Q6CSFX0IZVCtHzA9wX8mquwbmyr2jEA24f3jIA==","shasum":"0b7da16562fb3b3f8162f12900370e599f65b83e","tarball":"https://registry.npmjs.org/@aist-packages/aist-agent-sdk/-/aist-agent-sdk-0.3.0.tgz","fileCount":9,"unpackedSize":178841,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDC8jKQyojD60qkjMP1ARx6RlOjYt6am6TKuEbwga4EQgIhAID27R4T/tuN4JG7nP7uFQrE3J5ScEMYIuTQd9cRPdIY"}]},"_npmUser":{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"},"directories":{},"maintainers":[{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aist-agent-sdk_0.3.0_1786708428644_0.39275793624735544"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-08T13:56:35.861Z","modified":"2026-08-14T11:53:48.918Z","0.1.0":"2026-07-08T13:56:36.347Z","0.2.0":"2026-08-06T06:01:07.670Z","0.3.0":"2026-08-14T11:53:48.774Z"},"author":{"name":"Ilya Ignatev"},"license":"MIT","keywords":["aist","agent","ai","llm","sdk","tasks","client-tools","typescript"],"description":"TypeScript/JavaScript SDK for the Aist Agent gateway HTTP API (tasks, polling, client tools, file uploads).","maintainers":[{"name":"bashkirsky-kot","email":"silentwasd@gmail.com"}],"readme":"# @aist-packages/aist-agent-sdk\n\nTypeScript/JavaScript SDK для шлюза **Aist Agent** — создание тасков, опрос результата,\nавтоматический interrupt-цикл клиентских инструментов и загрузка файлов.\n\nИзоморфный (Node 18+ и браузер), без рантайм-зависимостей, на нативном `fetch`/`FormData`.\n\n## Установка\n\nПакет опубликован в публичном реестре npm:\n\n```bash\nnpm install @aist-packages/aist-agent-sdk\n```\n\n## Быстрый старт\n\n```ts\nimport { AistAgentClient, textInput } from '@aist-packages/aist-agent-sdk';\n\nconst client = new AistAgentClient({\n  baseUrl: 'https://agent.aist.neobash.ru',\n  token: process.env.AIST_AGENT_TOKEN!, // JWT (RS256)\n});\n\nconst { uuid } = await client.createTask({\n  assistant_id: 1,\n  input: [textInput('Привет! Кто ты?')],\n});\n\nconst task = await client.waitForTask(uuid, { stopOn: ['completed', 'failed'] });\nconsole.log(task.turn?.output);\n```\n\n## Клиентские инструменты (`runTask`)\n\n`runTask` создаёт таск и сам проходит весь interrupt-цикл: когда модель вызывает клиентский\nинструмент, SDK вызывает ваш обработчик, отправляет результат и продолжает — до завершения.\n\nСхему и обработчик можно указать **в одном месте** — SDK сам соберёт `client_tools` запроса:\n\n```ts\nconst task = await client.runTask(\n  {\n    assistant_id: 1,\n    input: [textInput('Какая погода в Москве?')],\n  },\n  {\n    tools: [\n      {\n        name: 'get_weather',\n        description: 'Текущая погода в городе.',\n        input_schema: {\n          type: 'object',\n          properties: { city: { type: 'string' } },\n          required: ['city'],\n        },\n        // args — разобранные аргументы вызова; вернуть строку, {content} или {error, reason}.\n        handler: async (args) =>\n          JSON.stringify({ city: args.city, temperature_c: 21, condition: 'Солнечно' }),\n      },\n    ],\n    onStatus: (t) => console.log(t.status),\n  },\n);\n```\n\nАльтернативно `opts.tools` принимает карту `{ имя: обработчик }`, тогда определения берутся\nиз `input.client_tools` (форма для случаев, когда схемы приходят из другого источника).\n\nЕсли для вызванного инструмента нет обработчика, бросается `MissingToolHandlerError`\n(или вызывается `opts.onMissingTool`).\n\n## Предельное время выполнения\n\n```ts\nconst task = await client.runTask({\n    assistant_id: 1,\n    input: [{ type: 'text', text: 'Собери отчёт' }],\n    max_execution_time: 600, // 10 минут\n});\n```\n\nОтсчёт идёт **от создания** таска, ожидание в очереди входит. Не уложившийся таск\nзакрывается со `status: 'failed'` и причиной в `error`\n(`Task exceeded maximum execution time (600s).`), а движку уходит команда прекратить\nработу — чтобы не жечь токены впустую. То, что модель успела наработать к этому моменту,\nостаётся в `turn`: у оборванного таска результат может быть частичным.\n\nБез `max_execution_time` действует серверный лимит (сутки). Значение больше него\nотклоняется с `422`. Текущий лимит и момент обрыва видны в `task.max_execution_time`\nи `task.deadline_at`.\n\n## Список тасков\n\n```ts\n// Все свои таски, свежие сверху.\nconst { data, meta } = await client.listTasks();\n\n// Только брошенные прерванные — что именно держит лимит.\nconst { data: stuck } = await client.listTasks({ status: 'interrupted' });\nfor (const task of stuck) {\n    console.log(task.uuid, task.pending_tool_calls);\n}\n\n// Несколько статусов + пагинация.\nawait client.listTasks({ status: ['pending', 'processing'], page: 2, perPage: 50 });\n```\n\nВ строке списка (`TaskSummary`) — `uuid`, `status`, `error`, `created_at`, `completed_at` и,\nдля `interrupted`, `pending_tool_calls`. Поля `turn` в списке **нет**: это весь ход целиком,\nна странице тасков он весил бы мегабайты — за результатом идите в `getTask(uuid)`.\n`perPage` — 1…100, дефолт на сервере 25; `meta` содержит `current_page`, `per_page`,\n`last_page`, `total`.\n\n## Отмена прерванных тасков\n\nТаск в `interrupted` ждёт результата клиентского инструмента и **считается активным**: он\nзанимает слот в лимите одновременных тасков, пока вы не ответите. Если отвечать нечем —\nпользователь закрыл приложение, инструмент недоступен, сценарий отменился, — не бросайте\nтаск, а отмените его:\n\n```ts\n// Конкретный таск: только из статуса interrupted, иначе TaskConflictError (409).\nawait client.cancelTask(uuid, { reason: 'Пользователь закрыл приложение' });\n\n// Все свои прерванные таски разом — уборка хвостов после падения процесса.\nconst { canceled, uuids } = await client.cancelInterruptedTasks();\nconsole.log(`отменено: ${canceled}`, uuids);\n```\n\nТаск переходит в терминальный `canceled`, `reason` (опционален, до 1000 символов) ложится\nв `task.error`, слот освобождается сразу. Если у таска был `callback_url`, отмена придёт и\nвебхуком. `cancelInterruptedTasks()` идемпотентен: отменять нечего — вернётся\n`{ canceled: 0, uuids: [] }`.\n\nТипичное место вызова — обработка `RateLimitError` (429). Если нужно разобраться, что\nименно занимает лимит, перед отменой посмотрите список:\n\n```ts\ntry {\n    await client.createTask(input);\n} catch (err) {\n    if (err instanceof RateLimitError) {\n        await client.cancelInterruptedTasks({ reason: 'Хвосты прошлой сессии' });\n        await client.createTask(input);\n    }\n}\n```\n\n`runTask` сам доводит interrupt-цикл до конца, но если ваш обработчик бросит исключение,\nтаск останется в `interrupted` — на этот случай оберните вызов и отмените таск в `catch`.\n\n## Загрузка файлов\n\n```ts\nimport { readFile } from 'node:fs/promises';\n\nconst buf = await readFile('photo.png');\nconst fileItem = await client.uploadFile(buf, { filename: 'photo.png', type: 'image/png' });\n\n// Объект готов к вставке прямо в input[]:\nawait client.createTask({ assistant_id: 1, input: [fileItem, textInput('Что на фото?')] });\n```\n\nВ браузере вместо `Buffer` передавайте `File`/`Blob` напрямую.\n\n## API\n\n### `new AistAgentClient(options)`\n- `baseUrl: string` — адрес шлюза.\n- `token: string` — JWT для `Authorization: Bearer`.\n- `headers?` — доп. заголовки на каждый запрос.\n- `timeoutMs?` — таймаут одиночного HTTP-запроса (`0` — без таймаута).\n- `fetch?` — кастомный fetch (тесты / Node < 18).\n\n### Низкоуровневые методы (1:1 с API)\n| Метод | Эндпоинт |\n|---|---|\n| `createTask(input)` | `POST /api/tasks` → `{uuid, status}` |\n| `listTasks(query?)` | `GET /api/tasks` → `{data: TaskSummary[], meta}` |\n| `getTask(uuid)` | `GET /api/tasks/{uuid}` → `Task` |\n| `submitToolResults(uuid, results)` | `POST /api/tasks/{uuid}/tool-results` |\n| `cancelTask(uuid, opts?)` | `POST /api/tasks/{uuid}/cancel` → `{uuid, status: 'canceled'}` |\n| `cancelInterruptedTasks(opts?)` | `POST /api/tasks/cancel-interrupted` → `{canceled, uuids}` |\n| `uploadFile(file, opts?)` | `POST /api/files` → input-ready объект |\n| `getStorageBase()` | `GET /api/storage/base` → `string` |\n\n### Высокоуровневые хелперы\n- `waitForTask(uuid, opts?)` — опрос до статуса из `stopOn` (дефолт `completed`/`failed`/`canceled`/`interrupted`),\n  с `pollIntervalMs`, `timeoutMs`, `onPoll`, `signal`.\n- `runTask(input, opts?)` — создание + автоматический interrupt-цикл клиентских инструментов.\n\n### Ошибки\nБазовый `AistAgentError`. HTTP-ошибки — `AistAgentApiError` (`.status`, `.body`) с подклассами:\n`UnauthorizedError` (401), `ForbiddenError` (403), `NotFoundError` (404), `TaskConflictError` (409),\n`ValidationError` (422), `RateLimitError` (429). Плюс `AistAgentTimeoutError` и `MissingToolHandlerError`.\n\n## Разработка\n\n```bash\nnpm install\nnpm run type-check   # строгая типизация\nnpm test             # vitest (мок-fetch, без сети)\nnpm run build        # tsup → dist/ (ESM + CJS + .d.ts)\n```\n\nСквозной прогон против живого сервера — см. `examples/` (`npx tsx examples/client-tools.ts`).\n\n## Публикация\n\n```bash\nnpm login                 # учётка с правами на scope @aist-packages\nnpm publish               # scoped-пакет уйдёт публично (--access public в publishConfig)\n```\n\n`prepublishOnly` автоматически собирает `dist/`. Реестр и публичный доступ заданы в\n`publishConfig` (`package.json`) — `registry.npmjs.org`, `access: public`.\n\n## Лицензия\n\n[MIT](./LICENSE)\n","readmeFilename":"README.md"}