anyclaude-sdk 0.9.0 → 0.10.0
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 +20 -0
- package/dist/team/broadcast-mailbox.d.ts +34 -0
- package/dist/team/broadcast-mailbox.js +85 -0
- package/dist/team/index.d.ts +1 -0
- package/dist/team/index.js +1 -0
- package/dist/team/mailbox.d.ts +5 -2
- package/dist/team/mailbox.js +7 -0
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,6 +198,26 @@ Optional off-main-thread execution via a Comlink worker harness
|
|
|
198
198
|
query({ prompt, workspace, llm, agents: {}, background: true })
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
+
### Agents in separate Web Workers
|
|
202
|
+
|
|
203
|
+
Two halves: **Comlink** for main→worker control (`wrapWorker` / `exposeBackgroundWorker`,
|
|
204
|
+
above), and **`BroadcastChannelMailbox`** so agents in *different* workers gossip
|
|
205
|
+
mailbox-style. It's a drop-in `Mailbox`, so the existing `team` tools
|
|
206
|
+
(`send_message` / `dispatch_tasks`) work unchanged across workers:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { BroadcastChannelMailbox } from 'anyclaude-sdk'
|
|
210
|
+
|
|
211
|
+
// inside each Web Worker / tab / worker_thread, same channel name:
|
|
212
|
+
const mailbox = new BroadcastChannelMailbox({ channelName: 'team', origin: 'planner' })
|
|
213
|
+
query({ prompt, workspace, llm, team: true, mailbox })
|
|
214
|
+
// messages sent by one worker land in the addressed agent's inbox in another.
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Uses the global `BroadcastChannel` by default; pass `{ channel }` (e.g. the
|
|
218
|
+
[`broadcast-channel`](https://www.npmjs.com/package/broadcast-channel) package)
|
|
219
|
+
for cross-tab durability or older runtimes.
|
|
220
|
+
|
|
201
221
|
## Pluggable backends
|
|
202
222
|
|
|
203
223
|
You aren't tied to WebContainer. A `Sandbox` is just a `FileSystem` plus a
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Mailbox } from './mailbox.js';
|
|
2
|
+
/** Minimal structural type for a BroadcastChannel-like transport, so callers
|
|
3
|
+
* can inject the `broadcast-channel` polyfill or any compatible object. */
|
|
4
|
+
export interface ChannelLike {
|
|
5
|
+
postMessage(data: unknown): void;
|
|
6
|
+
/** Native BroadcastChannel uses an `onmessage` setter with `{data}` events. */
|
|
7
|
+
onmessage?: ((ev: {
|
|
8
|
+
data: unknown;
|
|
9
|
+
}) => void) | null;
|
|
10
|
+
/** `broadcast-channel` polyfill uses addEventListener('message', fn). */
|
|
11
|
+
addEventListener?: (type: 'message', fn: (data: unknown) => void) => void;
|
|
12
|
+
close?: () => void;
|
|
13
|
+
}
|
|
14
|
+
export interface BroadcastChannelMailboxOptions {
|
|
15
|
+
/** Channel name (default 'anyclaude-team'). Ignored if `channel` is given. */
|
|
16
|
+
channelName?: string;
|
|
17
|
+
/** Inject a ready-made channel (e.g. the `broadcast-channel` package) or a
|
|
18
|
+
* custom BroadcastChannel factory. When omitted, the global BroadcastChannel
|
|
19
|
+
* is used. */
|
|
20
|
+
channel?: ChannelLike;
|
|
21
|
+
/** Stable origin id for this instance; defaults to a random id. Set it to a
|
|
22
|
+
* worker/agent name if you want deterministic, debuggable message ids. */
|
|
23
|
+
origin?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class BroadcastChannelMailbox extends Mailbox {
|
|
26
|
+
private readonly channel;
|
|
27
|
+
private readonly origin;
|
|
28
|
+
private closed;
|
|
29
|
+
constructor(opts?: BroadcastChannelMailboxOptions);
|
|
30
|
+
/** Send a message: append to the local replica and broadcast to peers. */
|
|
31
|
+
send(from: string, to: string, text: string): string;
|
|
32
|
+
/** Stop listening and release the channel. Safe to call more than once. */
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// A Mailbox that gossips across execution contexts (Web Workers, browser tabs,
|
|
2
|
+
// Node worker_threads) over a BroadcastChannel. Drop-in for the in-memory
|
|
3
|
+
// Mailbox: the existing `team` tools (send_message / dispatch_tasks) work
|
|
4
|
+
// unchanged, but messages now propagate to every agent on the same channel.
|
|
5
|
+
//
|
|
6
|
+
// Design: each instance keeps its own eventually-consistent replica of the
|
|
7
|
+
// message stream. `send()` appends locally AND posts on the channel; every
|
|
8
|
+
// other instance ingests the inbound message into its replica (de-duped by a
|
|
9
|
+
// globally-unique id). `inbox()`/`all()`/`markRead()` read/mutate the local
|
|
10
|
+
// replica synchronously — read state is per-instance (each agent tracks what
|
|
11
|
+
// *it* has seen), which is exactly the inbox semantics we want.
|
|
12
|
+
//
|
|
13
|
+
// Browser-safe: BroadcastChannel is a Web API (also a Node >=15 global inside
|
|
14
|
+
// worker_threads). For older runtimes or cross-tab durability, inject the
|
|
15
|
+
// `broadcast-channel` npm package's channel via the `channel` option.
|
|
16
|
+
import { Mailbox } from './mailbox.js';
|
|
17
|
+
function isWire(d) {
|
|
18
|
+
return !!d && typeof d === 'object' && d.__ac === 'msg';
|
|
19
|
+
}
|
|
20
|
+
function randomId() {
|
|
21
|
+
const g = globalThis;
|
|
22
|
+
if (g.crypto?.randomUUID)
|
|
23
|
+
return g.crypto.randomUUID().slice(0, 8);
|
|
24
|
+
// Fallback without Math.random reliance: derive from high-res-ish counters.
|
|
25
|
+
return 'o' + (Date.now().toString(36) + (originSeed++).toString(36));
|
|
26
|
+
}
|
|
27
|
+
let originSeed = 0;
|
|
28
|
+
export class BroadcastChannelMailbox extends Mailbox {
|
|
29
|
+
constructor(opts = {}) {
|
|
30
|
+
super();
|
|
31
|
+
this.closed = false;
|
|
32
|
+
this.origin = opts.origin ?? randomId();
|
|
33
|
+
let ch = opts.channel;
|
|
34
|
+
if (!ch) {
|
|
35
|
+
const BC = globalThis
|
|
36
|
+
.BroadcastChannel;
|
|
37
|
+
if (!BC) {
|
|
38
|
+
throw new Error('BroadcastChannel is not available in this runtime. Pass `channel` ' +
|
|
39
|
+
'(e.g. from the `broadcast-channel` npm package) to BroadcastChannelMailbox.');
|
|
40
|
+
}
|
|
41
|
+
ch = new BC(opts.channelName ?? 'anyclaude-team');
|
|
42
|
+
}
|
|
43
|
+
this.channel = ch;
|
|
44
|
+
// Normalize both delivery shapes: native BroadcastChannel hands the listener
|
|
45
|
+
// a MessageEvent ({data}); the `broadcast-channel` polyfill hands it the raw
|
|
46
|
+
// payload. Accept either, then de-dupe via the protected ingest().
|
|
47
|
+
const handle = (arg) => {
|
|
48
|
+
if (this.closed)
|
|
49
|
+
return;
|
|
50
|
+
let data = arg;
|
|
51
|
+
if (!isWire(arg) && arg && typeof arg === 'object' && 'data' in arg) {
|
|
52
|
+
data = arg.data;
|
|
53
|
+
}
|
|
54
|
+
if (isWire(data) && data.origin !== this.origin)
|
|
55
|
+
this.ingest(data.message);
|
|
56
|
+
};
|
|
57
|
+
// Single registration: addEventListener when available (native + polyfill
|
|
58
|
+
// both support it), otherwise the onmessage setter.
|
|
59
|
+
if (typeof this.channel.addEventListener === 'function') {
|
|
60
|
+
this.channel.addEventListener('message', handle);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.channel.onmessage = (ev) => handle(ev);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Send a message: append to the local replica and broadcast to peers. */
|
|
67
|
+
send(from, to, text) {
|
|
68
|
+
// Globally-unique id: origin-scoped so two workers never collide.
|
|
69
|
+
const id = `msg_${this.origin}_${++this.counter}`;
|
|
70
|
+
const m = { id, from, to, text, ts: Date.now(), read: false };
|
|
71
|
+
this.ingest(m);
|
|
72
|
+
if (!this.closed) {
|
|
73
|
+
const wire = { __ac: 'msg', origin: this.origin, message: m };
|
|
74
|
+
this.channel.postMessage(wire);
|
|
75
|
+
}
|
|
76
|
+
return id;
|
|
77
|
+
}
|
|
78
|
+
/** Stop listening and release the channel. Safe to call more than once. */
|
|
79
|
+
close() {
|
|
80
|
+
if (this.closed)
|
|
81
|
+
return;
|
|
82
|
+
this.closed = true;
|
|
83
|
+
this.channel.close?.();
|
|
84
|
+
}
|
|
85
|
+
}
|
package/dist/team/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { Mailbox, type AgentMessage } from './mailbox.js';
|
|
2
|
+
export { BroadcastChannelMailbox, type ChannelLike, type BroadcastChannelMailboxOptions, } from './broadcast-mailbox.js';
|
|
2
3
|
export { TaskBoard, type BoardTask, type TaskStatus } from './taskBoard.js';
|
|
3
4
|
export { TEAM_TOOLS, sendMessage, taskCreate, taskUpdate, taskGet, boardList, } from './tools.js';
|
|
4
5
|
export { coordinatorPrompt } from './prompt.js';
|
package/dist/team/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Teammate/coordinator MVP: shared in-memory mailbox + task board, the tools
|
|
2
2
|
// the coordinator uses to delegate, and the coordinator system-prompt addendum.
|
|
3
3
|
export { Mailbox } from './mailbox.js';
|
|
4
|
+
export { BroadcastChannelMailbox, } from './broadcast-mailbox.js';
|
|
4
5
|
export { TaskBoard } from './taskBoard.js';
|
|
5
6
|
export { TEAM_TOOLS, sendMessage, taskCreate, taskUpdate, taskGet, boardList, } from './tools.js';
|
|
6
7
|
export { coordinatorPrompt } from './prompt.js';
|
package/dist/team/mailbox.d.ts
CHANGED
|
@@ -7,10 +7,13 @@ export type AgentMessage = {
|
|
|
7
7
|
read: boolean;
|
|
8
8
|
};
|
|
9
9
|
export declare class Mailbox {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
protected messages: AgentMessage[];
|
|
11
|
+
protected counter: number;
|
|
12
12
|
/** Deliver a message; returns the message id. */
|
|
13
13
|
send(from: string, to: string, text: string): string;
|
|
14
|
+
/** Append a message produced elsewhere (e.g. another worker), de-duped by id.
|
|
15
|
+
* Subclasses that sync over a transport use this for inbound messages. */
|
|
16
|
+
protected ingest(m: AgentMessage): void;
|
|
14
17
|
/** Messages addressed to `agentId`, oldest first. */
|
|
15
18
|
inbox(agentId: string, opts?: {
|
|
16
19
|
unreadOnly?: boolean;
|
package/dist/team/mailbox.js
CHANGED
|
@@ -12,6 +12,13 @@ export class Mailbox {
|
|
|
12
12
|
this.messages.push({ id, from, to, text, ts: Date.now(), read: false });
|
|
13
13
|
return id;
|
|
14
14
|
}
|
|
15
|
+
/** Append a message produced elsewhere (e.g. another worker), de-duped by id.
|
|
16
|
+
* Subclasses that sync over a transport use this for inbound messages. */
|
|
17
|
+
ingest(m) {
|
|
18
|
+
if (this.messages.some((x) => x.id === m.id))
|
|
19
|
+
return;
|
|
20
|
+
this.messages.push(m);
|
|
21
|
+
}
|
|
15
22
|
/** Messages addressed to `agentId`, oldest first. */
|
|
16
23
|
inbox(agentId, opts) {
|
|
17
24
|
return this.messages.filter((m) => m.to === agentId && (!opts?.unreadOnly || !m.read));
|
package/dist/telemetry.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Bump on release so adoption can be bucketed by version. */
|
|
2
|
-
export declare const TELEMETRY_SDK_VERSION = "0.
|
|
2
|
+
export declare const TELEMETRY_SDK_VERSION = "0.10.0";
|
|
3
3
|
export interface TelemetryOptions {
|
|
4
4
|
/** Force-disable for this call (highest precedence besides the global opt-outs). */
|
|
5
5
|
disabled?: boolean;
|
package/dist/telemetry.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// See TELEMETRY.md for the full disclosure.
|
|
17
17
|
import { uuid } from './util/ids.js';
|
|
18
18
|
/** Bump on release so adoption can be bucketed by version. */
|
|
19
|
-
export const TELEMETRY_SDK_VERSION = '0.
|
|
19
|
+
export const TELEMETRY_SDK_VERSION = '0.10.0';
|
|
20
20
|
// Aggregate-only collector (Puter Worker; see examples/telemetry-collector).
|
|
21
21
|
// Override with `ANYCLAUDE_TELEMETRY_URL` / `telemetry: { url }`, or disable
|
|
22
22
|
// entirely with the opt-outs above. Set to '' to make telemetry a no-op.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anyclaude-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
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",
|