anyclaude-sdk 0.4.0 → 0.4.1
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 +6 -0
- package/dist/agent.js +13 -1
- package/dist/tools/bash.js +9 -1
- package/dist/workspace/webcontainer.d.ts +4 -0
- package/dist/workspace/webcontainer.js +26 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# anyclaude-sdk
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/anyclaude-sdk)
|
|
4
|
+
[](https://www.npmjs.com/package/anyclaude-react)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://anyclaude-docs.puter.site)
|
|
7
|
+
[](https://anyclaude-docs.puter.site/demo/)
|
|
8
|
+
|
|
3
9
|
Claude Code agent capabilities — tools, the tool loop, multi-turn conversations,
|
|
4
10
|
MCP, sub-agents, sessions — against **any OpenAI- or Anthropic-compatible LLM
|
|
5
11
|
endpoint**, running in the **browser** ([WebContainer](https://webcontainers.io)),
|
package/dist/agent.js
CHANGED
|
@@ -797,7 +797,19 @@ export async function* runAgent(options) {
|
|
|
797
797
|
isError = !!r.isError;
|
|
798
798
|
}
|
|
799
799
|
catch (err) {
|
|
800
|
-
|
|
800
|
+
const detail = err instanceof Error
|
|
801
|
+
? err.message
|
|
802
|
+
: typeof err === 'string'
|
|
803
|
+
? err
|
|
804
|
+
: (() => {
|
|
805
|
+
try {
|
|
806
|
+
return JSON.stringify(err);
|
|
807
|
+
}
|
|
808
|
+
catch {
|
|
809
|
+
return String(err);
|
|
810
|
+
}
|
|
811
|
+
})();
|
|
812
|
+
content = `Error executing ${name}: ${detail}`;
|
|
801
813
|
isError = true;
|
|
802
814
|
}
|
|
803
815
|
if (isError) {
|
package/dist/tools/bash.js
CHANGED
|
@@ -32,7 +32,15 @@ export const bash = {
|
|
|
32
32
|
return { content: 'Error: `command` is required.', isError: true };
|
|
33
33
|
}
|
|
34
34
|
const timeout = typeof input.timeout_ms === 'number' ? input.timeout_ms : undefined;
|
|
35
|
-
|
|
35
|
+
let result;
|
|
36
|
+
try {
|
|
37
|
+
result = await ctx.exec.exec(command, timeout);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
const msg = e instanceof Error ? e.message : typeof e === 'string' ? e : JSON.stringify(e);
|
|
41
|
+
return { content: `Failed to run command: ${msg}`, isError: true };
|
|
42
|
+
}
|
|
43
|
+
const { output, exitCode } = result;
|
|
36
44
|
if (exitCode !== 0) {
|
|
37
45
|
const body = output || '(no output)';
|
|
38
46
|
return {
|
|
@@ -39,7 +39,11 @@ export interface WebContainerProcess {
|
|
|
39
39
|
export declare class WebContainerWorkspace implements FileSystem, CommandExecutor {
|
|
40
40
|
readonly wc: WebContainerLike;
|
|
41
41
|
readonly cwd: string;
|
|
42
|
+
private cwdReady;
|
|
42
43
|
constructor(wc: WebContainerLike, cwd?: string);
|
|
44
|
+
/** Ensure the working directory exists before spawning into it (memoized).
|
|
45
|
+
* A fresh WebContainer has only `/`, so spawning with a missing cwd rejects. */
|
|
46
|
+
private ensureCwd;
|
|
43
47
|
/** Resolve a possibly-relative path against the workspace cwd. */
|
|
44
48
|
resolve(path: string): string;
|
|
45
49
|
readFile(path: string): Promise<string | null>;
|
|
@@ -8,9 +8,20 @@ const textDecoder = new TextDecoder();
|
|
|
8
8
|
*/
|
|
9
9
|
export class WebContainerWorkspace {
|
|
10
10
|
constructor(wc, cwd) {
|
|
11
|
+
this.cwdReady = null;
|
|
11
12
|
this.wc = wc;
|
|
12
13
|
this.cwd = cwd ?? wc.workdir ?? '/home/projects';
|
|
13
14
|
}
|
|
15
|
+
/** Ensure the working directory exists before spawning into it (memoized).
|
|
16
|
+
* A fresh WebContainer has only `/`, so spawning with a missing cwd rejects. */
|
|
17
|
+
ensureCwd() {
|
|
18
|
+
if (!this.cwdReady) {
|
|
19
|
+
this.cwdReady = Promise.resolve(this.wc.fs.mkdir(this.cwd, { recursive: true }))
|
|
20
|
+
.then(() => undefined)
|
|
21
|
+
.catch(() => undefined);
|
|
22
|
+
}
|
|
23
|
+
return this.cwdReady;
|
|
24
|
+
}
|
|
14
25
|
/** Resolve a possibly-relative path against the workspace cwd. */
|
|
15
26
|
resolve(path) {
|
|
16
27
|
if (path.startsWith('/'))
|
|
@@ -80,10 +91,21 @@ export class WebContainerWorkspace {
|
|
|
80
91
|
// ---- CommandExecutor ----
|
|
81
92
|
async exec(command, timeoutMs = 120_000, env) {
|
|
82
93
|
const sanitized = sanitizeCommand(command);
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
94
|
+
await this.ensureCwd();
|
|
95
|
+
let proc;
|
|
96
|
+
try {
|
|
97
|
+
proc = await this.wc.spawn('jsh', ['-c', sanitized], { env, cwd: this.cwd });
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
// Last-resort: spawn without an explicit cwd (defaults to /) so a bad cwd
|
|
101
|
+
// never hard-fails the tool; surface a real message if even that fails.
|
|
102
|
+
try {
|
|
103
|
+
proc = await this.wc.spawn('jsh', ['-c', sanitized], { env });
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
throw new Error(`failed to start shell (jsh): ${e instanceof Error ? e.message : String(e)}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
87
109
|
let output = '';
|
|
88
110
|
const reader = proc.output.getReader();
|
|
89
111
|
const collect = (async () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anyclaude-sdk",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
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",
|