@veris-ai/daytona-opencode 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/.opencode/plugin/daytona/core/logger.d.ts +15 -0
- package/.opencode/plugin/daytona/core/logger.js +65 -0
- package/.opencode/plugin/daytona/core/logger.js.map +1 -0
- package/.opencode/plugin/daytona/core/logger.ts +71 -0
- package/.opencode/plugin/daytona/core/project-data-storage.d.ts +63 -0
- package/.opencode/plugin/daytona/core/project-data-storage.js +213 -0
- package/.opencode/plugin/daytona/core/project-data-storage.js.map +1 -0
- package/.opencode/plugin/daytona/core/project-data-storage.ts +234 -0
- package/.opencode/plugin/daytona/core/session-manager.d.ts +74 -0
- package/.opencode/plugin/daytona/core/session-manager.js +441 -0
- package/.opencode/plugin/daytona/core/session-manager.js.map +1 -0
- package/.opencode/plugin/daytona/core/session-manager.ts +471 -0
- package/.opencode/plugin/daytona/core/toast.d.ts +47 -0
- package/.opencode/plugin/daytona/core/toast.js +70 -0
- package/.opencode/plugin/daytona/core/toast.js.map +1 -0
- package/.opencode/plugin/daytona/core/toast.ts +96 -0
- package/.opencode/plugin/daytona/core/types.d.ts +53 -0
- package/.opencode/plugin/daytona/core/types.js +12 -0
- package/.opencode/plugin/daytona/core/types.js.map +1 -0
- package/.opencode/plugin/daytona/core/types.ts +72 -0
- package/.opencode/plugin/daytona/git/host-git-manager.d.ts +58 -0
- package/.opencode/plugin/daytona/git/host-git-manager.js +342 -0
- package/.opencode/plugin/daytona/git/host-git-manager.js.map +1 -0
- package/.opencode/plugin/daytona/git/host-git-manager.ts +372 -0
- package/.opencode/plugin/daytona/git/index.d.ts +5 -0
- package/.opencode/plugin/daytona/git/index.js +6 -0
- package/.opencode/plugin/daytona/git/index.js.map +1 -0
- package/.opencode/plugin/daytona/git/index.ts +6 -0
- package/.opencode/plugin/daytona/git/sandbox-git-manager.d.ts +22 -0
- package/.opencode/plugin/daytona/git/sandbox-git-manager.js +80 -0
- package/.opencode/plugin/daytona/git/sandbox-git-manager.js.map +1 -0
- package/.opencode/plugin/daytona/git/sandbox-git-manager.ts +92 -0
- package/.opencode/plugin/daytona/git/session-git-manager.d.ts +54 -0
- package/.opencode/plugin/daytona/git/session-git-manager.js +184 -0
- package/.opencode/plugin/daytona/git/session-git-manager.js.map +1 -0
- package/.opencode/plugin/daytona/git/session-git-manager.ts +203 -0
- package/.opencode/plugin/daytona/index.d.ts +125 -0
- package/.opencode/plugin/daytona/index.js +60 -0
- package/.opencode/plugin/daytona/index.js.map +1 -0
- package/.opencode/plugin/daytona/index.ts +73 -0
- package/.opencode/plugin/daytona/plugins/custom-tools.d.ts +122 -0
- package/.opencode/plugin/daytona/plugins/custom-tools.js +18 -0
- package/.opencode/plugin/daytona/plugins/custom-tools.js.map +1 -0
- package/.opencode/plugin/daytona/plugins/custom-tools.ts +21 -0
- package/.opencode/plugin/daytona/plugins/session-events.d.ts +10 -0
- package/.opencode/plugin/daytona/plugins/session-events.js +63 -0
- package/.opencode/plugin/daytona/plugins/session-events.js.map +1 -0
- package/.opencode/plugin/daytona/plugins/session-events.ts +61 -0
- package/.opencode/plugin/daytona/plugins/system-transform.d.ts +10 -0
- package/.opencode/plugin/daytona/plugins/system-transform.js +38 -0
- package/.opencode/plugin/daytona/plugins/system-transform.js.map +1 -0
- package/.opencode/plugin/daytona/plugins/system-transform.ts +43 -0
- package/.opencode/plugin/daytona/tools/bash.d.ts +19 -0
- package/.opencode/plugin/daytona/tools/bash.js +42 -0
- package/.opencode/plugin/daytona/tools/bash.js.map +1 -0
- package/.opencode/plugin/daytona/tools/bash.ts +51 -0
- package/.opencode/plugin/daytona/tools/edit.d.ts +21 -0
- package/.opencode/plugin/daytona/tools/edit.js +33 -0
- package/.opencode/plugin/daytona/tools/edit.js.map +1 -0
- package/.opencode/plugin/daytona/tools/edit.ts +44 -0
- package/.opencode/plugin/daytona/tools/get-preview-url.d.ts +17 -0
- package/.opencode/plugin/daytona/tools/get-preview-url.js +17 -0
- package/.opencode/plugin/daytona/tools/get-preview-url.js.map +1 -0
- package/.opencode/plugin/daytona/tools/get-preview-url.ts +26 -0
- package/.opencode/plugin/daytona/tools/git-sync.d.ts +12 -0
- package/.opencode/plugin/daytona/tools/git-sync.js +26 -0
- package/.opencode/plugin/daytona/tools/git-sync.js.map +1 -0
- package/.opencode/plugin/daytona/tools/git-sync.ts +36 -0
- package/.opencode/plugin/daytona/tools/glob.d.ts +17 -0
- package/.opencode/plugin/daytona/tools/glob.js +21 -0
- package/.opencode/plugin/daytona/tools/glob.js.map +1 -0
- package/.opencode/plugin/daytona/tools/glob.ts +30 -0
- package/.opencode/plugin/daytona/tools/grep.d.ts +17 -0
- package/.opencode/plugin/daytona/tools/grep.js +29 -0
- package/.opencode/plugin/daytona/tools/grep.js.map +1 -0
- package/.opencode/plugin/daytona/tools/grep.ts +39 -0
- package/.opencode/plugin/daytona/tools/ls.d.ts +17 -0
- package/.opencode/plugin/daytona/tools/ls.js +22 -0
- package/.opencode/plugin/daytona/tools/ls.js.map +1 -0
- package/.opencode/plugin/daytona/tools/ls.ts +32 -0
- package/.opencode/plugin/daytona/tools/multiedit.d.ts +25 -0
- package/.opencode/plugin/daytona/tools/multiedit.js +37 -0
- package/.opencode/plugin/daytona/tools/multiedit.js.map +1 -0
- package/.opencode/plugin/daytona/tools/multiedit.ts +54 -0
- package/.opencode/plugin/daytona/tools/read.d.ts +17 -0
- package/.opencode/plugin/daytona/tools/read.js +18 -0
- package/.opencode/plugin/daytona/tools/read.js.map +1 -0
- package/.opencode/plugin/daytona/tools/read.ts +27 -0
- package/.opencode/plugin/daytona/tools/veris-receipt.d.ts +26 -0
- package/.opencode/plugin/daytona/tools/veris-receipt.js +76 -0
- package/.opencode/plugin/daytona/tools/veris-receipt.js.map +1 -0
- package/.opencode/plugin/daytona/tools/veris-receipt.ts +103 -0
- package/.opencode/plugin/daytona/tools/write.d.ts +19 -0
- package/.opencode/plugin/daytona/tools/write.js +18 -0
- package/.opencode/plugin/daytona/tools/write.js.map +1 -0
- package/.opencode/plugin/daytona/tools/write.ts +27 -0
- package/.opencode/plugin/daytona/tools.d.ts +119 -0
- package/.opencode/plugin/daytona/tools.js +35 -0
- package/.opencode/plugin/daytona/tools.js.map +1 -0
- package/.opencode/plugin/daytona/tools.ts +45 -0
- package/.opencode/plugin/index.d.ts +9 -0
- package/.opencode/plugin/index.js +10 -0
- package/.opencode/plugin/index.js.map +1 -0
- package/.opencode/plugin/index.ts +11 -0
- package/README.md +87 -0
- package/package.json +52 -0
|
@@ -0,0 +1,122 @@
|
|
|
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 { DaytonaSessionManager } from '../core/session-manager';
|
|
7
|
+
/**
|
|
8
|
+
* Custom tools for Daytona sandbox: file ops, command execution, search.
|
|
9
|
+
*/
|
|
10
|
+
export declare function customTools(ctx: PluginInput, sessionManager: DaytonaSessionManager): Promise<{
|
|
11
|
+
bash: {
|
|
12
|
+
description: string;
|
|
13
|
+
args: {
|
|
14
|
+
command: import("zod").ZodString;
|
|
15
|
+
background: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
16
|
+
};
|
|
17
|
+
execute(args: {
|
|
18
|
+
command: string;
|
|
19
|
+
background?: boolean;
|
|
20
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
21
|
+
};
|
|
22
|
+
read: {
|
|
23
|
+
description: string;
|
|
24
|
+
args: {
|
|
25
|
+
filePath: import("zod").ZodString;
|
|
26
|
+
};
|
|
27
|
+
execute(args: {
|
|
28
|
+
filePath: string;
|
|
29
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
30
|
+
};
|
|
31
|
+
write: {
|
|
32
|
+
description: string;
|
|
33
|
+
args: {
|
|
34
|
+
filePath: import("zod").ZodString;
|
|
35
|
+
content: import("zod").ZodString;
|
|
36
|
+
};
|
|
37
|
+
execute(args: {
|
|
38
|
+
filePath: string;
|
|
39
|
+
content: string;
|
|
40
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
41
|
+
};
|
|
42
|
+
edit: {
|
|
43
|
+
description: string;
|
|
44
|
+
args: {
|
|
45
|
+
filePath: import("zod").ZodString;
|
|
46
|
+
oldString: import("zod").ZodString;
|
|
47
|
+
newString: import("zod").ZodString;
|
|
48
|
+
};
|
|
49
|
+
execute(args: {
|
|
50
|
+
filePath: string;
|
|
51
|
+
oldString: string;
|
|
52
|
+
newString: string;
|
|
53
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
54
|
+
};
|
|
55
|
+
multiedit: {
|
|
56
|
+
description: string;
|
|
57
|
+
args: {
|
|
58
|
+
filePath: import("zod").ZodString;
|
|
59
|
+
edits: import("zod").ZodArray<import("zod").ZodObject<{
|
|
60
|
+
oldString: import("zod").ZodString;
|
|
61
|
+
newString: import("zod").ZodString;
|
|
62
|
+
}, import("zod/v4/core").$strip>>;
|
|
63
|
+
};
|
|
64
|
+
execute(args: {
|
|
65
|
+
filePath: string;
|
|
66
|
+
edits: Array<{
|
|
67
|
+
oldString: string;
|
|
68
|
+
newString: string;
|
|
69
|
+
}>;
|
|
70
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
71
|
+
};
|
|
72
|
+
ls: {
|
|
73
|
+
description: string;
|
|
74
|
+
args: {
|
|
75
|
+
dirPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
76
|
+
};
|
|
77
|
+
execute(args: {
|
|
78
|
+
dirPath?: string;
|
|
79
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
80
|
+
};
|
|
81
|
+
glob: {
|
|
82
|
+
description: string;
|
|
83
|
+
args: {
|
|
84
|
+
pattern: import("zod").ZodString;
|
|
85
|
+
};
|
|
86
|
+
execute(args: {
|
|
87
|
+
pattern: string;
|
|
88
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
89
|
+
};
|
|
90
|
+
grep: {
|
|
91
|
+
description: string;
|
|
92
|
+
args: {
|
|
93
|
+
pattern: import("zod").ZodString;
|
|
94
|
+
};
|
|
95
|
+
execute(args: {
|
|
96
|
+
pattern: string;
|
|
97
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
98
|
+
};
|
|
99
|
+
getPreviewURL: {
|
|
100
|
+
description: string;
|
|
101
|
+
args: {
|
|
102
|
+
port: import("zod").ZodNumber;
|
|
103
|
+
};
|
|
104
|
+
execute(args: {
|
|
105
|
+
port: number;
|
|
106
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
107
|
+
};
|
|
108
|
+
gitSync: {
|
|
109
|
+
description: string;
|
|
110
|
+
args: {};
|
|
111
|
+
execute(_args: {}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
112
|
+
};
|
|
113
|
+
verisReceipt: {
|
|
114
|
+
description: string;
|
|
115
|
+
args: {
|
|
116
|
+
service: import("zod").ZodOptional<import("zod").ZodString>;
|
|
117
|
+
};
|
|
118
|
+
execute(args: {
|
|
119
|
+
service?: string;
|
|
120
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
121
|
+
};
|
|
122
|
+
}>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { createDaytonaTools } from '../tools';
|
|
6
|
+
import { logger } from '../core/logger';
|
|
7
|
+
/**
|
|
8
|
+
* Custom tools for Daytona sandbox: file ops, command execution, search.
|
|
9
|
+
*/
|
|
10
|
+
export async function customTools(ctx, sessionManager) {
|
|
11
|
+
logger.info('OpenCode started with Daytona plugin');
|
|
12
|
+
const projectId = ctx.project.id;
|
|
13
|
+
// Active worktree (not ctx.project.worktree, which is the first-seen checkout persisted
|
|
14
|
+
// per project); see the matching comment in plugins/session-events.ts.
|
|
15
|
+
const worktree = ctx.worktree;
|
|
16
|
+
return createDaytonaTools(sessionManager, projectId, worktree, ctx);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=custom-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-tools.js","sourceRoot":"","sources":["custom-tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAGvC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAgB,EAAE,cAAqC;IACvF,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IACnD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IAChC,wFAAwF;IACxF,uEAAuE;IACvE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;IAC7B,OAAO,kBAAkB,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;AACrE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
7
|
+
import { createDaytonaTools } from '../tools'
|
|
8
|
+
import { logger } from '../core/logger'
|
|
9
|
+
import type { DaytonaSessionManager } from '../core/session-manager'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Custom tools for Daytona sandbox: file ops, command execution, search.
|
|
13
|
+
*/
|
|
14
|
+
export async function customTools(ctx: PluginInput, sessionManager: DaytonaSessionManager) {
|
|
15
|
+
logger.info('OpenCode started with Daytona plugin')
|
|
16
|
+
const projectId = ctx.project.id
|
|
17
|
+
// Active worktree (not ctx.project.worktree, which is the first-seen checkout persisted
|
|
18
|
+
// per project); see the matching comment in plugins/session-events.ts.
|
|
19
|
+
const worktree = ctx.worktree
|
|
20
|
+
return createDaytonaTools(sessionManager, projectId, worktree, ctx)
|
|
21
|
+
}
|
|
@@ -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 { DaytonaSessionManager } from '../core/session-manager';
|
|
7
|
+
/**
|
|
8
|
+
* Handles OpenCode session events.
|
|
9
|
+
*/
|
|
10
|
+
export declare function eventHandlers(ctx: PluginInput, sessionManager: DaytonaSessionManager, repoPath: string): Promise<(args: any) => Promise<void>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { SessionGitManager } from '../git/session-git-manager';
|
|
6
|
+
import { EVENT_TYPE_SESSION_DELETED, EVENT_TYPE_SESSION_IDLE } from '../core/types';
|
|
7
|
+
import { toast } from '../core/toast';
|
|
8
|
+
import { logger } from '../core/logger';
|
|
9
|
+
/**
|
|
10
|
+
* Handles OpenCode session events.
|
|
11
|
+
*/
|
|
12
|
+
export async function eventHandlers(ctx, sessionManager, repoPath) {
|
|
13
|
+
const projectId = ctx.project.id;
|
|
14
|
+
// Use the ACTIVE worktree, not ctx.project.worktree: the project worktree is persisted
|
|
15
|
+
// the first time a project is opened and never updated, so in linked-worktree setups
|
|
16
|
+
// (`git worktree add`) it can point at a different checkout than the one this OpenCode
|
|
17
|
+
// instance is running in. Git syncs must land in the active checkout.
|
|
18
|
+
const worktree = ctx.worktree;
|
|
19
|
+
return async (args) => {
|
|
20
|
+
const event = args.event;
|
|
21
|
+
if (event.type === EVENT_TYPE_SESSION_DELETED) {
|
|
22
|
+
const sessionId = event.properties.info.id;
|
|
23
|
+
try {
|
|
24
|
+
const deleted = await sessionManager.deleteSandbox(sessionId, projectId);
|
|
25
|
+
if (deleted) {
|
|
26
|
+
toast.show({ title: 'Session deleted', message: 'Sandbox deleted successfully.', variant: 'success' });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
toast.show({ title: 'Delete failed', message: err?.message || 'Failed to delete sandbox.', variant: 'error' });
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else if (event.type === EVENT_TYPE_SESSION_IDLE) {
|
|
35
|
+
const sessionId = event.properties.sessionID;
|
|
36
|
+
const start = Date.now();
|
|
37
|
+
try {
|
|
38
|
+
// The WHOLE pipeline is enqueued (synchronously, before any await) so that a
|
|
39
|
+
// dispose() or delete arriving while the sandbox is still being resolved cannot
|
|
40
|
+
// observe an empty queue and proceed mid-operation.
|
|
41
|
+
const didSync = await SessionGitManager.enqueueSessionSync(sessionId, async () => {
|
|
42
|
+
// Re-checked inside the queue entry: a deletion may have completed while this
|
|
43
|
+
// callback waited its turn, and syncing must not resurrect the sandbox.
|
|
44
|
+
if (sessionManager.isSessionDeleting(sessionId))
|
|
45
|
+
return false;
|
|
46
|
+
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, ctx);
|
|
47
|
+
const branchNumber = sessionManager.getBranchNumberForSandbox(projectId, sandbox.id);
|
|
48
|
+
if (!branchNumber)
|
|
49
|
+
return false;
|
|
50
|
+
const sessionGit = new SessionGitManager(sandbox, repoPath, worktree, branchNumber);
|
|
51
|
+
return sessionGit.autoCommitAndPull(ctx);
|
|
52
|
+
});
|
|
53
|
+
logger.info(`[idle] done sessionId=${sessionId} synced=${didSync} in ${Date.now() - start}ms`);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
// autoCommitAndPull already shows a toast; only log here to avoid a duplicate
|
|
57
|
+
// error toast and noisy propagation out of the idle event hook.
|
|
58
|
+
logger.error(`[idle] error sessionId=${sessionId} in ${Date.now() - start}ms: ${err}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=session-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-events.js","sourceRoot":"","sources":["session-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,0BAA0B,EAAE,uBAAuB,EAA4B,MAAM,eAAe,CAAA;AAC7G,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAGvC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAgB,EAAE,cAAqC,EAAE,QAAgB;IAC3G,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAA;IAChC,uFAAuF;IACvF,qFAAqF;IACrF,uFAAuF;IACvF,sEAAsE;IACtE,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;IAC7B,OAAO,KAAK,EAAE,IAAS,EAAE,EAAE;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,IAAI,KAAK,CAAC,IAAI,KAAK,0BAA0B,EAAE,CAAC;YAC9C,MAAM,SAAS,GAAI,KAA6B,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAA;YACnE,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;gBACxE,IAAI,OAAO,EAAE,CAAC;oBACZ,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,+BAA+B,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAA;gBACxG,CAAC;YACH,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,2BAA2B,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;gBAC9G,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;YAClD,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAA;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACxB,IAAI,CAAC;gBACH,6EAA6E;gBAC7E,gFAAgF;gBAChF,oDAAoD;gBACpD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;oBAC/E,8EAA8E;oBAC9E,wEAAwE;oBACxE,IAAI,cAAc,CAAC,iBAAiB,CAAC,SAAS,CAAC;wBAAE,OAAO,KAAK,CAAA;oBAC7D,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAA;oBACpF,MAAM,YAAY,GAAG,cAAc,CAAC,yBAAyB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;oBACpF,IAAI,CAAC,YAAY;wBAAE,OAAO,KAAK,CAAA;oBAC/B,MAAM,UAAU,GAAG,IAAI,iBAAiB,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAA;oBACnF,OAAO,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAA;gBAC1C,CAAC,CAAC,CAAA;gBACF,MAAM,CAAC,IAAI,CAAC,yBAAyB,SAAS,WAAW,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,CAAA;YAChG,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,8EAA8E;gBAC9E,gEAAgE;gBAChE,MAAM,CAAC,KAAK,CAAC,0BAA0B,SAAS,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,EAAE,CAAC,CAAA;YACxF,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
7
|
+
import { SessionGitManager } from '../git/session-git-manager'
|
|
8
|
+
import { EVENT_TYPE_SESSION_DELETED, EVENT_TYPE_SESSION_IDLE, type EventSessionDeleted } from '../core/types'
|
|
9
|
+
import { toast } from '../core/toast'
|
|
10
|
+
import { logger } from '../core/logger'
|
|
11
|
+
import type { DaytonaSessionManager } from '../core/session-manager'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Handles OpenCode session events.
|
|
15
|
+
*/
|
|
16
|
+
export async function eventHandlers(ctx: PluginInput, sessionManager: DaytonaSessionManager, repoPath: string) {
|
|
17
|
+
const projectId = ctx.project.id
|
|
18
|
+
// Use the ACTIVE worktree, not ctx.project.worktree: the project worktree is persisted
|
|
19
|
+
// the first time a project is opened and never updated, so in linked-worktree setups
|
|
20
|
+
// (`git worktree add`) it can point at a different checkout than the one this OpenCode
|
|
21
|
+
// instance is running in. Git syncs must land in the active checkout.
|
|
22
|
+
const worktree = ctx.worktree
|
|
23
|
+
return async (args: any) => {
|
|
24
|
+
const event = args.event
|
|
25
|
+
if (event.type === EVENT_TYPE_SESSION_DELETED) {
|
|
26
|
+
const sessionId = (event as EventSessionDeleted).properties.info.id
|
|
27
|
+
try {
|
|
28
|
+
const deleted = await sessionManager.deleteSandbox(sessionId, projectId)
|
|
29
|
+
if (deleted) {
|
|
30
|
+
toast.show({ title: 'Session deleted', message: 'Sandbox deleted successfully.', variant: 'success' })
|
|
31
|
+
}
|
|
32
|
+
} catch (err: any) {
|
|
33
|
+
toast.show({ title: 'Delete failed', message: err?.message || 'Failed to delete sandbox.', variant: 'error' })
|
|
34
|
+
throw err
|
|
35
|
+
}
|
|
36
|
+
} else if (event.type === EVENT_TYPE_SESSION_IDLE) {
|
|
37
|
+
const sessionId = event.properties.sessionID
|
|
38
|
+
const start = Date.now()
|
|
39
|
+
try {
|
|
40
|
+
// The WHOLE pipeline is enqueued (synchronously, before any await) so that a
|
|
41
|
+
// dispose() or delete arriving while the sandbox is still being resolved cannot
|
|
42
|
+
// observe an empty queue and proceed mid-operation.
|
|
43
|
+
const didSync = await SessionGitManager.enqueueSessionSync(sessionId, async () => {
|
|
44
|
+
// Re-checked inside the queue entry: a deletion may have completed while this
|
|
45
|
+
// callback waited its turn, and syncing must not resurrect the sandbox.
|
|
46
|
+
if (sessionManager.isSessionDeleting(sessionId)) return false
|
|
47
|
+
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, ctx)
|
|
48
|
+
const branchNumber = sessionManager.getBranchNumberForSandbox(projectId, sandbox.id)
|
|
49
|
+
if (!branchNumber) return false
|
|
50
|
+
const sessionGit = new SessionGitManager(sandbox, repoPath, worktree, branchNumber)
|
|
51
|
+
return sessionGit.autoCommitAndPull(ctx)
|
|
52
|
+
})
|
|
53
|
+
logger.info(`[idle] done sessionId=${sessionId} synced=${didSync} in ${Date.now() - start}ms`)
|
|
54
|
+
} catch (err: any) {
|
|
55
|
+
// autoCommitAndPull already shows a toast; only log here to avoid a duplicate
|
|
56
|
+
// error toast and noisy propagation out of the idle event hook.
|
|
57
|
+
logger.error(`[idle] error sessionId=${sessionId} in ${Date.now() - start}ms: ${err}`)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -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';
|
|
7
|
+
/**
|
|
8
|
+
* Adds Daytona-specific instructions to the system prompt.
|
|
9
|
+
*/
|
|
10
|
+
export declare function systemPromptTransform(ctx: PluginInput, repoPath: string): Promise<(input: ExperimentalChatSystemTransformInput, output: ExperimentalChatSystemTransformOutput) => Promise<void>>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Adds Daytona-specific instructions to the system prompt.
|
|
7
|
+
*/
|
|
8
|
+
export async function systemPromptTransform(ctx, repoPath) {
|
|
9
|
+
return async (input, output) => {
|
|
10
|
+
output.system.push([
|
|
11
|
+
'## Daytona Sandbox Integration',
|
|
12
|
+
'This session is integrated with a Daytona sandbox.',
|
|
13
|
+
`The main project repository is located at: ${repoPath}.`,
|
|
14
|
+
'Bash commands will run in this directory.',
|
|
15
|
+
'Put all projects in the project directory. Do NOT try to use the current working directory of the host system.',
|
|
16
|
+
"When executing long-running commands, use the 'background' option to run them asynchronously.",
|
|
17
|
+
'Before showing a preview URL, ensure the server is running in the sandbox on that port.',
|
|
18
|
+
'When the user asks to sync, hand off, or finalize changes, run the gitSync tool and report its result.',
|
|
19
|
+
'',
|
|
20
|
+
'## Veris Twin',
|
|
21
|
+
"This sandbox's outbound calls to external vendor APIs are answered by a Veris twin:",
|
|
22
|
+
'a stateful fake that speaks the real protocol at the real hostname. Code under test',
|
|
23
|
+
'is unmodified — production hostnames, production credentials, production client',
|
|
24
|
+
'libraries — and nothing you run here reaches the real vendor. Hosts the twin does',
|
|
25
|
+
'not answer for are BLOCKED, not silently forwarded, so a connection error to an',
|
|
26
|
+
'external API is information: that dependency is not part of this environment.',
|
|
27
|
+
'',
|
|
28
|
+
'A passing run proves nothing on its own. A test suite that skipped its integration',
|
|
29
|
+
'and a test suite that exercised it look identical from inside the sandbox, and so',
|
|
30
|
+
'does a call you believe you made but did not. Only the receipt distinguishes them.',
|
|
31
|
+
'So: after any change meant to reach an external API, run the verisReceipt tool and',
|
|
32
|
+
'read what the twin actually received. If the receipt is empty, the change does not',
|
|
33
|
+
'work yet — report that, do not report success. Cite the receipt when you claim an',
|
|
34
|
+
'integration works.',
|
|
35
|
+
].join('\n'));
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=system-transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-transform.js","sourceRoot":"","sources":["system-transform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,GAAgB,EAAE,QAAgB;IAC5E,OAAO,KAAK,EAAE,KAA2C,EAAE,MAA6C,EAAE,EAAE;QAC1G,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB;YACE,gCAAgC;YAChC,oDAAoD;YACpD,8CAA8C,QAAQ,GAAG;YACzD,2CAA2C;YAC3C,gHAAgH;YAChH,+FAA+F;YAC/F,yFAAyF;YACzF,wGAAwG;YACxG,EAAE;YACF,eAAe;YACf,qFAAqF;YACrF,qFAAqF;YACrF,iFAAiF;YACjF,mFAAmF;YACnF,iFAAiF;YACjF,+EAA+E;YAC/E,EAAE;YACF,oFAAoF;YACpF,mFAAmF;YACnF,oFAAoF;YACpF,oFAAoF;YACpF,oFAAoF;YACpF,mFAAmF;YACnF,oBAAoB;SACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;IACH,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
7
|
+
import type { ExperimentalChatSystemTransformInput, ExperimentalChatSystemTransformOutput } from '../core/types'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Adds Daytona-specific instructions to the system prompt.
|
|
11
|
+
*/
|
|
12
|
+
export async function systemPromptTransform(ctx: PluginInput, repoPath: string) {
|
|
13
|
+
return async (input: ExperimentalChatSystemTransformInput, output: ExperimentalChatSystemTransformOutput) => {
|
|
14
|
+
output.system.push(
|
|
15
|
+
[
|
|
16
|
+
'## Daytona Sandbox Integration',
|
|
17
|
+
'This session is integrated with a Daytona sandbox.',
|
|
18
|
+
`The main project repository is located at: ${repoPath}.`,
|
|
19
|
+
'Bash commands will run in this directory.',
|
|
20
|
+
'Put all projects in the project directory. Do NOT try to use the current working directory of the host system.',
|
|
21
|
+
"When executing long-running commands, use the 'background' option to run them asynchronously.",
|
|
22
|
+
'Before showing a preview URL, ensure the server is running in the sandbox on that port.',
|
|
23
|
+
'When the user asks to sync, hand off, or finalize changes, run the gitSync tool and report its result.',
|
|
24
|
+
'',
|
|
25
|
+
'## Veris Twin',
|
|
26
|
+
"This sandbox's outbound calls to external vendor APIs are answered by a Veris twin:",
|
|
27
|
+
'a stateful fake that speaks the real protocol at the real hostname. Code under test',
|
|
28
|
+
'is unmodified — production hostnames, production credentials, production client',
|
|
29
|
+
'libraries — and nothing you run here reaches the real vendor. Hosts the twin does',
|
|
30
|
+
'not answer for are BLOCKED, not silently forwarded, so a connection error to an',
|
|
31
|
+
'external API is information: that dependency is not part of this environment.',
|
|
32
|
+
'',
|
|
33
|
+
'A passing run proves nothing on its own. A test suite that skipped its integration',
|
|
34
|
+
'and a test suite that exercised it look identical from inside the sandbox, and so',
|
|
35
|
+
'does a call you believe you made but did not. Only the receipt distinguishes them.',
|
|
36
|
+
'So: after any change meant to reach an external API, run the verisReceipt tool and',
|
|
37
|
+
'read what the twin actually received. If the receipt is empty, the change does not',
|
|
38
|
+
'work yet — report that, do not report success. Cite the receipt when you claim an',
|
|
39
|
+
'integration works.',
|
|
40
|
+
].join('\n'),
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import type { DaytonaSessionManager } from '../core/session-manager';
|
|
9
|
+
export declare const bashTool: (sessionManager: DaytonaSessionManager, projectId: string, worktree: string, pluginCtx: PluginInput, repoPath: string) => {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {
|
|
12
|
+
command: z.ZodString;
|
|
13
|
+
background: z.ZodOptional<z.ZodBoolean>;
|
|
14
|
+
};
|
|
15
|
+
execute(args: {
|
|
16
|
+
command: string;
|
|
17
|
+
background?: boolean;
|
|
18
|
+
}, ctx: ToolContext): Promise<string>;
|
|
19
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { DaytonaNotFoundError } from '@daytona/sdk';
|
|
7
|
+
export const bashTool = (sessionManager, projectId, worktree, pluginCtx, repoPath) => ({
|
|
8
|
+
description: 'Executes shell commands in a Daytona sandbox',
|
|
9
|
+
args: {
|
|
10
|
+
command: z.string(),
|
|
11
|
+
background: z.boolean().optional(),
|
|
12
|
+
},
|
|
13
|
+
async execute(args, ctx) {
|
|
14
|
+
const sessionId = ctx.sessionID;
|
|
15
|
+
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, pluginCtx);
|
|
16
|
+
if (args.background) {
|
|
17
|
+
const execSessionId = `exec-session-${sessionId}`;
|
|
18
|
+
try {
|
|
19
|
+
await sandbox.process.getSession(execSessionId);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (!(err instanceof DaytonaNotFoundError)) {
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
await sandbox.process.createSession(execSessionId);
|
|
26
|
+
}
|
|
27
|
+
await sandbox.process.executeSessionCommand(execSessionId, {
|
|
28
|
+
command: `cd ${repoPath}`,
|
|
29
|
+
});
|
|
30
|
+
const result = await sandbox.process.executeSessionCommand(execSessionId, {
|
|
31
|
+
command: args.command,
|
|
32
|
+
runAsync: true,
|
|
33
|
+
});
|
|
34
|
+
return `Command started in background (cmdId: ${result.cmdId})`;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const result = await sandbox.process.executeCommand(args.command, repoPath);
|
|
38
|
+
return `Exit code: ${result.exitCode}\n${result.result}`;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["bash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAKnD,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,cAAqC,EACrC,SAAiB,EACjB,QAAgB,EAChB,SAAsB,EACtB,QAAgB,EAChB,EAAE,CAAC,CAAC;IACJ,WAAW,EAAE,8CAA8C;IAC3D,IAAI,EAAE;QACJ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;QACnB,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACnC;IACD,KAAK,CAAC,OAAO,CAAC,IAA+C,EAAE,GAAgB;QAC7E,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAA;QAC/B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QAE1F,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,aAAa,GAAG,gBAAgB,SAAS,EAAE,CAAA;YACjD,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;YACjD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,GAAG,YAAY,oBAAoB,CAAC,EAAE,CAAC;oBAC3C,MAAM,GAAG,CAAA;gBACX,CAAC;gBACD,MAAM,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAAA;YACpD,CAAC;YACD,MAAM,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,aAAa,EAAE;gBACzD,OAAO,EAAE,MAAM,QAAQ,EAAE;aAC1B,CAAC,CAAA;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,aAAa,EAAE;gBACxE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,QAAQ,EAAE,IAAI;aACf,CAAC,CAAA;YACF,OAAO,yCAAyC,MAAM,CAAC,KAAK,GAAG,CAAA;QACjE,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;YAC3E,OAAO,cAAc,MAAM,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,EAAE,CAAA;QAC1D,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
import { DaytonaNotFoundError } from '@daytona/sdk'
|
|
8
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
9
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool'
|
|
10
|
+
import type { DaytonaSessionManager } from '../core/session-manager'
|
|
11
|
+
|
|
12
|
+
export const bashTool = (
|
|
13
|
+
sessionManager: DaytonaSessionManager,
|
|
14
|
+
projectId: string,
|
|
15
|
+
worktree: string,
|
|
16
|
+
pluginCtx: PluginInput,
|
|
17
|
+
repoPath: string,
|
|
18
|
+
) => ({
|
|
19
|
+
description: 'Executes shell commands in a Daytona sandbox',
|
|
20
|
+
args: {
|
|
21
|
+
command: z.string(),
|
|
22
|
+
background: z.boolean().optional(),
|
|
23
|
+
},
|
|
24
|
+
async execute(args: { command: string; background?: boolean }, ctx: ToolContext) {
|
|
25
|
+
const sessionId = ctx.sessionID
|
|
26
|
+
const sandbox = await sessionManager.getSandbox(sessionId, projectId, worktree, pluginCtx)
|
|
27
|
+
|
|
28
|
+
if (args.background) {
|
|
29
|
+
const execSessionId = `exec-session-${sessionId}`
|
|
30
|
+
try {
|
|
31
|
+
await sandbox.process.getSession(execSessionId)
|
|
32
|
+
} catch (err) {
|
|
33
|
+
if (!(err instanceof DaytonaNotFoundError)) {
|
|
34
|
+
throw err
|
|
35
|
+
}
|
|
36
|
+
await sandbox.process.createSession(execSessionId)
|
|
37
|
+
}
|
|
38
|
+
await sandbox.process.executeSessionCommand(execSessionId, {
|
|
39
|
+
command: `cd ${repoPath}`,
|
|
40
|
+
})
|
|
41
|
+
const result = await sandbox.process.executeSessionCommand(execSessionId, {
|
|
42
|
+
command: args.command,
|
|
43
|
+
runAsync: true,
|
|
44
|
+
})
|
|
45
|
+
return `Command started in background (cmdId: ${result.cmdId})`
|
|
46
|
+
} else {
|
|
47
|
+
const result = await sandbox.process.executeCommand(args.command, repoPath)
|
|
48
|
+
return `Exit code: ${result.exitCode}\n${result.result}`
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import type { DaytonaSessionManager } from '../core/session-manager';
|
|
9
|
+
export declare const editTool: (sessionManager: DaytonaSessionManager, projectId: string, worktree: string, pluginCtx: PluginInput) => {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {
|
|
12
|
+
filePath: z.ZodString;
|
|
13
|
+
oldString: z.ZodString;
|
|
14
|
+
newString: z.ZodString;
|
|
15
|
+
};
|
|
16
|
+
execute(args: {
|
|
17
|
+
filePath: string;
|
|
18
|
+
oldString: string;
|
|
19
|
+
newString: string;
|
|
20
|
+
}, ctx: ToolContext): Promise<string>;
|
|
21
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export const editTool = (sessionManager, projectId, worktree, pluginCtx) => ({
|
|
7
|
+
description: 'Replaces text in a file in Daytona sandbox',
|
|
8
|
+
args: {
|
|
9
|
+
filePath: z.string(),
|
|
10
|
+
oldString: z.string(),
|
|
11
|
+
newString: z.string(),
|
|
12
|
+
},
|
|
13
|
+
async execute(args, ctx) {
|
|
14
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx);
|
|
15
|
+
const buffer = await sandbox.fs.downloadFile(args.filePath);
|
|
16
|
+
const decoder = new TextDecoder();
|
|
17
|
+
const content = decoder.decode(buffer);
|
|
18
|
+
if (args.oldString === '') {
|
|
19
|
+
throw new Error(`oldString must be non-empty; refusing to prepend to ${args.filePath}.`);
|
|
20
|
+
}
|
|
21
|
+
const occurrences = content.split(args.oldString).length - 1;
|
|
22
|
+
if (occurrences === 0) {
|
|
23
|
+
throw new Error(`oldString not found in ${args.filePath}; no changes were made.`);
|
|
24
|
+
}
|
|
25
|
+
if (occurrences > 1) {
|
|
26
|
+
throw new Error(`oldString is ambiguous (${occurrences} matches) in ${args.filePath}; no changes were made.`);
|
|
27
|
+
}
|
|
28
|
+
const newContent = content.replace(args.oldString, args.newString);
|
|
29
|
+
await sandbox.fs.uploadFile(Buffer.from(newContent), args.filePath);
|
|
30
|
+
return `Edited ${args.filePath}`;
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=edit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["edit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,MAAM,CAAC,MAAM,QAAQ,GAAG,CACtB,cAAqC,EACrC,SAAiB,EACjB,QAAgB,EAChB,SAAsB,EACtB,EAAE,CAAC,CAAC;IACJ,WAAW,EAAE,4CAA4C;IACzD,IAAI,EAAE;QACJ,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;QACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB;IACD,KAAK,CAAC,OAAO,CAAC,IAAgE,EAAE,GAAgB;QAC9F,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QAC9F,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC3D,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uDAAuD,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QAC1F,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAA;QAC5D,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,0BAA0B,IAAI,CAAC,QAAQ,yBAAyB,CAAC,CAAA;QACnF,CAAC;QACD,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,2BAA2B,WAAW,gBAAgB,IAAI,CAAC,QAAQ,yBAAyB,CAC7F,CAAA;QACH,CAAC;QACD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAClE,MAAM,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnE,OAAO,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAA;IAClC,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
8
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool'
|
|
9
|
+
import type { DaytonaSessionManager } from '../core/session-manager'
|
|
10
|
+
|
|
11
|
+
export const editTool = (
|
|
12
|
+
sessionManager: DaytonaSessionManager,
|
|
13
|
+
projectId: string,
|
|
14
|
+
worktree: string,
|
|
15
|
+
pluginCtx: PluginInput,
|
|
16
|
+
) => ({
|
|
17
|
+
description: 'Replaces text in a file in Daytona sandbox',
|
|
18
|
+
args: {
|
|
19
|
+
filePath: z.string(),
|
|
20
|
+
oldString: z.string(),
|
|
21
|
+
newString: z.string(),
|
|
22
|
+
},
|
|
23
|
+
async execute(args: { filePath: string; oldString: string; newString: string }, ctx: ToolContext) {
|
|
24
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx)
|
|
25
|
+
const buffer = await sandbox.fs.downloadFile(args.filePath)
|
|
26
|
+
const decoder = new TextDecoder()
|
|
27
|
+
const content = decoder.decode(buffer)
|
|
28
|
+
if (args.oldString === '') {
|
|
29
|
+
throw new Error(`oldString must be non-empty; refusing to prepend to ${args.filePath}.`)
|
|
30
|
+
}
|
|
31
|
+
const occurrences = content.split(args.oldString).length - 1
|
|
32
|
+
if (occurrences === 0) {
|
|
33
|
+
throw new Error(`oldString not found in ${args.filePath}; no changes were made.`)
|
|
34
|
+
}
|
|
35
|
+
if (occurrences > 1) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`oldString is ambiguous (${occurrences} matches) in ${args.filePath}; no changes were made.`,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
const newContent = content.replace(args.oldString, args.newString)
|
|
41
|
+
await sandbox.fs.uploadFile(Buffer.from(newContent), args.filePath)
|
|
42
|
+
return `Edited ${args.filePath}`
|
|
43
|
+
},
|
|
44
|
+
})
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool';
|
|
8
|
+
import type { DaytonaSessionManager } from '../core/session-manager';
|
|
9
|
+
export declare const getPreviewURLTool: (sessionManager: DaytonaSessionManager, projectId: string, worktree: string, pluginCtx: PluginInput) => {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {
|
|
12
|
+
port: z.ZodNumber;
|
|
13
|
+
};
|
|
14
|
+
execute(args: {
|
|
15
|
+
port: number;
|
|
16
|
+
}, ctx: ToolContext): Promise<string>;
|
|
17
|
+
};
|