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 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 items = [];
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(_input, exec) {
329
+ async execute(input, exec) {
291
330
  await exec.storage.delete('pendingCreateBranch').catch(() => { });
292
- const result = await exec.ui.requestForm({
293
- title: ctx.i18n.t('git.branch.create.title'),
294
- description: ctx.i18n.t('git.branch.create.desc'),
295
- submitLabel: ctx.i18n.t('git.branch.create.submit'),
296
- fields: [
297
- {
298
- key: 'branchName',
299
- label: ctx.i18n.t('git.branch.create.field'),
300
- type: 'text',
301
- required: true,
302
- placeholder: ctx.i18n.t('git.branch.create.ph'),
303
- },
304
- ],
305
- timeoutMs: 120_000,
306
- });
307
- if (!result.submitted) {
308
- return { content: [{ type: 'text', text: ctx.i18n.t('git.branch.create.cancelled') }] };
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 the user wants to create a new Git branch, use the create_git_branch tool which shows a form to collect the branch name.",
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. Opens a form to collect the branch name. Call when the user wants to create a new branch or says a branch name after clicking \"Create and checkout 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": "当用户需要创建 Git 分支时,使用 create_git_branch 工具。该工具会弹出表单让用户输入分支名称。",
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": "Create and switch to a new Git branch. Opens a form to collect the branch name. Call when the user wants to create a new branch or says a branch name after clicking \"创建并检出分支...\"."
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.8",
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": "当用户需要创建 Git 分支时,使用 create_git_branch 工具。该工具会弹出表单让用户输入分支名称。",
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"