{"_id":"@aispendguard/sdk","_rev":"4-b43f316b43ec96a2acbf66eac66f7690","name":"@aispendguard/sdk","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@aispendguard/sdk","version":"0.1.0","keywords":["ai","llm","cost","spending","tracking","openai","anthropic","gemini","langchain","observability"],"license":"MIT","_id":"@aispendguard/sdk@0.1.0","maintainers":[{"name":"aispendguard","email":"peterkacerik@gmail.com"}],"homepage":"https://aispendguard.com","bugs":{"url":"https://github.com/AISpendGuard/aispendguard-sdk/issues"},"dist":{"shasum":"d309533c3994d88dce95cda3a92c38bab97944bd","tarball":"https://registry.npmjs.org/@aispendguard/sdk/-/sdk-0.1.0.tgz","fileCount":25,"integrity":"sha512-KYMxenBJ3lEhRdiTL2rK/jw/HDj+vDNhZDwKzyOmH6ovDdvTKwe9SX7dgPEzFir3k3XyhFcSccl7GWJ3OMhBsA==","signatures":[{"sig":"MEQCIE/0t+u8eHLo/hr9MgefVqNlcmZTTmPdnU4nNmVTYL7OAiBZI2ByZqHosXuWO8hENPHPnsy5pvGUD/GoWFDhLCtHag==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":60338},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"e4a76b1f73e66dedd70779b4576ab0a9d058204d","scripts":{"test":"npm run build && node --test tests/*.test.mjs","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run test"},"_npmUser":{"name":"aispendguard","email":"peterkacerik@gmail.com"},"repository":{"url":"git+https://github.com/AISpendGuard/aispendguard-sdk.git","type":"git"},"_npmVersion":"11.9.0","description":"Tags-only SDK for tracking AI API spend with AISpendGuard. Supports OpenAI, Anthropic, Google Gemini, LangChain.js, and OpenTelemetry.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2","@types/node":"^22.13.10"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.0_1773520460099_0.49843169000965326","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@aispendguard/sdk","version":"0.1.2","keywords":["ai","llm","cost","spending","tracking","openai","anthropic","gemini","langchain","observability"],"license":"MIT","_id":"@aispendguard/sdk@0.1.2","maintainers":[{"name":"aispendguard","email":"peterkacerik@gmail.com"}],"homepage":"https://aispendguard.com","bugs":{"url":"https://github.com/AISpendGuard/aispendguard-sdk/issues"},"dist":{"shasum":"c37edc7b6cc8c3a9773caf6ce8edb8ab8536a4f7","tarball":"https://registry.npmjs.org/@aispendguard/sdk/-/sdk-0.1.2.tgz","fileCount":25,"integrity":"sha512-zBPswepQw/BhK4srzDbDGSRv1LpfIatJAjAzl6elLTtGbnHbiWUEe2ZgnGQ8w+8fwLH+9UIFGHUtJSd4wS5ZWQ==","signatures":[{"sig":"MEQCIDgY2/KW+jlJk/kqk4IgRvcWEzBUZjDnRWZ+goRIrKAUAiAR4EMgYAf+Evibns3XGye+mKqstAr/df5B4sYjpvTX8A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":62585},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"fc9843d47c4055be7f8002e999e9ba0c986c88ca","scripts":{"test":"npm run build && node --test tests/*.test.mjs","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run test"},"_npmUser":{"name":"aispendguard","email":"peterkacerik@gmail.com"},"repository":{"url":"git+https://github.com/AISpendGuard/aispendguard-sdk.git","type":"git"},"_npmVersion":"11.9.0","description":"Tags-only SDK for tracking AI API spend with AISpendGuard. Supports OpenAI, Anthropic, Google Gemini, LangChain.js, and OpenTelemetry.","directories":{},"_nodeVersion":"24.14.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2","@types/node":"^22.13.10"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.1.2_1773534435528_0.08311229557076105","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@aispendguard/sdk","version":"0.2.0","keywords":["ai","llm","cost","spending","tracking","openai","anthropic","gemini","langchain","observability"],"license":"MIT","_id":"@aispendguard/sdk@0.2.0","maintainers":[{"name":"aispendguard","email":"peterkacerik@gmail.com"}],"homepage":"https://aispendguard.com","bugs":{"url":"https://github.com/AISpendGuard/aispendguard-sdk/issues"},"dist":{"shasum":"b5c971398392c0bb526ec90bd9d6ef29b1c12916","tarball":"https://registry.npmjs.org/@aispendguard/sdk/-/sdk-0.2.0.tgz","fileCount":29,"integrity":"sha512-EDHjv68MYEysa4kAOBnIv+UzHJA2+SDmnlIFzAKn7L8dNWMAfKZXYlFl+asqxqUsBvwgctPNueTwvcFZmjQIZA==","signatures":[{"sig":"MEQCIDcuLK2Km40/agY5+B8J7ZWTsr0X2pR2LkoF67wohuIUAiAss3deUEVQac1GPYdM1vsNv3/yPrsURuCPmCGkZkl0TA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":89295},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18"},"gitHead":"946cd70662237637090bc55fe3e17631b39090bb","scripts":{"test":"npm run build && node --test tests/*.test.mjs","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","prepublishOnly":"npm run test"},"_npmUser":{"name":"aispendguard","email":"peterkacerik@gmail.com"},"repository":{"url":"git+https://github.com/AISpendGuard/aispendguard-sdk.git","type":"git"},"_npmVersion":"10.2.4","description":"Tags-only SDK for tracking AI API spend with AISpendGuard. Supports OpenAI, Anthropic, Google Gemini, LangChain.js, and OpenTelemetry.","directories":{},"_nodeVersion":"20.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.8.2","@types/node":"^22.13.10"},"_npmOperationalInternal":{"tmp":"tmp/sdk_0.2.0_1774900977994_0.5040217478075284","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@aispendguard/sdk","version":"0.2.1","description":"Tags-only SDK for tracking AI API spend with AISpendGuard. Supports OpenAI, Anthropic, Google Gemini, LangChain.js, and OpenTelemetry.","license":"MIT","main":"dist/index.js","types":"dist/index.d.ts","keywords":["ai","llm","cost","spending","tracking","openai","anthropic","gemini","langchain","observability"],"repository":{"type":"git","url":"git+https://github.com/AISpendGuard/aispendguard-sdk.git"},"homepage":"https://aispendguard.com","bugs":{"url":"https://github.com/AISpendGuard/aispendguard-sdk/issues"},"publishConfig":{"access":"public"},"engines":{"node":">=18"},"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","test":"npm run build && node --test tests/*.test.mjs","prepublishOnly":"npm run test"},"devDependencies":{"@types/node":"^22.13.10","typescript":"^5.8.2"},"_id":"@aispendguard/sdk@0.2.1","gitHead":"8bb24d737ab2211f560b317ef73caefe821f994f","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-ifQ8nkGugxAJyrMKHqQFJB3VNi8mdB4NjjoFoeEu2ZUp1zj2SyH5lTRf8+XtA10e0ndbqlUd3Kvw4nmLkxFZIg==","shasum":"8f04b5caccac9fb0ccf5583fb26658a47ca03105","tarball":"https://registry.npmjs.org/@aispendguard/sdk/-/sdk-0.2.1.tgz","fileCount":29,"unpackedSize":94649,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aispendguard%2fsdk@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCKU7DwL7qIG4mPOnYI4Ga20boXFpQaFjBfoKJi3U65rwIhAOaAoKeGPeqPtfCUj6uf+mjXnL9Phr5Wgh8mMmOmK4cw"}]},"_npmUser":{"name":"aispendguard","email":"peterkacerik@gmail.com"},"directories":{},"maintainers":[{"name":"aispendguard","email":"peterkacerik@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sdk_0.2.1_1775761887755_0.6425448602682724"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-14T20:34:19.982Z","modified":"2026-04-09T19:11:28.216Z","0.1.0":"2026-03-14T20:34:20.237Z","0.1.2":"2026-03-15T00:27:15.768Z","0.2.0":"2026-03-30T20:02:58.215Z","0.2.1":"2026-04-09T19:11:27.892Z"},"bugs":{"url":"https://github.com/AISpendGuard/aispendguard-sdk/issues"},"license":"MIT","homepage":"https://aispendguard.com","keywords":["ai","llm","cost","spending","tracking","openai","anthropic","gemini","langchain","observability"],"repository":{"type":"git","url":"git+https://github.com/AISpendGuard/aispendguard-sdk.git"},"description":"Tags-only SDK for tracking AI API spend with AISpendGuard. Supports OpenAI, Anthropic, Google Gemini, LangChain.js, and OpenTelemetry.","maintainers":[{"name":"aispendguard","email":"peterkacerik@gmail.com"}],"readme":"# AISpendGuard SDK\n\nTags-only SDK for sending AI usage events to AISpendGuard.\n\n## What it enforces\n- No prompt/output/content fields\n- Strict event validation\n- Required tags: `task_type`, `feature`, `route`\n- Custom tags allowed (lowercase snake_case keys), for example: `team`, `project_code`, `region`\n- Custom tag values can be either string values or array values (`string[]`)\n- API key auth via `x-api-key`\n\n## Install\n```bash\nnpm install @aispendguard/sdk\n```\n\n## Quick start\n```ts\nimport { init, trackUsage } from \"@aispendguard/sdk\";\n\ninit({\n  apiKey: process.env.AISPENDGUARD_API_KEY!,\n  endpoint: \"https://www.aispendguard.com/api/ingest\",\n});\n\nawait trackUsage({\n  provider: \"openai\",\n  model: \"gpt-4o-mini\",\n  inputTokens: 120,\n  outputTokens: 12,\n  latencyMs: 840,\n  costUsd: 0.0021,\n  timestamp: new Date(),\n  tags: {\n    task_type: \"classify\",\n    feature: \"lead_classifier\",\n    route: \"POST /api/ai/classify\",\n    environment: \"prod\",\n    customer_plan: \"free\"\n  }\n});\n```\n\n## OpenAI helper\n```ts\nimport { init, trackUsage, createOpenAIUsageEvent } from \"@aispendguard/sdk\";\n\ninit({\n  apiKey: process.env.AISPENDGUARD_API_KEY!,\n  endpoint: \"https://www.aispendguard.com/api/ingest\",\n});\n\nconst startedAt = Date.now();\nconst response = await openai.responses.create({\n  model: \"gpt-4o-mini\",\n  input: \"Classify this lead\"\n});\n\nconst event = createOpenAIUsageEvent({\n  model: \"gpt-4o-mini\",\n  resolvedModel: response.model,       // \"gpt-4o-mini-2024-07-18\" — pinned version\n  usage: response.usage,               // auto-extracts tokens, cache hits, reasoning tokens\n  latencyMs: Date.now() - startedAt,\n  tags: {\n    task_type: \"classify\",\n    feature: \"lead_classifier\",\n    route: \"POST /api/ai/classify\"\n  }\n});\n\nawait trackUsage(event);\n```\n\n## Anthropic helper\n```ts\nimport { init, trackUsage, createAnthropicUsageEvent } from \"@aispendguard/sdk\";\n\ninit({\n  apiKey: process.env.AISPENDGUARD_API_KEY!,\n  endpoint: \"https://www.aispendguard.com/api/ingest\"\n});\n\nconst startedAt = Date.now();\nconst message = await anthropic.messages.create({\n  model: \"claude-3-5-sonnet-latest\",\n  max_tokens: 200,\n  messages: [{ role: \"user\", content: \"Summarize this thread.\" }]\n});\n\nconst event = createAnthropicUsageEvent({\n  model: \"claude-3-5-sonnet-latest\",\n  resolvedModel: message.model,        // \"claude-3-5-sonnet-20241022\" — pinned version\n  usage: message.usage,                // auto-extracts tokens, cache_read, cache_creation\n  latencyMs: Date.now() - startedAt,\n  tags: {\n    task_type: \"summarize\",\n    feature: \"support_summary\",\n    route: \"POST /api/support/summary\"\n  }\n});\n\nawait trackUsage(event);\n```\n\n## Gemini helper\n```ts\nimport { init, trackUsage, createGeminiUsageEvent } from \"@aispendguard/sdk\";\n\ninit({\n  apiKey: process.env.AISPENDGUARD_API_KEY!,\n  endpoint: \"https://www.aispendguard.com/api/ingest\"\n});\n\nconst startedAt = Date.now();\nconst response = await gemini.models.generateContent({\n  model: \"gemini-2.0-flash\",\n  contents: [{ role: \"user\", parts: [{ text: \"Translate this to French.\" }] }]\n});\n\nconst event = createGeminiUsageEvent({\n  model: \"gemini-2.0-flash\",\n  resolvedModel: response.modelVersion, // \"gemini-2.0-flash-001\" — pinned version\n  usage: response.usageMetadata,        // auto-extracts tokens, cachedContent, thoughts\n  latencyMs: Date.now() - startedAt,\n  tags: {\n    task_type: \"translate\",\n    feature: \"ui_i18n\",\n    route: \"POST /api/translate\"\n  }\n});\n\nawait trackUsage(event);\n```\n\n## Streaming Responses\n\nWith streaming, usage data arrives in the **final chunk**. Accumulate the stream, then track:\n\n### OpenAI Streaming\n```ts\nconst startedAt = Date.now();\nconst stream = await openai.chat.completions.create({\n  model: \"gpt-4o-mini\",\n  messages: [{ role: \"user\", content: \"Hello\" }],\n  stream: true,\n  stream_options: { include_usage: true }, // required for usage in stream\n});\n\nlet usage;\nfor await (const chunk of stream) {\n  if (chunk.usage) usage = chunk.usage;\n  // ... process chunk.choices[0]?.delta\n}\n\nif (usage) {\n  const event = createOpenAIUsageEvent({\n    model: \"gpt-4o-mini\",\n    usage,\n    latencyMs: Date.now() - startedAt,\n    tags: { task_type: \"chat\", feature: \"assistant\", route: \"POST /api/chat\" },\n  });\n  await trackUsage(event);\n}\n```\n\n### Anthropic Streaming\n```ts\nconst startedAt = Date.now();\nconst stream = anthropic.messages.stream({\n  model: \"claude-sonnet-4-20250514\",\n  messages: [{ role: \"user\", content: \"Hello\" }],\n  max_tokens: 200,\n});\n\nfor await (const event of stream) {\n  // ... process text events\n}\n\nconst message = await stream.finalMessage();\n\nconst event = createAnthropicUsageEvent({\n  model: \"claude-sonnet-4-20250514\",\n  usage: message.usage,\n  latencyMs: Date.now() - startedAt,\n  tags: { task_type: \"chat\", feature: \"assistant\", route: \"POST /api/chat\" },\n});\nawait trackUsage(event);\n```\n\n> **Key point:** OpenAI requires `stream_options: { include_usage: true }` — without it, usage is `null` in the stream. Anthropic provides usage on the final message automatically.\n\n## API\n- `init(config)`\n- `trackUsage(event | event[])`\n- `createOpenAIUsageEvent(params)` — OpenAI Chat Completions + Responses API\n- `createAnthropicUsageEvent(params)` — Anthropic Messages API\n- `createGeminiUsageEvent(params)` — Google Gemini generateContent API\n- `new AISpendGuardClient(config).trackUsage(...)` — direct client usage (used by OpenClaw plugin)\n\n## Config\n- `apiKey` (required)\n- `endpoint` (default: `https://www.aispendguard.com/api/ingest`)\n- `timeoutMs` (default: `5000`)\n- `maxRetries` (default: `2`)\n- `strict` (default: `false`, if `true` throws on errors)\n\n## Notes\n- Non-strict mode logs and returns `{ ok: false, error }`.\n- Strict mode throws on validation/network/ingest errors.\n\n## Validation Limits\n- Required tags: `task_type`, `feature`, `route` (must be non-empty strings)\n- Known optional tags: `customer_plan`, `customer_id`, `provider`, `model`, `environment`, `agent_name`\n- Custom tag keys: lowercase snake_case only, regex `^[a-z][a-z0-9_]{1,63}$`\n- Custom tag values: `string` or `string[]`\n- Max tags per event: `24`\n- Max values in a single array tag: `16`\n- Max length per string value: `120`\n- Forbidden keys (blocked): prompt/content/output/message/attachment-like fields\n\n## Extended token fields (optional)\n\nThese optional fields give AISpendGuard the data it needs for accurate cost calculation and cost-spike detection. The provider helpers extract them automatically from `response.usage`.\n\n| Field | Type | What it is | Provider |\n|-------|------|-----------|----------|\n| `resolvedModel` | `string` | Pinned model version from response (e.g. `gpt-4o-mini-2024-07-18`) | All |\n| `inputTokensCached` | `number` | Cache read tokens — already in `inputTokens`, billed cheaper | OpenAI (0.5×) · Anthropic (0.1×) · Gemini |\n| `inputTokensCacheWrite` | `number` | Cache write tokens — already in `inputTokens`, billed at premium | Anthropic only (1.25×) |\n| `thinkingTokens` | `number` | Reasoning/thinking tokens — already in `outputTokens`, billed at full output rate | OpenAI o1/o3 · Gemini 2.5 |\n\n> **Anthropic note:** Extended thinking tokens (`claude-3-7-sonnet` with `thinking: enabled`) are\n> included in `output_tokens` but NOT separately reported in the `usage` object. You can count\n> `content` blocks of type `\"thinking\"` manually if you need the split.\n\n### Why these matter\n\nWithout them, cost calculations are inaccurate:\n- **Cache read tokens** cost 10–50% of normal — without tracking, you overstate spend on cached calls.\n- **Cache write tokens** (Anthropic) cost 25% more — without tracking, you understate spend when building cache.\n- **Thinking tokens** for o1/o3 can be 3–10× the visible output — without tracking, cost spikes are invisible.\n- **Resolved model** lets AISpendGuard detect silent provider upgrades between versions.\n\n### Manual override (no helper)\n\nIf you aren't using a helper, pass them directly in `trackUsage`:\n```ts\nawait trackUsage({\n  provider: \"openai\",\n  model: \"gpt-4o-mini\",\n  resolvedModel: response.model,\n  inputTokens: 1000,\n  outputTokens: 50,\n  inputTokensCached: 800,      // 800 of the 1000 input tokens were cache hits\n  thinkingTokens: 0,\n  latencyMs: 320,\n  timestamp: new Date(),\n  tags: { task_type: \"classify\", feature: \"router\", route: \"POST /api/route\" }\n});\n```\n\n## task_type values\n\nPick the value that describes what the model is being asked to **produce**.\nThe right `task_type` is what enables AISpendGuard's waste detection rules.\n\n| Value | What it does | Output size | Best model tier |\n|-------|-------------|-------------|-----------------|\n| `answer` | Q&A, RAG responses, knowledge retrieval | 100–800 tok | standard |\n| `classify` | Label, categorize, detect intent | **1–10 tok** | **micro** |\n| `extract` | Pull structured fields from text | 50–300 tok | micro |\n| `summarize` | Condense long content, TLDR | 100–500 tok | standard |\n| `generate` | Write/draft new content | 300–2000 tok | standard |\n| `rewrite` | Paraphrase, tone-adjust, edit | ≈ input | standard |\n| `translate` | Language translation | ≈ input | micro |\n| `code` | Generate, review, explain code | 200–1500 tok | premium |\n| `eval` | LLM-as-judge, quality score | **10–50 tok** | **micro** |\n| `embed` | Text embedding / vector | fixed vector | embedding models |\n| `route` | Decide which tool/path/agent | **1–20 tok** | **micro** |\n| `plan` | Decompose tasks, strategy | 100–500 tok | premium |\n| `agent_step` | Single step in agent loop | 50–800 tok | varies |\n| `vision` | Image/PDF/screenshot understanding | 100–600 tok | standard |\n| `chat` | Multi-turn stateful conversation | 100–500 tok | standard |\n| `other` | None of the above (avoid — disables waste detection) | — | — |\n\n**Model tiers:**\n- `micro` — haiku / gpt-4o-mini / flash-lite (80–95% cheaper than premium for short-output tasks)\n- `standard` — sonnet / gpt-4o / flash (best quality/cost balance for most workloads)\n- `premium` — opus / o1 / o3 / gpt-4-turbo (complex reasoning, nuanced code, planning)\n- `embedding` — text-embedding-3-small / embed-english-v3 (never use chat models for embeddings)\n\n**Waste rule:** if `classify`, `route`, or `eval` uses a `premium` model with avg output < 100 tokens,\nAISpendGuard will flag this and calculate the exact monthly saving from switching to `micro` tier.\n\n## OpenClaw plugin\n\nTrack every LLM call made by an [OpenClaw](https://openclaw.ai/) AI agent automatically — no code changes in the agent itself.\n\nThe `@aispendguard/openclaw-plugin` hooks into OpenClaw's `llm_output` lifecycle event and forwards token-usage data to AISpendGuard.\n\n### What gets tracked per LLM call\n\n| Field | Source |\n|---|---|\n| `provider` | hook — openai, anthropic, google, deepseek |\n| `model` | hook — e.g. claude-sonnet-4-20250514, gpt-4o |\n| `input_tokens` | `usage.input` |\n| `output_tokens` | `usage.output` |\n| `input_tokens_cached` | `usage.cacheRead` (when cache is used) |\n| `input_tokens_cache_write` | `usage.cacheWrite` (when cache is written) |\n| `cache_ttl` | plugin config — `\"5m\"` (1.25×) or `\"1h\"` (2.0×) |\n| `agent_name` | `ctx.agentId` |\n| `session_id` | `ctx.sessionId` |\n\n### Setup\n\n```bash\n# Set env vars for the OpenClaw plugin\nAISG_ENDPOINT=https://www.aispendguard.com/api/ingest\nAISG_API_KEY=ask_xxxxxxxxxxxxxxxx\nAISG_CACHE_TTL=5m  # \"5m\" (default) or \"1h\" for extended Anthropic caching\n```\n\nInstall the plugin into OpenClaw:\n```bash\ncp -r openclaw-aispendguard-plugin ~/.openclaw/plugins/aispendguard\ncd ~/.openclaw/plugins/aispendguard\nnpm install && npm run build\n```\n\nSee `openclaw-aispendguard-plugin/README.md` for full docs.\n\n## Tests\nRun unit-style tests:\n```bash\nnpm test\n```\n\nRun live ingest integration test (requires local app running and valid key/workspace):\n```bash\nAISPENDGUARD_API_KEY=asg_xxx \\\nAISPENDGUARD_ENDPOINT=https://www.aispendguard.com/api/ingest \\\nnpm test\n```\n","readmeFilename":"README.md"}