@provos/ironcurtain 0.4.0 → 0.5.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 +219 -248
- package/dist/cli.js +10 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/config-command.js +144 -6
- package/dist/config/config-command.js.map +1 -1
- package/dist/config/constitution-user-base.md +2 -0
- package/dist/config/first-start.js +77 -12
- package/dist/config/first-start.js.map +1 -1
- package/dist/config/generated/compiled-policy.json +199 -72
- package/dist/config/generated/tool-annotations.json +1018 -36
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/mcp-servers.json +13 -0
- package/dist/config/paths.d.ts +31 -0
- package/dist/config/paths.js +52 -2
- package/dist/config/paths.js.map +1 -1
- package/dist/config/types.d.ts +10 -0
- package/dist/config/user-config.d.ts +21 -3
- package/dist/config/user-config.js +34 -3
- package/dist/config/user-config.js.map +1 -1
- package/dist/docker/adapters/claude-code.d.ts +4 -0
- package/dist/docker/adapters/claude-code.js +96 -37
- package/dist/docker/adapters/claude-code.js.map +1 -1
- package/dist/docker/agent-adapter.d.ts +22 -13
- package/dist/docker/code-mode-proxy.d.ts +34 -0
- package/dist/docker/code-mode-proxy.js +137 -0
- package/dist/docker/code-mode-proxy.js.map +1 -0
- package/dist/docker/docker-agent-session.d.ts +22 -14
- package/dist/docker/docker-agent-session.js +144 -117
- package/dist/docker/docker-agent-session.js.map +1 -1
- package/dist/docker/docker-infrastructure.d.ts +51 -0
- package/dist/docker/docker-infrastructure.js +261 -0
- package/dist/docker/docker-infrastructure.js.map +1 -0
- package/dist/docker/docker-manager.js +27 -0
- package/dist/docker/docker-manager.js.map +1 -1
- package/dist/docker/mitm-proxy.js +4 -0
- package/dist/docker/mitm-proxy.js.map +1 -1
- package/dist/docker/oauth-credentials.d.ts +81 -0
- package/dist/docker/oauth-credentials.js +178 -0
- package/dist/docker/oauth-credentials.js.map +1 -0
- package/dist/docker/orientation.d.ts +3 -2
- package/dist/docker/orientation.js +4 -4
- package/dist/docker/orientation.js.map +1 -1
- package/dist/docker/provider-config.d.ts +3 -0
- package/dist/docker/provider-config.js +28 -0
- package/dist/docker/provider-config.js.map +1 -1
- package/dist/docker/pty-session.d.ts +27 -0
- package/dist/docker/pty-session.js +420 -0
- package/dist/docker/pty-session.js.map +1 -0
- package/dist/docker/pty-types.d.ts +24 -0
- package/dist/docker/pty-types.js +12 -0
- package/dist/docker/pty-types.js.map +1 -0
- package/dist/docker/types.d.ts +18 -2
- package/dist/escalation/escalation-watcher.d.ts +44 -0
- package/dist/escalation/escalation-watcher.js +92 -0
- package/dist/escalation/escalation-watcher.js.map +1 -0
- package/dist/escalation/listener-command.d.ts +10 -0
- package/dist/escalation/listener-command.js +407 -0
- package/dist/escalation/listener-command.js.map +1 -0
- package/dist/escalation/listener-state.d.ts +49 -0
- package/dist/escalation/listener-state.js +104 -0
- package/dist/escalation/listener-state.js.map +1 -0
- package/dist/escalation/session-registry.d.ts +17 -0
- package/dist/escalation/session-registry.js +98 -0
- package/dist/escalation/session-registry.js.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.js +2 -3
- package/dist/logger.js.map +1 -1
- package/dist/pipeline/annotate.js +35 -15
- package/dist/pipeline/annotate.js.map +1 -1
- package/dist/pipeline/constitution-customizer.d.ts +2 -1
- package/dist/pipeline/constitution-customizer.js +36 -3
- package/dist/pipeline/constitution-customizer.js.map +1 -1
- package/dist/pipeline/github-identity.d.ts +38 -0
- package/dist/pipeline/github-identity.js +64 -0
- package/dist/pipeline/github-identity.js.map +1 -0
- package/dist/pipeline/handwritten-scenarios.js +34 -0
- package/dist/pipeline/handwritten-scenarios.js.map +1 -1
- package/dist/sandbox/index.d.ts +25 -1
- package/dist/sandbox/index.js +90 -12
- package/dist/sandbox/index.js.map +1 -1
- package/dist/servers/fetch-server.d.ts +6 -1
- package/dist/servers/fetch-server.js +26 -14
- package/dist/servers/fetch-server.js.map +1 -1
- package/dist/session/agent-session.js +9 -5
- package/dist/session/agent-session.js.map +1 -1
- package/dist/session/base-transport.d.ts +19 -0
- package/dist/session/base-transport.js +36 -0
- package/dist/session/base-transport.js.map +1 -0
- package/dist/session/cli-transport.d.ts +3 -3
- package/dist/session/cli-transport.js +7 -4
- package/dist/session/cli-transport.js.map +1 -1
- package/dist/session/index.js +24 -106
- package/dist/session/index.js.map +1 -1
- package/dist/session/interaction-log.d.ts +13 -0
- package/dist/session/interaction-log.js +28 -0
- package/dist/session/interaction-log.js.map +1 -0
- package/dist/session/preflight.d.ts +3 -0
- package/dist/session/preflight.js +45 -18
- package/dist/session/preflight.js.map +1 -1
- package/dist/session/prompts.d.ts +9 -3
- package/dist/session/prompts.js +28 -10
- package/dist/session/prompts.js.map +1 -1
- package/dist/session/types.d.ts +2 -0
- package/dist/signal/bot-command.js +5 -0
- package/dist/signal/bot-command.js.map +1 -1
- package/dist/signal/format.d.ts +21 -1
- package/dist/signal/format.js +41 -3
- package/dist/signal/format.js.map +1 -1
- package/dist/signal/signal-bot-daemon.d.ts +53 -18
- package/dist/signal/signal-bot-daemon.js +344 -106
- package/dist/signal/signal-bot-daemon.js.map +1 -1
- package/dist/signal/signal-config.d.ts +4 -0
- package/dist/signal/signal-config.js +2 -0
- package/dist/signal/signal-config.js.map +1 -1
- package/dist/signal/signal-transport.d.ts +13 -7
- package/dist/signal/signal-transport.js +36 -12
- package/dist/signal/signal-transport.js.map +1 -1
- package/dist/trusted-process/audit-log.d.ts +6 -1
- package/dist/trusted-process/audit-log.js +22 -2
- package/dist/trusted-process/audit-log.js.map +1 -1
- package/dist/trusted-process/audit-redactor.d.ts +25 -0
- package/dist/trusted-process/audit-redactor.js +121 -0
- package/dist/trusted-process/audit-redactor.js.map +1 -0
- package/dist/trusted-process/escalation.d.ts +1 -1
- package/dist/trusted-process/escalation.js +6 -1
- package/dist/trusted-process/escalation.js.map +1 -1
- package/dist/trusted-process/index.d.ts +2 -1
- package/dist/trusted-process/index.js +24 -6
- package/dist/trusted-process/index.js.map +1 -1
- package/dist/trusted-process/mcp-client-manager.js +14 -2
- package/dist/trusted-process/mcp-client-manager.js.map +1 -1
- package/dist/trusted-process/mcp-error-utils.d.ts +11 -0
- package/dist/trusted-process/mcp-error-utils.js +50 -0
- package/dist/trusted-process/mcp-error-utils.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.d.ts +115 -1
- package/dist/trusted-process/mcp-proxy-server.js +318 -267
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -1
- package/dist/trusted-process/policy-engine.d.ts +3 -1
- package/dist/trusted-process/policy-engine.js +17 -6
- package/dist/trusted-process/policy-engine.js.map +1 -1
- package/dist/trusted-process/sandbox-integration.d.ts +16 -4
- package/dist/trusted-process/sandbox-integration.js +14 -8
- package/dist/trusted-process/sandbox-integration.js.map +1 -1
- package/dist/trusted-process/server-context.d.ts +21 -0
- package/dist/trusted-process/server-context.js +42 -0
- package/dist/trusted-process/server-context.js.map +1 -0
- package/dist/types/argument-roles.d.ts +12 -2
- package/dist/types/argument-roles.js +37 -4
- package/dist/types/argument-roles.js.map +1 -1
- package/docker/Dockerfile.claude-code +8 -3
- package/docker/entrypoint-claude-code.sh +64 -4
- package/package.json +19 -9
- package/src/config/constitution-user-base.md +2 -0
- package/src/config/generated/compiled-policy.json +199 -72
- package/src/config/generated/tool-annotations.json +1018 -36
- package/src/config/mcp-servers.json +13 -0
- package/dist/docker/managed-proxy.d.ts +0 -31
- package/dist/docker/managed-proxy.js +0 -265
- package/dist/docker/managed-proxy.js.map +0 -1
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
* - System prompt injection via --append-system-prompt
|
|
7
7
|
* - --continue for session resume across turns
|
|
8
8
|
* - --dangerously-skip-permissions (IronCurtain handles security)
|
|
9
|
+
*
|
|
10
|
+
* The system prompt composes two layers:
|
|
11
|
+
* 1. Code Mode instructions (from session/prompts.ts) for tool discovery
|
|
12
|
+
* 2. Docker environment context explaining workspace, host access, and policy
|
|
9
13
|
*/
|
|
10
|
-
import { anthropicProvider } from '../provider-config.js';
|
|
14
|
+
import { anthropicProvider, claudePlatformProvider, anthropicOAuthProvider, claudePlatformOAuthProvider, } from '../provider-config.js';
|
|
15
|
+
import { buildSystemPrompt } from '../../session/prompts.js';
|
|
11
16
|
const CLAUDE_CODE_IMAGE = 'ironcurtain-claude-code:latest';
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
return `You are running inside a sandboxed Docker container managed by IronCurtain.
|
|
15
|
-
|
|
16
|
-
## Environment Constraints
|
|
17
|
+
function buildDockerEnvironmentPrompt(context) {
|
|
18
|
+
return `## Docker Environment
|
|
17
19
|
|
|
18
20
|
### Workspace (\`${context.workspaceDir}\`)
|
|
19
21
|
This is YOUR local workspace inside the container. Use your normal built-in
|
|
@@ -24,40 +26,35 @@ Files you create at \`${context.workspaceDir}/foo.txt\` are visible to MCP tools
|
|
|
24
26
|
at \`${context.hostSandboxDir}/foo.txt\` and vice versa.
|
|
25
27
|
|
|
26
28
|
### Host Filesystem
|
|
27
|
-
To read or modify files on the host operating system you MUST use the
|
|
28
|
-
tools listed
|
|
29
|
-
every call is evaluated against
|
|
29
|
+
To read or modify files on the host operating system you MUST use the
|
|
30
|
+
\`execute_code\` MCP tool with the sandbox tools listed above. These tools are
|
|
31
|
+
mediated by IronCurtain's policy engine: every call is evaluated against
|
|
32
|
+
security rules and recorded in the audit log.
|
|
30
33
|
Your built-in file tools cannot reach the host filesystem.
|
|
31
34
|
|
|
32
35
|
### Network
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
git operations MUST go through the MCP tools below.
|
|
36
|
+
The container has NO direct internet access. All HTTP requests and
|
|
37
|
+
git operations MUST go through the sandbox tools via \`execute_code\`.
|
|
36
38
|
|
|
37
|
-
Your built-in web search
|
|
38
|
-
and will work
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
proxies. Direct internet access is blocked by firewall rules. All HTTP
|
|
42
|
-
requests and git operations MUST go through the MCP tools below.
|
|
39
|
+
IMPORTANT: Your built-in server-side web search tool (WebSearch) is DISABLED
|
|
40
|
+
and will NOT work — it is stripped by the security proxy. You MUST use the
|
|
41
|
+
sandbox tools via \`execute_code\` instead. Do NOT attempt to use your
|
|
42
|
+
built-in WebSearch or WebFetch tools.
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
### Available MCP Tools
|
|
50
|
-
${toolList}
|
|
44
|
+
To search the web:
|
|
45
|
+
\`const results = tools.fetch_web_search({ query: "search terms" });\`
|
|
46
|
+
To fetch a URL:
|
|
47
|
+
\`const page = tools.fetch_http_fetch({ url: "https://example.com" });\`
|
|
51
48
|
|
|
52
49
|
### Policy Enforcement
|
|
53
|
-
Every
|
|
50
|
+
Every tool call through \`execute_code\` is evaluated against security policy rules:
|
|
54
51
|
- **Allowed**: proceeds automatically
|
|
55
52
|
- **Denied**: blocked -- do NOT retry denied operations
|
|
56
53
|
- **Escalated**: requires human approval -- you will receive the result once approved
|
|
57
54
|
|
|
58
55
|
### Best Practices
|
|
59
56
|
1. Use your built-in tools for work inside ${context.workspaceDir}
|
|
60
|
-
2. Use
|
|
57
|
+
2. Use \`execute_code\` for anything on the host filesystem or network
|
|
61
58
|
3. Batch external operations to minimize escalation prompts
|
|
62
59
|
4. If an operation is denied, explain the denial and suggest alternatives
|
|
63
60
|
5. Do not attempt to bypass the sandbox
|
|
@@ -90,8 +87,37 @@ export const claudeCodeAdapter = {
|
|
|
90
87
|
];
|
|
91
88
|
},
|
|
92
89
|
generateOrientationFiles() {
|
|
93
|
-
//
|
|
94
|
-
|
|
90
|
+
// Wrapper script for PTY mode -- avoids shell quoting issues by reading
|
|
91
|
+
// the system prompt from $IRONCURTAIN_SYSTEM_PROMPT (set by entrypoint).
|
|
92
|
+
const startScript = `#!/bin/bash
|
|
93
|
+
exec claude --dangerously-skip-permissions \\
|
|
94
|
+
--mcp-config /etc/ironcurtain/claude-mcp-config.json \\
|
|
95
|
+
--append-system-prompt "$IRONCURTAIN_SYSTEM_PROMPT"
|
|
96
|
+
`;
|
|
97
|
+
// Helper script to resize the PTY that Claude Code is actually running on.
|
|
98
|
+
// docker exec stty targets a transient exec session PTY, not socat's PTY.
|
|
99
|
+
const resizeScript = `#!/bin/bash
|
|
100
|
+
# Called from the host via: docker exec <cid> /etc/ironcurtain/resize-pty.sh <cols> <rows>
|
|
101
|
+
COLS=$1
|
|
102
|
+
ROWS=$2
|
|
103
|
+
|
|
104
|
+
CLAUDE_PID=$(pgrep -f "claude --dangerously" | head -1)
|
|
105
|
+
if [ -z "$CLAUDE_PID" ]; then
|
|
106
|
+
exit 0 # claude not started yet; resize will be retried
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
PTS=$(readlink /proc/$CLAUDE_PID/fd/0 2>/dev/null)
|
|
110
|
+
if [ -z "$PTS" ]; then
|
|
111
|
+
exit 0
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
stty -F "$PTS" cols "$COLS" rows "$ROWS" 2>/dev/null
|
|
115
|
+
kill -WINCH "$CLAUDE_PID" 2>/dev/null
|
|
116
|
+
`;
|
|
117
|
+
return [
|
|
118
|
+
{ path: 'start-claude.sh', content: startScript, mode: 0o755 },
|
|
119
|
+
{ path: 'resize-pty.sh', content: resizeScript, mode: 0o755 },
|
|
120
|
+
];
|
|
95
121
|
},
|
|
96
122
|
buildCommand(message, systemPrompt) {
|
|
97
123
|
return [
|
|
@@ -109,18 +135,39 @@ export const claudeCodeAdapter = {
|
|
|
109
135
|
];
|
|
110
136
|
},
|
|
111
137
|
buildSystemPrompt(context) {
|
|
112
|
-
return
|
|
138
|
+
// Layer 1: Code Mode instructions (tool discovery, sync calls, return semantics)
|
|
139
|
+
const codeModePrompt = buildSystemPrompt(context.serverListings, context.hostSandboxDir);
|
|
140
|
+
// Layer 2: Docker environment specifics (workspace, host access, policy)
|
|
141
|
+
const dockerPrompt = buildDockerEnvironmentPrompt(context);
|
|
142
|
+
return `${codeModePrompt}\n${dockerPrompt}`;
|
|
113
143
|
},
|
|
114
|
-
getProviders() {
|
|
115
|
-
|
|
144
|
+
getProviders(authKind) {
|
|
145
|
+
if (authKind === 'oauth') {
|
|
146
|
+
return [anthropicOAuthProvider, claudePlatformOAuthProvider];
|
|
147
|
+
}
|
|
148
|
+
return [anthropicProvider, claudePlatformProvider];
|
|
116
149
|
},
|
|
117
|
-
buildEnv(
|
|
118
|
-
|
|
119
|
-
ANTHROPIC_API_KEY: fakeKeys.get('api.anthropic.com') ?? '',
|
|
150
|
+
buildEnv(config, fakeKeys) {
|
|
151
|
+
const env = {
|
|
120
152
|
CLAUDE_CODE_DISABLE_UPDATE_CHECK: '1',
|
|
121
153
|
// Node.js does not use the system CA store -- must set this explicitly
|
|
122
154
|
NODE_EXTRA_CA_CERTS: '/usr/local/share/ca-certificates/ironcurtain-ca.crt',
|
|
123
155
|
};
|
|
156
|
+
const fakeKey = fakeKeys.get('api.anthropic.com');
|
|
157
|
+
if (!fakeKey) {
|
|
158
|
+
throw new Error('No fake key generated for api.anthropic.com — cannot configure Claude Code authentication');
|
|
159
|
+
}
|
|
160
|
+
if (config.dockerAuth?.kind === 'oauth') {
|
|
161
|
+
// OAuth mode: pass fake token via Claude Code's native env var.
|
|
162
|
+
// Claude Code reads CLAUDE_CODE_OAUTH_TOKEN as its highest-priority auth.
|
|
163
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = fakeKey;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// API key mode: pass the fake key via a non-Claude env var; apiKeyHelper
|
|
167
|
+
// in settings.json echoes it so Claude Code never prompts for approval.
|
|
168
|
+
env.IRONCURTAIN_API_KEY = fakeKey;
|
|
169
|
+
}
|
|
170
|
+
return env;
|
|
124
171
|
},
|
|
125
172
|
extractResponse(exitCode, stdout) {
|
|
126
173
|
if (exitCode !== 0) {
|
|
@@ -128,6 +175,16 @@ export const claudeCodeAdapter = {
|
|
|
128
175
|
}
|
|
129
176
|
return parseClaudeCodeJson(stdout);
|
|
130
177
|
},
|
|
178
|
+
buildPtyCommand(_systemPrompt, ptySockPath, ptyPort) {
|
|
179
|
+
// The socat listener target depends on platform
|
|
180
|
+
const listenArg = ptySockPath
|
|
181
|
+
? `UNIX-LISTEN:${ptySockPath},fork` // Linux UDS
|
|
182
|
+
: `TCP-LISTEN:${ptyPort},reuseaddr`; // macOS TCP
|
|
183
|
+
// Interactive mode: claude runs via a wrapper script that reads the system
|
|
184
|
+
// prompt from an env var set by the entrypoint. This avoids shell quoting
|
|
185
|
+
// issues that occur when embedding large prompts in socat EXEC: strings.
|
|
186
|
+
return ['socat', listenArg, 'EXEC:/etc/ironcurtain/start-claude.sh,pty,setsid,ctty,stderr'];
|
|
187
|
+
},
|
|
131
188
|
};
|
|
132
189
|
/**
|
|
133
190
|
* Parses Claude Code's `--output-format json` response.
|
|
@@ -139,8 +196,10 @@ function parseClaudeCodeJson(stdout) {
|
|
|
139
196
|
if (parsed && typeof parsed === 'object' && 'result' in parsed) {
|
|
140
197
|
const obj = parsed;
|
|
141
198
|
const text = typeof obj.result === 'string' ? obj.result : stdout.trim();
|
|
142
|
-
|
|
143
|
-
|
|
199
|
+
if (typeof obj.total_cost_usd === 'number') {
|
|
200
|
+
return { text, costUsd: obj.total_cost_usd };
|
|
201
|
+
}
|
|
202
|
+
return { text };
|
|
144
203
|
}
|
|
145
204
|
}
|
|
146
205
|
catch {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/docker/adapters/claude-code.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/docker/adapters/claude-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { IronCurtainConfig } from '../config/types.js';
|
|
9
9
|
import type { ProviderConfig } from './provider-config.js';
|
|
10
|
+
import type { ServerListing } from '../session/prompts.js';
|
|
10
11
|
/**
|
|
11
12
|
* Structured response from an agent adapter, carrying both the
|
|
12
13
|
* text response and optional cost/usage metadata reported by the agent.
|
|
@@ -31,14 +32,8 @@ export interface AgentConfigFile {
|
|
|
31
32
|
readonly path: string;
|
|
32
33
|
/** File content. */
|
|
33
34
|
readonly content: string;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
* Information about a single MCP tool, used for orientation content.
|
|
37
|
-
*/
|
|
38
|
-
export interface ToolInfo {
|
|
39
|
-
readonly name: string;
|
|
40
|
-
readonly description?: string;
|
|
41
|
-
readonly inputSchema: Record<string, unknown>;
|
|
35
|
+
/** Optional file mode (e.g. 0o755 for executable scripts). */
|
|
36
|
+
readonly mode?: number;
|
|
42
37
|
}
|
|
43
38
|
/**
|
|
44
39
|
* Context passed to the adapter for generating orientation content.
|
|
@@ -48,8 +43,8 @@ export interface OrientationContext {
|
|
|
48
43
|
readonly workspaceDir: string;
|
|
49
44
|
/** The host-side path that is bind-mounted as workspaceDir. */
|
|
50
45
|
readonly hostSandboxDir: string;
|
|
51
|
-
/**
|
|
52
|
-
readonly
|
|
46
|
+
/** Server listings for progressive tool disclosure. */
|
|
47
|
+
readonly serverListings: ServerListing[];
|
|
53
48
|
/** Domains the agent may access via fetch MCP tool. */
|
|
54
49
|
readonly allowedDomains: string[];
|
|
55
50
|
/** Container network mode: 'none' (Linux UDS) or 'bridge' (macOS TCP). */
|
|
@@ -79,9 +74,8 @@ export interface AgentAdapter {
|
|
|
79
74
|
* the agent how to connect to IronCurtain's proxy.
|
|
80
75
|
*
|
|
81
76
|
* @param socketPath - container-side UDS path (e.g., /run/ironcurtain/proxy.sock)
|
|
82
|
-
* @param tools - list of available MCP tools for documentation
|
|
83
77
|
*/
|
|
84
|
-
generateMcpConfig(socketPath: string
|
|
78
|
+
generateMcpConfig(socketPath: string): AgentConfigFile[];
|
|
85
79
|
/**
|
|
86
80
|
* Generates orientation documents that teach the agent about
|
|
87
81
|
* the MCP-mediated environment.
|
|
@@ -102,8 +96,11 @@ export interface AgentAdapter {
|
|
|
102
96
|
* Returns LLM provider configurations for this agent.
|
|
103
97
|
* The MITM proxy uses these to build the host allowlist,
|
|
104
98
|
* generate fake API keys, swap keys in requests, and filter endpoints.
|
|
99
|
+
*
|
|
100
|
+
* @param authKind - When 'oauth', returns providers configured for bearer
|
|
101
|
+
* token injection instead of header-based API key injection.
|
|
105
102
|
*/
|
|
106
|
-
getProviders(): readonly ProviderConfig[];
|
|
103
|
+
getProviders(authKind?: 'oauth' | 'apikey'): readonly ProviderConfig[];
|
|
107
104
|
/**
|
|
108
105
|
* Constructs environment variables for the container.
|
|
109
106
|
* Receives fake keys instead of real keys -- the real keys never
|
|
@@ -119,4 +116,16 @@ export interface AgentAdapter {
|
|
|
119
116
|
* @param stdout - captured stdout from the container
|
|
120
117
|
*/
|
|
121
118
|
extractResponse(exitCode: number, stdout: string): AgentResponse;
|
|
119
|
+
/**
|
|
120
|
+
* Returns the Docker container command for PTY mode.
|
|
121
|
+
* When provided, the container runs this command directly instead of
|
|
122
|
+
* `sleep infinity`, and the host attaches via a PTY proxy.
|
|
123
|
+
*
|
|
124
|
+
* Adapters that do not implement this method do not support PTY mode.
|
|
125
|
+
*
|
|
126
|
+
* @param systemPrompt - the orientation prompt (written to a file, not embedded in shell)
|
|
127
|
+
* @param ptySockPath - the UDS path for the PTY listener (Linux), or undefined for TCP mode
|
|
128
|
+
* @param ptyPort - the TCP port for the PTY listener (macOS), or undefined for UDS mode
|
|
129
|
+
*/
|
|
130
|
+
buildPtyCommand?(systemPrompt: string, ptySockPath: string | undefined, ptyPort: number | undefined): readonly string[];
|
|
122
131
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeModeProxy -- MCP server that exposes a single `execute_code` tool
|
|
3
|
+
* backed by the UTCP Code Mode sandbox.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the old ManagedProxy (which spawned mcp-proxy-server.ts as a
|
|
6
|
+
* child process). Docker agents now send TypeScript via `execute_code`,
|
|
7
|
+
* sharing the same execution engine as builtin Code Mode sessions.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* Container (Claude Code) → socat → UDS/TCP socket
|
|
11
|
+
* → CodeModeProxy (MCP Server with execute_code)
|
|
12
|
+
* → Sandbox.executeCode(code)
|
|
13
|
+
* → V8 isolate → UTCP → per-server mcp-proxy-server.ts (stdio)
|
|
14
|
+
* → PolicyEngine → real MCP servers
|
|
15
|
+
*/
|
|
16
|
+
import { type HelpData } from '../sandbox/index.js';
|
|
17
|
+
import type { IronCurtainConfig } from '../config/types.js';
|
|
18
|
+
/** Public interface for the Docker session's proxy. */
|
|
19
|
+
export interface DockerProxy {
|
|
20
|
+
start(): Promise<void>;
|
|
21
|
+
getHelpData(): HelpData;
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
readonly socketPath: string;
|
|
24
|
+
readonly port: number | undefined;
|
|
25
|
+
}
|
|
26
|
+
export interface CodeModeProxyOptions {
|
|
27
|
+
/** Absolute path for the UDS socket (used in UDS mode, also stored for reference in TCP mode). */
|
|
28
|
+
readonly socketPath: string;
|
|
29
|
+
/** Session configuration passed to the Sandbox. */
|
|
30
|
+
readonly config: IronCurtainConfig;
|
|
31
|
+
/** Listen mode: 'uds' (default) or 'tcp'. TCP mode uses OS-assigned port. */
|
|
32
|
+
readonly listenMode?: 'uds' | 'tcp';
|
|
33
|
+
}
|
|
34
|
+
export declare function createCodeModeProxy(options: CodeModeProxyOptions): DockerProxy;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CodeModeProxy -- MCP server that exposes a single `execute_code` tool
|
|
3
|
+
* backed by the UTCP Code Mode sandbox.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the old ManagedProxy (which spawned mcp-proxy-server.ts as a
|
|
6
|
+
* child process). Docker agents now send TypeScript via `execute_code`,
|
|
7
|
+
* sharing the same execution engine as builtin Code Mode sessions.
|
|
8
|
+
*
|
|
9
|
+
* Architecture:
|
|
10
|
+
* Container (Claude Code) → socat → UDS/TCP socket
|
|
11
|
+
* → CodeModeProxy (MCP Server with execute_code)
|
|
12
|
+
* → Sandbox.executeCode(code)
|
|
13
|
+
* → V8 isolate → UTCP → per-server mcp-proxy-server.ts (stdio)
|
|
14
|
+
* → PolicyEngine → real MCP servers
|
|
15
|
+
*/
|
|
16
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
17
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
18
|
+
import { UdsServerTransport } from '../trusted-process/uds-server-transport.js';
|
|
19
|
+
import { TcpServerTransport } from '../trusted-process/tcp-server-transport.js';
|
|
20
|
+
import { Sandbox } from '../sandbox/index.js';
|
|
21
|
+
import { VERSION } from '../version.js';
|
|
22
|
+
export function createCodeModeProxy(options) {
|
|
23
|
+
const sandbox = new Sandbox();
|
|
24
|
+
const useTcp = options.listenMode === 'tcp';
|
|
25
|
+
let mcpServer = null; // eslint-disable-line @typescript-eslint/no-deprecated
|
|
26
|
+
let transport = null;
|
|
27
|
+
return {
|
|
28
|
+
socketPath: options.socketPath,
|
|
29
|
+
get port() {
|
|
30
|
+
if (transport instanceof TcpServerTransport) {
|
|
31
|
+
try {
|
|
32
|
+
return transport.port;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
async start() {
|
|
41
|
+
// 1. Initialize the sandbox (registers MCP proxy servers per backend)
|
|
42
|
+
await sandbox.initialize(options.config);
|
|
43
|
+
// 2. Create the MCP server exposing a single execute_code tool
|
|
44
|
+
mcpServer = new Server(// eslint-disable-line @typescript-eslint/no-deprecated
|
|
45
|
+
{ name: 'ironcurtain-code-mode', version: VERSION }, { capabilities: { tools: {} } });
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- MCP SDK handler must return Promise
|
|
47
|
+
mcpServer.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
48
|
+
tools: [
|
|
49
|
+
{
|
|
50
|
+
name: 'execute_code',
|
|
51
|
+
description: 'Execute TypeScript code in a secure sandbox. ' +
|
|
52
|
+
'Tool calls are synchronous (no await). ' +
|
|
53
|
+
'Use `return` to send a value back. ' +
|
|
54
|
+
'Call help.help() to discover available tools.',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
code: {
|
|
59
|
+
type: 'string',
|
|
60
|
+
description: 'TypeScript code to execute',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
required: ['code'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
}));
|
|
68
|
+
mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
69
|
+
if (request.params.name !== 'execute_code') {
|
|
70
|
+
return {
|
|
71
|
+
content: [{ type: 'text', text: `Unknown tool: ${request.params.name}` }],
|
|
72
|
+
isError: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const args = request.params.arguments;
|
|
76
|
+
const code = args?.code;
|
|
77
|
+
if (!code || typeof code !== 'string') {
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: 'text', text: 'Missing required parameter: code' }],
|
|
80
|
+
isError: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const { result, logs } = await sandbox.executeCode(code);
|
|
85
|
+
const parts = [];
|
|
86
|
+
if (logs.length > 0) {
|
|
87
|
+
parts.push(`[logs]\n${logs.join('\n')}`);
|
|
88
|
+
}
|
|
89
|
+
if (result === undefined) {
|
|
90
|
+
parts.push('(no return value)');
|
|
91
|
+
}
|
|
92
|
+
else if (typeof result === 'string') {
|
|
93
|
+
parts.push(result);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
parts.push(JSON.stringify(result, null, 2));
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
content: [{ type: 'text', text: parts.join('\n\n') }],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
return {
|
|
104
|
+
content: [
|
|
105
|
+
{
|
|
106
|
+
type: 'text',
|
|
107
|
+
text: `Execution error: ${err instanceof Error ? err.message : String(err)}`,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
isError: true,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// 3. Start the transport
|
|
115
|
+
if (useTcp) {
|
|
116
|
+
transport = new TcpServerTransport('127.0.0.1', 0);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
transport = new UdsServerTransport(options.socketPath);
|
|
120
|
+
}
|
|
121
|
+
await mcpServer.connect(transport);
|
|
122
|
+
},
|
|
123
|
+
getHelpData() {
|
|
124
|
+
return sandbox.getHelpData();
|
|
125
|
+
},
|
|
126
|
+
async stop() {
|
|
127
|
+
if (mcpServer) {
|
|
128
|
+
await mcpServer.close();
|
|
129
|
+
mcpServer = null;
|
|
130
|
+
}
|
|
131
|
+
// mcpServer.close() closes the transport, but shutdown sandbox separately
|
|
132
|
+
transport = null;
|
|
133
|
+
await sandbox.shutdown();
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=code-mode-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-mode-proxy.js","sourceRoot":"","sources":["../../src/docker/code-mode-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,7 +15,7 @@ import type { Session, SessionId, SessionInfo, ConversationTurn, DiagnosticEvent
|
|
|
15
15
|
import type { IronCurtainConfig } from '../config/types.js';
|
|
16
16
|
import type { AgentAdapter } from './agent-adapter.js';
|
|
17
17
|
import type { DockerManager } from './types.js';
|
|
18
|
-
import type {
|
|
18
|
+
import type { DockerProxy } from './code-mode-proxy.js';
|
|
19
19
|
import type { MitmProxy } from './mitm-proxy.js';
|
|
20
20
|
import type { CertificateAuthority } from './ca.js';
|
|
21
21
|
export interface DockerAgentSessionDeps {
|
|
@@ -23,7 +23,7 @@ export interface DockerAgentSessionDeps {
|
|
|
23
23
|
readonly sessionId: SessionId;
|
|
24
24
|
readonly adapter: AgentAdapter;
|
|
25
25
|
readonly docker: DockerManager;
|
|
26
|
-
readonly proxy:
|
|
26
|
+
readonly proxy: DockerProxy;
|
|
27
27
|
readonly mitmProxy: MitmProxy;
|
|
28
28
|
readonly ca: CertificateAuthority;
|
|
29
29
|
readonly fakeKeys: ReadonlyMap<string, string>;
|
|
@@ -36,6 +36,19 @@ export interface DockerAgentSessionDeps {
|
|
|
36
36
|
readonly onEscalation?: (request: EscalationRequest) => void;
|
|
37
37
|
readonly onEscalationExpired?: () => void;
|
|
38
38
|
readonly onDiagnostic?: (event: DiagnosticEvent) => void;
|
|
39
|
+
/**
|
|
40
|
+
* When set, proxies are already started, orientation is built, and
|
|
41
|
+
* the image name is resolved. initialize() skips those steps and
|
|
42
|
+
* proceeds directly to container creation + watchers.
|
|
43
|
+
*/
|
|
44
|
+
readonly preBuiltInfrastructure?: {
|
|
45
|
+
readonly systemPrompt: string;
|
|
46
|
+
readonly image: string;
|
|
47
|
+
readonly mitmAddr: {
|
|
48
|
+
socketPath?: string;
|
|
49
|
+
port?: number;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
39
52
|
}
|
|
40
53
|
export declare class DockerAgentSession implements Session {
|
|
41
54
|
private readonly sessionId;
|
|
@@ -54,25 +67,25 @@ export declare class DockerAgentSession implements Session {
|
|
|
54
67
|
private status;
|
|
55
68
|
private readonly createdAt;
|
|
56
69
|
private containerId;
|
|
70
|
+
private sidecarContainerId;
|
|
57
71
|
private networkName;
|
|
58
72
|
private systemPrompt;
|
|
59
73
|
private turns;
|
|
60
74
|
private diagnosticLog;
|
|
61
|
-
private
|
|
62
|
-
private seenEscalationIds;
|
|
63
|
-
private escalationPollInterval;
|
|
75
|
+
private escalationWatcher;
|
|
64
76
|
private auditTailer;
|
|
65
77
|
private cumulativeActiveMs;
|
|
66
78
|
private cumulativeCostUsd;
|
|
67
79
|
private readonly onEscalation?;
|
|
68
80
|
private readonly onEscalationExpired?;
|
|
69
81
|
private readonly onDiagnostic?;
|
|
82
|
+
private readonly preBuiltInfrastructure?;
|
|
70
83
|
constructor(deps: DockerAgentSessionDeps);
|
|
71
84
|
/**
|
|
72
85
|
* Initialize the Docker agent session:
|
|
73
|
-
* 1. Start
|
|
74
|
-
* 2. Start MITM proxy (UDS)
|
|
75
|
-
* 3.
|
|
86
|
+
* 1. Start Code Mode proxy (UDS/TCP)
|
|
87
|
+
* 2. Start MITM proxy (UDS/TCP)
|
|
88
|
+
* 3. Build server listings from sandbox help data
|
|
76
89
|
* 4. Generate orientation files
|
|
77
90
|
* 5. Ensure Docker image exists (with CA cert baked in)
|
|
78
91
|
* 6. Create and start container (--network=none)
|
|
@@ -92,15 +105,10 @@ export declare class DockerAgentSession implements Session {
|
|
|
92
105
|
private emitDiagnostic;
|
|
93
106
|
/**
|
|
94
107
|
* Checks whether the container can reach host-side proxies via the
|
|
95
|
-
* internal Docker network. Throws if connectivity fails.
|
|
108
|
+
* socat sidecar on the internal Docker network. Throws if connectivity fails.
|
|
96
109
|
*/
|
|
97
110
|
private checkInternalNetworkConnectivity;
|
|
98
|
-
private startEscalationWatcher;
|
|
99
|
-
private stopEscalationWatcher;
|
|
100
|
-
private pollEscalationDirectory;
|
|
101
|
-
private checkEscalationExpiry;
|
|
102
111
|
private writeUserContext;
|
|
103
|
-
private extractEscalationId;
|
|
104
112
|
/**
|
|
105
113
|
* Ensures the Docker image exists and is up-to-date, building it
|
|
106
114
|
* (and the base image) if needed.
|