orbitx 0.2.9 → 0.3.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.
Files changed (141) hide show
  1. package/Readme.md +478 -456
  2. package/dist/agents/backend.d.ts +4 -0
  3. package/dist/agents/backend.d.ts.map +1 -0
  4. package/dist/agents/backend.js +54 -0
  5. package/dist/agents/backend.js.map +1 -0
  6. package/dist/agents/frontend.d.ts +4 -0
  7. package/dist/agents/frontend.d.ts.map +1 -0
  8. package/dist/agents/frontend.js +50 -0
  9. package/dist/agents/frontend.js.map +1 -0
  10. package/dist/agents/index.d.ts +10 -0
  11. package/dist/agents/index.d.ts.map +1 -0
  12. package/dist/agents/index.js +22 -0
  13. package/dist/agents/index.js.map +1 -0
  14. package/dist/agents/planner.d.ts +4 -0
  15. package/dist/agents/planner.d.ts.map +1 -0
  16. package/dist/agents/planner.js +86 -0
  17. package/dist/agents/planner.js.map +1 -0
  18. package/dist/agents/protocol.d.ts +5 -0
  19. package/dist/agents/protocol.d.ts.map +1 -0
  20. package/dist/agents/protocol.js +70 -0
  21. package/dist/agents/protocol.js.map +1 -0
  22. package/dist/agents/reasoner.d.ts +5 -0
  23. package/dist/agents/reasoner.d.ts.map +1 -0
  24. package/dist/agents/reasoner.js +96 -0
  25. package/dist/agents/reasoner.js.map +1 -0
  26. package/dist/agents/research.d.ts +4 -0
  27. package/dist/agents/research.d.ts.map +1 -0
  28. package/dist/agents/research.js +28 -0
  29. package/dist/agents/research.js.map +1 -0
  30. package/dist/agents/tester.d.ts +4 -0
  31. package/dist/agents/tester.d.ts.map +1 -0
  32. package/dist/agents/tester.js +70 -0
  33. package/dist/agents/tester.js.map +1 -0
  34. package/dist/core/agent-definition.d.ts +61 -0
  35. package/dist/core/agent-definition.d.ts.map +1 -0
  36. package/dist/core/agent-definition.js +82 -0
  37. package/dist/core/agent-definition.js.map +1 -0
  38. package/dist/core/ai-provider.d.ts +3 -0
  39. package/dist/core/ai-provider.d.ts.map +1 -1
  40. package/dist/core/ai-provider.js.map +1 -1
  41. package/dist/core/anthropic-provider.d.ts +1 -0
  42. package/dist/core/anthropic-provider.d.ts.map +1 -1
  43. package/dist/core/anthropic-provider.js +3 -0
  44. package/dist/core/anthropic-provider.js.map +1 -1
  45. package/dist/core/base-agent.d.ts +51 -28
  46. package/dist/core/base-agent.d.ts.map +1 -1
  47. package/dist/core/base-agent.js +118 -26
  48. package/dist/core/base-agent.js.map +1 -1
  49. package/dist/core/deepseek-provider.d.ts +1 -0
  50. package/dist/core/deepseek-provider.d.ts.map +1 -1
  51. package/dist/core/deepseek-provider.js +3 -0
  52. package/dist/core/deepseek-provider.js.map +1 -1
  53. package/dist/core/mcp-computer.d.ts +14 -1
  54. package/dist/core/mcp-computer.d.ts.map +1 -1
  55. package/dist/core/mcp-computer.js +352 -71
  56. package/dist/core/mcp-computer.js.map +1 -1
  57. package/dist/core/ollama-provider.d.ts +1 -0
  58. package/dist/core/ollama-provider.d.ts.map +1 -1
  59. package/dist/core/ollama-provider.js +3 -0
  60. package/dist/core/ollama-provider.js.map +1 -1
  61. package/dist/core/openai-provider.d.ts +1 -0
  62. package/dist/core/openai-provider.d.ts.map +1 -1
  63. package/dist/core/openai-provider.js +3 -0
  64. package/dist/core/openai-provider.js.map +1 -1
  65. package/dist/core/swarm-base.d.ts +88 -0
  66. package/dist/core/swarm-base.d.ts.map +1 -0
  67. package/dist/core/swarm-base.js +427 -0
  68. package/dist/core/swarm-base.js.map +1 -0
  69. package/dist/index.d.ts +7 -5
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +4 -3
  72. package/dist/index.js.map +1 -1
  73. package/dist/tests/agents/default-agents.test.d.ts +2 -0
  74. package/dist/tests/agents/default-agents.test.d.ts.map +1 -0
  75. package/dist/tests/agents/default-agents.test.js +106 -0
  76. package/dist/tests/agents/default-agents.test.js.map +1 -0
  77. package/dist/tests/core/agent-definition.test.d.ts +2 -0
  78. package/dist/tests/core/agent-definition.test.d.ts.map +1 -0
  79. package/dist/tests/core/agent-definition.test.js +99 -0
  80. package/dist/tests/core/agent-definition.test.js.map +1 -0
  81. package/dist/tests/core/scripted-provider.d.ts +38 -0
  82. package/dist/tests/core/scripted-provider.d.ts.map +1 -0
  83. package/dist/tests/core/scripted-provider.js +85 -0
  84. package/dist/tests/core/scripted-provider.js.map +1 -0
  85. package/dist/tests/core/swarm-base.test.d.ts +2 -0
  86. package/dist/tests/core/swarm-base.test.d.ts.map +1 -0
  87. package/dist/tests/core/swarm-base.test.js +387 -0
  88. package/dist/tests/core/swarm-base.test.js.map +1 -0
  89. package/dist/tests/index.d.ts +3 -0
  90. package/dist/tests/index.d.ts.map +1 -1
  91. package/dist/tests/index.js +3 -0
  92. package/dist/tests/index.js.map +1 -1
  93. package/dist/tests/tools/agent/agent-tools.test.js +225 -153
  94. package/dist/tests/tools/agent/agent-tools.test.js.map +1 -1
  95. package/dist/tools/agent/active.d.ts +5 -0
  96. package/dist/tools/agent/active.d.ts.map +1 -0
  97. package/dist/tools/agent/active.js +40 -0
  98. package/dist/tools/agent/active.js.map +1 -0
  99. package/dist/tools/agent/fire.d.ts +5 -0
  100. package/dist/tools/agent/fire.d.ts.map +1 -0
  101. package/dist/tools/agent/fire.js +38 -0
  102. package/dist/tools/agent/fire.js.map +1 -0
  103. package/dist/tools/agent/hire.d.ts +2 -2
  104. package/dist/tools/agent/hire.d.ts.map +1 -1
  105. package/dist/tools/agent/hire.js +43 -10
  106. package/dist/tools/agent/hire.js.map +1 -1
  107. package/dist/tools/agent/index.d.ts +22 -19
  108. package/dist/tools/agent/index.d.ts.map +1 -1
  109. package/dist/tools/agent/index.js +29 -21
  110. package/dist/tools/agent/index.js.map +1 -1
  111. package/dist/tools/agent/prompt.d.ts +2 -2
  112. package/dist/tools/agent/prompt.d.ts.map +1 -1
  113. package/dist/tools/agent/prompt.js +19 -53
  114. package/dist/tools/agent/prompt.js.map +1 -1
  115. package/dist/tools/agent/registry.d.ts +74 -24
  116. package/dist/tools/agent/registry.d.ts.map +1 -1
  117. package/dist/tools/agent/registry.js +93 -48
  118. package/dist/tools/agent/registry.js.map +1 -1
  119. package/dist/tools/agent/report-group.d.ts +5 -0
  120. package/dist/tools/agent/report-group.d.ts.map +1 -0
  121. package/dist/tools/agent/report-group.js +50 -0
  122. package/dist/tools/agent/report-group.js.map +1 -0
  123. package/dist/tools/agent/report-parent.d.ts +5 -0
  124. package/dist/tools/agent/report-parent.d.ts.map +1 -0
  125. package/dist/tools/agent/report-parent.js +36 -0
  126. package/dist/tools/agent/report-parent.js.map +1 -0
  127. package/dist/tools/agent/types.d.ts +5 -0
  128. package/dist/tools/agent/types.d.ts.map +1 -0
  129. package/dist/tools/agent/types.js +17 -0
  130. package/dist/tools/agent/types.js.map +1 -0
  131. package/docs/agents.md +173 -228
  132. package/docs/api-reference.md +9 -4
  133. package/docs/getting-started.md +78 -78
  134. package/docs/index.md +24 -23
  135. package/docs/mcp-architecture.md +29 -6
  136. package/docs/providers.md +258 -254
  137. package/docs/skills.md +0 -1
  138. package/docs/streaming.md +133 -133
  139. package/docs/swarm.md +503 -0
  140. package/docs/tools.md +214 -212
  141. package/package.json +1 -1
@@ -1,78 +1,78 @@
1
- # Getting Started
2
-
3
- ## Install
4
-
5
- ```bash
6
- npm install orbitx
7
- ```
8
-
9
- ## Your first agent
10
-
11
- The fastest path is `SimpleAgent`: give it a provider, an instruction, and a list of tools/skills. It wires up an in-process MCP server/client for you automatically.
12
-
13
- ```ts
14
- import { OllamaProvider, SimpleAgent, GetCurrentTimeTool } from "orbitx";
15
-
16
- const provider = new OllamaProvider("gemma4:e4b");
17
-
18
- const agent = new SimpleAgent({
19
- aiProvider: provider,
20
- instruction: "You are a helpful assistant.",
21
- tools: [GetCurrentTimeTool()],
22
- });
23
-
24
- await agent.run("what is current time?", (chunk) => {
25
- process.stdout.write(chunk.content);
26
- });
27
- ```
28
-
29
- `agent.run(prompt, streamCallback)` resolves once the model has stopped calling tools and produced a final answer. The `streamCallback` is optional — omit it if you only care about the eventual message history via `getCurrentAgentStates()`.
30
-
31
- See [Streaming](./streaming.md) for the full chunk shape (roles, tool call/result chunks, `done` flag).
32
-
33
- ## Choosing a provider
34
-
35
- ```ts
36
- import { OllamaProvider, DeepSeekProvider, AnthropicProvider, OpenAIProvider } from "orbitx";
37
-
38
- new OllamaProvider("gemma4:e4b"); // local, via Ollama
39
- new DeepSeekProvider("api-key", "deepseek-v4-flash"); // hosted
40
- new AnthropicProvider("api-key", "claude-sonnet-5"); // hosted
41
- new OpenAIProvider("api-key", "gpt-5"); // hosted
42
- ```
43
-
44
- Every provider implements the same `AIProvider` interface, so switching models is a one-line change to your agent's `aiProvider`. Details, capability flags, and the main/image role split are in [Providers](./providers.md).
45
-
46
- ## Tools and skills up front
47
-
48
- `SimpleAgent`'s `tools` and `skills` lists are baked into the system prompt once, at construction time — there's no per-turn tool selection/routing step deciding what the model is allowed to see. If you want the model to be able to call something, put it in `tools` (or bundle it inside a `Skill`). See [Tools](./tools.md) and [Skills](./skills.md).
49
-
50
- ## Recovering an agent's state
51
-
52
- `getCurrentAgentStates()` returns a plain JSON-serializable snapshot: message history (each message carrying its own token usage) and running memory summary. Persist it anywhere; pass it back in as `initData` to resume the exact same agent later (after a process restart, in a new request handler, etc.):
53
-
54
- ```ts
55
- import { writeFileSync, existsSync, readFileSync } from "fs";
56
-
57
- const initData = existsSync("./state.json")
58
- ? JSON.parse(readFileSync("./state.json", "utf-8"))
59
- : undefined;
60
-
61
- const agent = new SimpleAgent({
62
- aiProvider: provider,
63
- instruction: "You are a helpful assistant.",
64
- tools: [GetCurrentTimeTool()],
65
- ...(initData ? { initData } : {}),
66
- });
67
-
68
- // after any run() call:
69
- writeFileSync("./state.json", JSON.stringify(agent.getCurrentAgentStates()));
70
- ```
71
-
72
- Messages are only ever appended, never rewritten. When the conversation grows past the memory threshold, OrbitX retires the working context into `retiredMessages` and resets the model's *active* context (`messagesCompact`) from a running summary (`compactMemory`), so an agent can keep going indefinitely without losing the ability to act on what happened earlier — nothing on disk is ever deleted, it just moves from one array to the other. Mechanics are covered in [Agents](./agents.md#memory-compaction).
73
-
74
- ## Next steps
75
-
76
- - Full control over the MCP transport (custom server/client, IPC, WebSocket, sandboxed Docker execution): [MCP Architecture](./mcp-architecture.md).
77
- - Writing your own tool or skill: [Tools](./tools.md#writing-a-custom-tool), [Skills](./skills.md#writing-a-custom-skill).
78
- - Every public export: [API Reference](./api-reference.md).
1
+ # Getting Started
2
+
3
+ ## Install
4
+
5
+ ```bash
6
+ npm install orbitx
7
+ ```
8
+
9
+ ## Your first agent
10
+
11
+ The fastest path is `SimpleAgent`: give it a provider, an instruction, and a list of tools/skills. It wires up an in-process MCP server/client for you automatically.
12
+
13
+ ```ts
14
+ import { OllamaProvider, SimpleAgent, GetCurrentTimeTool } from "orbitx";
15
+
16
+ const provider = new OllamaProvider("gemma4:e4b");
17
+
18
+ const agent = new SimpleAgent({
19
+ aiProvider: provider,
20
+ instruction: "You are a helpful assistant.",
21
+ tools: [GetCurrentTimeTool()],
22
+ });
23
+
24
+ await agent.run("what is current time?", (chunk) => {
25
+ process.stdout.write(chunk.content);
26
+ });
27
+ ```
28
+
29
+ `agent.run(prompt, streamCallback)` resolves once the model has stopped calling tools and produced a final answer. The `streamCallback` is optional — omit it if you only care about the eventual message history via `getCurrentAgentStates()`.
30
+
31
+ See [Streaming](./streaming.md) for the full chunk shape (roles, tool call/result chunks, `done` flag).
32
+
33
+ ## Choosing a provider
34
+
35
+ ```ts
36
+ import { OllamaProvider, DeepSeekProvider, AnthropicProvider, OpenAIProvider } from "orbitx";
37
+
38
+ new OllamaProvider("gemma4:e4b"); // local, via Ollama
39
+ new DeepSeekProvider("api-key", "deepseek-v4-flash"); // hosted
40
+ new AnthropicProvider("api-key", "claude-sonnet-5"); // hosted
41
+ new OpenAIProvider("api-key", "gpt-5"); // hosted
42
+ ```
43
+
44
+ Every provider implements the same `AIProvider` interface, so switching models is a one-line change to your agent's `aiProvider`. Details, capability flags, and the main/image role split are in [Providers](./providers.md).
45
+
46
+ ## Tools and skills up front
47
+
48
+ `SimpleAgent`'s `tools` and `skills` lists are baked into the system prompt once, at construction time — there's no per-turn tool selection/routing step deciding what the model is allowed to see. If you want the model to be able to call something, put it in `tools` (or bundle it inside a `Skill`). See [Tools](./tools.md) and [Skills](./skills.md).
49
+
50
+ ## Recovering an agent's state
51
+
52
+ `getCurrentAgentStates()` returns a plain JSON-serializable snapshot: message history (each message carrying its own token usage) and running memory summary. Persist it anywhere; pass it back in as `initData` to resume the exact same agent later (after a process restart, in a new request handler, etc.):
53
+
54
+ ```ts
55
+ import { writeFileSync, existsSync, readFileSync } from "fs";
56
+
57
+ const initData = existsSync("./state.json")
58
+ ? JSON.parse(readFileSync("./state.json", "utf-8"))
59
+ : undefined;
60
+
61
+ const agent = new SimpleAgent({
62
+ aiProvider: provider,
63
+ instruction: "You are a helpful assistant.",
64
+ tools: [GetCurrentTimeTool()],
65
+ ...(initData ? { initData } : {}),
66
+ });
67
+
68
+ // after any run() call:
69
+ writeFileSync("./state.json", JSON.stringify(agent.getCurrentAgentStates()));
70
+ ```
71
+
72
+ Messages are only ever appended, never rewritten. When the conversation grows past the memory threshold, OrbitX retires the working context into `retiredMessages` and resets the model's *active* context (`messagesCompact`) from a running summary (`compactMemory`), so an agent can keep going indefinitely without losing the ability to act on what happened earlier — nothing on disk is ever deleted, it just moves from one array to the other. Mechanics are covered in [Agents](./agents.md#memory-compaction).
73
+
74
+ ## Next steps
75
+
76
+ - Full control over the MCP transport (custom server/client, IPC, WebSocket, sandboxed Docker execution): [MCP Architecture](./mcp-architecture.md).
77
+ - Writing your own tool or skill: [Tools](./tools.md#writing-a-custom-tool), [Skills](./skills.md#writing-a-custom-skill).
78
+ - Every public export: [API Reference](./api-reference.md).
package/docs/index.md CHANGED
@@ -1,23 +1,24 @@
1
- # OrbitX Docs
2
-
3
- OrbitX is a TypeScript SDK for building AI agents: pluggable model providers, a tool/skill system, an MCP-based execution layer (in-process, IPC, or WebSocket), and a resumable agent loop with automatic memory compaction.
4
-
5
- This directory is written for two audiences at once:
6
-
7
- - **Humans** learning the library for the first time — read top to bottom.
8
- - **AI coding agents** working inside a project that depends on `orbitx` — each page is self-contained enough to be read on its own when you only need one topic (e.g. "how do I define a tool").
9
-
10
- ## Pages
11
-
12
- 1. [Getting Started](./getting-started.md) — install, first agent, streaming output, resuming state.
13
- 2. [Providers](./providers.md) — `AIProvider`, the four built-in providers, capabilities, main/image roles.
14
- 3. [Agents](./agents.md) — `BaseAgent` vs `SimpleAgent`, the run loop, memory compaction, tokens, and multi-agent (`WorkerAgent`/`AgentTools`).
15
- 4. [Tools](./tools.md) — the `MCPTool` shape, built-in tool catalog, writing your own tools.
16
- 5. [Skills](./skills.md) — bundling instructions + tools, built-in skill catalog, writing your own.
17
- 6. [MCP Architecture](./mcp-architecture.md) — `MCPServer`/`MCPClient`/connections, in-process vs IPC vs WS, `MCPComputer` sandbox.
18
- 7. [Streaming](./streaming.md) — the `StreamCallback` chunk shape and how to consume it.
19
- 8. [API Reference](./api-reference.md) — flat index of every public export from `orbitx`.
20
-
21
- ## The shape of the library, in one paragraph
22
-
23
- You construct one or more `AIProvider` instances (OpenAI, Anthropic, DeepSeek, or Ollama), a list of `MCPTool`s and/or `Skill`s (a skill is just instructions + tools bundled together), and hand them to `SimpleAgent` (or `BaseAgent` for full control over the underlying MCP transport). Calling `agent.run(prompt, streamCallback)` drives a loop: send the conversation + tool schemas to the provider, dispatch any tool calls the model requests, feed results back, repeat until the model stops calling tools. Everything the model can see (tools, skills, instructions) is decided once, up front — there's no dynamic tool routing/selection step. Long conversations are handled by summarizing into a running `memory` string instead of ever deleting messages; the full history is preserved in `getCurrentAgentStates()` for persistence/resume.
1
+ # OrbitX Docs
2
+
3
+ OrbitX is a TypeScript SDK for building AI agents: pluggable model providers, a tool/skill system, an MCP-based execution layer (in-process, IPC, or WebSocket), and a resumable agent loop with automatic memory compaction.
4
+
5
+ This directory is written for two audiences at once:
6
+
7
+ - **Humans** learning the library for the first time — read top to bottom.
8
+ - **AI coding agents** working inside a project that depends on `orbitx` — each page is self-contained enough to be read on its own when you only need one topic (e.g. "how do I define a tool").
9
+
10
+ ## Pages
11
+
12
+ 1. [Getting Started](./getting-started.md) — install, first agent, streaming output, resuming state.
13
+ 2. [Providers](./providers.md) — `AIProvider`, the four built-in providers, capabilities, main/image roles.
14
+ 3. [Agents](./agents.md) — `BaseAgent` vs `SimpleAgent`, the run loop, memory compaction, tokens.
15
+ 4. [Swarm](./swarm.md) — many agents that hire, task, and report to each other: `SwarmBase`, `AgentDefinition`, `getAgentTools()`.
16
+ 5. [Tools](./tools.md) — the `MCPTool` shape, built-in tool catalog, writing your own tools.
17
+ 6. [Skills](./skills.md) — bundling instructions + tools, built-in skill catalog, writing your own.
18
+ 7. [MCP Architecture](./mcp-architecture.md) — `MCPServer`/`MCPClient`/connections, in-process vs IPC vs WS, `MCPComputer` sandbox.
19
+ 8. [Streaming](./streaming.md) — the `StreamCallback` chunk shape and how to consume it.
20
+ 9. [API Reference](./api-reference.md) — flat index of every public export from `orbitx`.
21
+
22
+ ## The shape of the library, in one paragraph
23
+
24
+ You construct one or more `AIProvider` instances (OpenAI, Anthropic, DeepSeek, or Ollama), a list of `MCPTool`s and/or `Skill`s (a skill is just instructions + tools bundled together), and hand them to `SimpleAgent` (or `BaseAgent` for full control over the underlying MCP transport). Calling `agent.run(prompt, streamCallback)` drives a loop: send the conversation + tool schemas to the provider, dispatch any tool calls the model requests, feed results back, repeat until the model stops calling tools. Everything the model can see (tools, skills, instructions) is decided once, up front — there's no dynamic tool routing/selection step. Long conversations are handled by summarizing into a running `memory` string instead of ever deleting messages; the full history is preserved in `getCurrentAgentStates()` for persistence/resume.
@@ -30,7 +30,7 @@ mcpClient.callTool(name: string, inputs: Record<string, any>, toolCallId?: strin
30
30
  mcpClient.setExecuteProviderHandler(handler: (toolCallId: string, type: ProviderType, input: Record<string, any>) => Promise<{ output: Record<string, any> }>): void;
31
31
  ```
32
32
 
33
- `toolCallId` on `callTool()` and the handler installed via `setExecuteProviderHandler()` are what `BaseAgent` wires up automatically so `mcp.executeProvider(...)` works inside a tool's `execute()` — see [Custom `MCP` subclasses](#custom-mcp-subclasses) below. You don't need to call either yourself unless you're driving `MCPClient` outside of `BaseAgent`.
33
+ `toolCallId` on `callTool()` and the handler installed via `setExecuteProviderHandler()` are what `BaseAgent` wires up automatically so `mcp.executeProvider(...)` works inside a tool's `execute()` — see [Custom `MCP` subclasses](#custom-mcp-subclasses) below. You don't need to call either yourself unless you're driving `MCPClient` outside of `BaseAgent`. A `SwarmBase` takes that handler back after building each agent, so in a swarm the provider call is answered by the swarm — see [Swarm](./swarm.md#providers-a-tool-reaches-for).
34
34
 
35
35
  This is what you pass into `BaseAgent({ mcpClient, ... })`. `envID` scopes storage/RNG state per logical environment/session — pass a stable id (e.g. a user or conversation id) if you want isolated tool state per agent instance sharing a server. Accepting an array of connections lets one client fan out across multiple servers.
36
36
 
@@ -82,12 +82,35 @@ const connection = computer.getConnection();
82
82
  await computer.stop();
83
83
  ```
84
84
 
85
- - `mountPath` — host directory mounted into the container (this is what filesystem tools inside the sandbox actually touch).
86
- - `ports` — ports to expose from the container, or `"*"` for host network mode (Linux only, or Windows via WSL2).
87
- - `getConnection()` — returns a ready `MCPConnection`: IPC on Linux/macOS, WebSocket on Windows (auth token generated automatically).
88
- - `stop()` — kills the container.
85
+ ```ts
86
+ new MCPComputer(mountPath: string, ports: number[] | "*", image?: string, options?: MCPComputerOptions);
87
+ ```
88
+
89
+ - `mountPath` — host directory mounted into the container (this is what filesystem tools inside the sandbox actually touch). Four subdirectories are created under it and mounted: `workspace`, `mcp-server-storage`, `presents`, `user-inputs`.
90
+ - `ports` — ports to publish from the container, or `"*"` for host network mode. **`"*"` is Linux-only**: on Windows and macOS the container joins a VM's network namespace, so nothing it binds is reachable from your machine and published ports are ignored — the constructor throws rather than letting that surface later as a connection timeout.
91
+ - `image` — defaults to `aliafsordeh/orbitx-sandbox:0.2`.
92
+ - `start()` — verifies the Docker daemon is reachable, prepares the mount, launches the container, waits for its ready log, and then waits for the connection endpoint to actually accept traffic. It resolves only when the sandbox is genuinely reachable, and rejects with the container's own output when it is not.
93
+ - `getConnection(wsHost?)` — returns a ready `MCPConnection`, cached (repeated calls hand back the same object). In `"ws"` mode it must be called after `start()`, since the port is only chosen there.
94
+ - `waitUntilConnected(timeoutMs?)` — optional; resolves once the transport is carrying traffic, if you want the MCP handshake up before the first tool call.
95
+ - `getPresentsHostPath()`, `getConnectionPort()`, `getContainerName()`, `isRunning()` — host-side accessors.
96
+ - `stop()` — removes the container, closes the connection, and cleans up the socket directory. Idempotent.
97
+
98
+ `MCPComputerOptions`:
99
+
100
+ | Option | Default | Purpose |
101
+ | --- | --- | --- |
102
+ | `connectionMode` | `"ipc"` on Linux, `"ws"` elsewhere | Transport between your process and the sandbox. |
103
+ | `readyTimeoutMs` | `60_000` | Wait for the sandbox's ready log once the container is running. |
104
+ | `pullTimeoutMs` | `300_000` | Inactivity budget while docker pulls the image, so a first run isn't killed mid-download. |
105
+ | `handshakeTimeoutMs` | `20_000` | Wait for the endpoint to accept traffic after the ready log. |
106
+ | `onLog` | — | `(line, "stdout" \| "stderr") => void`; receives everything the container writes. |
107
+ | `dockerBin` | `"docker"` | Override the executable (e.g. `"podman"`, or an absolute path). |
108
+
109
+ The transport default is not a style choice: Docker Desktop on Windows and macOS runs the daemon inside a VM and shares the mount over a network filesystem, which cannot carry a unix-domain socket. IPC therefore only works when the daemon and your process share a kernel, and WebSocket (loopback-published, with an auto-generated auth token) is used everywhere else.
110
+
111
+ Requires the `aliafsordeh/orbitx-sandbox:0.2` image (pull it, or build it yourself from the `Dockerfile.sandbox` at the repo root). Note that the sandbox's own stdout/stderr are drained continuously for the life of the container — a piped-but-unread stream fills its OS buffer after ~64KB and blocks the sandbox process on its next write, which surfaces much later as tool calls that never return.
89
112
 
90
- Requires the `aliafsordeh/orbitx-sandbox:0.1` image (pull it, or build it yourself from the `Dockerfile.sandbox` at the repo root).
113
+ Servers started *inside* the sandbox must bind `0.0.0.0`, not `localhost`, to be reachable through a published port; `getInstructions()` tells agents this.
91
114
 
92
115
  ## Storage and RNG
93
116