remote-opencode 1.3.0 → 1.3.1
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.
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { SlashCommandBuilder, MessageFlags } from 'discord.js';
|
|
2
|
-
import {
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import * as dataStore from '../services/dataStore.js';
|
|
5
|
-
const
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
6
|
const MAX_LENGTH = 1900;
|
|
7
7
|
const CODE_BLOCK_OVERHEAD = 8; // ```diff\n...\n```
|
|
8
|
+
const GIT_REF_PATTERN = /^[a-zA-Z0-9._\/-]+$/;
|
|
8
9
|
function formatDiff(raw) {
|
|
9
10
|
const maxContent = MAX_LENGTH - CODE_BLOCK_OVERHEAD;
|
|
10
11
|
if (raw.length <= maxContent) {
|
|
@@ -61,23 +62,27 @@ export const diff = {
|
|
|
61
62
|
});
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
65
|
+
if (target === 'branch' && !GIT_REF_PATTERN.test(base)) {
|
|
66
|
+
await i.reply({ content: '❌ Invalid base branch name.', flags: MessageFlags.Ephemeral });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
64
69
|
await i.deferReply();
|
|
65
70
|
try {
|
|
66
71
|
let gitArgs;
|
|
67
72
|
switch (target) {
|
|
68
73
|
case 'staged':
|
|
69
|
-
gitArgs = '
|
|
74
|
+
gitArgs = ['diff', '--cached'];
|
|
70
75
|
break;
|
|
71
76
|
case 'branch':
|
|
72
|
-
gitArgs =
|
|
77
|
+
gitArgs = ['diff', `${base}...HEAD`];
|
|
73
78
|
break;
|
|
74
79
|
default:
|
|
75
|
-
gitArgs = '
|
|
80
|
+
gitArgs = ['diff'];
|
|
76
81
|
}
|
|
77
82
|
if (stat) {
|
|
78
|
-
gitArgs
|
|
83
|
+
gitArgs.push('--stat');
|
|
79
84
|
}
|
|
80
|
-
const { stdout } = await
|
|
85
|
+
const { stdout } = await execFileAsync('git', gitArgs, { cwd: projectPath });
|
|
81
86
|
const output = stdout.trim();
|
|
82
87
|
if (!output) {
|
|
83
88
|
const targetLabel = target === 'branch' ? `branch (base: ${base})` : target;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
4
|
import { join, resolve } from 'node:path';
|
|
5
|
-
const
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
6
|
export function sanitizeBranchName(name) {
|
|
7
7
|
return name
|
|
8
8
|
.trim()
|
|
@@ -13,8 +13,8 @@ export function sanitizeBranchName(name) {
|
|
|
13
13
|
export async function branchExists(projectPath, branchName) {
|
|
14
14
|
try {
|
|
15
15
|
const [localRes, remoteRes] = await Promise.all([
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
execFileAsync('git', ['branch', '--list', branchName], { cwd: projectPath }).catch(() => ({ stdout: '' })),
|
|
17
|
+
execFileAsync('git', ['branch', '-r', '--list', `origin/${branchName}`], { cwd: projectPath }).catch(() => ({ stdout: '' }))
|
|
18
18
|
]);
|
|
19
19
|
return {
|
|
20
20
|
local: localRes.stdout.trim().length > 0,
|
|
@@ -33,12 +33,12 @@ export async function createWorktree(projectPath, branchName) {
|
|
|
33
33
|
const { local, remote } = await branchExists(projectPath, sanitizedBranch);
|
|
34
34
|
try {
|
|
35
35
|
if (local || remote) {
|
|
36
|
-
await
|
|
36
|
+
await execFileAsync('git', ['worktree', 'add', `./worktrees/${sanitizedBranch}`, sanitizedBranch], {
|
|
37
37
|
cwd: projectPath
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
await
|
|
41
|
+
await execFileAsync('git', ['worktree', 'add', `./worktrees/${sanitizedBranch}`, '-b', sanitizedBranch], {
|
|
42
42
|
cwd: projectPath
|
|
43
43
|
});
|
|
44
44
|
}
|
|
@@ -53,13 +53,13 @@ export async function removeWorktree(worktreePath, deleteBranch) {
|
|
|
53
53
|
try {
|
|
54
54
|
let branchName;
|
|
55
55
|
if (deleteBranch) {
|
|
56
|
-
const { stdout } = await
|
|
56
|
+
const { stdout } = await execFileAsync('git', ['branch', '--show-current'], { cwd: worktreePath });
|
|
57
57
|
branchName = stdout.trim();
|
|
58
58
|
}
|
|
59
59
|
const projectPath = resolve(worktreePath, '..', '..');
|
|
60
|
-
await
|
|
60
|
+
await execFileAsync('git', ['worktree', 'remove', worktreePath, '--force'], { cwd: projectPath });
|
|
61
61
|
if (deleteBranch && branchName) {
|
|
62
|
-
await
|
|
62
|
+
await execFileAsync('git', ['branch', '-D', branchName], { cwd: projectPath });
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
catch (error) {
|
|
@@ -69,7 +69,7 @@ export async function removeWorktree(worktreePath, deleteBranch) {
|
|
|
69
69
|
}
|
|
70
70
|
export async function getCurrentBranch(cwd) {
|
|
71
71
|
try {
|
|
72
|
-
const { stdout } = await
|
|
72
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd });
|
|
73
73
|
return stdout.trim() || null;
|
|
74
74
|
}
|
|
75
75
|
catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remote-opencode",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Discord bot for remote OpenCode CLI access",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -52,5 +52,8 @@
|
|
|
52
52
|
"ts-node": "^10.9.2",
|
|
53
53
|
"typescript": "^5.9.3",
|
|
54
54
|
"vitest": "^4.0.18"
|
|
55
|
+
},
|
|
56
|
+
"overrides": {
|
|
57
|
+
"undici": "^6.23.0"
|
|
55
58
|
}
|
|
56
59
|
}
|