@matthias-hausberger/beige 0.2.0-beta1 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matthias-hausberger/beige",
3
- "version": "0.2.0-beta1",
3
+ "version": "0.2.0",
4
4
  "description": "Secure sandboxed agent system",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -20,6 +20,7 @@
20
20
  "files": [
21
21
  "dist",
22
22
  "tools",
23
+ "sandbox",
23
24
  "config.schema.json"
24
25
  ],
25
26
  "dependencies": {
@@ -0,0 +1,28 @@
1
+ FROM denoland/deno:2.2.3
2
+
3
+ # Install common utilities
4
+ RUN apt-get update && apt-get install -y --no-install-recommends \
5
+ curl \
6
+ jq \
7
+ git \
8
+ ca-certificates \
9
+ && rm -rf /var/lib/apt/lists/*
10
+
11
+ # Create workspace directory
12
+ RUN mkdir -p /workspace /tools/bin /tools/packages /beige
13
+
14
+ # Copy tool-client source
15
+ COPY tool-client.ts /beige/tool-client.ts
16
+
17
+ # Create a wrapper script that runs tool-client via deno
18
+ # --allow-read: read the socket file path
19
+ # --allow-write: needed for some Deno versions with Unix sockets
20
+ # --allow-env: environment variables
21
+ # --unstable-net: Unix domain socket support (needed for some Deno 2.x builds)
22
+ RUN echo '#!/bin/sh' > /beige/tool-client && \
23
+ echo 'exec deno run --allow-read --allow-write --allow-net --allow-env --unstable-net /beige/tool-client.ts "$@"' >> /beige/tool-client && \
24
+ chmod +x /beige/tool-client
25
+
26
+ WORKDIR /workspace
27
+
28
+ # No CMD — container is started with "sleep infinity" by the gateway
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Tool client — runs INSIDE the sandbox (Deno).
3
+ * Connects to the gateway via Unix domain socket and sends tool requests.
4
+ *
5
+ * Usage: tool-client <tool-name> [args...]
6
+ *
7
+ * Mounted read-only into the sandbox at /beige/tool-client.ts.
8
+ * Run via the wrapper: /beige/tool-client (which invokes deno run ...)
9
+ */
10
+
11
+ const SOCKET_PATH = "/beige/gateway.sock";
12
+
13
+ const toolName = Deno.args[0];
14
+ const args = Deno.args.slice(1);
15
+
16
+ if (!toolName) {
17
+ console.error("Usage: tool-client <tool-name> [args...]");
18
+ Deno.exit(1);
19
+ }
20
+
21
+ function buildSessionContext(): Record<string, string> | undefined {
22
+ const sessionKey = Deno.env.get("BEIGE_SESSION_KEY");
23
+ const channel = Deno.env.get("BEIGE_CHANNEL");
24
+ const agentName = Deno.env.get("BEIGE_AGENT_NAME");
25
+ const chatId = Deno.env.get("BEIGE_CHAT_ID");
26
+ const threadId = Deno.env.get("BEIGE_THREAD_ID");
27
+
28
+ if (!sessionKey || !channel) {
29
+ return undefined;
30
+ }
31
+
32
+ const ctx: Record<string, string> = { sessionKey, channel };
33
+ if (agentName) ctx.agentName = agentName;
34
+ if (chatId) ctx.chatId = chatId;
35
+ if (threadId) ctx.threadId = threadId;
36
+ return ctx;
37
+ }
38
+
39
+ const sessionContext = buildSessionContext();
40
+
41
+ const request: Record<string, unknown> = {
42
+ type: "tool_request",
43
+ tool: toolName,
44
+ args,
45
+ };
46
+
47
+ if (sessionContext) {
48
+ request.sessionContext = sessionContext;
49
+ }
50
+
51
+ const requestJson = JSON.stringify(request) + "\n";
52
+
53
+ let conn: Deno.UnixConn;
54
+ try {
55
+ conn = await Deno.connect({ transport: "unix", path: SOCKET_PATH });
56
+ } catch (err) {
57
+ console.error(
58
+ `Failed to connect to gateway socket at ${SOCKET_PATH}:`,
59
+ err instanceof Error ? err.message : err
60
+ );
61
+ Deno.exit(1);
62
+ }
63
+
64
+ const encoder = new TextEncoder();
65
+ const decoder = new TextDecoder();
66
+
67
+ try {
68
+ await conn.write(encoder.encode(requestJson));
69
+
70
+ let responseText = "";
71
+ const buf = new Uint8Array(65536);
72
+ while (!responseText.includes("\n")) {
73
+ const n = await conn.read(buf);
74
+ if (n === null) break;
75
+ responseText += decoder.decode(buf.subarray(0, n));
76
+ }
77
+
78
+ conn.close();
79
+
80
+ const parsed = JSON.parse(responseText.trim());
81
+ if (parsed.success) {
82
+ if (parsed.output) {
83
+ await Deno.stdout.write(encoder.encode(parsed.output));
84
+ }
85
+ Deno.exit(parsed.exitCode ?? 0);
86
+ } else {
87
+ if (parsed.error) {
88
+ await Deno.stderr.write(encoder.encode(parsed.error + "\n"));
89
+ }
90
+ Deno.exit(parsed.exitCode ?? 1);
91
+ }
92
+ } catch (err) {
93
+ console.error("Failed to communicate with gateway:", err instanceof Error ? err.message : err);
94
+ Deno.exit(1);
95
+ }