@wavexzore/sandbox 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/Dockerfile +14 -0
- package/LICENSE +661 -0
- package/NOTICE +3 -0
- package/README.md +153 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/sandbox/cli/install.d.ts +5 -0
- package/dist/sandbox/cli/install.js +335 -0
- package/dist/sandbox/cli/local-store.d.ts +87 -0
- package/dist/sandbox/cli/local-store.js +604 -0
- package/dist/sandbox/cli/opencode-config.d.ts +25 -0
- package/dist/sandbox/cli/opencode-config.js +240 -0
- package/dist/sandbox/cli/path.d.ts +64 -0
- package/dist/sandbox/cli/path.js +127 -0
- package/dist/sandbox/cli/types.d.ts +145 -0
- package/dist/sandbox/cli/types.js +6 -0
- package/dist/sandbox/cli/wavexzore-sandbox.d.ts +65 -0
- package/dist/sandbox/cli/wavexzore-sandbox.js +577 -0
- package/dist/sandbox/core/cli-helper.d.ts +19 -0
- package/dist/sandbox/core/cli-helper.js +64 -0
- package/dist/sandbox/core/docker-archive-utils.d.ts +3 -0
- package/dist/sandbox/core/docker-archive-utils.js +50 -0
- package/dist/sandbox/core/docker-sandbox.d.ts +51 -0
- package/dist/sandbox/core/docker-sandbox.js +675 -0
- package/dist/sandbox/core/edit/filediff.d.ts +16 -0
- package/dist/sandbox/core/edit/filediff.js +21 -0
- package/dist/sandbox/core/edit/index.d.ts +5 -0
- package/dist/sandbox/core/edit/index.js +5 -0
- package/dist/sandbox/core/edit/line-endings.d.ts +4 -0
- package/dist/sandbox/core/edit/line-endings.js +10 -0
- package/dist/sandbox/core/edit/lock.d.ts +1 -0
- package/dist/sandbox/core/edit/lock.js +18 -0
- package/dist/sandbox/core/edit/replace.d.ts +10 -0
- package/dist/sandbox/core/edit/replace.js +14 -0
- package/dist/sandbox/core/edit/replacers.d.ts +15 -0
- package/dist/sandbox/core/edit/replacers.js +241 -0
- package/dist/sandbox/core/logger.d.ts +15 -0
- package/dist/sandbox/core/logger.js +59 -0
- package/dist/sandbox/core/lsp/client.d.ts +63 -0
- package/dist/sandbox/core/lsp/client.js +533 -0
- package/dist/sandbox/core/lsp/config.d.ts +13 -0
- package/dist/sandbox/core/lsp/config.js +36 -0
- package/dist/sandbox/core/lsp/diagnostics.d.ts +12 -0
- package/dist/sandbox/core/lsp/diagnostics.js +65 -0
- package/dist/sandbox/core/lsp/index.d.ts +4 -0
- package/dist/sandbox/core/lsp/index.js +4 -0
- package/dist/sandbox/core/lsp/language.d.ts +24 -0
- package/dist/sandbox/core/lsp/language.js +249 -0
- package/dist/sandbox/core/lsp/manager.d.ts +77 -0
- package/dist/sandbox/core/lsp/manager.js +237 -0
- package/dist/sandbox/core/lsp/tooling.d.ts +14 -0
- package/dist/sandbox/core/lsp/tooling.js +78 -0
- package/dist/sandbox/core/patch-parser.d.ts +23 -0
- package/dist/sandbox/core/patch-parser.js +248 -0
- package/dist/sandbox/core/path-map.d.ts +9 -0
- package/dist/sandbox/core/path-map.js +73 -0
- package/dist/sandbox/core/project-data-storage.d.ts +42 -0
- package/dist/sandbox/core/project-data-storage.js +167 -0
- package/dist/sandbox/core/read/binary.d.ts +4 -0
- package/dist/sandbox/core/read/binary.js +80 -0
- package/dist/sandbox/core/read/format.d.ts +38 -0
- package/dist/sandbox/core/read/format.js +85 -0
- package/dist/sandbox/core/read/index.d.ts +3 -0
- package/dist/sandbox/core/read/index.js +3 -0
- package/dist/sandbox/core/read/permissions.d.ts +7 -0
- package/dist/sandbox/core/read/permissions.js +13 -0
- package/dist/sandbox/core/session-manager.d.ts +29 -0
- package/dist/sandbox/core/session-manager.js +338 -0
- package/dist/sandbox/core/shell/config.d.ts +7 -0
- package/dist/sandbox/core/shell/config.js +82 -0
- package/dist/sandbox/core/shell/output.d.ts +35 -0
- package/dist/sandbox/core/shell/output.js +80 -0
- package/dist/sandbox/core/shell/parser.d.ts +7 -0
- package/dist/sandbox/core/shell/parser.js +122 -0
- package/dist/sandbox/core/shell/permissions.d.ts +13 -0
- package/dist/sandbox/core/shell/permissions.js +33 -0
- package/dist/sandbox/core/shell/workdir.d.ts +4 -0
- package/dist/sandbox/core/shell/workdir.js +19 -0
- package/dist/sandbox/core/stream-utils.d.ts +23 -0
- package/dist/sandbox/core/stream-utils.js +97 -0
- package/dist/sandbox/core/toast.d.ts +47 -0
- package/dist/sandbox/core/toast.js +73 -0
- package/dist/sandbox/core/types.d.ts +159 -0
- package/dist/sandbox/core/types.js +11 -0
- package/dist/sandbox/core/write/bom.d.ts +8 -0
- package/dist/sandbox/core/write/bom.js +15 -0
- package/dist/sandbox/core/write/config.d.ts +14 -0
- package/dist/sandbox/core/write/config.js +188 -0
- package/dist/sandbox/core/write/diagnostics.d.ts +19 -0
- package/dist/sandbox/core/write/diagnostics.js +120 -0
- package/dist/sandbox/core/write/diff.d.ts +7 -0
- package/dist/sandbox/core/write/diff.js +21 -0
- package/dist/sandbox/core/write/formatter.d.ts +16 -0
- package/dist/sandbox/core/write/formatter.js +51 -0
- package/dist/sandbox/core/write/index.d.ts +6 -0
- package/dist/sandbox/core/write/index.js +5 -0
- package/dist/sandbox/core/write/permissions.d.ts +13 -0
- package/dist/sandbox/core/write/permissions.js +19 -0
- package/dist/sandbox/core/write/pipeline.d.ts +48 -0
- package/dist/sandbox/core/write/pipeline.js +229 -0
- package/dist/sandbox/core/write/read-tracker.d.ts +13 -0
- package/dist/sandbox/core/write/read-tracker.js +30 -0
- package/dist/sandbox/git/host-git-manager.d.ts +40 -0
- package/dist/sandbox/git/host-git-manager.js +278 -0
- package/dist/sandbox/git/index.d.ts +5 -0
- package/dist/sandbox/git/index.js +5 -0
- package/dist/sandbox/git/sandbox-git-manager.d.ts +14 -0
- package/dist/sandbox/git/sandbox-git-manager.js +54 -0
- package/dist/sandbox/git/session-git-manager.d.ts +18 -0
- package/dist/sandbox/git/session-git-manager.js +85 -0
- package/dist/sandbox/index.d.ts +205 -0
- package/dist/sandbox/index.js +70 -0
- package/dist/sandbox/plugins/custom-tools.d.ts +203 -0
- package/dist/sandbox/plugins/custom-tools.js +15 -0
- package/dist/sandbox/plugins/session-events.d.ts +10 -0
- package/dist/sandbox/plugins/session-events.js +56 -0
- package/dist/sandbox/plugins/system-transform.d.ts +10 -0
- package/dist/sandbox/plugins/system-transform.js +23 -0
- package/dist/sandbox/tools/bash-output.d.ts +17 -0
- package/dist/sandbox/tools/bash-output.js +35 -0
- package/dist/sandbox/tools/bash-status.d.ts +13 -0
- package/dist/sandbox/tools/bash-status.js +29 -0
- package/dist/sandbox/tools/bash-stop.d.ts +13 -0
- package/dist/sandbox/tools/bash-stop.js +28 -0
- package/dist/sandbox/tools/bash.d.ts +26 -0
- package/dist/sandbox/tools/bash.js +120 -0
- package/dist/sandbox/tools/edit.d.ts +20 -0
- package/dist/sandbox/tools/edit.js +87 -0
- package/dist/sandbox/tools/get-preview-url.d.ts +17 -0
- package/dist/sandbox/tools/get-preview-url.js +16 -0
- package/dist/sandbox/tools/glob.d.ts +17 -0
- package/dist/sandbox/tools/glob.js +23 -0
- package/dist/sandbox/tools/grep.d.ts +17 -0
- package/dist/sandbox/tools/grep.js +23 -0
- package/dist/sandbox/tools/ls.d.ts +17 -0
- package/dist/sandbox/tools/ls.js +21 -0
- package/dist/sandbox/tools/lsp.d.ts +41 -0
- package/dist/sandbox/tools/lsp.js +198 -0
- package/dist/sandbox/tools/multiedit.d.ts +24 -0
- package/dist/sandbox/tools/multiedit.js +83 -0
- package/dist/sandbox/tools/patch.d.ts +14 -0
- package/dist/sandbox/tools/patch.js +260 -0
- package/dist/sandbox/tools/read.d.ts +22 -0
- package/dist/sandbox/tools/read.js +105 -0
- package/dist/sandbox/tools/write.d.ts +16 -0
- package/dist/sandbox/tools/write.js +27 -0
- package/dist/sandbox/tools.d.ts +200 -0
- package/dist/sandbox/tools.js +43 -0
- package/package.json +55 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { Sandbox } from '../core/types.js';
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
export declare class SessionGitManager {
|
|
8
|
+
private readonly sandboxGit;
|
|
9
|
+
private readonly hostGit;
|
|
10
|
+
private readonly sandbox;
|
|
11
|
+
private readonly repoPath;
|
|
12
|
+
private readonly worktree;
|
|
13
|
+
constructor(sandbox: Sandbox, repoPath: string, worktree: string, _branchNumber: number);
|
|
14
|
+
static allocateAndReserveBranchNumber(worktree: string, prefix?: string): number;
|
|
15
|
+
hasLocalRepo(): boolean;
|
|
16
|
+
initializeAndSync(pluginCtx?: PluginInput): Promise<void>;
|
|
17
|
+
autoCommitAndPull(pluginCtx?: PluginInput): Promise<boolean>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from '../core/logger.js';
|
|
6
|
+
import { toast } from '../core/toast.js';
|
|
7
|
+
import { LocalSandboxGitManager } from './sandbox-git-manager.js';
|
|
8
|
+
import { HostGitManager } from './host-git-manager.js';
|
|
9
|
+
export class SessionGitManager {
|
|
10
|
+
sandboxGit;
|
|
11
|
+
hostGit;
|
|
12
|
+
sandbox;
|
|
13
|
+
repoPath;
|
|
14
|
+
worktree;
|
|
15
|
+
constructor(sandbox, repoPath, worktree, _branchNumber) {
|
|
16
|
+
void _branchNumber;
|
|
17
|
+
this.sandbox = sandbox;
|
|
18
|
+
this.repoPath = repoPath;
|
|
19
|
+
this.worktree = worktree;
|
|
20
|
+
this.sandboxGit = new LocalSandboxGitManager(sandbox, repoPath);
|
|
21
|
+
this.hostGit = new HostGitManager();
|
|
22
|
+
}
|
|
23
|
+
static allocateAndReserveBranchNumber(worktree, prefix = 'opencode') {
|
|
24
|
+
return new HostGitManager().allocateAndReserveBranchNumber(worktree, prefix);
|
|
25
|
+
}
|
|
26
|
+
hasLocalRepo() {
|
|
27
|
+
return this.hostGit.hasRepo(this.worktree);
|
|
28
|
+
}
|
|
29
|
+
async initializeAndSync(pluginCtx) {
|
|
30
|
+
if (pluginCtx?.client?.tui) {
|
|
31
|
+
toast.initialize(pluginCtx.client.tui);
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
if (!this.hostGit.hasRepo(this.worktree)) {
|
|
35
|
+
await this.sandboxGit.ensureDirectory();
|
|
36
|
+
logger.warn('No local git repository found. Git syncing is disabled.');
|
|
37
|
+
toast.show({
|
|
38
|
+
title: 'Git syncing disabled',
|
|
39
|
+
message: 'No local git repository found. Git syncing is disabled for this session.',
|
|
40
|
+
variant: 'warning',
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await this.sandboxGit.ensureRepo();
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
toast.show({
|
|
48
|
+
title: 'Git sync error',
|
|
49
|
+
message: err?.message || 'Failed to initialize git repo.',
|
|
50
|
+
variant: 'error',
|
|
51
|
+
});
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async autoCommitAndPull(pluginCtx) {
|
|
56
|
+
if (pluginCtx?.client?.tui) {
|
|
57
|
+
toast.initialize(pluginCtx.client.tui);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
if (!this.hostGit.hasRepo(this.worktree)) {
|
|
61
|
+
logger.warn('No local git repository found. Git syncing is disabled.');
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
await this.sandboxGit.ensureRepo();
|
|
65
|
+
const hasChanges = await this.sandboxGit.autoCommit();
|
|
66
|
+
if (hasChanges) {
|
|
67
|
+
toast.show({
|
|
68
|
+
title: 'Changes committed',
|
|
69
|
+
message: 'Changes auto-committed in sandbox',
|
|
70
|
+
variant: 'success',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return hasChanges;
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
toast.show({
|
|
77
|
+
title: 'Commit failed',
|
|
78
|
+
message: err?.message || 'Failed to auto-commit.',
|
|
79
|
+
variant: 'error',
|
|
80
|
+
});
|
|
81
|
+
logger.error(`[idle/git] error sandboxId=${this.sandbox.id}: ${err}`);
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
6
|
+
export type { EventSessionDeleted, LogLevel, SandboxInfo, SessionInfo, ProjectSessionData } from './core/types.js';
|
|
7
|
+
declare function sandboxPlugin(ctx: PluginInput): Promise<{
|
|
8
|
+
tool: {
|
|
9
|
+
bash: {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {
|
|
12
|
+
command: import("zod").ZodString;
|
|
13
|
+
timeout: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
14
|
+
workdir: import("zod").ZodOptional<import("zod").ZodString>;
|
|
15
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
16
|
+
background: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
17
|
+
};
|
|
18
|
+
execute(args: {
|
|
19
|
+
command: string;
|
|
20
|
+
timeout?: number;
|
|
21
|
+
workdir?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
background?: boolean;
|
|
24
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
25
|
+
};
|
|
26
|
+
bash_status: {
|
|
27
|
+
description: string;
|
|
28
|
+
args: {
|
|
29
|
+
cmdId: import("zod").ZodString;
|
|
30
|
+
};
|
|
31
|
+
execute(args: {
|
|
32
|
+
cmdId: string;
|
|
33
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
34
|
+
};
|
|
35
|
+
bash_output: {
|
|
36
|
+
description: string;
|
|
37
|
+
args: {
|
|
38
|
+
cmdId: import("zod").ZodString;
|
|
39
|
+
maxBytes: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
40
|
+
maxLines: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
41
|
+
};
|
|
42
|
+
execute(args: {
|
|
43
|
+
cmdId: string;
|
|
44
|
+
maxBytes?: number;
|
|
45
|
+
maxLines?: number;
|
|
46
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
47
|
+
};
|
|
48
|
+
bash_stop: {
|
|
49
|
+
description: string;
|
|
50
|
+
args: {
|
|
51
|
+
cmdId: import("zod").ZodString;
|
|
52
|
+
};
|
|
53
|
+
execute(args: {
|
|
54
|
+
cmdId: string;
|
|
55
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
56
|
+
};
|
|
57
|
+
read: {
|
|
58
|
+
description: string;
|
|
59
|
+
args: {
|
|
60
|
+
filePath: import("zod").ZodString;
|
|
61
|
+
offset: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
62
|
+
limit: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
63
|
+
};
|
|
64
|
+
execute(args: {
|
|
65
|
+
filePath: string;
|
|
66
|
+
offset?: number;
|
|
67
|
+
limit?: number;
|
|
68
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
69
|
+
};
|
|
70
|
+
write: {
|
|
71
|
+
description: string;
|
|
72
|
+
args: {
|
|
73
|
+
filePath: import("zod").ZodString;
|
|
74
|
+
content: import("zod").ZodString;
|
|
75
|
+
};
|
|
76
|
+
execute(args: {
|
|
77
|
+
filePath: string;
|
|
78
|
+
content: string;
|
|
79
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
80
|
+
};
|
|
81
|
+
edit: {
|
|
82
|
+
description: string;
|
|
83
|
+
args: {
|
|
84
|
+
filePath: import("zod").ZodString;
|
|
85
|
+
oldString: import("zod").ZodString;
|
|
86
|
+
newString: import("zod").ZodString;
|
|
87
|
+
replaceAll: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
88
|
+
};
|
|
89
|
+
execute(args: {
|
|
90
|
+
filePath: string;
|
|
91
|
+
oldString: string;
|
|
92
|
+
newString: string;
|
|
93
|
+
replaceAll?: boolean;
|
|
94
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
95
|
+
};
|
|
96
|
+
multiedit: {
|
|
97
|
+
description: string;
|
|
98
|
+
args: {
|
|
99
|
+
filePath: import("zod").ZodString;
|
|
100
|
+
edits: import("zod").ZodArray<import("zod").ZodObject<{
|
|
101
|
+
oldString: import("zod").ZodString;
|
|
102
|
+
newString: import("zod").ZodString;
|
|
103
|
+
replaceAll: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
104
|
+
}, import("zod/v4/core").$strip>>;
|
|
105
|
+
};
|
|
106
|
+
execute(args: {
|
|
107
|
+
filePath: string;
|
|
108
|
+
edits: Array<{
|
|
109
|
+
oldString: string;
|
|
110
|
+
newString: string;
|
|
111
|
+
replaceAll?: boolean;
|
|
112
|
+
}>;
|
|
113
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
114
|
+
};
|
|
115
|
+
apply_patch: {
|
|
116
|
+
description: string;
|
|
117
|
+
args: {
|
|
118
|
+
patchText: import("zod").ZodString;
|
|
119
|
+
};
|
|
120
|
+
execute(args: {
|
|
121
|
+
patchText: string;
|
|
122
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
123
|
+
};
|
|
124
|
+
patch: {
|
|
125
|
+
description: string;
|
|
126
|
+
args: {
|
|
127
|
+
patchText: import("zod").ZodString;
|
|
128
|
+
};
|
|
129
|
+
execute(args: {
|
|
130
|
+
patchText: string;
|
|
131
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
132
|
+
};
|
|
133
|
+
ls: {
|
|
134
|
+
description: string;
|
|
135
|
+
args: {
|
|
136
|
+
dirPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
137
|
+
};
|
|
138
|
+
execute(args: {
|
|
139
|
+
dirPath?: string;
|
|
140
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
141
|
+
};
|
|
142
|
+
glob: {
|
|
143
|
+
description: string;
|
|
144
|
+
args: {
|
|
145
|
+
pattern: import("zod").ZodString;
|
|
146
|
+
};
|
|
147
|
+
execute(args: {
|
|
148
|
+
pattern: string;
|
|
149
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
150
|
+
};
|
|
151
|
+
grep: {
|
|
152
|
+
description: string;
|
|
153
|
+
args: {
|
|
154
|
+
pattern: import("zod").ZodString;
|
|
155
|
+
};
|
|
156
|
+
execute(args: {
|
|
157
|
+
pattern: string;
|
|
158
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
159
|
+
};
|
|
160
|
+
lsp: {
|
|
161
|
+
description: string;
|
|
162
|
+
args: {
|
|
163
|
+
operation: import("zod").ZodEnum<{
|
|
164
|
+
status: "status";
|
|
165
|
+
diagnostics: "diagnostics";
|
|
166
|
+
hover: "hover";
|
|
167
|
+
documentSymbol: "documentSymbol";
|
|
168
|
+
workspaceSymbol: "workspaceSymbol";
|
|
169
|
+
references: "references";
|
|
170
|
+
findReferences: "findReferences";
|
|
171
|
+
definition: "definition";
|
|
172
|
+
goToDefinition: "goToDefinition";
|
|
173
|
+
implementation: "implementation";
|
|
174
|
+
goToImplementation: "goToImplementation";
|
|
175
|
+
prepareCallHierarchy: "prepareCallHierarchy";
|
|
176
|
+
incomingCalls: "incomingCalls";
|
|
177
|
+
outgoingCalls: "outgoingCalls";
|
|
178
|
+
}>;
|
|
179
|
+
filePath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
180
|
+
line: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
181
|
+
character: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
182
|
+
query: import("zod").ZodOptional<import("zod").ZodString>;
|
|
183
|
+
};
|
|
184
|
+
execute(args: {
|
|
185
|
+
operation: "status" | "diagnostics" | "hover" | "documentSymbol" | "workspaceSymbol" | "references" | "findReferences" | "definition" | "goToDefinition" | "implementation" | "goToImplementation" | "prepareCallHierarchy" | "incomingCalls" | "outgoingCalls";
|
|
186
|
+
filePath?: string;
|
|
187
|
+
line?: number;
|
|
188
|
+
character?: number;
|
|
189
|
+
query?: string;
|
|
190
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
191
|
+
};
|
|
192
|
+
getPreviewURL: {
|
|
193
|
+
description: string;
|
|
194
|
+
args: {
|
|
195
|
+
port: import("zod").ZodNumber;
|
|
196
|
+
};
|
|
197
|
+
execute(args: {
|
|
198
|
+
port: number;
|
|
199
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
event: (args: any) => Promise<void>;
|
|
203
|
+
'experimental.chat.system.transform': (input: import("./core/types.js").ExperimentalChatSystemTransformInput, output: import("./core/types.js").ExperimentalChatSystemTransformOutput) => Promise<void>;
|
|
204
|
+
}>;
|
|
205
|
+
export default sandboxPlugin;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* OpenCode Plugin: Docker Sandbox Integration
|
|
7
|
+
*
|
|
8
|
+
* OpenCode plugins extend the AI coding assistant by adding custom tools, handling events,
|
|
9
|
+
* and modifying behavior. Plugins are TypeScript/JavaScript modules that export functions
|
|
10
|
+
* which return hooks for various lifecycle events.
|
|
11
|
+
*
|
|
12
|
+
* This plugin integrates Docker sandboxes with OpenCode, providing isolated development
|
|
13
|
+
* environments for each session. It adds custom tools for file operations, command execution,
|
|
14
|
+
* and search within sandboxes, and automatically cleans up resources when sessions end.
|
|
15
|
+
*
|
|
16
|
+
* Learn more: https://opencode.ai/docs/plugins/
|
|
17
|
+
*
|
|
18
|
+
* Docker Sandbox Integration Tools
|
|
19
|
+
*
|
|
20
|
+
* Requires:
|
|
21
|
+
* - Docker daemon accessible via socket
|
|
22
|
+
* - Environment: SANDBOX_IMAGE (optional, defaults to opencode-sandbox:latest)
|
|
23
|
+
*/
|
|
24
|
+
import { join } from 'path';
|
|
25
|
+
import { homedir } from 'os';
|
|
26
|
+
import { existsSync, readFileSync } from 'fs';
|
|
27
|
+
const xdgData = process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
|
|
28
|
+
import { setLogFilePath } from './core/logger.js';
|
|
29
|
+
import { logger } from './core/logger.js';
|
|
30
|
+
import { doctorCliHelper } from './core/cli-helper.js';
|
|
31
|
+
import { SandboxSessionManager } from './core/session-manager.js';
|
|
32
|
+
import { toast } from './core/toast.js';
|
|
33
|
+
import { customTools } from './plugins/custom-tools.js';
|
|
34
|
+
import { eventHandlers } from './plugins/session-events.js';
|
|
35
|
+
import { systemPromptTransform } from './plugins/system-transform.js';
|
|
36
|
+
const LOG_FILE = join(xdgData, 'opencode', 'log', 'sandbox.log');
|
|
37
|
+
const STORAGE_DIR = join(xdgData, 'opencode', 'storage', 'sandbox');
|
|
38
|
+
const REPO_PATH = '/home/sandbox/project';
|
|
39
|
+
setLogFilePath(LOG_FILE);
|
|
40
|
+
const sessionManager = new SandboxSessionManager('', STORAGE_DIR, REPO_PATH);
|
|
41
|
+
async function sandboxPlugin(ctx) {
|
|
42
|
+
toast.initialize(ctx.client?.tui);
|
|
43
|
+
const helper = doctorCliHelper();
|
|
44
|
+
if (helper.ok) {
|
|
45
|
+
logger.info(`OpenCode helper ready: ${helper.cliPath}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
logger.warn(`OpenCode helper unavailable at ${helper.cliPath}: ${helper.error || 'doctor failed'}`);
|
|
49
|
+
}
|
|
50
|
+
const projectDir = ctx.project.worktree;
|
|
51
|
+
const sandboxConfigPath = join(projectDir, '.opencode', 'sandbox.json');
|
|
52
|
+
if (existsSync(sandboxConfigPath)) {
|
|
53
|
+
try {
|
|
54
|
+
const raw = JSON.parse(readFileSync(sandboxConfigPath, 'utf-8'));
|
|
55
|
+
if (raw?.image) {
|
|
56
|
+
sessionManager.setImage(raw.image);
|
|
57
|
+
logger.info(`Using sandbox image from config: ${raw.image}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger.warn(`Failed to read sandbox config ${sandboxConfigPath}: ${error}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
tool: await customTools(ctx, sessionManager),
|
|
66
|
+
event: await eventHandlers(ctx, sessionManager, REPO_PATH),
|
|
67
|
+
'experimental.chat.system.transform': await systemPromptTransform(ctx, REPO_PATH),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export default sandboxPlugin;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
6
|
+
import type { SandboxSessionManager } from '../core/session-manager.js';
|
|
7
|
+
/**
|
|
8
|
+
* Custom tools for Docker sandbox: file ops, command execution, search.
|
|
9
|
+
*/
|
|
10
|
+
export declare function customTools(ctx: PluginInput, sessionManager: SandboxSessionManager): Promise<{
|
|
11
|
+
bash: {
|
|
12
|
+
description: string;
|
|
13
|
+
args: {
|
|
14
|
+
command: import("zod").ZodString;
|
|
15
|
+
timeout: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
16
|
+
workdir: import("zod").ZodOptional<import("zod").ZodString>;
|
|
17
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
18
|
+
background: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
19
|
+
};
|
|
20
|
+
execute(args: {
|
|
21
|
+
command: string;
|
|
22
|
+
timeout?: number;
|
|
23
|
+
workdir?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
background?: boolean;
|
|
26
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
27
|
+
};
|
|
28
|
+
bash_status: {
|
|
29
|
+
description: string;
|
|
30
|
+
args: {
|
|
31
|
+
cmdId: import("zod").ZodString;
|
|
32
|
+
};
|
|
33
|
+
execute(args: {
|
|
34
|
+
cmdId: string;
|
|
35
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
36
|
+
};
|
|
37
|
+
bash_output: {
|
|
38
|
+
description: string;
|
|
39
|
+
args: {
|
|
40
|
+
cmdId: import("zod").ZodString;
|
|
41
|
+
maxBytes: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
42
|
+
maxLines: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
43
|
+
};
|
|
44
|
+
execute(args: {
|
|
45
|
+
cmdId: string;
|
|
46
|
+
maxBytes?: number;
|
|
47
|
+
maxLines?: number;
|
|
48
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
49
|
+
};
|
|
50
|
+
bash_stop: {
|
|
51
|
+
description: string;
|
|
52
|
+
args: {
|
|
53
|
+
cmdId: import("zod").ZodString;
|
|
54
|
+
};
|
|
55
|
+
execute(args: {
|
|
56
|
+
cmdId: string;
|
|
57
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
58
|
+
};
|
|
59
|
+
read: {
|
|
60
|
+
description: string;
|
|
61
|
+
args: {
|
|
62
|
+
filePath: import("zod").ZodString;
|
|
63
|
+
offset: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
64
|
+
limit: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
65
|
+
};
|
|
66
|
+
execute(args: {
|
|
67
|
+
filePath: string;
|
|
68
|
+
offset?: number;
|
|
69
|
+
limit?: number;
|
|
70
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
71
|
+
};
|
|
72
|
+
write: {
|
|
73
|
+
description: string;
|
|
74
|
+
args: {
|
|
75
|
+
filePath: import("zod").ZodString;
|
|
76
|
+
content: import("zod").ZodString;
|
|
77
|
+
};
|
|
78
|
+
execute(args: {
|
|
79
|
+
filePath: string;
|
|
80
|
+
content: string;
|
|
81
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
82
|
+
};
|
|
83
|
+
edit: {
|
|
84
|
+
description: string;
|
|
85
|
+
args: {
|
|
86
|
+
filePath: import("zod").ZodString;
|
|
87
|
+
oldString: import("zod").ZodString;
|
|
88
|
+
newString: import("zod").ZodString;
|
|
89
|
+
replaceAll: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
90
|
+
};
|
|
91
|
+
execute(args: {
|
|
92
|
+
filePath: string;
|
|
93
|
+
oldString: string;
|
|
94
|
+
newString: string;
|
|
95
|
+
replaceAll?: boolean;
|
|
96
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
97
|
+
};
|
|
98
|
+
multiedit: {
|
|
99
|
+
description: string;
|
|
100
|
+
args: {
|
|
101
|
+
filePath: import("zod").ZodString;
|
|
102
|
+
edits: import("zod").ZodArray<import("zod").ZodObject<{
|
|
103
|
+
oldString: import("zod").ZodString;
|
|
104
|
+
newString: import("zod").ZodString;
|
|
105
|
+
replaceAll: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
106
|
+
}, import("zod/v4/core").$strip>>;
|
|
107
|
+
};
|
|
108
|
+
execute(args: {
|
|
109
|
+
filePath: string;
|
|
110
|
+
edits: Array<{
|
|
111
|
+
oldString: string;
|
|
112
|
+
newString: string;
|
|
113
|
+
replaceAll?: boolean;
|
|
114
|
+
}>;
|
|
115
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
116
|
+
};
|
|
117
|
+
apply_patch: {
|
|
118
|
+
description: string;
|
|
119
|
+
args: {
|
|
120
|
+
patchText: import("zod").ZodString;
|
|
121
|
+
};
|
|
122
|
+
execute(args: {
|
|
123
|
+
patchText: string;
|
|
124
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
125
|
+
};
|
|
126
|
+
patch: {
|
|
127
|
+
description: string;
|
|
128
|
+
args: {
|
|
129
|
+
patchText: import("zod").ZodString;
|
|
130
|
+
};
|
|
131
|
+
execute(args: {
|
|
132
|
+
patchText: string;
|
|
133
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
134
|
+
};
|
|
135
|
+
ls: {
|
|
136
|
+
description: string;
|
|
137
|
+
args: {
|
|
138
|
+
dirPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
139
|
+
};
|
|
140
|
+
execute(args: {
|
|
141
|
+
dirPath?: string;
|
|
142
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
143
|
+
};
|
|
144
|
+
glob: {
|
|
145
|
+
description: string;
|
|
146
|
+
args: {
|
|
147
|
+
pattern: import("zod").ZodString;
|
|
148
|
+
};
|
|
149
|
+
execute(args: {
|
|
150
|
+
pattern: string;
|
|
151
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
152
|
+
};
|
|
153
|
+
grep: {
|
|
154
|
+
description: string;
|
|
155
|
+
args: {
|
|
156
|
+
pattern: import("zod").ZodString;
|
|
157
|
+
};
|
|
158
|
+
execute(args: {
|
|
159
|
+
pattern: string;
|
|
160
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
161
|
+
};
|
|
162
|
+
lsp: {
|
|
163
|
+
description: string;
|
|
164
|
+
args: {
|
|
165
|
+
operation: import("zod").ZodEnum<{
|
|
166
|
+
status: "status";
|
|
167
|
+
diagnostics: "diagnostics";
|
|
168
|
+
hover: "hover";
|
|
169
|
+
documentSymbol: "documentSymbol";
|
|
170
|
+
workspaceSymbol: "workspaceSymbol";
|
|
171
|
+
references: "references";
|
|
172
|
+
findReferences: "findReferences";
|
|
173
|
+
definition: "definition";
|
|
174
|
+
goToDefinition: "goToDefinition";
|
|
175
|
+
implementation: "implementation";
|
|
176
|
+
goToImplementation: "goToImplementation";
|
|
177
|
+
prepareCallHierarchy: "prepareCallHierarchy";
|
|
178
|
+
incomingCalls: "incomingCalls";
|
|
179
|
+
outgoingCalls: "outgoingCalls";
|
|
180
|
+
}>;
|
|
181
|
+
filePath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
182
|
+
line: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
183
|
+
character: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
184
|
+
query: import("zod").ZodOptional<import("zod").ZodString>;
|
|
185
|
+
};
|
|
186
|
+
execute(args: {
|
|
187
|
+
operation: "status" | "diagnostics" | "hover" | "documentSymbol" | "workspaceSymbol" | "references" | "findReferences" | "definition" | "goToDefinition" | "implementation" | "goToImplementation" | "prepareCallHierarchy" | "incomingCalls" | "outgoingCalls";
|
|
188
|
+
filePath?: string;
|
|
189
|
+
line?: number;
|
|
190
|
+
character?: number;
|
|
191
|
+
query?: string;
|
|
192
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
193
|
+
};
|
|
194
|
+
getPreviewURL: {
|
|
195
|
+
description: string;
|
|
196
|
+
args: {
|
|
197
|
+
port: import("zod").ZodNumber;
|
|
198
|
+
};
|
|
199
|
+
execute(args: {
|
|
200
|
+
port: number;
|
|
201
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
202
|
+
};
|
|
203
|
+
}>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { createSandboxTools } from '../tools.js';
|
|
6
|
+
import { logger } from '../core/logger.js';
|
|
7
|
+
/**
|
|
8
|
+
* Custom tools for Docker sandbox: file ops, command execution, search.
|
|
9
|
+
*/
|
|
10
|
+
export async function customTools(ctx, sessionManager) {
|
|
11
|
+
logger.info('OpenCode started with Docker sandbox plugin');
|
|
12
|
+
const projectId = ctx.project.id;
|
|
13
|
+
const worktree = ctx.project.worktree;
|
|
14
|
+
return createSandboxTools(sessionManager, projectId, worktree, ctx);
|
|
15
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
6
|
+
import type { SandboxSessionManager } from '../core/session-manager.js';
|
|
7
|
+
/**
|
|
8
|
+
* Handles OpenCode session events.
|
|
9
|
+
*/
|
|
10
|
+
export declare function eventHandlers(ctx: PluginInput, sessionManager: SandboxSessionManager, repoPath: string): Promise<(args: any) => Promise<void>>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { SessionGitManager } from '../git/session-git-manager.js';
|
|
6
|
+
import { EVENT_TYPE_SESSION_DELETED, EVENT_TYPE_SESSION_IDLE } from '../core/types.js';
|
|
7
|
+
import { toast } from '../core/toast.js';
|
|
8
|
+
import { logger } from '../core/logger.js';
|
|
9
|
+
import { hostLspManager } from '../core/lsp/index.js';
|
|
10
|
+
import { readRegistry } from '../core/write/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Handles OpenCode session events.
|
|
13
|
+
*/
|
|
14
|
+
export async function eventHandlers(ctx, sessionManager, repoPath) {
|
|
15
|
+
const projectId = ctx.project.id;
|
|
16
|
+
const worktree = ctx.project.worktree;
|
|
17
|
+
return async (args) => {
|
|
18
|
+
const event = args.event;
|
|
19
|
+
if (event.type === EVENT_TYPE_SESSION_DELETED) {
|
|
20
|
+
const sessionId = event.properties.info.id;
|
|
21
|
+
try {
|
|
22
|
+
await hostLspManager
|
|
23
|
+
.shutdownSession(sessionId)
|
|
24
|
+
.catch((err) => logger.warn(`Host LSP shutdown failed for session ${sessionId}: ${err}`));
|
|
25
|
+
readRegistry.clearSession(sessionId);
|
|
26
|
+
sessionManager.deleteSandboxSync(sessionId, projectId);
|
|
27
|
+
logger.info(`Session deleted event handled synchronously for ${sessionId}`);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
logger.error(`Sync delete failed for session ${sessionId}: ${err}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (event.type === EVENT_TYPE_SESSION_IDLE) {
|
|
34
|
+
const sessionId = event.properties.sessionID;
|
|
35
|
+
const start = Date.now();
|
|
36
|
+
try {
|
|
37
|
+
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, ctx);
|
|
38
|
+
const branchNumber = sessionManager.getBranchNumberForSandbox(projectId, sandbox.id);
|
|
39
|
+
if (!branchNumber)
|
|
40
|
+
return;
|
|
41
|
+
const sessionGit = new SessionGitManager(sandbox, repoPath, worktree, branchNumber);
|
|
42
|
+
const didSync = await sessionGit.autoCommitAndPull(ctx);
|
|
43
|
+
logger.info(`[idle] done sessionId=${sessionId} sandboxId=${sandbox.id} synced=${didSync} in ${Date.now() - start}ms`);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
logger.error(`[idle] error sessionId=${sessionId} in ${Date.now() - start}ms: ${err}`);
|
|
47
|
+
toast.show({
|
|
48
|
+
title: 'Auto-commit error',
|
|
49
|
+
message: err?.message || 'Failed to auto-commit and pull.',
|
|
50
|
+
variant: 'error',
|
|
51
|
+
});
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
6
|
+
import type { ExperimentalChatSystemTransformInput, ExperimentalChatSystemTransformOutput } from '../core/types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Adds sandbox-specific instructions to the system prompt.
|
|
9
|
+
*/
|
|
10
|
+
export declare function systemPromptTransform(ctx: PluginInput, repoPath: string): Promise<(input: ExperimentalChatSystemTransformInput, output: ExperimentalChatSystemTransformOutput) => Promise<void>>;
|