finch-git-branch 0.2.8 → 0.2.10
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/dist/index.js +70 -21
- package/i18n/en-US.json +5 -2
- package/i18n/zh-CN.json +5 -2
- package/icons/handshake.svg +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4,11 +4,17 @@ import { execFile } from 'node:child_process';
|
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
6
|
const CURRENT_BRANCH_KEY = 'currentBranch';
|
|
7
|
+
const CO_AUTHOR_ENABLED_KEY = 'coAuthorEnabled';
|
|
8
|
+
const FINCH_CODE_EMAIL = 'noreply@finchwork.app';
|
|
7
9
|
// Tracks the most-recently-seen cwd so the background poller can use it.
|
|
8
10
|
let activeCwd;
|
|
9
11
|
function readIconSvg(name) {
|
|
10
12
|
return readFileSync(new URL(`../icons/${name}.svg`, import.meta.url), 'utf-8');
|
|
11
13
|
}
|
|
14
|
+
async function getCoAuthorTrailer(ctx) {
|
|
15
|
+
const { assistantName } = await ctx.app.getInfo();
|
|
16
|
+
return `Co-authored-by: ${assistantName} <${FINCH_CODE_EMAIL}>`;
|
|
17
|
+
}
|
|
12
18
|
// ── Git helpers ──────────────────────────────────────────────────────────────
|
|
13
19
|
async function git(cwd, args, timeout = 5000) {
|
|
14
20
|
const { stdout } = await execFileAsync('git', ['-C', cwd, ...args], {
|
|
@@ -122,6 +128,7 @@ export function activate(ctx) {
|
|
|
122
128
|
ctx.subscriptions.push(ctx.icons.register('git-branch', {
|
|
123
129
|
plus: { svg: readIconSvg('plus'), description: 'Create branch' },
|
|
124
130
|
'plus-circle': { svg: readIconSvg('plus-circle'), description: 'Create branch' },
|
|
131
|
+
handshake: { svg: readIconSvg('handshake'), description: 'Include Finch Code co-author' },
|
|
125
132
|
}));
|
|
126
133
|
const composerAction = ctx.composerActions.register('git-branch', {
|
|
127
134
|
async getBadge({ cwd }) {
|
|
@@ -138,6 +145,12 @@ export function activate(ctx) {
|
|
|
138
145
|
}
|
|
139
146
|
return await ctx.storage.get(CURRENT_BRANCH_KEY);
|
|
140
147
|
},
|
|
148
|
+
async getReminder({ cwd, surface }) {
|
|
149
|
+
if (surface === 'home' || !cwd || !isGitRepo(cwd) || (await ctx.storage.get(CO_AUTHOR_ENABLED_KEY)) === false) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
return `When creating any Git commit, append a blank line followed by the exact trailer: ${await getCoAuthorTrailer(ctx)}`;
|
|
153
|
+
},
|
|
141
154
|
async getMenu({ cwd }) {
|
|
142
155
|
if (!cwd)
|
|
143
156
|
return [];
|
|
@@ -164,7 +177,19 @@ export function activate(ctx) {
|
|
|
164
177
|
if (desc)
|
|
165
178
|
pinnedDiffs.set(b, desc);
|
|
166
179
|
}));
|
|
167
|
-
const
|
|
180
|
+
const coAuthorEnabled = await ctx.storage.get(CO_AUTHOR_ENABLED_KEY) !== false;
|
|
181
|
+
const { assistantName } = await ctx.app.getInfo();
|
|
182
|
+
const items = [{
|
|
183
|
+
id: '__toggle_co_author__',
|
|
184
|
+
label: ctx.i18n.t('git.branch.coauthor.label', { finchName: assistantName }),
|
|
185
|
+
description: ctx.i18n.t(coAuthorEnabled ? 'git.branch.coauthor.on' : 'git.branch.coauthor.off'),
|
|
186
|
+
current: coAuthorEnabled,
|
|
187
|
+
iconName: 'ext:git-branch/handshake',
|
|
188
|
+
}, {
|
|
189
|
+
id: '__coauthor_sep__',
|
|
190
|
+
label: '',
|
|
191
|
+
separator: true,
|
|
192
|
+
}];
|
|
168
193
|
items.push({
|
|
169
194
|
id: currentBranch,
|
|
170
195
|
label: currentBranch,
|
|
@@ -222,6 +247,12 @@ export function activate(ctx) {
|
|
|
222
247
|
async execute({ cwd }, itemId, actions) {
|
|
223
248
|
if (!cwd || !itemId)
|
|
224
249
|
return;
|
|
250
|
+
if (itemId === '__toggle_co_author__') {
|
|
251
|
+
const enabled = await ctx.storage.get(CO_AUTHOR_ENABLED_KEY) !== false;
|
|
252
|
+
await ctx.storage.set(CO_AUTHOR_ENABLED_KEY, !enabled);
|
|
253
|
+
composerAction.notifyUpdate();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
225
256
|
// ── Create branch: 直接填入 Prompt ────────────────────────────
|
|
226
257
|
if (itemId === '__create_branch__') {
|
|
227
258
|
await actions.fillComposer(ctx.i18n.t('git.branch.create.prompt'));
|
|
@@ -252,6 +283,9 @@ export function activate(ctx) {
|
|
|
252
283
|
await git(cwd, [
|
|
253
284
|
'commit', '-m',
|
|
254
285
|
ctx.i18n.t('git.branch.switch.commit.msg', { branch: itemId }),
|
|
286
|
+
...(await ctx.storage.get(CO_AUTHOR_ENABLED_KEY) !== false
|
|
287
|
+
? ['-m', await getCoAuthorTrailer(ctx)]
|
|
288
|
+
: []),
|
|
255
289
|
]);
|
|
256
290
|
checkpointCommit = await git(cwd, ['rev-parse', '--short', 'HEAD']).catch(() => undefined);
|
|
257
291
|
}
|
|
@@ -283,31 +317,43 @@ export function activate(ctx) {
|
|
|
283
317
|
description: ctx.i18n.t('tool.create.desc'),
|
|
284
318
|
inputSchema: {
|
|
285
319
|
type: 'object',
|
|
286
|
-
properties: {
|
|
320
|
+
properties: {
|
|
321
|
+
branchName: {
|
|
322
|
+
type: 'string',
|
|
323
|
+
description: 'The new branch name. When provided, create and check out the branch without showing a form.',
|
|
324
|
+
},
|
|
325
|
+
},
|
|
287
326
|
required: [],
|
|
288
327
|
},
|
|
289
328
|
risk: 'medium',
|
|
290
|
-
async execute(
|
|
329
|
+
async execute(input, exec) {
|
|
291
330
|
await exec.storage.delete('pendingCreateBranch').catch(() => { });
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
331
|
+
const suppliedBranchName = input.branchName;
|
|
332
|
+
let branchName;
|
|
333
|
+
if (typeof suppliedBranchName === 'string') {
|
|
334
|
+
branchName = suppliedBranchName;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
const result = await exec.ui.requestForm({
|
|
338
|
+
title: ctx.i18n.t('git.branch.create.title'),
|
|
339
|
+
description: ctx.i18n.t('git.branch.create.desc'),
|
|
340
|
+
submitLabel: ctx.i18n.t('git.branch.create.submit'),
|
|
341
|
+
fields: [
|
|
342
|
+
{
|
|
343
|
+
key: 'branchName',
|
|
344
|
+
label: ctx.i18n.t('git.branch.create.field'),
|
|
345
|
+
type: 'text',
|
|
346
|
+
required: true,
|
|
347
|
+
placeholder: ctx.i18n.t('git.branch.create.ph'),
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
timeoutMs: 120_000,
|
|
351
|
+
});
|
|
352
|
+
if (!result.submitted) {
|
|
353
|
+
return { content: [{ type: 'text', text: ctx.i18n.t('git.branch.create.cancelled') }] };
|
|
354
|
+
}
|
|
355
|
+
branchName = result.values.branchName;
|
|
309
356
|
}
|
|
310
|
-
const branchName = result.values.branchName;
|
|
311
357
|
if (!branchName || !/^[a-zA-Z0-9_./-]+$/.test(branchName)) {
|
|
312
358
|
return {
|
|
313
359
|
content: [
|
|
@@ -326,6 +372,9 @@ export function activate(ctx) {
|
|
|
326
372
|
await git(cwd, [
|
|
327
373
|
'commit', '-m',
|
|
328
374
|
`checkpoint: before creating branch ${branchName}`,
|
|
375
|
+
...(await ctx.storage.get(CO_AUTHOR_ENABLED_KEY) !== false
|
|
376
|
+
? ['-m', await getCoAuthorTrailer(ctx)]
|
|
377
|
+
: []),
|
|
329
378
|
]);
|
|
330
379
|
}
|
|
331
380
|
await git(cwd, ['checkout', '-b', branchName], 10_000);
|
package/i18n/en-US.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Git Branch",
|
|
3
3
|
"description": "Manage Git branches from the dialog box.",
|
|
4
|
-
"systemPrompt": "When
|
|
4
|
+
"systemPrompt": "When creating a Git branch, use create_git_branch. Pass branchName to create and check out a known branch without a form; otherwise omit it to collect the name in a form.",
|
|
5
5
|
"toolMeta": {
|
|
6
6
|
"name": "Git Branch"
|
|
7
7
|
},
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
|
|
14
|
+
"git.branch.coauthor.label": "Include {finchName} as code co-author",
|
|
15
|
+
"git.branch.coauthor.on": "On",
|
|
16
|
+
"git.branch.coauthor.off": "Off",
|
|
14
17
|
"git.branch.changes": "{count} changes",
|
|
15
18
|
"git.branch.more": "More branches",
|
|
16
19
|
"git.branch.more.group": "Branches",
|
|
@@ -39,5 +42,5 @@
|
|
|
39
42
|
"git.branch.create.success": "✅ Created and switched to branch `{name}`",
|
|
40
43
|
"git.branch.create.checkpoint": "\n\nUncommitted changes were auto-committed as a checkpoint.",
|
|
41
44
|
"tool.create.title": "Create Git Branch",
|
|
42
|
-
"tool.create.desc": "Create and switch to a new Git branch.
|
|
45
|
+
"tool.create.desc": "Create and switch to a new Git branch. Pass branchName to create it without a form when the name is known; otherwise omit it to collect the name in a form."
|
|
43
46
|
}
|
package/i18n/zh-CN.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Git 分支",
|
|
3
3
|
"description": "在对话框里管理 Git 分支的小工具",
|
|
4
|
-
"systemPrompt": "
|
|
4
|
+
"systemPrompt": "当需要创建 Git 分支时,使用 create_git_branch 工具。已确定分支名时传入 branchName 参数以静默创建并检出;否则省略该参数以弹出表单收集分支名。",
|
|
5
5
|
"toolMeta": {
|
|
6
6
|
"name": "Git 分支"
|
|
7
7
|
},
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
},
|
|
13
13
|
|
|
14
|
+
"git.branch.coauthor.label": "包含 {finchName} 作为代码协作者",
|
|
15
|
+
"git.branch.coauthor.on": "已开启",
|
|
16
|
+
"git.branch.coauthor.off": "已关闭",
|
|
14
17
|
"git.branch.changes": "{count} 个改动",
|
|
15
18
|
"git.branch.more": "更多分支",
|
|
16
19
|
"git.branch.more.group": "分支",
|
|
@@ -39,5 +42,5 @@
|
|
|
39
42
|
"git.branch.create.success": "✅ 已创建并切换到分支 `{name}`",
|
|
40
43
|
"git.branch.create.checkpoint": "\n\n已自动提交当前工作区的更改作为 checkpoint。",
|
|
41
44
|
"tool.create.title": "Create Git Branch",
|
|
42
|
-
"tool.create.desc": "
|
|
45
|
+
"tool.create.desc": "创建并检出 Git 分支。已确定分支名时传入 branchName 参数,以静默创建;否则省略该参数以打开表单收集分支名。"
|
|
43
46
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-handshake-icon lucide-handshake"><path d="m11 17 2 2a1 1 0 1 0 3-3"/><path d="m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4"/><path d="m21 3 1 11h-2"/><path d="M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3"/><path d="M3 4h8"/></svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "finch-git-branch",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "Git Branch Manager for Finch Composer toolbar.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Finch Team",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"id": "git-branch",
|
|
24
24
|
"name": "Git Branch",
|
|
25
25
|
"description": "Switch Git branches from the Composer toolbar with change previews.",
|
|
26
|
-
"systemPrompt": "
|
|
26
|
+
"systemPrompt": "When creating a Git branch, use create_git_branch. Pass branchName to create and check out a known branch without a form; otherwise omit it to collect the name in a form.",
|
|
27
27
|
"main": "dist/index.js",
|
|
28
28
|
"activationEvents": [
|
|
29
29
|
"onStartup"
|