anyclaude-sdk 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/query.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // Returns an AsyncGenerator<SDKMessage>. Accepts either a single string prompt
4
4
  // or an async iterable of SDKUserMessage (for multi-turn / interactive use).
5
5
  import { runAgent } from './agent.js';
6
- import { track, telemetryEnabled } from './telemetry.js';
6
+ import { track, telemetryEnabled, tokenBucket } from './telemetry.js';
7
7
  import { profileForModel } from './llm/profiles.js';
8
8
  export function query(options) {
9
9
  const prompt = typeof options.prompt === 'string'
@@ -59,17 +59,18 @@ export function query(options) {
59
59
  settings: options.settings,
60
60
  skills: options.skills,
61
61
  });
62
- gen.interrupt = () => abortController.abort();
63
- // Anonymous, aggregate adoption signal one event per public run. Fire-and-forget,
64
- // never blocks the generator, no-ops unless enabled + a collector is configured.
65
- // Only booleans + a coarse model-family bucket leave the process (see telemetry.ts).
62
+ // Anonymous, aggregate adoption signal. Fire-and-forget, never blocks, no-ops
63
+ // unless enabled + a collector is configured. Only booleans + coarse buckets
64
+ // (model family, token-volume bucket) ever leave the process see telemetry.ts.
66
65
  const telemetry = {
67
66
  disabled: options.disableTelemetry,
68
67
  ...options.telemetry,
69
68
  };
70
- if (telemetryEnabled(telemetry)) {
69
+ const modelFamily = profileForModel(options.model).name;
70
+ const enabled = telemetryEnabled(telemetry);
71
+ if (enabled) {
71
72
  track('run', {
72
- model_family: profileForModel(options.model).name,
73
+ model_family: modelFamily,
73
74
  client_workspace_tools: !!options.clientWorkspaceTools,
74
75
  client_tools: !!options.clientTools?.length,
75
76
  survivor: options.maxDurationMs != null,
@@ -83,7 +84,29 @@ export function query(options) {
83
84
  resumed: !!options.continueRun || !!options.resume,
84
85
  }, telemetry);
85
86
  }
86
- return gen;
87
+ if (!enabled) {
88
+ gen.interrupt = () => abortController.abort();
89
+ return gen;
90
+ }
91
+ // Wrap to emit one `run_end` with a coarse token-volume bucket when the run
92
+ // finishes (tokens aren't known until the `result` message). Pass-through only.
93
+ const wrapped = (async function* () {
94
+ let totalTokens = 0;
95
+ try {
96
+ for await (const m of gen) {
97
+ if (m.type === 'result' && m.usage) {
98
+ const u = m.usage;
99
+ totalTokens = (u.input_tokens || 0) + (u.output_tokens || 0);
100
+ }
101
+ yield m;
102
+ }
103
+ }
104
+ finally {
105
+ track('run_end', { model_family: modelFamily, tokens_bucket: tokenBucket(totalTokens) }, telemetry);
106
+ }
107
+ })();
108
+ wrapped.interrupt = () => abortController.abort();
109
+ return wrapped;
87
110
  }
88
111
  /** Wrap a single text prompt into the async-iterable form runAgent expects. */
89
112
  export async function* singlePrompt(text) {
@@ -6,6 +6,8 @@ export interface TelemetryOptions {
6
6
  /** Collector URL. Defaults to `ANYCLAUDE_TELEMETRY_URL` then the built-in default. */
7
7
  url?: string;
8
8
  }
9
+ /** Coarse token-volume bucket — never an exact count, so a single run isn't fingerprintable. */
10
+ export declare function tokenBucket(total: number): string;
9
11
  /** Resolve whether telemetry may run, honoring every documented opt-out. */
10
12
  export declare function telemetryEnabled(opts?: TelemetryOptions): boolean;
11
13
  /** Coarse runtime bucket — never anything machine-identifying. */
package/dist/telemetry.js CHANGED
@@ -24,7 +24,21 @@ const DEFAULT_TELEMETRY_URL = 'https://anyclaude-telemetry.puter.work';
24
24
  // Only these prop keys are ever transmitted, and only with safe value types.
25
25
  // Booleans pass through; these specific string keys pass through as-is (they are
26
26
  // coarse buckets we set ourselves — never free-form / user data).
27
- const ALLOWED_STRING_KEYS = new Set(['model_family', 'event_detail']);
27
+ const ALLOWED_STRING_KEYS = new Set(['model_family', 'event_detail', 'tokens_bucket']);
28
+ /** Coarse token-volume bucket — never an exact count, so a single run isn't fingerprintable. */
29
+ export function tokenBucket(total) {
30
+ if (!Number.isFinite(total) || total <= 0)
31
+ return '0';
32
+ if (total < 1_000)
33
+ return '<1k';
34
+ if (total < 10_000)
35
+ return '1k-10k';
36
+ if (total < 100_000)
37
+ return '10k-100k';
38
+ if (total < 1_000_000)
39
+ return '100k-1m';
40
+ return '1m+';
41
+ }
28
42
  function readEnv(name) {
29
43
  const p = globalThis.process;
30
44
  return p?.env?.[name];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anyclaude-sdk",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Standalone, browser-compatible SDK providing Claude Code agent capabilities (tools, tool loop, multi-turn, MCP, sub-agents, sessions) against any OpenAI/Anthropic-compatible LLM endpoint. Runs in the browser (WebContainer), Node, and Bun — no backend required.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",