{"_id":"@agent-web-portal/client","_rev":"2-c4b6cdb1a2949754194a71fba261a17d","name":"@agent-web-portal/client","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@agent-web-portal/client","version":"0.1.0","keywords":["mcp","ai-agent","agent-web-portal","awp","client","sdk","blob","s3"],"author":{"name":"Agent Web Portal Contributors"},"license":"MIT","_id":"@agent-web-portal/client@0.1.0","maintainers":[{"name":"shazhou.ww","email":"shazhou.ww@gmail.com"}],"homepage":"https://github.com/anthropics/agent-web-portal#readme","bugs":{"url":"https://github.com/anthropics/agent-web-portal/issues"},"dist":{"shasum":"3d1a70cab891e7a829fa456b529ff814807c7776","tarball":"https://registry.npmjs.org/@agent-web-portal/client/-/client-0.1.0.tgz","fileCount":9,"integrity":"sha512-zWTJgVrWhMc8dvgopHxt09fxHU1EkNiMxRXHnLlBVZ8tVwwWtHz+bltslSqgs5fsTS3j0aS7N+sd7xLAZHbSHQ==","signatures":[{"sig":"MEYCIQDH43ENpu6OE5dzsnVgeQSheWUk1hdLi2xVrm32WeP5HwIhALuXQnI6EQXTylVilKZGCQyYfMG00Hg+4CFLy/k7neKd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25576},"main":"src/index.ts","type":"module","types":"src/index.ts","exports":{".":{"types":"./src/index.ts","import":"./src/index.ts"}},"gitHead":"775a13ba357a3164925dac6fd943f64188b54dd4","scripts":{"lint":"biome check .","check":"tsc --noEmit && biome check .","lint:fix":"biome check --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"shazhou.ww","email":"shazhou.ww@gmail.com"},"repository":{"url":"git+https://github.com/anthropics/agent-web-portal.git","type":"git","directory":"packages/client"},"_npmVersion":"11.6.2","description":"Client SDK for Agent Web Portal - handles blob storage and presigned URL management","directories":{},"_nodeVersion":"24.12.0","dependencies":{"@agent-web-portal/core":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"bun-types":"^1.3.6","@types/bun":"latest","@aws-sdk/client-s3":"^3.600.0","@aws-sdk/s3-request-presigner":"^3.600.0"},"peerDependencies":{"typescript":"^5","@aws-sdk/client-s3":"^3.0.0","@aws-sdk/s3-request-presigner":"^3.0.0"},"peerDependenciesMeta":{"@aws-sdk/client-s3":{"optional":true},"@aws-sdk/s3-request-presigner":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/client_0.1.0_1769099674385_0.5033311185289915","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@agent-web-portal/client","version":"0.2.0","description":"Client SDK for Agent Web Portal - handles blob storage and presigned URL management","license":"MIT","author":{"name":"Agent Web Portal Contributors"},"repository":{"type":"git","url":"git+https://github.com/anthropics/agent-web-portal.git","directory":"packages/client"},"homepage":"https://github.com/anthropics/agent-web-portal#readme","bugs":{"url":"https://github.com/anthropics/agent-web-portal/issues"},"publishConfig":{"access":"public"},"keywords":["mcp","ai-agent","agent-web-portal","awp","client","sdk","blob","s3"],"type":"module","main":"src/index.ts","types":"src/index.ts","exports":{".":{"import":"./src/index.ts","types":"./src/index.ts"}},"scripts":{"clean":"rimraf .turbo dist","typecheck":"tsc --noEmit","lint":"biome check .","lint:fix":"biome check --write .","check":"tsc --noEmit && biome check ."},"dependencies":{"@agent-web-portal/core":"^0.2.0"},"devDependencies":{"@aws-sdk/client-s3":"^3.600.0","@aws-sdk/s3-request-presigner":"^3.600.0","@types/bun":"latest","bun-types":"^1.3.6"},"peerDependencies":{"@aws-sdk/client-s3":"^3.0.0","@aws-sdk/s3-request-presigner":"^3.0.0","typescript":"^5"},"peerDependenciesMeta":{"@aws-sdk/client-s3":{"optional":true},"@aws-sdk/s3-request-presigner":{"optional":true}},"gitHead":"ee9e9127b046b65772299a166ae6c03eb8009ea9","_id":"@agent-web-portal/client@0.2.0","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-otxR1Uhfg8sEJiz5qYCtK4hQIEzK8gw178RRJqwvCb7a22XYlU6WMRZz4Kgf2QrkMJcNZMJtmrO4J/P7JOksrQ==","shasum":"92d0953ac37e091585c69eba3db2da4b2d2dfd2e","tarball":"https://registry.npmjs.org/@agent-web-portal/client/-/client-0.2.0.tgz","fileCount":14,"unpackedSize":61843,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCBUxjdBXCbGUsfjSDZUdA/7Bw7t1i5hI+FgRcSqBBGJQIgX4uf05CrBFcg1VO3lzd5W5012rCk+9ygZMoaFg4Qhqo="}]},"_npmUser":{"name":"shazhou.ww","email":"shazhou.ww@gmail.com"},"directories":{},"maintainers":[{"name":"shazhou.ww","email":"shazhou.ww@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/client_0.2.0_1769334901569_0.5016428920629938"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-22T16:34:34.298Z","modified":"2026-01-25T09:55:01.878Z","0.1.0":"2026-01-22T16:34:34.539Z","0.2.0":"2026-01-25T09:55:01.732Z"},"bugs":{"url":"https://github.com/anthropics/agent-web-portal/issues"},"author":{"name":"Agent Web Portal Contributors"},"license":"MIT","homepage":"https://github.com/anthropics/agent-web-portal#readme","keywords":["mcp","ai-agent","agent-web-portal","awp","client","sdk","blob","s3"],"repository":{"type":"git","url":"git+https://github.com/anthropics/agent-web-portal.git","directory":"packages/client"},"description":"Client SDK for Agent Web Portal - handles blob storage and presigned URL management","maintainers":[{"name":"shazhou.ww","email":"shazhou.ww@gmail.com"}],"readme":"# @agent-web-portal/client\r\n\r\nAgent Web Portal 客户端 SDK，提供自动 Blob 处理、预签名 URL 管理和基于密钥对的认证支持。\r\n\r\n## 概述\r\n\r\n`@agent-web-portal/client` 提供：\r\n\r\n- **AwpClient** - 高级客户端类\r\n- **Blob 自动处理** - 自动生成预签名 URL\r\n- **Storage Provider** - 抽象存储接口 (支持 S3)\r\n- **AwpAuth** - 基于 ECDSA P-256 密钥对的认证\r\n\r\n## 安装\r\n\r\n```bash\r\nbun add @agent-web-portal/client\r\n\r\n# 如果使用 S3 存储\r\nbun add @aws-sdk/client-s3 @aws-sdk/s3-request-presigner\r\n```\r\n\r\n## 快速开始\r\n\r\n```typescript\r\nimport { AwpClient, AwpAuth, FileKeyStorage, S3StorageProvider } from \"@agent-web-portal/client\";\r\n\r\n// 创建认证处理器\r\nconst auth = new AwpAuth({\r\n  clientName: \"My AI Agent\",\r\n  keyStorage: new FileKeyStorage({ directory: \"~/.awp/keys\" }),\r\n  callbacks: {\r\n    onAuthRequired: async (challenge) => {\r\n      console.log(\"请访问:\", challenge.authUrl);\r\n      console.log(\"验证码:\", challenge.verificationCode);\r\n      // 等待用户完成授权...\r\n      return true;\r\n    },\r\n  },\r\n});\r\n\r\nconst client = new AwpClient({\r\n  endpoint: \"https://my-awp-server.com/mcp\",\r\n  auth,\r\n  storage: new S3StorageProvider({\r\n    region: \"us-east-1\",\r\n    bucket: \"my-bucket\",\r\n  }),\r\n});\r\n\r\n// 调用 Tool\r\nconst result = await client.callTool(\"greet\", { name: \"World\" });\r\nconsole.log(result.data); // { message: \"Hello, World!\" }\r\n```\r\n\r\n## 认证机制\r\n\r\nAWP 使用基于 ECDSA P-256 密钥对的认证方案，流程如下：\r\n\r\n```\r\n┌─────────────────────────────────────────────────────────────────┐\r\n│                        认证流程                                  │\r\n├─────────────────────────────────────────────────────────────────┤\r\n│                                                                  │\r\n│  1. 首次请求 → Server 返回 401 + auth_endpoint                   │\r\n│                                                                  │\r\n│  2. Client 生成密钥对 + 验证码                                   │\r\n│     - 生成 ECDSA P-256 keypair                                   │\r\n│     - 生成 32-byte 随机数 nonce                                  │\r\n│     - 签名生成 8 位验证码                                        │\r\n│                                                                  │\r\n│  3. 引导用户访问 authUrl                                         │\r\n│     authUrl = authEndpoint?pubkey=...&nonce=...&client=...      │\r\n│                                                                  │\r\n│  4. 用户在 Server 登录后输入验证码                               │\r\n│     Server 验签成功 → 存储 pubkey + userId + TTL                 │\r\n│                                                                  │\r\n│  5. Client 后续请求签名                                          │\r\n│     签名内容: timestamp.METHOD.path.bodyHash                     │\r\n│     Headers: X-AWP-Pubkey, X-AWP-Timestamp, X-AWP-Signature     │\r\n│                                                                  │\r\n│  6. Server 验签 → 获取关联的 userId → 处理请求                   │\r\n│                                                                  │\r\n└─────────────────────────────────────────────────────────────────┘\r\n```\r\n\r\n### 基本用法\r\n\r\n```typescript\r\nimport { AwpAuth, FileKeyStorage } from \"@agent-web-portal/client\";\r\n\r\nconst auth = new AwpAuth({\r\n  clientName: \"Claude Desktop\",\r\n  keyStorage: new FileKeyStorage({ directory: \"~/.awp/keys\" }),\r\n  callbacks: {\r\n    // 需要授权时调用\r\n    onAuthRequired: async (challenge) => {\r\n      console.log(\"请访问以下链接完成授权:\");\r\n      console.log(challenge.authUrl);\r\n      console.log(\"验证码:\", challenge.verificationCode);\r\n      \r\n      // 在 CLI 中可以等待用户确认\r\n      const confirmed = await askUserConfirmation(\"授权完成后按回车继续...\");\r\n      return confirmed;\r\n    },\r\n    \r\n    // 授权成功\r\n    onAuthSuccess: () => {\r\n      console.log(\"授权成功！\");\r\n    },\r\n    \r\n    // 授权失败\r\n    onAuthFailed: (error) => {\r\n      console.error(\"授权失败:\", error.message);\r\n    },\r\n  },\r\n});\r\n```\r\n\r\n### Key Storage 实现\r\n\r\n提供三种开箱即用的存储实现：\r\n\r\n```typescript\r\n// 文件存储 (适用于 CLI/服务端)\r\nimport { FileKeyStorage } from \"@agent-web-portal/client\";\r\nconst storage = new FileKeyStorage({ directory: \"~/.awp/keys\" });\r\n\r\n// 内存存储 (适用于测试)\r\nimport { MemoryKeyStorage } from \"@agent-web-portal/client\";\r\nconst storage = new MemoryKeyStorage();\r\n\r\n// localStorage 存储 (适用于浏览器)\r\nimport { LocalStorageKeyStorage } from \"@agent-web-portal/client\";\r\nconst storage = new LocalStorageKeyStorage({ prefix: \"awp-key:\" });\r\n```\r\n\r\n### 密钥轮换\r\n\r\n密钥可以在过期前自动或手动轮换，无需用户重新授权：\r\n\r\n```typescript\r\n// 手动轮换\r\nawait auth.rotateKey(endpoint, `${endpoint}/auth/rotate`);\r\n\r\n// 自动轮换提醒 (通过回调)\r\nconst auth = new AwpAuth({\r\n  // ...\r\n  autoRotateDays: 7, // 剩余 7 天时提醒\r\n  callbacks: {\r\n    onKeyExpiring: (daysRemaining) => {\r\n      console.log(`密钥将在 ${daysRemaining} 天后过期`);\r\n      // 可以自动触发轮换\r\n    },\r\n  },\r\n});\r\n```\r\n\r\n## Blob 处理\r\n\r\n客户端自动处理 Blob 字段：\r\n\r\n```typescript\r\n// 调用带 Blob 的 Tool\r\nconst result = await client.callTool(\"process-document\", {\r\n  document: \"s3://my-bucket/input/doc.pdf\",  // 输入 Blob URI\r\n  options: { quality: 80 },\r\n});\r\n\r\n// 结果中的 Blob 字段自动填充为永久 URI\r\nconsole.log(result.data.thumbnail); // \"s3://my-bucket/output/thumb.png\"\r\nconsole.log(result.data.metadata);  // { pageCount: 10 }\r\n```\r\n\r\n## API\r\n\r\n### `AwpClient`\r\n\r\n```typescript\r\nconst client = new AwpClient({\r\n  endpoint: string,           // AWP 服务器 URL\r\n  auth?: AwpAuth,             // 认证处理器 (可选)\r\n  storage?: StorageProvider,  // 存储提供者 (Blob 处理时需要)\r\n  outputPrefix?: string,      // 输出 Blob 前缀\r\n  headers?: Record<string, string>,  // 自定义请求头\r\n  fetch?: typeof fetch,       // 自定义 fetch 函数\r\n});\r\n\r\n// 方法\r\nawait client.initialize();                    // 初始化连接\r\nawait client.listTools();                     // 列出所有 Tools\r\nawait client.callTool(name, args, schema?);   // 调用 Tool\r\nawait client.getToolBlobSchema(name);         // 获取 Tool 的 Blob Schema\r\nclient.setToolBlobSchema(name, schema);       // 设置 Tool 的 Blob Schema\r\n```\r\n\r\n### `AwpAuth`\r\n\r\n```typescript\r\nconst auth = new AwpAuth({\r\n  clientName: string,         // 客户端名称 (授权时显示)\r\n  keyStorage: KeyStorage,     // 密钥存储实现\r\n  callbacks?: AuthCallbacks,  // 事件回调\r\n  autoRotateDays?: number,    // 自动轮换提醒天数 (默认 7)\r\n});\r\n\r\n// 方法\r\nawait auth.hasValidKey(endpoint);             // 是否有有效密钥\r\nawait auth.sign(endpoint, method, url, body); // 签名请求\r\nawait auth.handleUnauthorized(endpoint, res); // 处理 401 响应\r\nawait auth.rotateKey(endpoint, rotateUrl);    // 轮换密钥\r\nawait auth.clearKey(endpoint);                // 清除密钥\r\n```\r\n\r\n### `S3StorageProvider`\r\n\r\n```typescript\r\nconst storage = new S3StorageProvider({\r\n  region: \"us-east-1\",\r\n  bucket: \"my-bucket\",\r\n  keyPrefix?: \"data/\",        // 可选前缀\r\n  defaultExpiresIn?: 3600,    // 预签名 URL 有效期 (秒)\r\n});\r\n```\r\n\r\n### 自定义 Key Storage\r\n\r\n实现 `KeyStorage` 接口：\r\n\r\n```typescript\r\ninterface KeyStorage {\r\n  load(endpoint: string): Promise<StoredKeyData | null>;\r\n  save(endpoint: string, data: StoredKeyData): Promise<void>;\r\n  delete(endpoint: string): Promise<void>;\r\n  list(): Promise<string[]>;\r\n}\r\n```\r\n\r\n### 自定义 Storage Provider\r\n\r\n实现 `StorageProvider` 接口：\r\n\r\n```typescript\r\ninterface StorageProvider {\r\n  canHandle(uri: string): boolean;\r\n  generatePresignedGetUrl(uri: string): Promise<string>;\r\n  generatePresignedPutUrl(prefix: string): Promise<PresignedUrlPair>;\r\n}\r\n\r\ninterface PresignedUrlPair {\r\n  uri: string;          // 永久 URI (如 s3://bucket/key)\r\n  presignedUrl: string; // 预签名 URL\r\n}\r\n```\r\n\r\n## 类型导出\r\n\r\n- `AwpClient` - 客户端类\r\n- `AwpClientOptions` - 客户端选项\r\n- `AwpAuth` - 认证处理器\r\n- `AwpAuthOptions` - 认证选项\r\n- `AuthCallbacks` - 认证回调\r\n- `AuthChallenge` - 授权挑战信息\r\n- `KeyStorage` - 密钥存储接口\r\n- `FileKeyStorage` - 文件存储实现\r\n- `MemoryKeyStorage` - 内存存储实现\r\n- `LocalStorageKeyStorage` - 浏览器存储实现\r\n- `S3StorageProvider` - S3 存储提供者\r\n- `StorageProvider` - 存储提供者接口\r\n- `BlobInterceptor` - Blob 拦截器\r\n- `ToolBlobSchema` - Tool Blob Schema\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}