{"_id":"@ai-hands/gateway-sdk","_rev":"2-5f109b12ce2e7451440afed8f18d2337","name":"@ai-hands/gateway-sdk","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@ai-hands/gateway-sdk","version":"0.1.0","keywords":["ai-hands","gateway","grpc","sdk"],"author":"","license":"MIT","_id":"@ai-hands/gateway-sdk@0.1.0","maintainers":[{"name":"alex_white","email":"cyh@zhusun.io"}],"dist":{"shasum":"619f62c02a374a4736f8253f92b0cdfca0da7d4b","tarball":"https://registry.npmjs.org/@ai-hands/gateway-sdk/-/gateway-sdk-0.1.0.tgz","fileCount":10,"integrity":"sha512-JOgqhdVnTdTuHTAYgHoVmzBoUYPPN3fASNZ8dT2fhs5IuCPsGp5AH2j4CPGTwa+yjUEQ6Ym4k7/zsRLEZezFeQ==","signatures":[{"sig":"MEUCIQDZVrldmKGTqaBCVc8NhTz3BUbZM6uXHFwG5bvDeyc2DgIge/v3d+6ijWvuILfaP5IaG4sAIULHIMoQkcHQhhhUGj4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61351},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"9d1edc906efb4989b50bb15f25838a3823e658b5","scripts":{"dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src","test":"vitest run","build":"tsup src/index.ts --format cjs,esm --dts --clean","prepublishOnly":"npm run build"},"_npmUser":{"name":"alex_white","email":"cyh@zhusun.io"},"_npmVersion":"10.9.4","description":"TypeScript SDK for AI Hands Gateway","directories":{},"_nodeVersion":"22.21.0","dependencies":{"uuid":"^9.0.0","@grpc/grpc-js":"^1.9.0","@grpc/proto-loader":"^0.7.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.0.0","eslint":"^8.0.0","vitest":"^1.0.0","typescript":"^5.0.0","@types/node":"^20.0.0","@types/uuid":"^9.0.0"},"peerDependencies":{"typescript":">=5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/gateway-sdk_0.1.0_1769494772154_0.3896583456843916","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@ai-hands/gateway-sdk","version":"0.1.1","description":"TypeScript SDK for AI Hands Gateway","author":"","license":"MIT","repository":{"type":"git","url":"git+https://github.com/ChainbotAI/ai-hands-gateway.git","directory":"sdk/typescript"},"bugs":{"url":"https://github.com/ChainbotAI/ai-hands-gateway/issues"},"homepage":"https://github.com/ChainbotAI/ai-hands-gateway/tree/main/sdk/typescript#readme","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"scripts":{"proto:embed":"node scripts/embed-proto.js","build":"npm run proto:embed && tsup src/index.ts --format cjs,esm --dts --clean","dev":"tsup src/index.ts --format cjs,esm --dts --watch","lint":"eslint src","test":"vitest run","prepublishOnly":"npm run build"},"keywords":["ai-hands","gateway","grpc","sdk"],"dependencies":{"@grpc/grpc-js":"^1.9.0","@grpc/proto-loader":"^0.7.0","uuid":"^9.0.0"},"devDependencies":{"@types/node":"^20.0.0","@types/uuid":"^9.0.0","eslint":"^8.0.0","tsup":"^8.0.0","typescript":"^5.0.0","vitest":"^1.0.0"},"peerDependencies":{"typescript":">=5.0.0"},"engines":{"node":">=18.0.0"},"_id":"@ai-hands/gateway-sdk@0.1.1","gitHead":"a46b8e8951def969314de4afa1b0c4c87996f013","_nodeVersion":"20.20.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-yhgQQxS+7kwRnQ7DIZ5c5iJfg3HPKqkW/V19kT5OtH/bGZXKJP7/fIw7zBXIVxT/OWGBDDZfp0Zg5w7qL5G1CA==","shasum":"8afbf2f7acdd9ff8e2a69d25e6fe497823a0f011","tarball":"https://registry.npmjs.org/@ai-hands/gateway-sdk/-/gateway-sdk-0.1.1.tgz","fileCount":10,"unpackedSize":87979,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDP994/AYS+P3P5oXlAfFr2+oyOUF0xxbYLZnox9rlP0QIhAMJd7RddHoCBcKJ7qH4eYKUteqirJUa0U8hIkCEt70vS"}]},"_npmUser":{"name":"alex_white","email":"cyh@zhusun.io"},"directories":{},"maintainers":[{"name":"alex_white","email":"cyh@zhusun.io"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gateway-sdk_0.1.1_1769575380757_0.9409955300094923"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-27T06:19:32.092Z","modified":"2026-01-28T04:43:01.027Z","0.1.0":"2026-01-27T06:19:32.295Z","0.1.1":"2026-01-28T04:43:00.892Z"},"license":"MIT","keywords":["ai-hands","gateway","grpc","sdk"],"description":"TypeScript SDK for AI Hands Gateway","maintainers":[{"name":"alex_white","email":"cyh@zhusun.io"}],"readme":"# AI Hands Gateway TypeScript SDK\n\nTypeScript/Node.js SDK for interacting with the AI Hands Gateway.\n\n## Installation\n\n### From npm (when published)\n\n```bash\nnpm install @ai-hands/gateway-sdk\n# or\nyarn add @ai-hands/gateway-sdk\n# or\npnpm add @ai-hands/gateway-sdk\n```\n\n### From source (development)\n\n```bash\n# Clone the repository\ngit clone https://github.com/ChainbotAI/ai-hands-gateway.git\ncd ai-hands-gateway/sdk/typescript\n\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Link for local development\nnpm link\n\n# In your project\nnpm link @ai-hands/gateway-sdk\n```\n\n## Usage\n\n### Basic Usage\n\n```typescript\nimport { GatewayClient } from '@ai-hands/gateway-sdk';\n\n// Create client\nconst client = new GatewayClient({\n  endpoint: 'gateway.example.com:8443',\n  auth: {\n    username: 'admin',\n    password: 'secret',\n  },\n});\n\n// List online devices\nconst devices = await client.listDevices();\nconsole.log('Online devices:', devices);\n\n// Execute command on a device\nconst result = await client.exec({\n  deviceId: 'device-uuid-here',\n  command: 'echo \"Hello, World!\"',\n});\nconsole.log('Output:', result.stdout.toString());\nconsole.log('Exit code:', result.exitCode);\n\n// Close client when done\nclient.close();\n```\n\n### Device Binding Flow\n\nThe device binding flow allows users to securely bind devices to their accounts:\n\n```typescript\nimport { GatewayClient } from '@ai-hands/gateway-sdk';\n\nconst client = new GatewayClient({\n  endpoint: 'gateway.example.com:8443',\n  auth: { username: 'admin', password: 'secret' },\n});\n\n// Bind a device using the binding code displayed on the device\nconst bindResult = await client.bindDevice({\n  bindingCode: 'ABCD-1234-EFGH', // Code shown on device terminal\n  userId: 'user-123',\n  deviceName: 'My MacBook Pro', // Optional friendly name\n});\n\nif (bindResult.ok) {\n  console.log('Device bound successfully!');\n  console.log('Device ID:', bindResult.deviceId);\n  console.log('Short ID:', bindResult.shortId); // e.g., \"a1b2c3d4\"\n} else {\n  console.error('Binding failed:', bindResult.error);\n}\n\n// List user's devices\nconst userDevices = await client.listUserDevices({\n  userId: 'user-123',\n  includeOffline: true,\n});\n\nconsole.log('User devices:', userDevices.devices);\nconsole.log('Online status:', userDevices.online);\n\n// Unbind a device\nawait client.unbindDevice({\n  deviceId: 'a1b2c3d4', // Can use short_id or full device_id\n  userId: 'user-123',\n});\n\n// Delete a device completely\nawait client.deleteDevice({\n  deviceId: 'a1b2c3d4',\n  userId: 'user-123',\n});\n```\n\n### File Operations\n\n```typescript\n// Read a file from a device\nconst content = await client.readFile({\n  deviceId: 'device-uuid',\n  path: '/etc/hostname',\n});\nconsole.log('File content:', content.toString());\n\n// Write a file to a device\nconst writeResult = await client.writeFile({\n  deviceId: 'device-uuid',\n  path: '/tmp/hello.txt',\n  data: Buffer.from('Hello, World!\\n'),\n  mode: 0o644,\n});\n\nif (writeResult.ok) {\n  console.log('File written, SHA256:', writeResult.sha256);\n} else {\n  console.error('Write failed:', writeResult.error);\n}\n```\n\n### Next.js API Route Example\n\n```typescript\n// app/api/devices/route.ts\nimport { NextResponse } from 'next/server';\nimport { GatewayClient } from '@ai-hands/gateway-sdk';\n\nconst client = new GatewayClient({\n  endpoint: process.env.GATEWAY_ENDPOINT!,\n  auth: {\n    username: process.env.GATEWAY_USERNAME!,\n    password: process.env.GATEWAY_PASSWORD!,\n  },\n});\n\nexport async function GET(request: Request) {\n  const { searchParams } = new URL(request.url);\n  const userId = searchParams.get('userId');\n\n  if (!userId) {\n    return NextResponse.json({ error: 'userId required' }, { status: 400 });\n  }\n\n  try {\n    const result = await client.listUserDevices({\n      userId,\n      includeOffline: true,\n    });\n    return NextResponse.json(result);\n  } catch (error) {\n    return NextResponse.json({ error: String(error) }, { status: 500 });\n  }\n}\n\n// POST /api/devices/bind\nexport async function POST(request: Request) {\n  const body = await request.json();\n  const { bindingCode, userId, deviceName } = body;\n\n  try {\n    const result = await client.bindDevice({\n      bindingCode,\n      userId,\n      deviceName,\n    });\n    return NextResponse.json(result);\n  } catch (error) {\n    return NextResponse.json({ error: String(error) }, { status: 500 });\n  }\n}\n```\n\n## API Reference\n\n### `GatewayClient`\n\n#### Constructor\n\n```typescript\nnew GatewayClient(config: GatewayClientConfig)\n```\n\n- `endpoint`: Gateway address (host:port)\n- `auth`: Optional Basic Auth credentials\n- `useTls`: Use TLS (default: auto-detect from endpoint)\n- `timeoutMs`: Request timeout (default: 30000)\n\n#### Methods\n\n| Method | Description |\n|--------|-------------|\n| `listDevices(tags?)` | List all online devices |\n| `exec(request)` | Execute a command on a device |\n| `readFile(request)` | Read a file from a device |\n| `writeFile(request)` | Write a file to a device |\n| `bindDevice(request)` | Bind a device using binding code |\n| `unbindDevice(request)` | Unbind a device from user |\n| `deleteDevice(request)` | Delete a device completely |\n| `listUserDevices(request)` | List devices for a user |\n| `close()` | Close the client connection |\n\n## Environment Variables\n\nWhen using with Next.js, set these in your `.env.local`:\n\n```bash\nGATEWAY_ENDPOINT=gateway.example.com:8443\nGATEWAY_USERNAME=admin\nGATEWAY_PASSWORD=your-secret-password\n```\n\n## Publishing (Maintainers)\n\nSDK 版本号跟随 Gateway 的「主.次」版本，「补丁」版本独立维护。\n\n### Setup (First time)\n\n1. Create npm organization `ai-hands` at https://www.npmjs.com/org/create\n2. Configure OIDC trusted publishing on npm:\n   - Go to package settings on npmjs.com\n   - Add trusted publisher with:\n     - **Repository**: `ChainbotAI/ai-hands-gateway`\n     - **Workflow**: `publish-ts-sdk.yml`\n     - **Environment**: (leave empty)\n\n### Release\n\n```bash\n# Tag format: sdk/v{major}.{minor}.{patch}\ngit tag sdk/v0.1.0\ngit push origin sdk/v0.1.0\n```\n\nGitHub Actions will automatically build and publish to npm via OIDC (no token management needed).\n\n## License\n\nMIT\n","readmeFilename":"README.md","homepage":"https://github.com/ChainbotAI/ai-hands-gateway/tree/main/sdk/typescript#readme","repository":{"type":"git","url":"git+https://github.com/ChainbotAI/ai-hands-gateway.git","directory":"sdk/typescript"},"bugs":{"url":"https://github.com/ChainbotAI/ai-hands-gateway/issues"}}