anyclaude-react 0.2.2 → 0.4.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 CHANGED
@@ -55,15 +55,24 @@ const { messages, streamingText, status, tokens, cost, send, interrupt, clear }
55
55
 
56
56
  ## Client-side tools (server brain, browser hands)
57
57
 
58
- Run the agent on your server but execute chosen tools in the browser — e.g. `bash` on a WebContainer. Pair `query({ clientTools: ['bash'] })` server-side with a `clientTools` executor map here; `client_tool_request`s are auto-executed and the results streamed back:
58
+ Run the agent on your server but execute its file/shell tools **in the browser**against a WebContainer, an IndexedDB filesystem, OPFS, or memory. Pair `query({ clientTools: WORKSPACE_TOOL_NAMES })` server-side with a turnkey executor map here. `client_tool_request`s are auto-executed and the results streamed back; it reuses the real SDK tool implementations, so behavior matches server-side exactly.
59
59
 
60
60
  ```tsx
61
- useAgent({
62
- endpoint: '/api/agent',
63
- clientTools: { bash: async ({ command }) => ({ content: await runOnWebContainer(command) }) },
64
- })
61
+ import { useAgent, createWebContainerClientTools, createWorkspaceClientTools } from 'anyclaude-react'
62
+ import { DexieFileSystem } from 'anyclaude-sdk/fs'
63
+
64
+ // real shell + files in a WebContainer:
65
+ useAgent({ endpoint: '/api/agent', clientTools: createWebContainerClientTools(wc) })
66
+
67
+ // or point the file tools at the user's own IndexedDB (no shell):
68
+ useAgent({ endpoint: '/api/agent', clientTools: createWorkspaceClientTools(new DexieFileSystem('my-db')) })
69
+
70
+ // fully overridable per tool:
71
+ createWorkspaceClientTools(workspace, { only: ['write_file','read_file'], extra: { bash: myBash } })
65
72
  ```
66
73
 
74
+ You can still hand-write a `clientTools` map (`{ bash: async ({command}) => ({ content }) }`) for full control.
75
+
67
76
  ## Components
68
77
 
69
78
  **Chat**
@@ -78,15 +87,26 @@ useAgent({
78
87
  | `<Composer onSend>` | Textarea + send (Enter sends, Shift+Enter newline). |
79
88
  | `<Working active paused>` | Shimmering "Working…" indicator. |
80
89
 
81
- **IDE** (optional peers: `@xterm/xterm`, `codemirror`)
90
+ **Lightweight UI (root, no heavy deps)**
82
91
 
83
92
  | Component | Purpose |
84
93
  |---|---|
85
- | `<Terminal spawn>` | xterm.js bound to a streaming shell (e.g. a WebContainer process). |
86
94
  | `<FileExplorer list onOpen>` | Collapsible file tree over any filesystem adapter. |
87
- | `<CodeEditor value onChange>` | Controlled CodeMirror 6 editor. |
88
95
  | `<AskUser question onAnswer>` | Renders an `ask_user_question` prompt; pair with the SDK's `onAskUser`. |
89
96
 
97
+ **IDE — `anyclaude-react/ide` subpath** (so the root barrel stays dependency-light)
98
+
99
+ ```tsx
100
+ import { Terminal, CodeEditor } from 'anyclaude-react/ide'
101
+ ```
102
+
103
+ | Component | Purpose | Peer dep |
104
+ |---|---|---|
105
+ | `<Terminal spawn>` | xterm.js terminal bound to a streaming shell (e.g. a WebContainer process). | `@xterm/xterm` + `@xterm/addon-fit` |
106
+ | `<CodeEditor value onChange>` | Controlled CodeMirror 6 editor. | `codemirror` + `@codemirror/*` |
107
+
108
+ The root export (`useAgent`, chat components, `FileExplorer`, `AskUser`, the client/workspace helpers) pulls **neither** `@xterm` nor `codemirror` — install those only if you import from `/ide`.
109
+
90
110
  ## Styling
91
111
 
92
112
  Everything is class-based (`.ac-*`) with `data-role` attributes. Import the
package/dist/ide.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { Terminal } from './components/Terminal.js';
2
+ export type { TerminalProps, ShellProcess } from './components/Terminal.js';
3
+ export { CodeEditor } from './components/CodeEditor.js';
4
+ export type { CodeEditorProps } from './components/CodeEditor.js';
package/dist/ide.js ADDED
@@ -0,0 +1,7 @@
1
+ // anyclaude-react/ide — heavy IDE components, split onto a subpath so the root
2
+ // barrel stays dependency-light. These are the only components that need the
3
+ // optional peers @xterm/* (Terminal) and codemirror/@codemirror/* (CodeEditor).
4
+ //
5
+ // import { Terminal, CodeEditor } from 'anyclaude-react/ide'
6
+ export { Terminal } from './components/Terminal.js';
7
+ export { CodeEditor } from './components/CodeEditor.js';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { createAgentClient, createEndpointClient } from './client.js';
2
+ export { createWorkspaceClientTools, createWebContainerClientTools, type WorkspaceLike, type WorkspaceClientToolsOptions, } from './workspaceTools.js';
2
3
  export type { AgentClient, RunFn, RunOptions, EndpointClientOptions, ClientToolMap, ClientToolExecutor, ClientToolResult, } from './client.js';
3
4
  export { useAgent } from './useAgent.js';
4
5
  export type { UseAgentOptions, UseAgentResult, AgentStatus } from './useAgent.js';
@@ -17,11 +18,7 @@ export { AgentChat } from './components/AgentChat.js';
17
18
  export type { AgentChatProps } from './components/AgentChat.js';
18
19
  export { ChatPanel } from './components/ChatPanel.js';
19
20
  export type { ChatPanelProps } from './components/ChatPanel.js';
20
- export { Terminal } from './components/Terminal.js';
21
- export type { TerminalProps, ShellProcess } from './components/Terminal.js';
22
21
  export { FileExplorer } from './components/FileExplorer.js';
23
22
  export type { FileExplorerProps, FileEntry } from './components/FileExplorer.js';
24
- export { CodeEditor } from './components/CodeEditor.js';
25
- export type { CodeEditorProps } from './components/CodeEditor.js';
26
23
  export { AskUser } from './components/AskUser.js';
27
24
  export type { AskUserProps, AskUserQuestion } from './components/AskUser.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // anyclaude-react — restylable React UI kit for anyclaude-sdk.
2
2
  export { createAgentClient, createEndpointClient } from './client.js';
3
+ export { createWorkspaceClientTools, createWebContainerClientTools, } from './workspaceTools.js';
3
4
  export { useAgent } from './useAgent.js';
4
5
  export { renderMarkdown } from './markdown.js';
5
6
  export { Message, MarkdownMessage } from './components/Message.js';
@@ -9,8 +10,8 @@ export { Working } from './components/Working.js';
9
10
  export { Transcript } from './components/Transcript.js';
10
11
  export { AgentChat } from './components/AgentChat.js';
11
12
  export { ChatPanel } from './components/ChatPanel.js';
12
- // IDE-grade components (optional peer deps: @xterm/*, @codemirror/*)
13
- export { Terminal } from './components/Terminal.js';
14
13
  export { FileExplorer } from './components/FileExplorer.js';
15
- export { CodeEditor } from './components/CodeEditor.js';
16
14
  export { AskUser } from './components/AskUser.js';
15
+ // Heavy IDE components (Terminal → @xterm/*, CodeEditor → codemirror) live on a
16
+ // subpath so this root barrel stays dependency-light:
17
+ // import { Terminal, CodeEditor } from 'anyclaude-react/ide'
@@ -0,0 +1,48 @@
1
+ import { WebContainerWorkspace } from 'anyclaude-sdk/workspace';
2
+ import type { ClientToolMap } from './client.js';
3
+ /** Structural view of an SDK workspace: a FileSystem, optionally a shell.
4
+ * `DexieFileSystem`, `WebContainerWorkspace`, `OpfsFileSystem`,
5
+ * `MemoryFileSystem` all satisfy this. */
6
+ export interface WorkspaceLike {
7
+ readFile(path: string): Promise<string | null>;
8
+ writeFile(path: string, contents: string): Promise<void>;
9
+ readdir(path: string): Promise<Array<{
10
+ name: string;
11
+ isDir: boolean;
12
+ }> | null>;
13
+ deleteFile(path: string): Promise<void>;
14
+ mkdir?(path: string): Promise<void>;
15
+ readBinary?(path: string): Promise<Uint8Array | null>;
16
+ writeBinary?(path: string, data: Uint8Array): Promise<void>;
17
+ /** Present on shell-capable workspaces (e.g. WebContainerWorkspace). */
18
+ exec?(command: string, timeoutMs?: number): Promise<{
19
+ output: string;
20
+ exitCode: number;
21
+ }>;
22
+ cwd?: string;
23
+ }
24
+ export interface WorkspaceClientToolsOptions {
25
+ /** Working directory for the tools (default: workspace.cwd ?? '/'). */
26
+ cwd?: string;
27
+ /** Restrict to these tool names (default: all supported by the workspace). */
28
+ only?: string[];
29
+ /** Extra or overriding executors, merged on top of the generated map. */
30
+ extra?: ClientToolMap;
31
+ }
32
+ /**
33
+ * Build a `ClientToolMap` that executes the SDK's built-in workspace tools
34
+ * against any SDK workspace. `bash` is included only when the workspace has a
35
+ * shell (`exec`); filesystem-only workspaces (e.g. IndexedDB) omit it.
36
+ *
37
+ * useAgent({ endpoint: '/api/agent',
38
+ * clientTools: createWorkspaceClientTools(new DexieFileSystem('my-db')) })
39
+ */
40
+ export declare function createWorkspaceClientTools(workspace: WorkspaceLike, opts?: WorkspaceClientToolsOptions): ClientToolMap;
41
+ /**
42
+ * Convenience: client tools backed by a booted WebContainer — real files + a
43
+ * real `jsh` shell, all in the browser tab.
44
+ *
45
+ * const wc = await WebContainer.boot()
46
+ * useAgent({ endpoint: '/api/agent', clientTools: createWebContainerClientTools(wc) })
47
+ */
48
+ export declare function createWebContainerClientTools(wc: ConstructorParameters<typeof WebContainerWorkspace>[0], opts?: WorkspaceClientToolsOptions): ClientToolMap;
@@ -0,0 +1,57 @@
1
+ // createWorkspaceClientTools — run the SDK's built-in workspace tools
2
+ // (read/write/edit/multi_edit/delete/list/glob/grep, and bash when a shell is
3
+ // available) on the HOST instead of the server. Pair with the server-side
4
+ // `query({ clientTools: WORKSPACE_TOOL_NAMES })`: the agent emits a
5
+ // `client_tool_request`, this map executes it against the chosen workspace —
6
+ // a browser WebContainer, an IndexedDB `DexieFileSystem`, OPFS, or memory — and
7
+ // the result is streamed back. Reuses the real SDK tool implementations, so the
8
+ // behavior matches server-side exactly.
9
+ import { bash, readFile, writeFile, editFile, multiEdit, deleteFile, listFiles, glob, grep, } from 'anyclaude-sdk/tools';
10
+ import { WebContainerWorkspace } from 'anyclaude-sdk/workspace';
11
+ const WORKSPACE_TOOLS = [bash, writeFile, readFile, editFile, multiEdit, deleteFile, listFiles, glob, grep];
12
+ const NOOP_EXEC = {
13
+ async exec() {
14
+ return { output: 'No shell available in this workspace (filesystem-only).', exitCode: 127 };
15
+ },
16
+ };
17
+ /**
18
+ * Build a `ClientToolMap` that executes the SDK's built-in workspace tools
19
+ * against any SDK workspace. `bash` is included only when the workspace has a
20
+ * shell (`exec`); filesystem-only workspaces (e.g. IndexedDB) omit it.
21
+ *
22
+ * useAgent({ endpoint: '/api/agent',
23
+ * clientTools: createWorkspaceClientTools(new DexieFileSystem('my-db')) })
24
+ */
25
+ export function createWorkspaceClientTools(workspace, opts = {}) {
26
+ const hasExec = typeof workspace.exec === 'function';
27
+ const ctx = {
28
+ fs: workspace,
29
+ exec: hasExec ? workspace : NOOP_EXEC,
30
+ cwd: opts.cwd ?? workspace.cwd ?? '/',
31
+ readFiles: new Set(),
32
+ };
33
+ const map = {};
34
+ for (const t of WORKSPACE_TOOLS) {
35
+ const name = t.def.function.name;
36
+ if (opts.only && !opts.only.includes(name))
37
+ continue;
38
+ if (name === 'bash' && !hasExec)
39
+ continue;
40
+ map[name] = async (input) => {
41
+ const r = await t.run(input, ctx);
42
+ return { content: r.content, is_error: r.isError };
43
+ };
44
+ }
45
+ return { ...map, ...(opts.extra ?? {}) };
46
+ }
47
+ /**
48
+ * Convenience: client tools backed by a booted WebContainer — real files + a
49
+ * real `jsh` shell, all in the browser tab.
50
+ *
51
+ * const wc = await WebContainer.boot()
52
+ * useAgent({ endpoint: '/api/agent', clientTools: createWebContainerClientTools(wc) })
53
+ */
54
+ export function createWebContainerClientTools(wc, opts = {}) {
55
+ const ws = new WebContainerWorkspace(wc, opts.cwd);
56
+ return createWorkspaceClientTools(ws, opts);
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anyclaude-react",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "description": "React UI kit for anyclaude-sdk — restylable hooks + components (useAgent, Transcript, Composer, AgentChat, Terminal, FileExplorer, CodeEditor, ChatPanel, AskUser) with built-in serverless 'survivor' stream-stitching. Build chatbots, agents, research assistants, browser IDEs.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,6 +11,10 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js"
13
13
  },
14
+ "./ide": {
15
+ "types": "./dist/ide.d.ts",
16
+ "import": "./dist/ide.js"
17
+ },
14
18
  "./styles.css": "./styles.css"
15
19
  },
16
20
  "files": [
@@ -54,7 +58,7 @@
54
58
  "@codemirror/view": ">=6.0.0",
55
59
  "@xterm/addon-fit": ">=0.10.0",
56
60
  "@xterm/xterm": ">=5.3.0",
57
- "anyclaude-sdk": ">=0.1.0",
61
+ "anyclaude-sdk": ">=0.4.4",
58
62
  "codemirror": ">=6.0.0",
59
63
  "react": ">=18"
60
64
  },