@provos/ironcurtain 0.1.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/LICENSE +202 -0
- package/README.md +311 -0
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.js +71 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/prompts.d.ts +5 -0
- package/dist/agent/prompts.js +26 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/tools.d.ts +13 -0
- package/dist/agent/tools.js +51 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/constitution.md +16 -0
- package/dist/config/generated/compiled-policy.json +236 -0
- package/dist/config/generated/test-scenarios.json +765 -0
- package/dist/config/generated/tool-annotations.json +955 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.js +151 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/mcp-servers.json +22 -0
- package/dist/config/model-provider.d.ts +49 -0
- package/dist/config/model-provider.js +78 -0
- package/dist/config/model-provider.js.map +1 -0
- package/dist/config/paths.d.ts +59 -0
- package/dist/config/paths.js +96 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/types.d.ts +89 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/user-config.d.ts +93 -0
- package/dist/config/user-config.js +309 -0
- package/dist/config/user-config.js.map +1 -0
- package/dist/hash.d.ts +17 -0
- package/dist/hash.js +34 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +93 -0
- package/dist/logger.js.map +1 -0
- package/dist/pipeline/annotate.d.ts +9 -0
- package/dist/pipeline/annotate.js +136 -0
- package/dist/pipeline/annotate.js.map +1 -0
- package/dist/pipeline/compile.d.ts +23 -0
- package/dist/pipeline/compile.js +386 -0
- package/dist/pipeline/compile.js.map +1 -0
- package/dist/pipeline/constitution-compiler.d.ts +22 -0
- package/dist/pipeline/constitution-compiler.js +197 -0
- package/dist/pipeline/constitution-compiler.js.map +1 -0
- package/dist/pipeline/generate-with-repair.d.ts +22 -0
- package/dist/pipeline/generate-with-repair.js +64 -0
- package/dist/pipeline/generate-with-repair.js.map +1 -0
- package/dist/pipeline/handwritten-scenarios.d.ts +9 -0
- package/dist/pipeline/handwritten-scenarios.js +321 -0
- package/dist/pipeline/handwritten-scenarios.js.map +1 -0
- package/dist/pipeline/llm-logger.d.ts +42 -0
- package/dist/pipeline/llm-logger.js +78 -0
- package/dist/pipeline/llm-logger.js.map +1 -0
- package/dist/pipeline/pipeline-shared.d.ts +47 -0
- package/dist/pipeline/pipeline-shared.js +145 -0
- package/dist/pipeline/pipeline-shared.js.map +1 -0
- package/dist/pipeline/policy-verifier.d.ts +46 -0
- package/dist/pipeline/policy-verifier.js +277 -0
- package/dist/pipeline/policy-verifier.js.map +1 -0
- package/dist/pipeline/scenario-generator.d.ts +11 -0
- package/dist/pipeline/scenario-generator.js +128 -0
- package/dist/pipeline/scenario-generator.js.map +1 -0
- package/dist/pipeline/tool-annotator.d.ts +24 -0
- package/dist/pipeline/tool-annotator.js +201 -0
- package/dist/pipeline/tool-annotator.js.map +1 -0
- package/dist/pipeline/types.d.ts +122 -0
- package/dist/pipeline/types.js +10 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/sandbox/index.d.ts +39 -0
- package/dist/sandbox/index.js +178 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/session/agent-session.d.ts +83 -0
- package/dist/session/agent-session.js +382 -0
- package/dist/session/agent-session.js.map +1 -0
- package/dist/session/cli-transport.d.ts +61 -0
- package/dist/session/cli-transport.js +320 -0
- package/dist/session/cli-transport.js.map +1 -0
- package/dist/session/errors.d.ts +19 -0
- package/dist/session/errors.js +33 -0
- package/dist/session/errors.js.map +1 -0
- package/dist/session/index.d.ts +29 -0
- package/dist/session/index.js +104 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/message-compactor.d.ts +32 -0
- package/dist/session/message-compactor.js +81 -0
- package/dist/session/message-compactor.js.map +1 -0
- package/dist/session/prompts.d.ts +5 -0
- package/dist/session/prompts.js +62 -0
- package/dist/session/prompts.js.map +1 -0
- package/dist/session/resource-budget-tracker.d.ts +124 -0
- package/dist/session/resource-budget-tracker.js +327 -0
- package/dist/session/resource-budget-tracker.js.map +1 -0
- package/dist/session/step-loop-detector.d.ts +63 -0
- package/dist/session/step-loop-detector.js +136 -0
- package/dist/session/step-loop-detector.js.map +1 -0
- package/dist/session/transport.d.ts +24 -0
- package/dist/session/transport.js +2 -0
- package/dist/session/transport.js.map +1 -0
- package/dist/session/truncate-result.d.ts +35 -0
- package/dist/session/truncate-result.js +71 -0
- package/dist/session/truncate-result.js.map +1 -0
- package/dist/session/types.d.ts +220 -0
- package/dist/session/types.js +6 -0
- package/dist/session/types.js.map +1 -0
- package/dist/trusted-process/audit-log.d.ts +7 -0
- package/dist/trusted-process/audit-log.js +21 -0
- package/dist/trusted-process/audit-log.js.map +1 -0
- package/dist/trusted-process/call-circuit-breaker.d.ts +33 -0
- package/dist/trusted-process/call-circuit-breaker.js +61 -0
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -0
- package/dist/trusted-process/escalation.d.ts +7 -0
- package/dist/trusted-process/escalation.js +38 -0
- package/dist/trusted-process/escalation.js.map +1 -0
- package/dist/trusted-process/index.d.ts +32 -0
- package/dist/trusted-process/index.js +151 -0
- package/dist/trusted-process/index.js.map +1 -0
- package/dist/trusted-process/mcp-client-manager.d.ts +25 -0
- package/dist/trusted-process/mcp-client-manager.js +90 -0
- package/dist/trusted-process/mcp-client-manager.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.d.ts +24 -0
- package/dist/trusted-process/mcp-proxy-server.js +451 -0
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -0
- package/dist/trusted-process/path-utils.d.ts +50 -0
- package/dist/trusted-process/path-utils.js +158 -0
- package/dist/trusted-process/path-utils.js.map +1 -0
- package/dist/trusted-process/policy-engine.d.ts +88 -0
- package/dist/trusted-process/policy-engine.js +523 -0
- package/dist/trusted-process/policy-engine.js.map +1 -0
- package/dist/trusted-process/policy-roots.d.ts +50 -0
- package/dist/trusted-process/policy-roots.js +67 -0
- package/dist/trusted-process/policy-roots.js.map +1 -0
- package/dist/trusted-process/policy-types.d.ts +6 -0
- package/dist/trusted-process/policy-types.js +2 -0
- package/dist/trusted-process/policy-types.js.map +1 -0
- package/dist/trusted-process/sandbox-integration.d.ts +92 -0
- package/dist/trusted-process/sandbox-integration.js +184 -0
- package/dist/trusted-process/sandbox-integration.js.map +1 -0
- package/dist/types/argument-roles.d.ts +112 -0
- package/dist/types/argument-roles.js +344 -0
- package/dist/types/argument-roles.js.map +1 -0
- package/dist/types/audit.d.ts +18 -0
- package/dist/types/audit.js +2 -0
- package/dist/types/audit.js.map +1 -0
- package/dist/types/mcp.d.ts +20 -0
- package/dist/types/mcp.js +2 -0
- package/dist/types/mcp.js.map +1 -0
- package/package.json +83 -0
- package/src/config/constitution.md +16 -0
- package/src/config/generated/compiled-policy.json +236 -0
- package/src/config/generated/test-scenarios.json +765 -0
- package/src/config/generated/tool-annotations.json +955 -0
- package/src/config/mcp-servers.json +22 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IronCurtainConfig, MCPServerConfig } from './types.js';
|
|
2
|
+
import type { CompiledPolicyFile, ToolAnnotationsFile } from '../pipeline/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Computes the list of protected paths that the policy engine should
|
|
5
|
+
* prevent agents from modifying. When the active generated dir differs
|
|
6
|
+
* from the package-bundled dir, both are protected.
|
|
7
|
+
*/
|
|
8
|
+
export declare function computeProtectedPaths(opts: {
|
|
9
|
+
constitutionPath: string;
|
|
10
|
+
generatedDir: string;
|
|
11
|
+
packageGeneratedDir: string;
|
|
12
|
+
mcpServersPath: string;
|
|
13
|
+
auditLogPath: string;
|
|
14
|
+
}): string[];
|
|
15
|
+
export declare function loadConfig(): IronCurtainConfig;
|
|
16
|
+
/**
|
|
17
|
+
* Extracts domain allowlists from MCP server sandbox network configurations.
|
|
18
|
+
* Filters out the `*` wildcard since it means "no domain restriction".
|
|
19
|
+
* Returns a map from server name to its list of restricted domains.
|
|
20
|
+
*/
|
|
21
|
+
export declare function extractServerDomainAllowlists(mcpServers: Record<string, MCPServerConfig>): Map<string, string[]>;
|
|
22
|
+
export declare function loadGeneratedPolicy(generatedDir: string, fallbackDir?: string): {
|
|
23
|
+
compiledPolicy: CompiledPolicyFile;
|
|
24
|
+
toolAnnotations: ToolAnnotationsFile;
|
|
25
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { resolve, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { getIronCurtainHome, getUserGeneratedDir } from './paths.js';
|
|
5
|
+
import { resolveRealPath } from '../types/argument-roles.js';
|
|
6
|
+
import { loadUserConfig } from './user-config.js';
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
/**
|
|
9
|
+
* Returns the user-local generated dir if it contains compiled-policy.json,
|
|
10
|
+
* otherwise falls back to the package-bundled generated dir.
|
|
11
|
+
*/
|
|
12
|
+
function resolveGeneratedDir(packageGeneratedDir) {
|
|
13
|
+
const userDir = getUserGeneratedDir();
|
|
14
|
+
if (existsSync(resolve(userDir, 'compiled-policy.json'))) {
|
|
15
|
+
return userDir;
|
|
16
|
+
}
|
|
17
|
+
return packageGeneratedDir;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Computes the list of protected paths that the policy engine should
|
|
21
|
+
* prevent agents from modifying. When the active generated dir differs
|
|
22
|
+
* from the package-bundled dir, both are protected.
|
|
23
|
+
*/
|
|
24
|
+
export function computeProtectedPaths(opts) {
|
|
25
|
+
const paths = [
|
|
26
|
+
resolveRealPath(opts.constitutionPath),
|
|
27
|
+
resolveRealPath(opts.generatedDir),
|
|
28
|
+
resolveRealPath(opts.mcpServersPath),
|
|
29
|
+
resolveRealPath(opts.auditLogPath),
|
|
30
|
+
];
|
|
31
|
+
if (opts.generatedDir !== opts.packageGeneratedDir) {
|
|
32
|
+
paths.push(resolveRealPath(opts.packageGeneratedDir));
|
|
33
|
+
}
|
|
34
|
+
return paths;
|
|
35
|
+
}
|
|
36
|
+
export function loadConfig() {
|
|
37
|
+
const userConfig = loadUserConfig();
|
|
38
|
+
const auditLogPath = process.env.AUDIT_LOG_PATH ?? './audit.jsonl';
|
|
39
|
+
// Default to a path under the IronCurtain home directory.
|
|
40
|
+
// In practice, the session factory overrides this per-session,
|
|
41
|
+
// so this default is a fallback for non-session usage (e.g., pipeline).
|
|
42
|
+
const defaultAllowedDir = resolve(getIronCurtainHome(), 'sandbox');
|
|
43
|
+
const allowedDirectory = process.env.ALLOWED_DIRECTORY ?? defaultAllowedDir;
|
|
44
|
+
const mcpServersPath = resolve(__dirname, 'mcp-servers.json');
|
|
45
|
+
const mcpServers = JSON.parse(readFileSync(mcpServersPath, 'utf-8'));
|
|
46
|
+
// Sync the filesystem server's allowed directory with the configured value.
|
|
47
|
+
// The mcp-servers.json ships with a default path that may differ from
|
|
48
|
+
// the ALLOWED_DIRECTORY environment variable.
|
|
49
|
+
const fsServer = mcpServers['filesystem'];
|
|
50
|
+
if (fsServer) {
|
|
51
|
+
const defaultDir = '/tmp/ironcurtain-sandbox';
|
|
52
|
+
const dirIndex = fsServer.args.indexOf(defaultDir);
|
|
53
|
+
if (dirIndex !== -1) {
|
|
54
|
+
fsServer.args[dirIndex] = allowedDirectory;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Resolve node_modules/ relative paths to absolute paths.
|
|
58
|
+
// Bundled MCP servers reference binaries via node_modules/ which only works
|
|
59
|
+
// from the dev checkout root. After npm install, deps may be hoisted to a
|
|
60
|
+
// parent node_modules/, so we walk up from the package root to find them.
|
|
61
|
+
const packageRoot = resolve(__dirname, '..', '..');
|
|
62
|
+
for (const config of Object.values(mcpServers)) {
|
|
63
|
+
if (config.command.startsWith('node_modules/')) {
|
|
64
|
+
config.command = resolveNodeModulesPath(config.command, packageRoot);
|
|
65
|
+
}
|
|
66
|
+
for (let i = 0; i < config.args.length; i++) {
|
|
67
|
+
if (config.args[i].startsWith('node_modules/')) {
|
|
68
|
+
config.args[i] = resolveNodeModulesPath(config.args[i], packageRoot);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const constitutionPath = resolve(__dirname, 'constitution.md');
|
|
73
|
+
const packageGeneratedDir = resolve(__dirname, 'generated');
|
|
74
|
+
const generatedDir = resolveGeneratedDir(packageGeneratedDir);
|
|
75
|
+
const protectedPaths = computeProtectedPaths({
|
|
76
|
+
constitutionPath,
|
|
77
|
+
generatedDir,
|
|
78
|
+
packageGeneratedDir,
|
|
79
|
+
mcpServersPath,
|
|
80
|
+
auditLogPath,
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
auditLogPath,
|
|
84
|
+
allowedDirectory,
|
|
85
|
+
mcpServers,
|
|
86
|
+
protectedPaths,
|
|
87
|
+
generatedDir,
|
|
88
|
+
constitutionPath,
|
|
89
|
+
agentModelId: userConfig.agentModelId,
|
|
90
|
+
escalationTimeoutSeconds: userConfig.escalationTimeoutSeconds,
|
|
91
|
+
userConfig,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Extracts domain allowlists from MCP server sandbox network configurations.
|
|
96
|
+
* Filters out the `*` wildcard since it means "no domain restriction".
|
|
97
|
+
* Returns a map from server name to its list of restricted domains.
|
|
98
|
+
*/
|
|
99
|
+
export function extractServerDomainAllowlists(mcpServers) {
|
|
100
|
+
const allowlists = new Map();
|
|
101
|
+
for (const [serverName, config] of Object.entries(mcpServers)) {
|
|
102
|
+
if (config.sandbox && typeof config.sandbox === 'object' && config.sandbox.network && typeof config.sandbox.network === 'object') {
|
|
103
|
+
const domains = config.sandbox.network.allowedDomains.filter(d => d !== '*');
|
|
104
|
+
if (domains.length > 0) {
|
|
105
|
+
allowlists.set(serverName, domains);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return allowlists;
|
|
110
|
+
}
|
|
111
|
+
export function loadGeneratedPolicy(generatedDir, fallbackDir) {
|
|
112
|
+
const compiledPolicy = JSON.parse(readGeneratedFile(generatedDir, 'compiled-policy.json', fallbackDir));
|
|
113
|
+
const toolAnnotations = JSON.parse(readGeneratedFile(generatedDir, 'tool-annotations.json', fallbackDir));
|
|
114
|
+
return { compiledPolicy, toolAnnotations };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Reads a generated artifact file, trying the primary dir first then the fallback.
|
|
118
|
+
*/
|
|
119
|
+
function readGeneratedFile(generatedDir, filename, fallbackDir) {
|
|
120
|
+
const primaryPath = resolve(generatedDir, filename);
|
|
121
|
+
if (existsSync(primaryPath)) {
|
|
122
|
+
return readFileSync(primaryPath, 'utf-8');
|
|
123
|
+
}
|
|
124
|
+
if (fallbackDir) {
|
|
125
|
+
const fallbackPath = resolve(fallbackDir, filename);
|
|
126
|
+
if (existsSync(fallbackPath)) {
|
|
127
|
+
return readFileSync(fallbackPath, 'utf-8');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Neither primary nor fallback exist -- read primary to throw with a clear path
|
|
131
|
+
return readFileSync(primaryPath, 'utf-8');
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Resolves a node_modules/ relative path by walking up from startDir.
|
|
135
|
+
* Handles npm's dependency hoisting where packages may live in a parent node_modules/.
|
|
136
|
+
*/
|
|
137
|
+
function resolveNodeModulesPath(relativePath, startDir) {
|
|
138
|
+
let dir = startDir;
|
|
139
|
+
for (;;) {
|
|
140
|
+
const candidate = resolve(dir, relativePath);
|
|
141
|
+
if (existsSync(candidate))
|
|
142
|
+
return candidate;
|
|
143
|
+
const parent = dirname(dir);
|
|
144
|
+
if (parent === dir)
|
|
145
|
+
break;
|
|
146
|
+
dir = parent;
|
|
147
|
+
}
|
|
148
|
+
// Fallback: assume it's directly under the package root
|
|
149
|
+
return resolve(startDir, relativePath);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"filesystem": {
|
|
3
|
+
"command": "npx",
|
|
4
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/ironcurtain-sandbox"],
|
|
5
|
+
"sandbox": false
|
|
6
|
+
},
|
|
7
|
+
"git": {
|
|
8
|
+
"command": "node",
|
|
9
|
+
"args": ["node_modules/.bin/git-mcp-server"],
|
|
10
|
+
"env": {
|
|
11
|
+
"MCP_TRANSPORT_TYPE": "stdio"
|
|
12
|
+
},
|
|
13
|
+
"sandbox": {
|
|
14
|
+
"filesystem": {
|
|
15
|
+
"denyRead": ["~/.gnupg", "~/.aws"]
|
|
16
|
+
},
|
|
17
|
+
"network": {
|
|
18
|
+
"allowedDomains": ["github.com", "*.github.com", "gitlab.com", "*.gitlab.com"]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-provider model resolution.
|
|
3
|
+
*
|
|
4
|
+
* Parses qualified model ID strings ("provider:model-id") and creates
|
|
5
|
+
* LanguageModel instances using the appropriate AI SDK provider package.
|
|
6
|
+
*
|
|
7
|
+
* Provider packages are dynamically imported so that only the packages
|
|
8
|
+
* for providers actually in use need to be installed.
|
|
9
|
+
*
|
|
10
|
+
* Adding a new provider requires:
|
|
11
|
+
* 1. Adding the identifier to ProviderId
|
|
12
|
+
* 2. Adding a case to createLanguageModel()
|
|
13
|
+
* 3. Optionally adding a key field to UserConfig
|
|
14
|
+
* 4. Installing the @ai-sdk/<provider> package
|
|
15
|
+
*/
|
|
16
|
+
import type { LanguageModelV3 } from '@ai-sdk/provider';
|
|
17
|
+
import type { ResolvedUserConfig } from './user-config.js';
|
|
18
|
+
/** Supported LLM provider identifiers. */
|
|
19
|
+
export type ProviderId = 'anthropic' | 'google' | 'openai';
|
|
20
|
+
/**
|
|
21
|
+
* Parsed model specifier. A "qualified model ID" has the form
|
|
22
|
+
* "provider:model-name". A bare model ID defaults to Anthropic.
|
|
23
|
+
*/
|
|
24
|
+
export interface ParsedModelId {
|
|
25
|
+
readonly provider: ProviderId;
|
|
26
|
+
readonly modelId: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Parses a qualified model ID string into provider and model components.
|
|
30
|
+
*
|
|
31
|
+
* Format: "provider:model-id" or just "model-id" (defaults to anthropic).
|
|
32
|
+
*
|
|
33
|
+
* @throws Error if the provider prefix is not recognized or model ID is empty
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseModelId(qualifiedId: string): ParsedModelId;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a LanguageModel from a qualified model ID and user config.
|
|
38
|
+
*
|
|
39
|
+
* Provider packages are dynamically imported so that only the packages
|
|
40
|
+
* for providers actually in use need to be installed.
|
|
41
|
+
*
|
|
42
|
+
* API key validation is deferred to the first API call -- the AI SDK
|
|
43
|
+
* providers give better error messages than we could produce here.
|
|
44
|
+
*
|
|
45
|
+
* @param qualifiedId - Model specifier like "anthropic:claude-sonnet-4-6"
|
|
46
|
+
* @param config - Resolved user config for API key lookup
|
|
47
|
+
* @returns A LanguageModelV3 instance ready for use with generateText()
|
|
48
|
+
*/
|
|
49
|
+
export declare function createLanguageModel(qualifiedId: string, config: ResolvedUserConfig): Promise<LanguageModelV3>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-provider model resolution.
|
|
3
|
+
*
|
|
4
|
+
* Parses qualified model ID strings ("provider:model-id") and creates
|
|
5
|
+
* LanguageModel instances using the appropriate AI SDK provider package.
|
|
6
|
+
*
|
|
7
|
+
* Provider packages are dynamically imported so that only the packages
|
|
8
|
+
* for providers actually in use need to be installed.
|
|
9
|
+
*
|
|
10
|
+
* Adding a new provider requires:
|
|
11
|
+
* 1. Adding the identifier to ProviderId
|
|
12
|
+
* 2. Adding a case to createLanguageModel()
|
|
13
|
+
* 3. Optionally adding a key field to UserConfig
|
|
14
|
+
* 4. Installing the @ai-sdk/<provider> package
|
|
15
|
+
*/
|
|
16
|
+
/** Default provider when no prefix is specified. */
|
|
17
|
+
const DEFAULT_PROVIDER = 'anthropic';
|
|
18
|
+
/** Known provider identifiers for validation. */
|
|
19
|
+
const KNOWN_PROVIDERS = new Set(['anthropic', 'google', 'openai']);
|
|
20
|
+
/**
|
|
21
|
+
* Parses a qualified model ID string into provider and model components.
|
|
22
|
+
*
|
|
23
|
+
* Format: "provider:model-id" or just "model-id" (defaults to anthropic).
|
|
24
|
+
*
|
|
25
|
+
* @throws Error if the provider prefix is not recognized or model ID is empty
|
|
26
|
+
*/
|
|
27
|
+
export function parseModelId(qualifiedId) {
|
|
28
|
+
const colonIndex = qualifiedId.indexOf(':');
|
|
29
|
+
if (colonIndex === -1) {
|
|
30
|
+
return { provider: DEFAULT_PROVIDER, modelId: qualifiedId };
|
|
31
|
+
}
|
|
32
|
+
const prefix = qualifiedId.substring(0, colonIndex);
|
|
33
|
+
const modelId = qualifiedId.substring(colonIndex + 1);
|
|
34
|
+
if (!KNOWN_PROVIDERS.has(prefix)) {
|
|
35
|
+
const known = [...KNOWN_PROVIDERS].sort().join(', ');
|
|
36
|
+
throw new Error(`Unknown model provider "${prefix}" in "${qualifiedId}". ` +
|
|
37
|
+
`Supported providers: ${known}`);
|
|
38
|
+
}
|
|
39
|
+
if (!modelId) {
|
|
40
|
+
throw new Error(`Empty model ID in "${qualifiedId}". ` +
|
|
41
|
+
`Expected format: "provider:model-id"`);
|
|
42
|
+
}
|
|
43
|
+
return { provider: prefix, modelId };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates a LanguageModel from a qualified model ID and user config.
|
|
47
|
+
*
|
|
48
|
+
* Provider packages are dynamically imported so that only the packages
|
|
49
|
+
* for providers actually in use need to be installed.
|
|
50
|
+
*
|
|
51
|
+
* API key validation is deferred to the first API call -- the AI SDK
|
|
52
|
+
* providers give better error messages than we could produce here.
|
|
53
|
+
*
|
|
54
|
+
* @param qualifiedId - Model specifier like "anthropic:claude-sonnet-4-6"
|
|
55
|
+
* @param config - Resolved user config for API key lookup
|
|
56
|
+
* @returns A LanguageModelV3 instance ready for use with generateText()
|
|
57
|
+
*/
|
|
58
|
+
export async function createLanguageModel(qualifiedId, config) {
|
|
59
|
+
const { provider, modelId } = parseModelId(qualifiedId);
|
|
60
|
+
switch (provider) {
|
|
61
|
+
case 'anthropic': {
|
|
62
|
+
const { createAnthropic } = await import('@ai-sdk/anthropic');
|
|
63
|
+
const apiKey = config.anthropicApiKey || undefined;
|
|
64
|
+
return createAnthropic({ apiKey })(modelId);
|
|
65
|
+
}
|
|
66
|
+
case 'google': {
|
|
67
|
+
const { createGoogleGenerativeAI } = await import('@ai-sdk/google');
|
|
68
|
+
const apiKey = config.googleApiKey || undefined;
|
|
69
|
+
return createGoogleGenerativeAI({ apiKey })(modelId);
|
|
70
|
+
}
|
|
71
|
+
case 'openai': {
|
|
72
|
+
const { createOpenAI } = await import('@ai-sdk/openai');
|
|
73
|
+
const apiKey = config.openaiApiKey || undefined;
|
|
74
|
+
return createOpenAI({ apiKey })(modelId);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=model-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider.js","sourceRoot":"","sources":["../../src/config/model-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,oDAAoD;AACpD,MAAM,gBAAgB,GAAe,WAAW,CAAC;AAEjD,iDAAiD;AACjD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAS,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAW3E;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAE5C,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAC9D,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;IAEtD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,CAAC,GAAG,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,IAAI,KAAK,CACb,2BAA2B,MAAM,SAAS,WAAW,KAAK;YAC1D,wBAAwB,KAAK,EAAE,CAChC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,sBAAsB,WAAW,KAAK;YACtC,sCAAsC,CACvC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,MAAoB,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,EACnB,MAA0B;IAE1B,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAExD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,eAAe,IAAI,SAAS,CAAC;YACnD,OAAO,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,wBAAwB,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACpE,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC;YAChD,OAAO,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,IAAI,SAAS,CAAC;YAChD,OAAO,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the IronCurtain home directory.
|
|
3
|
+
* Defaults to ~/.ironcurtain, overridable via IRONCURTAIN_HOME env var.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getIronCurtainHome(): string;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the sessions base directory: {home}/sessions/
|
|
8
|
+
*/
|
|
9
|
+
export declare function getSessionsDir(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the session directory for a given session ID:
|
|
12
|
+
* {home}/sessions/{sessionId}/
|
|
13
|
+
*/
|
|
14
|
+
export declare function getSessionDir(sessionId: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the sandbox directory for a given session:
|
|
17
|
+
* {home}/sessions/{sessionId}/sandbox/
|
|
18
|
+
*/
|
|
19
|
+
export declare function getSessionSandboxDir(sessionId: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Returns the escalation IPC directory for a given session:
|
|
22
|
+
* {home}/sessions/{sessionId}/escalations/
|
|
23
|
+
*/
|
|
24
|
+
export declare function getSessionEscalationDir(sessionId: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the audit log path for a given session:
|
|
27
|
+
* {home}/sessions/{sessionId}/audit.jsonl
|
|
28
|
+
*/
|
|
29
|
+
export declare function getSessionAuditLogPath(sessionId: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the session log path for a given session:
|
|
32
|
+
* {home}/sessions/{sessionId}/session.log
|
|
33
|
+
*/
|
|
34
|
+
export declare function getSessionLogPath(sessionId: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Returns the LLM interaction log path for a given session:
|
|
37
|
+
* {home}/sessions/{sessionId}/llm-interactions.jsonl
|
|
38
|
+
*/
|
|
39
|
+
export declare function getSessionLlmLogPath(sessionId: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the user config file path: {home}/config.json
|
|
42
|
+
*/
|
|
43
|
+
export declare function getUserConfigPath(): string;
|
|
44
|
+
/**
|
|
45
|
+
* Returns the logs directory: {home}/logs/
|
|
46
|
+
*/
|
|
47
|
+
export declare function getLogsDir(): string;
|
|
48
|
+
/**
|
|
49
|
+
* Returns the user constitution file path: {home}/constitution-user.md
|
|
50
|
+
* User policy customizations live in this file, separate from the
|
|
51
|
+
* base constitution (which is version-controlled).
|
|
52
|
+
*/
|
|
53
|
+
export declare function getUserConstitutionPath(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the user-local generated artifacts directory: {home}/generated/
|
|
56
|
+
* Pipeline commands write here; runtime reads from here first, falling back
|
|
57
|
+
* to the package-bundled defaults in dist/config/generated/.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getUserGeneratedDir(): string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the IronCurtain home directory.
|
|
5
|
+
* Defaults to ~/.ironcurtain, overridable via IRONCURTAIN_HOME env var.
|
|
6
|
+
*/
|
|
7
|
+
export function getIronCurtainHome() {
|
|
8
|
+
return process.env.IRONCURTAIN_HOME ?? resolve(homedir(), '.ironcurtain');
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Returns the sessions base directory: {home}/sessions/
|
|
12
|
+
*/
|
|
13
|
+
export function getSessionsDir() {
|
|
14
|
+
return resolve(getIronCurtainHome(), 'sessions');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates that a session ID contains only safe characters
|
|
18
|
+
* (alphanumeric, hyphens, underscores) to prevent path traversal.
|
|
19
|
+
*/
|
|
20
|
+
function validateSessionId(sessionId) {
|
|
21
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(sessionId)) {
|
|
22
|
+
throw new Error(`Invalid session ID: ${sessionId}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the session directory for a given session ID:
|
|
27
|
+
* {home}/sessions/{sessionId}/
|
|
28
|
+
*/
|
|
29
|
+
export function getSessionDir(sessionId) {
|
|
30
|
+
validateSessionId(sessionId);
|
|
31
|
+
return resolve(getSessionsDir(), sessionId);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns the sandbox directory for a given session:
|
|
35
|
+
* {home}/sessions/{sessionId}/sandbox/
|
|
36
|
+
*/
|
|
37
|
+
export function getSessionSandboxDir(sessionId) {
|
|
38
|
+
return resolve(getSessionDir(sessionId), 'sandbox');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns the escalation IPC directory for a given session:
|
|
42
|
+
* {home}/sessions/{sessionId}/escalations/
|
|
43
|
+
*/
|
|
44
|
+
export function getSessionEscalationDir(sessionId) {
|
|
45
|
+
return resolve(getSessionDir(sessionId), 'escalations');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns the audit log path for a given session:
|
|
49
|
+
* {home}/sessions/{sessionId}/audit.jsonl
|
|
50
|
+
*/
|
|
51
|
+
export function getSessionAuditLogPath(sessionId) {
|
|
52
|
+
return resolve(getSessionDir(sessionId), 'audit.jsonl');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the session log path for a given session:
|
|
56
|
+
* {home}/sessions/{sessionId}/session.log
|
|
57
|
+
*/
|
|
58
|
+
export function getSessionLogPath(sessionId) {
|
|
59
|
+
return resolve(getSessionDir(sessionId), 'session.log');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns the LLM interaction log path for a given session:
|
|
63
|
+
* {home}/sessions/{sessionId}/llm-interactions.jsonl
|
|
64
|
+
*/
|
|
65
|
+
export function getSessionLlmLogPath(sessionId) {
|
|
66
|
+
return resolve(getSessionDir(sessionId), 'llm-interactions.jsonl');
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns the user config file path: {home}/config.json
|
|
70
|
+
*/
|
|
71
|
+
export function getUserConfigPath() {
|
|
72
|
+
return resolve(getIronCurtainHome(), 'config.json');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Returns the logs directory: {home}/logs/
|
|
76
|
+
*/
|
|
77
|
+
export function getLogsDir() {
|
|
78
|
+
return resolve(getIronCurtainHome(), 'logs');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Returns the user constitution file path: {home}/constitution-user.md
|
|
82
|
+
* User policy customizations live in this file, separate from the
|
|
83
|
+
* base constitution (which is version-controlled).
|
|
84
|
+
*/
|
|
85
|
+
export function getUserConstitutionPath() {
|
|
86
|
+
return resolve(getIronCurtainHome(), 'constitution-user.md');
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns the user-local generated artifacts directory: {home}/generated/
|
|
90
|
+
* Pipeline commands write here; runtime reads from here first, falling back
|
|
91
|
+
* to the package-bundled defaults in dist/config/generated/.
|
|
92
|
+
*/
|
|
93
|
+
export function getUserGeneratedDir() {
|
|
94
|
+
return resolve(getIronCurtainHome(), 'generated');
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAC5E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,uBAAuB,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7B,OAAO,OAAO,CAAC,cAAc,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACvD,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,OAAO,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,wBAAwB,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,aAAa,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,sBAAsB,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,CAAC,kBAAkB,EAAE,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { ResolvedUserConfig } from './user-config.js';
|
|
2
|
+
/**
|
|
3
|
+
* Network access configuration for a sandboxed MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Invariant: when `allowedDomains` is empty, no network access is permitted.
|
|
6
|
+
* `deniedDomains` takes precedence and is checked first.
|
|
7
|
+
*/
|
|
8
|
+
export interface SandboxNetworkConfig {
|
|
9
|
+
/** Domains the server may connect to. Supports wildcards (e.g., "*.github.com"). */
|
|
10
|
+
readonly allowedDomains: string[];
|
|
11
|
+
/** Domains explicitly blocked even if they match an allowed pattern. */
|
|
12
|
+
readonly deniedDomains?: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Filesystem access configuration for a sandboxed MCP server.
|
|
16
|
+
*
|
|
17
|
+
* Invariant: `allowWrite` always includes the session sandbox directory
|
|
18
|
+
* (injected at runtime, not specified here). Paths listed here are
|
|
19
|
+
* *additional* write-allowed directories beyond the sandbox.
|
|
20
|
+
*
|
|
21
|
+
* Reads are allowed by default. Use `denyRead` to block sensitive
|
|
22
|
+
* paths like ~/.ssh or ~/.gnupg.
|
|
23
|
+
*/
|
|
24
|
+
export interface SandboxFilesystemConfig {
|
|
25
|
+
/** Additional directories the server may write to, beyond the session sandbox. */
|
|
26
|
+
readonly allowWrite?: string[];
|
|
27
|
+
/** Directories the server may not read. */
|
|
28
|
+
readonly denyRead?: string[];
|
|
29
|
+
/** Directories the server may not write to, even within allowed paths. */
|
|
30
|
+
readonly denyWrite?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Per-server sandbox configuration.
|
|
34
|
+
*
|
|
35
|
+
* Discriminated on presence/shape:
|
|
36
|
+
* - `false`: server opts out of sandboxing entirely
|
|
37
|
+
* - `object`: server is sandboxed with the specified overrides
|
|
38
|
+
* - `undefined` (omitted): server is sandboxed with restrictive defaults
|
|
39
|
+
* (session sandbox write-only, no network)
|
|
40
|
+
*/
|
|
41
|
+
export type ServerSandboxConfig = false | {
|
|
42
|
+
/** Filesystem restrictions beyond the automatic session sandbox directory. */
|
|
43
|
+
readonly filesystem?: SandboxFilesystemConfig;
|
|
44
|
+
/**
|
|
45
|
+
* Network access. `false` means no network (default).
|
|
46
|
+
* An object specifies allowed/denied domains.
|
|
47
|
+
*/
|
|
48
|
+
readonly network?: false | SandboxNetworkConfig;
|
|
49
|
+
};
|
|
50
|
+
export interface MCPServerConfig {
|
|
51
|
+
command: string;
|
|
52
|
+
args: string[];
|
|
53
|
+
env?: Record<string, string>;
|
|
54
|
+
/** OS-level sandbox configuration. Omit for restrictive defaults, `false` to opt out. */
|
|
55
|
+
sandbox?: ServerSandboxConfig;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Controls behavior when sandbox-runtime is unavailable on the current
|
|
59
|
+
* platform (e.g., Windows, Linux without bubblewrap).
|
|
60
|
+
*
|
|
61
|
+
* - "enforce": refuse to start servers that require sandboxing
|
|
62
|
+
* - "warn": log a warning and start the server without sandbox (default)
|
|
63
|
+
*/
|
|
64
|
+
export type SandboxAvailabilityPolicy = 'enforce' | 'warn';
|
|
65
|
+
export interface IronCurtainConfig {
|
|
66
|
+
auditLogPath: string;
|
|
67
|
+
allowedDirectory: string;
|
|
68
|
+
mcpServers: Record<string, MCPServerConfig>;
|
|
69
|
+
protectedPaths: string[];
|
|
70
|
+
generatedDir: string;
|
|
71
|
+
constitutionPath: string;
|
|
72
|
+
/** Per-session escalation directory for file-based IPC with the proxy. Optional for backward compatibility. */
|
|
73
|
+
escalationDir?: string;
|
|
74
|
+
/** Per-session log file path for capturing child process output. Optional for backward compatibility. */
|
|
75
|
+
sessionLogPath?: string;
|
|
76
|
+
/** Per-session LLM interaction log path. When set, all LLM calls are logged to this JSONL file. */
|
|
77
|
+
llmLogPath?: string;
|
|
78
|
+
/** AI SDK model ID for the interactive agent (e.g. 'anthropic:claude-sonnet-4-6'). */
|
|
79
|
+
agentModelId: string;
|
|
80
|
+
/** Escalation timeout in seconds (30-600). Controls how long to wait for human approval. */
|
|
81
|
+
escalationTimeoutSeconds: number;
|
|
82
|
+
/** Resolved user configuration. Provides API keys for model resolution. */
|
|
83
|
+
userConfig: ResolvedUserConfig;
|
|
84
|
+
/**
|
|
85
|
+
* Controls behavior when OS-level sandboxing is unavailable.
|
|
86
|
+
* Default: "warn" -- log and continue without sandbox.
|
|
87
|
+
*/
|
|
88
|
+
sandboxPolicy?: SandboxAvailabilityPolicy;
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/config/types.ts"],"names":[],"mappings":""}
|