@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,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Veris AI
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* The eleventh tool, and the only one this fork adds.
|
|
6
|
+
*
|
|
7
|
+
* Every other tool tells the agent what its own code did. This one tells it
|
|
8
|
+
* what the VENDOR received — read from the twin, not from the sandbox — which
|
|
9
|
+
* is the only way to tell a real integration from a plausible-looking one. An
|
|
10
|
+
* agent that says "I called the Stripe API and it worked" and an agent that
|
|
11
|
+
* fabricated the response produce identical transcripts; they produce different
|
|
12
|
+
* receipts.
|
|
13
|
+
*/
|
|
14
|
+
import { z } from 'zod';
|
|
15
|
+
import { isVerisSandbox } from '@veris-ai/daytona';
|
|
16
|
+
export const verisReceiptTool = (sessionManager, projectId, worktree, pluginCtx) => ({
|
|
17
|
+
description: 'Read the Veris receipt: what the vendor twin ACTUALLY received from this sandbox. ' +
|
|
18
|
+
'Use it after any change that is supposed to reach an external API, and before ' +
|
|
19
|
+
'reporting that the change works. A green run with an empty receipt means the code ' +
|
|
20
|
+
'never reached the dependency — the two are indistinguishable from inside the sandbox. ' +
|
|
21
|
+
'Pass a service name to see that service alone.',
|
|
22
|
+
args: {
|
|
23
|
+
service: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('Service name (e.g. "stripe"). Omit for every service on the twin.'),
|
|
27
|
+
},
|
|
28
|
+
async execute(args, ctx) {
|
|
29
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx);
|
|
30
|
+
// Without this OpenCode renders the call as "verisReceipt Unknown".
|
|
31
|
+
const title = (t) => ctx.metadata({ title: t });
|
|
32
|
+
if (!isVerisSandbox(sandbox)) {
|
|
33
|
+
title('no twin attached');
|
|
34
|
+
return ('No Veris twin is attached to this sandbox, so there is no receipt to read.\n' +
|
|
35
|
+
'Set VERIS_API_KEY and VERIS_ENVIRONMENT_ID and start a new session to get one.');
|
|
36
|
+
}
|
|
37
|
+
if (args.service) {
|
|
38
|
+
const entry = await sandbox.veris.receipt(args.service);
|
|
39
|
+
title(`${args.service}: ${entry.requests} request(s)`);
|
|
40
|
+
if (entry.requests === 0) {
|
|
41
|
+
return (`Receipt for '${args.service}': ZERO requests.\n\n` +
|
|
42
|
+
`The twin was reachable and answered nothing — the code under test never called it. ` +
|
|
43
|
+
`Do not report this change as working.`);
|
|
44
|
+
}
|
|
45
|
+
const lines = entry.entries
|
|
46
|
+
.slice(0, 50)
|
|
47
|
+
.map((r) => ` ${r.method} ${r.path} -> ${r.status ?? 'no response (fault)'}`);
|
|
48
|
+
return (`Receipt for '${args.service}': ${entry.requests} request(s).\n` +
|
|
49
|
+
`${lines.join('\n')}${entry.entries.length > 50 ? `\n … ${entry.entries.length - 50} more` : ''}`);
|
|
50
|
+
}
|
|
51
|
+
const receipt = await sandbox.veris.receipt();
|
|
52
|
+
const names = Object.keys(receipt.services);
|
|
53
|
+
const total = names.reduce((n, k) => n + (receipt.services[k]?.requests ?? 0), 0);
|
|
54
|
+
title(`${total} request(s) across ${names.length} service(s)`);
|
|
55
|
+
const header = `Veris receipt — twin ${sandbox.verisSandboxId}\n` +
|
|
56
|
+
` interception: ${receipt.mode} integrity: ${receipt.integrity}\n` +
|
|
57
|
+
(receipt.leaks.length ? ` blind spots: ${receipt.leaks.join(', ')}\n` : '');
|
|
58
|
+
if (total === 0) {
|
|
59
|
+
return (header +
|
|
60
|
+
`\nZERO requests reached the twin, across ${names.length || 'no'} service(s).\n\n` +
|
|
61
|
+
`Whatever just ran did not touch its external dependencies. If you were asked to ` +
|
|
62
|
+
`make an integration work, it does not work yet — say so rather than reporting success.`);
|
|
63
|
+
}
|
|
64
|
+
const body = names
|
|
65
|
+
.map((name) => {
|
|
66
|
+
const e = receipt.services[name];
|
|
67
|
+
const calls = e.entries
|
|
68
|
+
.slice(0, 20)
|
|
69
|
+
.map((r) => ` ${r.method} ${r.path} -> ${r.status ?? 'no response (fault)'}`);
|
|
70
|
+
return ` ${name}: ${e.requests} request(s)\n${calls.join('\n')}`;
|
|
71
|
+
})
|
|
72
|
+
.join('\n');
|
|
73
|
+
return `${header}\n${total} request(s) reached the twin:\n${body}`;
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=veris-receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"veris-receipt.js","sourceRoot":"","sources":["veris-receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Veris AI
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* The eleventh tool, and the only one this fork adds.
|
|
6
|
+
*
|
|
7
|
+
* Every other tool tells the agent what its own code did. This one tells it
|
|
8
|
+
* what the VENDOR received — read from the twin, not from the sandbox — which
|
|
9
|
+
* is the only way to tell a real integration from a plausible-looking one. An
|
|
10
|
+
* agent that says "I called the Stripe API and it worked" and an agent that
|
|
11
|
+
* fabricated the response produce identical transcripts; they produce different
|
|
12
|
+
* receipts.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { z } from 'zod'
|
|
16
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
17
|
+
import type { ToolContext } from '@opencode-ai/plugin/tool'
|
|
18
|
+
import { isVerisSandbox } from '@veris-ai/daytona'
|
|
19
|
+
import type { DaytonaSessionManager } from '../core/session-manager'
|
|
20
|
+
|
|
21
|
+
export const verisReceiptTool = (
|
|
22
|
+
sessionManager: DaytonaSessionManager,
|
|
23
|
+
projectId: string,
|
|
24
|
+
worktree: string,
|
|
25
|
+
pluginCtx: PluginInput,
|
|
26
|
+
) => ({
|
|
27
|
+
description:
|
|
28
|
+
'Read the Veris receipt: what the vendor twin ACTUALLY received from this sandbox. ' +
|
|
29
|
+
'Use it after any change that is supposed to reach an external API, and before ' +
|
|
30
|
+
'reporting that the change works. A green run with an empty receipt means the code ' +
|
|
31
|
+
'never reached the dependency — the two are indistinguishable from inside the sandbox. ' +
|
|
32
|
+
'Pass a service name to see that service alone.',
|
|
33
|
+
args: {
|
|
34
|
+
service: z
|
|
35
|
+
.string()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe('Service name (e.g. "stripe"). Omit for every service on the twin.'),
|
|
38
|
+
},
|
|
39
|
+
async execute(args: { service?: string }, ctx: ToolContext) {
|
|
40
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx)
|
|
41
|
+
|
|
42
|
+
// Without this OpenCode renders the call as "verisReceipt Unknown".
|
|
43
|
+
const title = (t: string) => ctx.metadata({ title: t })
|
|
44
|
+
|
|
45
|
+
if (!isVerisSandbox(sandbox)) {
|
|
46
|
+
title('no twin attached')
|
|
47
|
+
return (
|
|
48
|
+
'No Veris twin is attached to this sandbox, so there is no receipt to read.\n' +
|
|
49
|
+
'Set VERIS_API_KEY and VERIS_ENVIRONMENT_ID and start a new session to get one.'
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (args.service) {
|
|
54
|
+
const entry = await sandbox.veris.receipt(args.service)
|
|
55
|
+
title(`${args.service}: ${entry.requests} request(s)`)
|
|
56
|
+
if (entry.requests === 0) {
|
|
57
|
+
return (
|
|
58
|
+
`Receipt for '${args.service}': ZERO requests.\n\n` +
|
|
59
|
+
`The twin was reachable and answered nothing — the code under test never called it. ` +
|
|
60
|
+
`Do not report this change as working.`
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
const lines = entry.entries
|
|
64
|
+
.slice(0, 50)
|
|
65
|
+
.map((r) => ` ${r.method} ${r.path} -> ${r.status ?? 'no response (fault)'}`)
|
|
66
|
+
return (
|
|
67
|
+
`Receipt for '${args.service}': ${entry.requests} request(s).\n` +
|
|
68
|
+
`${lines.join('\n')}${entry.entries.length > 50 ? `\n … ${entry.entries.length - 50} more` : ''}`
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const receipt = await sandbox.veris.receipt()
|
|
73
|
+
const names = Object.keys(receipt.services)
|
|
74
|
+
const total = names.reduce((n, k) => n + (receipt.services[k]?.requests ?? 0), 0)
|
|
75
|
+
title(`${total} request(s) across ${names.length} service(s)`)
|
|
76
|
+
|
|
77
|
+
const header =
|
|
78
|
+
`Veris receipt — twin ${sandbox.verisSandboxId}\n` +
|
|
79
|
+
` interception: ${receipt.mode} integrity: ${receipt.integrity}\n` +
|
|
80
|
+
(receipt.leaks.length ? ` blind spots: ${receipt.leaks.join(', ')}\n` : '')
|
|
81
|
+
|
|
82
|
+
if (total === 0) {
|
|
83
|
+
return (
|
|
84
|
+
header +
|
|
85
|
+
`\nZERO requests reached the twin, across ${names.length || 'no'} service(s).\n\n` +
|
|
86
|
+
`Whatever just ran did not touch its external dependencies. If you were asked to ` +
|
|
87
|
+
`make an integration work, it does not work yet — say so rather than reporting success.`
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const body = names
|
|
92
|
+
.map((name) => {
|
|
93
|
+
const e = receipt.services[name]!
|
|
94
|
+
const calls = e.entries
|
|
95
|
+
.slice(0, 20)
|
|
96
|
+
.map((r) => ` ${r.method} ${r.path} -> ${r.status ?? 'no response (fault)'}`)
|
|
97
|
+
return ` ${name}: ${e.requests} request(s)\n${calls.join('\n')}`
|
|
98
|
+
})
|
|
99
|
+
.join('\n')
|
|
100
|
+
|
|
101
|
+
return `${header}\n${total} request(s) reached the twin:\n${body}`
|
|
102
|
+
},
|
|
103
|
+
})
|
|
@@ -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 writeTool: (sessionManager: DaytonaSessionManager, projectId: string, worktree: string, pluginCtx: PluginInput) => {
|
|
10
|
+
description: string;
|
|
11
|
+
args: {
|
|
12
|
+
filePath: z.ZodString;
|
|
13
|
+
content: z.ZodString;
|
|
14
|
+
};
|
|
15
|
+
execute(args: {
|
|
16
|
+
filePath: string;
|
|
17
|
+
content: string;
|
|
18
|
+
}, ctx: ToolContext): Promise<string>;
|
|
19
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export const writeTool = (sessionManager, projectId, worktree, pluginCtx) => ({
|
|
7
|
+
description: 'Writes content to file in Daytona sandbox',
|
|
8
|
+
args: {
|
|
9
|
+
filePath: z.string(),
|
|
10
|
+
content: z.string(),
|
|
11
|
+
},
|
|
12
|
+
async execute(args, ctx) {
|
|
13
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx);
|
|
14
|
+
await sandbox.fs.uploadFile(Buffer.from(args.content), args.filePath);
|
|
15
|
+
return `Written ${Buffer.byteLength(args.content, 'utf8')} bytes to ${args.filePath}`;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["write.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAKvB,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,cAAqC,EACrC,SAAiB,EACjB,QAAgB,EAChB,SAAsB,EACtB,EAAE,CAAC,CAAC;IACJ,WAAW,EAAE,2CAA2C;IACxD,IAAI,EAAE;QACJ,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB;IACD,KAAK,CAAC,OAAO,CAAC,IAA2C,EAAE,GAAgB;QACzE,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;QAC9F,MAAM,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACrE,OAAO,WAAW,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,aAAa,IAAI,CAAC,QAAQ,EAAE,CAAA;IACvF,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
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 writeTool = (
|
|
12
|
+
sessionManager: DaytonaSessionManager,
|
|
13
|
+
projectId: string,
|
|
14
|
+
worktree: string,
|
|
15
|
+
pluginCtx: PluginInput,
|
|
16
|
+
) => ({
|
|
17
|
+
description: 'Writes content to file in Daytona sandbox',
|
|
18
|
+
args: {
|
|
19
|
+
filePath: z.string(),
|
|
20
|
+
content: z.string(),
|
|
21
|
+
},
|
|
22
|
+
async execute(args: { filePath: string; content: string }, ctx: ToolContext) {
|
|
23
|
+
const sandbox = await sessionManager.getSandbox(ctx.sessionID, projectId, worktree, pluginCtx)
|
|
24
|
+
await sandbox.fs.uploadFile(Buffer.from(args.content), args.filePath)
|
|
25
|
+
return `Written ${Buffer.byteLength(args.content, 'utf8')} bytes to ${args.filePath}`
|
|
26
|
+
},
|
|
27
|
+
})
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import type { DaytonaSessionManager } from './core/session-manager';
|
|
6
|
+
import type { PluginInput } from '@opencode-ai/plugin';
|
|
7
|
+
export declare function createDaytonaTools(sessionManager: DaytonaSessionManager, projectId: string, worktree: string, pluginCtx: PluginInput): {
|
|
8
|
+
bash: {
|
|
9
|
+
description: string;
|
|
10
|
+
args: {
|
|
11
|
+
command: import("zod").ZodString;
|
|
12
|
+
background: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
13
|
+
};
|
|
14
|
+
execute(args: {
|
|
15
|
+
command: string;
|
|
16
|
+
background?: boolean;
|
|
17
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
18
|
+
};
|
|
19
|
+
read: {
|
|
20
|
+
description: string;
|
|
21
|
+
args: {
|
|
22
|
+
filePath: import("zod").ZodString;
|
|
23
|
+
};
|
|
24
|
+
execute(args: {
|
|
25
|
+
filePath: string;
|
|
26
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
27
|
+
};
|
|
28
|
+
write: {
|
|
29
|
+
description: string;
|
|
30
|
+
args: {
|
|
31
|
+
filePath: import("zod").ZodString;
|
|
32
|
+
content: import("zod").ZodString;
|
|
33
|
+
};
|
|
34
|
+
execute(args: {
|
|
35
|
+
filePath: string;
|
|
36
|
+
content: string;
|
|
37
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
38
|
+
};
|
|
39
|
+
edit: {
|
|
40
|
+
description: string;
|
|
41
|
+
args: {
|
|
42
|
+
filePath: import("zod").ZodString;
|
|
43
|
+
oldString: import("zod").ZodString;
|
|
44
|
+
newString: import("zod").ZodString;
|
|
45
|
+
};
|
|
46
|
+
execute(args: {
|
|
47
|
+
filePath: string;
|
|
48
|
+
oldString: string;
|
|
49
|
+
newString: string;
|
|
50
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
51
|
+
};
|
|
52
|
+
multiedit: {
|
|
53
|
+
description: string;
|
|
54
|
+
args: {
|
|
55
|
+
filePath: import("zod").ZodString;
|
|
56
|
+
edits: import("zod").ZodArray<import("zod").ZodObject<{
|
|
57
|
+
oldString: import("zod").ZodString;
|
|
58
|
+
newString: import("zod").ZodString;
|
|
59
|
+
}, import("zod/v4/core").$strip>>;
|
|
60
|
+
};
|
|
61
|
+
execute(args: {
|
|
62
|
+
filePath: string;
|
|
63
|
+
edits: Array<{
|
|
64
|
+
oldString: string;
|
|
65
|
+
newString: string;
|
|
66
|
+
}>;
|
|
67
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
68
|
+
};
|
|
69
|
+
ls: {
|
|
70
|
+
description: string;
|
|
71
|
+
args: {
|
|
72
|
+
dirPath: import("zod").ZodOptional<import("zod").ZodString>;
|
|
73
|
+
};
|
|
74
|
+
execute(args: {
|
|
75
|
+
dirPath?: string;
|
|
76
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
77
|
+
};
|
|
78
|
+
glob: {
|
|
79
|
+
description: string;
|
|
80
|
+
args: {
|
|
81
|
+
pattern: import("zod").ZodString;
|
|
82
|
+
};
|
|
83
|
+
execute(args: {
|
|
84
|
+
pattern: string;
|
|
85
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
86
|
+
};
|
|
87
|
+
grep: {
|
|
88
|
+
description: string;
|
|
89
|
+
args: {
|
|
90
|
+
pattern: import("zod").ZodString;
|
|
91
|
+
};
|
|
92
|
+
execute(args: {
|
|
93
|
+
pattern: string;
|
|
94
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
95
|
+
};
|
|
96
|
+
getPreviewURL: {
|
|
97
|
+
description: string;
|
|
98
|
+
args: {
|
|
99
|
+
port: import("zod").ZodNumber;
|
|
100
|
+
};
|
|
101
|
+
execute(args: {
|
|
102
|
+
port: number;
|
|
103
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
104
|
+
};
|
|
105
|
+
gitSync: {
|
|
106
|
+
description: string;
|
|
107
|
+
args: {};
|
|
108
|
+
execute(_args: {}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
109
|
+
};
|
|
110
|
+
verisReceipt: {
|
|
111
|
+
description: string;
|
|
112
|
+
args: {
|
|
113
|
+
service: import("zod").ZodOptional<import("zod").ZodString>;
|
|
114
|
+
};
|
|
115
|
+
execute(args: {
|
|
116
|
+
service?: string;
|
|
117
|
+
}, ctx: import("@opencode-ai/plugin").ToolContext): Promise<string>;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Tool implementations for Daytona sandbox integration
|
|
7
|
+
*/
|
|
8
|
+
import { bashTool } from './tools/bash';
|
|
9
|
+
import { readTool } from './tools/read';
|
|
10
|
+
import { writeTool } from './tools/write';
|
|
11
|
+
import { editTool } from './tools/edit';
|
|
12
|
+
import { multieditTool } from './tools/multiedit';
|
|
13
|
+
import { lsTool } from './tools/ls';
|
|
14
|
+
import { globTool } from './tools/glob';
|
|
15
|
+
import { grepTool } from './tools/grep';
|
|
16
|
+
import { getPreviewURLTool } from './tools/get-preview-url';
|
|
17
|
+
import { gitSyncTool } from './tools/git-sync';
|
|
18
|
+
import { verisReceiptTool } from './tools/veris-receipt';
|
|
19
|
+
export function createDaytonaTools(sessionManager, projectId, worktree, pluginCtx) {
|
|
20
|
+
const repoPath = sessionManager.repoPath;
|
|
21
|
+
return {
|
|
22
|
+
bash: bashTool(sessionManager, projectId, worktree, pluginCtx, repoPath),
|
|
23
|
+
read: readTool(sessionManager, projectId, worktree, pluginCtx),
|
|
24
|
+
write: writeTool(sessionManager, projectId, worktree, pluginCtx),
|
|
25
|
+
edit: editTool(sessionManager, projectId, worktree, pluginCtx),
|
|
26
|
+
multiedit: multieditTool(sessionManager, projectId, worktree, pluginCtx),
|
|
27
|
+
ls: lsTool(sessionManager, projectId, worktree, pluginCtx),
|
|
28
|
+
glob: globTool(sessionManager, projectId, worktree, pluginCtx),
|
|
29
|
+
grep: grepTool(sessionManager, projectId, worktree, pluginCtx),
|
|
30
|
+
getPreviewURL: getPreviewURLTool(sessionManager, projectId, worktree, pluginCtx),
|
|
31
|
+
gitSync: gitSyncTool(sessionManager, projectId, worktree, pluginCtx),
|
|
32
|
+
verisReceipt: verisReceiptTool(sessionManager, projectId, worktree, pluginCtx),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAKxD,MAAM,UAAU,kBAAkB,CAChC,cAAqC,EACrC,SAAiB,EACjB,QAAgB,EAChB,SAAsB;IAEtB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAA;IACxC,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC;QACxE,IAAI,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC9D,KAAK,EAAE,SAAS,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAChE,IAAI,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC9D,SAAS,EAAE,aAAa,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QACxE,EAAE,EAAE,MAAM,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC1D,IAAI,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC9D,IAAI,EAAE,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAC9D,aAAa,EAAE,iBAAiB,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QAChF,OAAO,EAAE,WAAW,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;QACpE,YAAY,EAAE,gBAAgB,CAAC,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;KAC/E,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tool implementations for Daytona sandbox integration
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { bashTool } from './tools/bash'
|
|
11
|
+
import { readTool } from './tools/read'
|
|
12
|
+
import { writeTool } from './tools/write'
|
|
13
|
+
import { editTool } from './tools/edit'
|
|
14
|
+
import { multieditTool } from './tools/multiedit'
|
|
15
|
+
import { lsTool } from './tools/ls'
|
|
16
|
+
import { globTool } from './tools/glob'
|
|
17
|
+
import { grepTool } from './tools/grep'
|
|
18
|
+
import { getPreviewURLTool } from './tools/get-preview-url'
|
|
19
|
+
import { gitSyncTool } from './tools/git-sync'
|
|
20
|
+
import { verisReceiptTool } from './tools/veris-receipt'
|
|
21
|
+
|
|
22
|
+
import type { DaytonaSessionManager } from './core/session-manager'
|
|
23
|
+
import type { PluginInput } from '@opencode-ai/plugin'
|
|
24
|
+
|
|
25
|
+
export function createDaytonaTools(
|
|
26
|
+
sessionManager: DaytonaSessionManager,
|
|
27
|
+
projectId: string,
|
|
28
|
+
worktree: string,
|
|
29
|
+
pluginCtx: PluginInput,
|
|
30
|
+
) {
|
|
31
|
+
const repoPath = sessionManager.repoPath
|
|
32
|
+
return {
|
|
33
|
+
bash: bashTool(sessionManager, projectId, worktree, pluginCtx, repoPath),
|
|
34
|
+
read: readTool(sessionManager, projectId, worktree, pluginCtx),
|
|
35
|
+
write: writeTool(sessionManager, projectId, worktree, pluginCtx),
|
|
36
|
+
edit: editTool(sessionManager, projectId, worktree, pluginCtx),
|
|
37
|
+
multiedit: multieditTool(sessionManager, projectId, worktree, pluginCtx),
|
|
38
|
+
ls: lsTool(sessionManager, projectId, worktree, pluginCtx),
|
|
39
|
+
glob: globTool(sessionManager, projectId, worktree, pluginCtx),
|
|
40
|
+
grep: grepTool(sessionManager, projectId, worktree, pluginCtx),
|
|
41
|
+
getPreviewURL: getPreviewURLTool(sessionManager, projectId, worktree, pluginCtx),
|
|
42
|
+
gitSync: gitSyncTool(sessionManager, projectId, worktree, pluginCtx),
|
|
43
|
+
verisReceipt: verisReceiptTool(sessionManager, projectId, worktree, pluginCtx),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Daytona Platforms Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Main entry point for the OpenCode Daytona plugin.
|
|
7
|
+
* Re-exports the default plugin from daytona.
|
|
8
|
+
*/
|
|
9
|
+
export { default } from './daytona/index';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA"}
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @veris-ai/daytona-opencode
|
|
2
|
+
|
|
3
|
+
An [OpenCode](https://opencode.ai) plugin. Every session runs in a
|
|
4
|
+
[Daytona](https://daytona.io) sandbox whose calls to `api.stripe.com` and the
|
|
5
|
+
rest of your vendor stack are answered by **Veris twins** — stateful,
|
|
6
|
+
contract-accurate fakes — and the agent gets a tool that shows what the vendor
|
|
7
|
+
actually received.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```jsonc
|
|
12
|
+
// opencode.json
|
|
13
|
+
{ "plugin": ["@veris-ai/daytona-opencode"] }
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| variable | where from |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `DAYTONA_API_KEY` | [app.daytona.io/dashboard/keys](https://app.daytona.io/dashboard/keys) |
|
|
19
|
+
| `VERIS_API_KEY` | [studio.veris.ai](https://studio.veris.ai) |
|
|
20
|
+
| `VERIS_ENVIRONMENT_ID` | a Veris environment — it decides which vendor services your twin gets |
|
|
21
|
+
|
|
22
|
+
Then `opencode`. No image to build, no network configuration, nothing to start.
|
|
23
|
+
|
|
24
|
+
## What the agent gets
|
|
25
|
+
|
|
26
|
+
The ten sandbox-backed tools from [`@daytona/opencode`](https://www.npmjs.com/package/@daytona/opencode)
|
|
27
|
+
— bash, read, write, edit, multiedit, ls, glob, grep, getPreviewURL, gitSync —
|
|
28
|
+
plus one.
|
|
29
|
+
|
|
30
|
+
**`verisReceipt`** reports what the twin *received*.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Veris receipt — twin sbx_a1b2c3
|
|
34
|
+
interception: gateway integrity: verified
|
|
35
|
+
|
|
36
|
+
1 request(s) reached the twin:
|
|
37
|
+
stripe: 1 request(s)
|
|
38
|
+
POST /v1/charges -> 200
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This is the tool that separates a real integration from a plausible-looking one.
|
|
42
|
+
Ask an agent to call the Stripe API and it will report success whether or not it
|
|
43
|
+
made the call — the transcripts are identical. The receipts are not:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Receipt for 'stripe': ZERO requests.
|
|
47
|
+
|
|
48
|
+
The twin was reachable and answered nothing — the code under test never called
|
|
49
|
+
it. Do not report this change as working.
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The system prompt tells the agent to check it before claiming an integration
|
|
53
|
+
works. You can also just ask for it.
|
|
54
|
+
|
|
55
|
+
## Why the sandbox cannot reach the real vendor
|
|
56
|
+
|
|
57
|
+
The sandbox is created with a `domainAllowList` — the vendor hostnames the twin
|
|
58
|
+
answers for, the Veris gateway, the twin's data planes, and package registries —
|
|
59
|
+
and an `outboundProxyUrl` pointing at the gateway. Daytona drops anything not on
|
|
60
|
+
the list and forwards the rest to the gateway, which answers vendor hostnames
|
|
61
|
+
from the twin. `npm install` still works; `api.stripe.com` reaches your twin.
|
|
62
|
+
|
|
63
|
+
Everything above happens inside `@veris-ai/daytona`, which this plugin uses in
|
|
64
|
+
place of `@daytona/sdk`. See [its README](https://www.npmjs.com/package/@veris-ai/daytona)
|
|
65
|
+
if you want the same thing without an agent.
|
|
66
|
+
|
|
67
|
+
## Relationship to `@daytona/opencode`
|
|
68
|
+
|
|
69
|
+
This is a fork of `@daytona/opencode` 0.192.0 (Apache-2.0, Copyright Daytona
|
|
70
|
+
Platforms Inc.), and a deliberately small one: one changed import, one added
|
|
71
|
+
tool, one paragraph in the system prompt, and a check that the Veris
|
|
72
|
+
coordinates are set. The ten inherited tools, the git-sync flow and the session
|
|
73
|
+
bookkeeping are untouched, so upstream changes stay easy to take.
|
|
74
|
+
|
|
75
|
+
## Limitations
|
|
76
|
+
|
|
77
|
+
- **Requires a Veris control plane that serves an HTTP CONNECT gateway.**
|
|
78
|
+
Without one, the first tool call fails saying exactly that.
|
|
79
|
+
- **Git sync into the sandbox can fail with `Host key verification failed`.**
|
|
80
|
+
Inherited from upstream; the agent works, but local changes are not pushed
|
|
81
|
+
into the sandbox. Setting `DAYTONA_SSH_KNOWN_HOSTS` is the likely fix.
|
|
82
|
+
- **QUIC/HTTP3 and ECH are not intercepted.** Both are reported in the receipt's
|
|
83
|
+
`leaks` rather than silently omitted.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
Apache-2.0. Source: [veris-ai/veris-daytona](https://github.com/veris-ai/veris-daytona).
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@veris-ai/daytona-opencode",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Run every OpenCode session in a Daytona sandbox whose vendor API calls are answered by a Veris twin. One line in opencode.json: unmodified code, real hostnames, and a receipt of what the vendor actually received.",
|
|
5
|
+
"main": "./.opencode/plugin/index.js",
|
|
6
|
+
"types": "./.opencode/plugin/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
".opencode",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git+https://github.com/veris-ai/veris-daytona.git",
|
|
14
|
+
"directory": "daytona-opencode"
|
|
15
|
+
},
|
|
16
|
+
"author": "Veris (https://veris.ai)",
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/veris-ai/veris-daytona/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/veris-ai/veris-daytona/tree/main/daytona-opencode#readme",
|
|
22
|
+
"keywords": [
|
|
23
|
+
"opencode",
|
|
24
|
+
"opencode-plugin",
|
|
25
|
+
"veris",
|
|
26
|
+
"daytona",
|
|
27
|
+
"sandbox",
|
|
28
|
+
"integration-testing"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"opencode": ">=1.16 <2"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"typecheck": "tsc --noEmit",
|
|
36
|
+
"prepublishOnly": "npm run build"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@veris-ai/daytona": "^0.1.0",
|
|
40
|
+
"@daytona/sdk": "^0.204.1",
|
|
41
|
+
"@opencode-ai/plugin": "1.1.59",
|
|
42
|
+
"xdg-basedir": "^5.1.0",
|
|
43
|
+
"zod": "^4.2.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^22",
|
|
47
|
+
"typescript": "^5.6.0"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
}
|
|
52
|
+
}
|