gencode-ai 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/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
# Proposal: Sandboxing
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0034
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement sandboxing capabilities to run untrusted code and commands in isolated environments, protecting the host system from potentially harmful operations.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Code execution carries risks:
|
|
16
|
+
|
|
17
|
+
1. **Malicious commands**: Intentional or accidental damage
|
|
18
|
+
2. **Side effects**: Unintended system changes
|
|
19
|
+
3. **Resource exhaustion**: CPU/memory abuse
|
|
20
|
+
4. **Network access**: Unauthorized connections
|
|
21
|
+
5. **File system**: Access to sensitive files
|
|
22
|
+
|
|
23
|
+
Sandboxing provides isolation and safety.
|
|
24
|
+
|
|
25
|
+
## Detailed Design
|
|
26
|
+
|
|
27
|
+
### API Design
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// src/sandbox/types.ts
|
|
31
|
+
type SandboxType = 'docker' | 'firejail' | 'nsjail' | 'vm';
|
|
32
|
+
|
|
33
|
+
interface SandboxConfig {
|
|
34
|
+
type: SandboxType;
|
|
35
|
+
enabled: boolean;
|
|
36
|
+
image?: string; // For Docker
|
|
37
|
+
profile?: string; // For firejail
|
|
38
|
+
limits: ResourceLimits;
|
|
39
|
+
network: NetworkPolicy;
|
|
40
|
+
filesystem: FilesystemPolicy;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ResourceLimits {
|
|
44
|
+
cpuPercent: number; // 0-100
|
|
45
|
+
memoryMB: number;
|
|
46
|
+
diskMB: number;
|
|
47
|
+
timeoutSeconds: number;
|
|
48
|
+
maxProcesses: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface NetworkPolicy {
|
|
52
|
+
enabled: boolean;
|
|
53
|
+
allowedHosts?: string[];
|
|
54
|
+
blockedPorts?: number[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface FilesystemPolicy {
|
|
58
|
+
readOnly: string[]; // Read-only paths
|
|
59
|
+
readWrite: string[]; // Read-write paths
|
|
60
|
+
hidden: string[]; // Inaccessible paths
|
|
61
|
+
tempDir: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface SandboxResult {
|
|
65
|
+
success: boolean;
|
|
66
|
+
stdout: string;
|
|
67
|
+
stderr: string;
|
|
68
|
+
exitCode: number;
|
|
69
|
+
resourceUsage: {
|
|
70
|
+
cpuTime: number;
|
|
71
|
+
memoryPeak: number;
|
|
72
|
+
wallTime: number;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Sandbox Manager
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// src/sandbox/manager.ts
|
|
81
|
+
class SandboxManager {
|
|
82
|
+
private config: SandboxConfig;
|
|
83
|
+
private backend: SandboxBackend;
|
|
84
|
+
|
|
85
|
+
constructor(config?: Partial<SandboxConfig>) {
|
|
86
|
+
this.config = {
|
|
87
|
+
type: 'docker',
|
|
88
|
+
enabled: false,
|
|
89
|
+
limits: {
|
|
90
|
+
cpuPercent: 50,
|
|
91
|
+
memoryMB: 512,
|
|
92
|
+
diskMB: 1024,
|
|
93
|
+
timeoutSeconds: 60,
|
|
94
|
+
maxProcesses: 50
|
|
95
|
+
},
|
|
96
|
+
network: { enabled: false },
|
|
97
|
+
filesystem: {
|
|
98
|
+
readOnly: ['/'],
|
|
99
|
+
readWrite: ['/tmp'],
|
|
100
|
+
hidden: ['/etc/passwd', '/etc/shadow'],
|
|
101
|
+
tempDir: '/tmp/mycode-sandbox'
|
|
102
|
+
},
|
|
103
|
+
...config
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
this.backend = this.createBackend();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async execute(command: string, options?: ExecuteOptions): Promise<SandboxResult> {
|
|
110
|
+
if (!this.config.enabled) {
|
|
111
|
+
throw new Error('Sandbox not enabled');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return this.backend.execute(command, {
|
|
115
|
+
...options,
|
|
116
|
+
limits: this.config.limits,
|
|
117
|
+
network: this.config.network,
|
|
118
|
+
filesystem: this.config.filesystem
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private createBackend(): SandboxBackend {
|
|
123
|
+
switch (this.config.type) {
|
|
124
|
+
case 'docker':
|
|
125
|
+
return new DockerSandbox(this.config);
|
|
126
|
+
case 'firejail':
|
|
127
|
+
return new FirejailSandbox(this.config);
|
|
128
|
+
case 'nsjail':
|
|
129
|
+
return new NsjailSandbox(this.config);
|
|
130
|
+
default:
|
|
131
|
+
throw new Error(`Unknown sandbox type: ${this.config.type}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Docker implementation
|
|
137
|
+
class DockerSandbox implements SandboxBackend {
|
|
138
|
+
async execute(command: string, options: SandboxOptions): Promise<SandboxResult> {
|
|
139
|
+
const containerArgs = [
|
|
140
|
+
'run', '--rm',
|
|
141
|
+
'--network', options.network.enabled ? 'bridge' : 'none',
|
|
142
|
+
'--memory', `${options.limits.memoryMB}m`,
|
|
143
|
+
'--cpus', `${options.limits.cpuPercent / 100}`,
|
|
144
|
+
'--pids-limit', String(options.limits.maxProcesses),
|
|
145
|
+
'--read-only',
|
|
146
|
+
'-v', `${options.filesystem.tempDir}:/workspace:rw`,
|
|
147
|
+
'-w', '/workspace',
|
|
148
|
+
this.config.image || 'ubuntu:22.04',
|
|
149
|
+
'/bin/bash', '-c', command
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
const result = await execAsync(`docker ${containerArgs.join(' ')}`);
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
success: result.code === 0,
|
|
156
|
+
stdout: result.stdout,
|
|
157
|
+
stderr: result.stderr,
|
|
158
|
+
exitCode: result.code,
|
|
159
|
+
resourceUsage: await this.getResourceUsage()
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Bash Tool Integration
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// Updated src/tools/bash/bash-tool.ts
|
|
169
|
+
async execute(input: BashInput, context: ToolContext): Promise<BashOutput> {
|
|
170
|
+
if (this.config.sandboxMode && sandboxManager.isEnabled()) {
|
|
171
|
+
return this.executeInSandbox(input, context);
|
|
172
|
+
}
|
|
173
|
+
return this.executeDirect(input, context);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private async executeInSandbox(
|
|
177
|
+
input: BashInput,
|
|
178
|
+
context: ToolContext
|
|
179
|
+
): Promise<BashOutput> {
|
|
180
|
+
const result = await sandboxManager.execute(input.command, {
|
|
181
|
+
cwd: context.cwd,
|
|
182
|
+
timeout: input.timeout
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
success: result.success,
|
|
187
|
+
stdout: result.stdout,
|
|
188
|
+
stderr: result.stderr,
|
|
189
|
+
exit_code: result.exitCode,
|
|
190
|
+
duration_ms: result.resourceUsage.wallTime
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### File Changes
|
|
196
|
+
|
|
197
|
+
| File | Action | Description |
|
|
198
|
+
|------|--------|-------------|
|
|
199
|
+
| `src/sandbox/types.ts` | Create | Type definitions |
|
|
200
|
+
| `src/sandbox/manager.ts` | Create | Sandbox management |
|
|
201
|
+
| `src/sandbox/backends/docker.ts` | Create | Docker backend |
|
|
202
|
+
| `src/sandbox/backends/firejail.ts` | Create | Firejail backend |
|
|
203
|
+
| `src/sandbox/index.ts` | Create | Module exports |
|
|
204
|
+
| `src/tools/bash/bash-tool.ts` | Modify | Sandbox integration |
|
|
205
|
+
|
|
206
|
+
## User Experience
|
|
207
|
+
|
|
208
|
+
### Enable Sandbox Mode
|
|
209
|
+
```
|
|
210
|
+
User: /settings sandbox enable
|
|
211
|
+
|
|
212
|
+
Sandbox mode enabled.
|
|
213
|
+
Backend: Docker
|
|
214
|
+
Memory limit: 512MB
|
|
215
|
+
CPU limit: 50%
|
|
216
|
+
Network: Disabled
|
|
217
|
+
Timeout: 60s
|
|
218
|
+
|
|
219
|
+
Commands will now run in isolated containers.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Sandboxed Execution
|
|
223
|
+
```
|
|
224
|
+
Agent: [Bash: npm install && npm test (sandboxed)]
|
|
225
|
+
|
|
226
|
+
┌─ Sandbox Execution ───────────────────────────────┐
|
|
227
|
+
│ Container: mycode-sandbox-abc123 │
|
|
228
|
+
│ Image: node:18-slim │
|
|
229
|
+
│ Network: disabled │
|
|
230
|
+
│ Memory: 512MB max │
|
|
231
|
+
└───────────────────────────────────────────────────┘
|
|
232
|
+
|
|
233
|
+
Running...
|
|
234
|
+
|
|
235
|
+
✓ Completed in 12.3s
|
|
236
|
+
CPU: 34% peak
|
|
237
|
+
Memory: 287MB peak
|
|
238
|
+
Exit code: 0
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Resource Limit Hit
|
|
242
|
+
```
|
|
243
|
+
Agent: [Bash: stress --vm 4 --vm-bytes 1G (sandboxed)]
|
|
244
|
+
|
|
245
|
+
⚠️ Sandbox Limit Exceeded
|
|
246
|
+
|
|
247
|
+
The command exceeded resource limits:
|
|
248
|
+
Memory: 512MB limit exceeded
|
|
249
|
+
|
|
250
|
+
The container was terminated for safety.
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Security Considerations
|
|
254
|
+
|
|
255
|
+
1. Container escape prevention
|
|
256
|
+
2. Network isolation verification
|
|
257
|
+
3. Resource limit enforcement
|
|
258
|
+
4. Secure image sources
|
|
259
|
+
5. Cleanup on completion
|
|
260
|
+
|
|
261
|
+
## Migration Path
|
|
262
|
+
|
|
263
|
+
1. **Phase 1**: Docker sandbox
|
|
264
|
+
2. **Phase 2**: Firejail for lighter isolation
|
|
265
|
+
3. **Phase 3**: Resource monitoring
|
|
266
|
+
4. **Phase 4**: Network policies
|
|
267
|
+
5. **Phase 5**: Custom images
|
|
268
|
+
|
|
269
|
+
## References
|
|
270
|
+
|
|
271
|
+
- [Docker Security](https://docs.docker.com/engine/security/)
|
|
272
|
+
- [Firejail](https://firejail.wordpress.com/)
|
|
273
|
+
- [gVisor](https://gvisor.dev/)
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# Proposal: Auto-updater
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0035
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement an auto-update mechanism to keep mycode current with the latest features and security fixes, with configurable update policies and rollback support.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Manual updates cause issues:
|
|
16
|
+
|
|
17
|
+
1. **Version lag**: Users run outdated versions
|
|
18
|
+
2. **Security risk**: Missing security patches
|
|
19
|
+
3. **Feature gaps**: Delayed access to improvements
|
|
20
|
+
4. **Inconsistency**: Teams on different versions
|
|
21
|
+
5. **Manual effort**: Extra steps for users
|
|
22
|
+
|
|
23
|
+
Auto-updates ensure users stay current.
|
|
24
|
+
|
|
25
|
+
## Detailed Design
|
|
26
|
+
|
|
27
|
+
### API Design
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// src/updater/types.ts
|
|
31
|
+
interface UpdateConfig {
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
checkInterval: number; // Hours between checks
|
|
34
|
+
channel: 'stable' | 'beta' | 'nightly';
|
|
35
|
+
autoInstall: boolean; // Install without asking
|
|
36
|
+
allowDowngrade: boolean;
|
|
37
|
+
rollbackOnError: boolean;
|
|
38
|
+
proxy?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface UpdateInfo {
|
|
42
|
+
version: string;
|
|
43
|
+
releaseDate: Date;
|
|
44
|
+
channel: string;
|
|
45
|
+
changelog: string;
|
|
46
|
+
downloadUrl: string;
|
|
47
|
+
checksum: string;
|
|
48
|
+
size: number;
|
|
49
|
+
breaking?: boolean;
|
|
50
|
+
securityFix?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface UpdateResult {
|
|
54
|
+
success: boolean;
|
|
55
|
+
previousVersion: string;
|
|
56
|
+
newVersion: string;
|
|
57
|
+
restartRequired: boolean;
|
|
58
|
+
error?: string;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Update Manager
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// src/updater/manager.ts
|
|
66
|
+
class UpdateManager {
|
|
67
|
+
private config: UpdateConfig;
|
|
68
|
+
private currentVersion: string;
|
|
69
|
+
|
|
70
|
+
constructor(config?: Partial<UpdateConfig>) {
|
|
71
|
+
this.config = {
|
|
72
|
+
enabled: true,
|
|
73
|
+
checkInterval: 24,
|
|
74
|
+
channel: 'stable',
|
|
75
|
+
autoInstall: false,
|
|
76
|
+
allowDowngrade: false,
|
|
77
|
+
rollbackOnError: true,
|
|
78
|
+
...config
|
|
79
|
+
};
|
|
80
|
+
this.currentVersion = this.getInstalledVersion();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async checkForUpdates(): Promise<UpdateInfo | null> {
|
|
84
|
+
const latestUrl = `https://releases.mycode.dev/${this.config.channel}/latest.json`;
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(latestUrl);
|
|
88
|
+
const latest = await response.json() as UpdateInfo;
|
|
89
|
+
|
|
90
|
+
if (this.isNewerVersion(latest.version)) {
|
|
91
|
+
return latest;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('Update check failed:', error);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async update(info: UpdateInfo): Promise<UpdateResult> {
|
|
101
|
+
const previousVersion = this.currentVersion;
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
// Download update
|
|
105
|
+
const tempPath = await this.download(info);
|
|
106
|
+
|
|
107
|
+
// Verify checksum
|
|
108
|
+
if (!await this.verifyChecksum(tempPath, info.checksum)) {
|
|
109
|
+
throw new Error('Checksum verification failed');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Backup current installation
|
|
113
|
+
await this.backup();
|
|
114
|
+
|
|
115
|
+
// Install update
|
|
116
|
+
await this.install(tempPath);
|
|
117
|
+
|
|
118
|
+
// Verify new installation
|
|
119
|
+
if (!await this.verifyInstallation(info.version)) {
|
|
120
|
+
if (this.config.rollbackOnError) {
|
|
121
|
+
await this.rollback();
|
|
122
|
+
throw new Error('Installation verification failed, rolled back');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
success: true,
|
|
128
|
+
previousVersion,
|
|
129
|
+
newVersion: info.version,
|
|
130
|
+
restartRequired: true
|
|
131
|
+
};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
previousVersion,
|
|
136
|
+
newVersion: info.version,
|
|
137
|
+
restartRequired: false,
|
|
138
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async rollback(): Promise<boolean> {
|
|
144
|
+
const backupPath = this.getBackupPath();
|
|
145
|
+
if (!fs.existsSync(backupPath)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
await this.restore(backupPath);
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
startBackgroundChecker(): void {
|
|
154
|
+
if (!this.config.enabled) return;
|
|
155
|
+
|
|
156
|
+
setInterval(async () => {
|
|
157
|
+
const update = await this.checkForUpdates();
|
|
158
|
+
if (update) {
|
|
159
|
+
if (this.config.autoInstall) {
|
|
160
|
+
await this.update(update);
|
|
161
|
+
} else {
|
|
162
|
+
this.notifyUpdate(update);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}, this.config.checkInterval * 60 * 60 * 1000);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private isNewerVersion(version: string): boolean {
|
|
169
|
+
const current = this.parseVersion(this.currentVersion);
|
|
170
|
+
const target = this.parseVersion(version);
|
|
171
|
+
|
|
172
|
+
for (let i = 0; i < 3; i++) {
|
|
173
|
+
if (target[i] > current[i]) return true;
|
|
174
|
+
if (target[i] < current[i]) return false;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private parseVersion(version: string): number[] {
|
|
180
|
+
return version.replace(/^v/, '').split('.').map(Number);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const updateManager = new UpdateManager();
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### CLI Commands
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
// src/cli/commands/update.ts
|
|
191
|
+
const updateCommands = {
|
|
192
|
+
'/update check': 'Check for updates',
|
|
193
|
+
'/update install': 'Install available update',
|
|
194
|
+
'/update rollback': 'Rollback to previous version',
|
|
195
|
+
'/update channel <name>': 'Switch update channel',
|
|
196
|
+
'/update auto <on|off>': 'Toggle auto-updates'
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
async function handleUpdate(args: string[]): Promise<void> {
|
|
200
|
+
const [subcommand, ...rest] = args;
|
|
201
|
+
|
|
202
|
+
switch (subcommand) {
|
|
203
|
+
case 'check':
|
|
204
|
+
const update = await updateManager.checkForUpdates();
|
|
205
|
+
if (update) {
|
|
206
|
+
console.log(`Update available: ${update.version}`);
|
|
207
|
+
console.log(`Changelog:\n${update.changelog}`);
|
|
208
|
+
} else {
|
|
209
|
+
console.log('You are running the latest version.');
|
|
210
|
+
}
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case 'install':
|
|
214
|
+
const info = await updateManager.checkForUpdates();
|
|
215
|
+
if (!info) {
|
|
216
|
+
console.log('No update available.');
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const result = await updateManager.update(info);
|
|
220
|
+
if (result.success) {
|
|
221
|
+
console.log(`Updated to ${result.newVersion}`);
|
|
222
|
+
if (result.restartRequired) {
|
|
223
|
+
console.log('Please restart mycode to complete the update.');
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### File Changes
|
|
232
|
+
|
|
233
|
+
| File | Action | Description |
|
|
234
|
+
|------|--------|-------------|
|
|
235
|
+
| `src/updater/types.ts` | Create | Type definitions |
|
|
236
|
+
| `src/updater/manager.ts` | Create | Update logic |
|
|
237
|
+
| `src/updater/download.ts` | Create | Download handling |
|
|
238
|
+
| `src/updater/verify.ts` | Create | Checksum verification |
|
|
239
|
+
| `src/updater/index.ts` | Create | Module exports |
|
|
240
|
+
| `src/cli/commands/update.ts` | Create | CLI commands |
|
|
241
|
+
|
|
242
|
+
## User Experience
|
|
243
|
+
|
|
244
|
+
### Update Notification
|
|
245
|
+
```
|
|
246
|
+
┌─ Update Available ────────────────────────────────┐
|
|
247
|
+
│ │
|
|
248
|
+
│ mycode v2.1.0 is available (you have v2.0.3) │
|
|
249
|
+
│ │
|
|
250
|
+
│ Highlights: │
|
|
251
|
+
│ • New LSP tool for code intelligence │
|
|
252
|
+
│ • Performance improvements │
|
|
253
|
+
│ • Security fix for CVE-2025-1234 │
|
|
254
|
+
│ │
|
|
255
|
+
│ Run /update install to update │
|
|
256
|
+
│ │
|
|
257
|
+
└───────────────────────────────────────────────────┘
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Update Process
|
|
261
|
+
```
|
|
262
|
+
User: /update install
|
|
263
|
+
|
|
264
|
+
Downloading mycode v2.1.0 (15.2 MB)...
|
|
265
|
+
████████████████████████████████ 100%
|
|
266
|
+
|
|
267
|
+
Verifying checksum... ✓
|
|
268
|
+
Backing up current version... ✓
|
|
269
|
+
Installing update... ✓
|
|
270
|
+
Verifying installation... ✓
|
|
271
|
+
|
|
272
|
+
✓ Updated to v2.1.0
|
|
273
|
+
|
|
274
|
+
Please restart mycode to complete the update.
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Rollback
|
|
278
|
+
```
|
|
279
|
+
User: /update rollback
|
|
280
|
+
|
|
281
|
+
Rolling back to v2.0.3...
|
|
282
|
+
|
|
283
|
+
Restoring backup... ✓
|
|
284
|
+
Verifying restoration... ✓
|
|
285
|
+
|
|
286
|
+
✓ Rolled back to v2.0.3
|
|
287
|
+
|
|
288
|
+
Restart mycode to complete the rollback.
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Security Considerations
|
|
292
|
+
|
|
293
|
+
1. HTTPS for all downloads
|
|
294
|
+
2. Checksum verification (SHA-256)
|
|
295
|
+
3. Code signing verification
|
|
296
|
+
4. Secure backup storage
|
|
297
|
+
5. Atomic updates
|
|
298
|
+
|
|
299
|
+
## Migration Path
|
|
300
|
+
|
|
301
|
+
1. **Phase 1**: Manual update check
|
|
302
|
+
2. **Phase 2**: Download and install
|
|
303
|
+
3. **Phase 3**: Background checking
|
|
304
|
+
4. **Phase 4**: Auto-install option
|
|
305
|
+
5. **Phase 5**: Rollback support
|
|
306
|
+
|
|
307
|
+
## References
|
|
308
|
+
|
|
309
|
+
- [Electron Auto-updater](https://www.electron.build/auto-update)
|
|
310
|
+
- [Squirrel](https://github.com/Squirrel)
|
|
311
|
+
- [Code Signing Best Practices](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/code-signing-best-practices)
|