anyclaude-sdk 0.7.1 → 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/README.md +40 -2
- package/dist/query.js +31 -8
- package/dist/telemetry.d.ts +2 -0
- package/dist/telemetry.js +15 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -358,9 +358,43 @@ npm install anyclaude-react
|
|
|
358
358
|
|
|
359
359
|
`useAgent()` plus restylable components — chat (`AgentChat`, `ChatPanel`, `Transcript`, `MarkdownMessage`, `Composer`, `Working`, `ToolCall`) and an IDE set (`Terminal`, `FileExplorer`, `CodeEditor`, `AskUser`). `createAgentClient` / `createEndpointClient` auto-stitch `paused` continuations and run `clientTools` in the browser.
|
|
360
360
|
|
|
361
|
+
## Run Claude Code against any model — `anyclaude-sdk/anthropic-endpoint`
|
|
362
|
+
|
|
363
|
+
Stand up an Anthropic Messages API-compatible endpoint backed by any OpenAI-compatible model, so **Claude Code itself** (or any Anthropic-Messages client) runs against DeepSeek / Qwen / GLM / Kimi / local Ollama. Unlike a naive proxy, inline tool-call **dialects are recovered into proper `tool_use` blocks**, so tool use actually works on cheap models.
|
|
364
|
+
|
|
365
|
+
```ts
|
|
366
|
+
import { createOpenAIClient } from 'anyclaude-sdk/llm'
|
|
367
|
+
import { anthropicToChat, anthropicSSE } from 'anyclaude-sdk/anthropic-endpoint'
|
|
368
|
+
|
|
369
|
+
const llm = createOpenAIClient({ baseUrl: 'https://api.deepseek.com/v1', model: 'deepseek-chat', apiKey })
|
|
370
|
+
// POST /v1/messages:
|
|
371
|
+
for await (const evt of anthropicSSE(llm, anthropicToChat(body), { model: 'deepseek-chat' })) res.write(evt)
|
|
372
|
+
// then: ANTHROPIC_BASE_URL=http://localhost:8787 claude
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
Runnable: [`examples/claude-code-router`](examples/claude-code-router).
|
|
376
|
+
|
|
377
|
+
## Reliable tool use on cheap / open models
|
|
378
|
+
|
|
379
|
+
Frontier models emit clean native function-calls; cheaper ones often don't. Three layers (in `anyclaude-sdk/llm`) close the gap: **tool-call dialects** (`parseToolCalls` — xml-function / hermes / json-fence), **auto-detected model profiles** (`profileForModel` — qwen/deepseek/moonshot/zhipu/mistral/llama), and **self-healing argument repair** (`query({ repairToolCalls })`, on by default — validates args and feeds the model a corrective tool_result instead of running with garbage). Prove it on your endpoints with [`scripts/compat-matrix.mjs`](scripts/compat-matrix.mjs) → [COMPATIBILITY.md](COMPATIBILITY.md).
|
|
380
|
+
|
|
381
|
+
## Scaffold an in-browser AI IDE
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
npm create anyclaude-app@latest my-app # template: bolt — WebContainer + chat + live preview, no backend
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
The `bolt` template wires `useWebContainerPreview({ wc })` (boot a dev server → live preview URL) + a browser-side `query()` + the IDE components. See [`anyclaude-react`](#react-ui-kit--anyclaude-react).
|
|
388
|
+
|
|
389
|
+
## Other niceties
|
|
390
|
+
|
|
391
|
+
- **Live compaction marker** — `autoCompact` emits a `compact_boundary` with `status: 'start'` *before* summarizing (for a live "compacting…" shimmer) and `status: 'end'` after with `post_tokens`.
|
|
392
|
+
- **Cancel a queued message** — `MessageQueue.push()` returns a stable id; `remove(id)` cancels a single pending message (per-pill ✕ in a UI).
|
|
393
|
+
- **BYO LLM client** — reuse the SDK's wire codec: `toOpenAIMessages`, `consumeSSE`, and the LLM types from `anyclaude-sdk/llm` (no bare-root import in browser bundles).
|
|
394
|
+
|
|
361
395
|
## Examples & live demo
|
|
362
396
|
|
|
363
|
-
Runnable Vite projects in [`examples/`](examples/): **`browser-ide`** (WebContainer IDE — real shell + Node in the tab), `browser-chat`, `vercel-kv-survivor`, `vercel-supabase-survivor`, `vercel-indexeddb-survivor`, **`vercel-clienttools`** (server brain / browser hands). Try the **[live demo](https://anyclaude-docs.puter.site/demo/)**.
|
|
397
|
+
Runnable Vite projects in [`examples/`](examples/): **`browser-ide`** (WebContainer IDE — real shell + Node in the tab), `browser-chat`, `claude-code-router`, `vercel-kv-survivor`, `vercel-supabase-survivor`, `vercel-indexeddb-survivor`, **`vercel-clienttools`** (server brain / browser hands). Try the **[live demo](https://anyclaude-docs.puter.site/demo/)**.
|
|
364
398
|
|
|
365
399
|
## API
|
|
366
400
|
|
|
@@ -376,6 +410,10 @@ Runnable Vite projects in [`examples/`](examples/): **`browser-ide`** (WebContai
|
|
|
376
410
|
- `WebContainerWorkspace`, `MemoryFileSystem`, `NoopCommandExecutor`, `LocalSandbox`, `composeWorkspace`
|
|
377
411
|
- `defineTool` (custom tools), `projectMessages` (server-side stream redaction)
|
|
378
412
|
- `ALL_CLAUDE_CODE_TOOLS`, individual tools, `toolDefs`, `toolByName`
|
|
413
|
+
- browser-clean subpaths: `anyclaude-sdk/{query,loop,llm,fs,workspace,tools,session,memory,compact,permissions,skills,queue,prompt,anthropic-endpoint,telemetry}`
|
|
414
|
+
- `anyclaude-sdk/llm`: `parseToolCalls` + dialects, `profileForModel` (model profiles), `validateToolArguments` (repair), `toOpenAIMessages` / `consumeSSE` (BYO-client codec)
|
|
415
|
+
- `anyclaude-sdk/anthropic-endpoint`: `anthropicToChat`, `anthropicSSE`, `streamResultToAnthropicMessage` (Claude-Code router)
|
|
416
|
+
- `runToolLoop` (`/loop`), `compactWithWindow` (`/compact`), `track`/`telemetryEnabled` (`/telemetry`)
|
|
379
417
|
- All `SDK*` message types, `ContentBlockParam`, `LLMClient`, `ToolDef`, `SessionStoreLike`, etc.
|
|
380
418
|
|
|
381
419
|
## Differences from the official SDK
|
|
@@ -392,7 +430,7 @@ Runnable Vite projects in [`examples/`](examples/): **`browser-ide`** (WebContai
|
|
|
392
430
|
|
|
393
431
|
## Telemetry
|
|
394
432
|
|
|
395
|
-
The SDK emits **anonymous, opt-out** usage telemetry (SDK version, runtime, a coarse model-family bucket, and which features are used) — never code, prompts, repo identity, paths, or keys
|
|
433
|
+
The SDK emits **anonymous, opt-out** usage telemetry (SDK version, runtime, a coarse model-family bucket, and which features are used) — never code, prompts, repo identity, paths, or keys. It sends to an aggregate-only collector (a Puter Worker; source in [`examples/telemetry-collector`](examples/telemetry-collector)). Disable with `ANYCLAUDE_TELEMETRY=0`, `DO_NOT_TRACK=1`, or `query({ disableTelemetry: true })`; repoint with `ANYCLAUDE_TELEMETRY_URL` (or set it to `''` to send nowhere). Full disclosure: [TELEMETRY.md](TELEMETRY.md).
|
|
396
434
|
|
|
397
435
|
## License
|
|
398
436
|
|
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
|
-
|
|
63
|
-
//
|
|
64
|
-
//
|
|
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
|
-
|
|
69
|
+
const modelFamily = profileForModel(options.model).name;
|
|
70
|
+
const enabled = telemetryEnabled(telemetry);
|
|
71
|
+
if (enabled) {
|
|
71
72
|
track('run', {
|
|
72
|
-
model_family:
|
|
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
|
-
|
|
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) {
|
package/dist/telemetry.d.ts
CHANGED
|
@@ -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.
|
|
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",
|