@alpacachen/dsh-simple-worktree 1.0.4 → 1.0.6
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/README.md +21 -11
- package/README.zh.md +21 -11
- package/client/client.js +2 -2
- package/docs/preview.png +0 -0
- package/lib/index.js +14 -8
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# dsh-
|
|
1
|
+
# dsh-worktree
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A Git worktree plugin for DeepSeek Harness that creates task branches, registers worktrees as DSH Workspaces, and opens isolated sessions.
|
|
4
|
+
|
|
5
|
+
> npm package: `@alpacachen/dsh-simple-worktree`
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/@alpacachen/dsh-simple-worktree)
|
|
6
8
|

|
|
@@ -9,11 +11,13 @@ A lightweight Git worktree plugin for DeepSeek Harness.
|
|
|
9
11
|
|
|
10
12
|
[简体中文](README.zh.md) · **English**
|
|
11
13
|
|
|
14
|
+

|
|
15
|
+
|
|
12
16
|
## Features
|
|
13
17
|
|
|
14
|
-
- Create a Git worktree from any Git Workspace.
|
|
18
|
+
- Create a Git worktree from a new-session action or any Git Workspace menu.
|
|
15
19
|
- Choose the current branch or the repository's main branch.
|
|
16
|
-
- Register and open the new worktree as a DSH Workspace.
|
|
20
|
+
- Register and open the new worktree as a DSH Workspace with an isolated session.
|
|
17
21
|
- Create task branches as `task/<name>`.
|
|
18
22
|
- No additional service or project configuration.
|
|
19
23
|
- Supports DSH themes, Chinese, and English.
|
|
@@ -30,13 +34,19 @@ Restart `dsh web` after installation.
|
|
|
30
34
|
|
|
31
35
|
You can also install from GitHub with `dsh plugin --profile web add github:alpacachen/dsh-worktree`.
|
|
32
36
|
|
|
33
|
-
### Create a
|
|
37
|
+
### Create from a new session
|
|
38
|
+
|
|
39
|
+
1. Open **New Session** in a Git Workspace.
|
|
40
|
+
2. Choose **Create worktree** above the composer.
|
|
41
|
+
3. Enter a task name. The repository's main branch is selected by default.
|
|
42
|
+
4. Click **Create and open**.
|
|
43
|
+
|
|
44
|
+
### Create from a Workspace menu
|
|
34
45
|
|
|
35
|
-
1. Open a Git Workspace
|
|
36
|
-
2.
|
|
37
|
-
3.
|
|
38
|
-
4.
|
|
39
|
-
5. Click **Create and open**.
|
|
46
|
+
1. Open a Git Workspace menu and choose **Create worktree**.
|
|
47
|
+
2. Enter a task name, such as `login-fix`.
|
|
48
|
+
3. Choose **Current branch** or **Main branch**.
|
|
49
|
+
4. Click **Create and open**.
|
|
40
50
|
|
|
41
51
|
The worktree is created at:
|
|
42
52
|
|
|
@@ -45,4 +55,4 @@ project.worktrees/login-fix/
|
|
|
45
55
|
└── branch: task/login-fix
|
|
46
56
|
```
|
|
47
57
|
|
|
48
|
-
The new Workspace is named `<parent>/<task>`.
|
|
58
|
+
The new Workspace is named `<parent>/<task>`. Removing the worktree Workspace does not delete its Git branch.
|
package/README.zh.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
# dsh-
|
|
1
|
+
# dsh-worktree
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个用于 DeepSeek Harness 的 Git Worktree 插件:创建任务分支、注册 DSH Workspace,并打开隔离会话。
|
|
4
|
+
|
|
5
|
+
> npm 包:`@alpacachen/dsh-simple-worktree`
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/@alpacachen/dsh-simple-worktree)
|
|
6
8
|

|
|
@@ -9,11 +11,13 @@
|
|
|
9
11
|
|
|
10
12
|
**简体中文** · [English](README.md)
|
|
11
13
|
|
|
14
|
+

|
|
15
|
+
|
|
12
16
|
## 功能
|
|
13
17
|
|
|
14
|
-
-
|
|
18
|
+
- 从新建对话入口或任意 Git Workspace 菜单创建 Worktree。
|
|
15
19
|
- 支持当前分支和仓库主分支。
|
|
16
|
-
- 将新 Worktree
|
|
20
|
+
- 将新 Worktree 注册为 DSH Workspace,并打开隔离会话。
|
|
17
21
|
- 自动创建 `task/<name>` 格式的任务分支。
|
|
18
22
|
- 不需要额外服务或项目配置。
|
|
19
23
|
- 支持 DSH 主题、中文和英文界面。
|
|
@@ -30,13 +34,19 @@ dsh plugin --profile web add @alpacachen/dsh-simple-worktree
|
|
|
30
34
|
|
|
31
35
|
也可以通过 GitHub 安装:`dsh plugin --profile web add github:alpacachen/dsh-worktree`。
|
|
32
36
|
|
|
33
|
-
###
|
|
37
|
+
### 从新建对话创建
|
|
38
|
+
|
|
39
|
+
1. 在 Git Workspace 中打开**新建对话**。
|
|
40
|
+
2. 点击输入框上方的**创建 Worktree**。
|
|
41
|
+
3. 输入任务名称;此入口默认选择仓库主分支。
|
|
42
|
+
4. 点击**创建并打开**。
|
|
43
|
+
|
|
44
|
+
### 从 Workspace 菜单创建
|
|
34
45
|
|
|
35
|
-
1.
|
|
36
|
-
2.
|
|
37
|
-
3.
|
|
38
|
-
4.
|
|
39
|
-
5. 点击 **创建并打开**。
|
|
46
|
+
1. 打开 Git Workspace 菜单,选择**创建 Worktree**。
|
|
47
|
+
2. 输入任务名称,例如 `login-fix`。
|
|
48
|
+
3. 选择**当前分支**或**主分支**。
|
|
49
|
+
4. 点击**创建并打开**。
|
|
40
50
|
|
|
41
51
|
Worktree 会创建在:
|
|
42
52
|
|
|
@@ -45,4 +55,4 @@ project.worktrees/login-fix/
|
|
|
45
55
|
└── branch: task/login-fix
|
|
46
56
|
```
|
|
47
57
|
|
|
48
|
-
新 Workspace 的名称为 `<父 Workspace
|
|
58
|
+
新 Workspace 的名称为 `<父 Workspace>/<任务名称>`。删除 Worktree Workspace 不会删除对应的 Git 分支。
|
package/client/client.js
CHANGED
|
@@ -92,7 +92,7 @@ window.__ModuleLoader__.load({
|
|
|
92
92
|
.dswt-button-primary { min-width: 96px; border-color: var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary, #2563eb)); color: var(--dsw-alias-label-primary-foreground, #fff); background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-brand-primary, #2563eb)); }
|
|
93
93
|
.dswt-button-primary:hover:not(:disabled) { background: var(--dsw-alias-button-primary-hover, var(--dsw-alias-brand-primary, #2563eb)); }
|
|
94
94
|
.dswt-button:disabled { cursor: not-allowed; opacity: .5; }
|
|
95
|
-
.dswt-new-session-action { display: flex; box-sizing: border-box; width: 100%; justify-content: flex-start; }
|
|
95
|
+
.dswt-new-session-action { display: flex; box-sizing: border-box; width: 100%; justify-content: flex-start; padding-left: 20px; }
|
|
96
96
|
.dswt-new-session-button { min-height: 28px; padding: 4px 10px; border-radius: 7px; color: var(--dsw-alias-label-secondary, #666); background: var(--dsw-alias-bg-base, transparent); font-size: 12px; }
|
|
97
97
|
.dswt-new-session-button svg { width: 14px; height: 14px; }
|
|
98
98
|
.dswt-spin { animation: dswt-spin 1s linear infinite; }
|
|
@@ -148,7 +148,7 @@ window.__ModuleLoader__.load({
|
|
|
148
148
|
|
|
149
149
|
If you want to hide the \`${a.titleName}\`, you can wrap it with our VisuallyHidden component.
|
|
150
150
|
|
|
151
|
-
For more information, see https://radix-ui.com/primitives/docs/components/${a.docsSlug}`;return w.useEffect(()=>{e&&(document.getElementById(e)||console.error(t))},[t,e]),null},kr="DialogDescriptionWarning",yr=({contentRef:e,descriptionId:a})=>{let o=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${Gt(kr).contentName}}.`;return w.useEffect(()=>{let r=e.current?.getAttribute("aria-describedby");a&&r&&(document.getElementById(a)||console.warn(o))},[o,e,a]),null},Vt=At;var zt=Mt,_t=Ft,Xt=Tt,Kt=qt,jt=Ut,Zt=Wt;var _=require("react/jsx-runtime");function ve({className:e="",...a}){return(0,_.jsx)("button",{className:`dswt-button ${e}`,...a})}function Jt({className:e="",...a}){return(0,_.jsx)("input",{className:`dswt-input ${e}`,...a})}function $t({children:e,...a}){return(0,_.jsx)(Vt,{...a,children:e})}function Qt({children:e}){let a=de();return(0,_.jsxs)(zt,{children:[(0,_.jsx)(_t,{className:"dswt-dialog-overlay"}),(0,_.jsxs)(Xt,{className:"dswt-dialog-content",children:[e,(0,_.jsx)(Zt,{className:"dswt-dialog-close","aria-label":a("close"),children:(0,_.jsx)(Le,{size:16})})]})]})}var Yt=Kt,eo=jt;var S=require("react/jsx-runtime");function ao({target:e,api:a,workspaces:t,sessions:o,defaultBaseChoice:r="current",onCreated:u,onClose:d}){let l=de(),[n,f]=(0,Y.useState)(null),[c,p]=(0,Y.useState)(""),[L,m]=(0,Y.useState)(r),[x,s]=(0,Y.useState)(""),[i,h]=(0,Y.useState)(!1);(0,Y.useEffect)(()=>{let D=!0;return f(null),s(""),p(""),m(r),a.list(e.path).then(F=>{D&&f(F)}).catch(F=>{D&&s(String(F?.message??F))}),()=>{D=!1}},[a,r,e.path]);let C=n?.repoPath,v=Ba(c),R=`task/${v}`,b=C?Ma(C,v):"",A=n?.worktrees.find(D=>E(D.path)===E(e.path))?.branch??"HEAD",I=n?.defaultBranch??n?.worktrees.find(D=>D.isMain)?.branch??A,W=L==="main"?I:A,j=async()=>{if(!C||!c.trim()){s(l("fillTaskName"));return}h(!0),s("");let D,F;try{let X=await a.create({repoPath:C,path:b,branch:R,baseRef:W});D=X.path,F=await t.create({path:X.path}),await t.rename(F.workspaceId,`${e.title}/${v}`);let lo=await t.connectWorkspace(F.workspaceId);u(X.path),o.open(lo),d()}catch(X){F?.workspaceId&&t.delete(F.workspaceId).catch(()=>{}),D&&a.remove({repoPath:C,path:D}).catch(()=>{}),s(`${l("operationFailed")}${String(X?.message??X)}`)}finally{h(!1)}};return(0,S.jsx)($t,{open:!0,onOpenChange:D=>{!D&&!i&&d()},children:(0,S.jsxs)(Qt,{children:[(0,S.jsx)(Yt,{className:"dswt-dialog-title",children:Da(l("dialogTitle"),{name:e.title})}),(0,S.jsx)(eo,{className:"dswt-visually-hidden",children:e.title}),x?(0,S.jsxs)("div",{className:"dswt-error",role:"alert",children:[(0,S.jsx)(Z,{size:14})," ",x]}):null,(0,S.jsxs)("label",{className:"dswt-field",children:[(0,S.jsx)("span",{className:"dswt-field-label",children:l("taskName")}),(0,S.jsx)(Jt,{"aria-label":l("taskName"),value:c,disabled:i,onChange:D=>p(D.target.value),placeholder:l("taskNamePlaceholder"),autoFocus:!0})]}),(0,S.jsxs)("fieldset",{className:"dswt-field dswt-base-fieldset",disabled:i||!n,children:[(0,S.jsx)("legend",{className:"dswt-field-label",children:l("basedOn")}),(0,S.jsxs)("div",{className:"dswt-radio-group",role:"radiogroup","aria-label":l("basedOn"),children:[(0,S.jsxs)("label",{className:"dswt-radio-option","data-selected":L==="current"?"true":void 0,children:[(0,S.jsx)("input",{className:"dswt-radio-input",type:"radio",name:"dswt-base-branch",value:"current",checked:L==="current",onChange:()=>m("current")}),(0,S.jsxs)("span",{className:"dswt-radio-copy",children:[(0,S.jsx)("span",{className:"dswt-radio-label",children:l("currentBranch")}),(0,S.jsx)("span",{className:"dswt-radio-branch",children:A})]})]}),(0,S.jsxs)("label",{className:"dswt-radio-option","data-selected":L==="main"?"true":void 0,children:[(0,S.jsx)("input",{className:"dswt-radio-input",type:"radio",name:"dswt-base-branch",value:"main",checked:L==="main",onChange:()=>m("main")}),(0,S.jsxs)("span",{className:"dswt-radio-copy",children:[(0,S.jsx)("span",{className:"dswt-radio-label",children:l("mainBranch")}),(0,S.jsx)("span",{className:"dswt-radio-branch",children:I})]})]})]})]}),(0,S.jsxs)("div",{className:"dswt-dialog-actions",children:[(0,S.jsx)(ve,{type:"button",disabled:i,onClick:d,children:l("cancel")}),(0,S.jsxs)(ve,{type:"button",className:"dswt-button-primary",disabled:i||!c.trim()||!n,onClick:j,children:[i?(0,S.jsx)(J,{size:14,className:"dswt-spin"}):null,l(i?"creating":"createAndOpen")]})]})]})})}var ue=require("react/jsx-runtime");function Pe(){return(0,ue.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[(0,ue.jsx)("path",{d:"M4 2.25v8.5a2.25 2.25 0 1 0 1.5 0V7.75h4v3a2.25 2.25 0 1 0 1.5 0V6.25H5.5v-4H4Z",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"4.75",cy:"12.75",r:"1.5",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"10.25",cy:"12.75",r:"1.5",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"4.75",cy:"2.25",r:"1.5",fill:"currentColor"})]})}var ke=require("react/jsx-runtime");function to({session:e,useWorkspaces:a,onOpen:t}){let o=de(),r=a(u=>u.items.find(d=>d.sessionIds?.includes(e.sessionId)));return!e.blank||!r?null:(0,ke.jsx)("div",{className:"dswt-new-session-action",children:(0,ke.jsxs)(ve,{type:"button",className:"dswt-new-session-button",onClick:()=>t(r),children:[(0,ke.jsx)(Pe,{}),o("createWorktree")]})})}var Rr="/dsh-simple-worktree";function oo(e){async function a(t,o){let r=await e.rpc.call(Rr,t,o);if(!r?.ok){let u=new Error(r?.error?.message??"worktree operation failed");throw u.code=r?.error?.code,u}return r.value}return{list:t=>a("worktree.list",{path:t}),classify:t=>a("worktree.classify",{path:t}),create:t=>a("worktree.create",t),remove:t=>a("worktree.remove",t)}}var ye=require("react/jsx-runtime"),ro="data-dsh-simple-worktree-style";function Ar(){if(typeof document>"u"||document.querySelector(`style[${ro}]`))return;let e=document.createElement("style");e.setAttribute(ro,""),e.textContent=wa,document.head.appendChild(e)}var uo={name:"@alpacachen/dsh-simple-worktree",inject:["slots","connection","locale","workspaces","sessions","workspaceExtensions"],apply(e){Ar
|
|
151
|
+
For more information, see https://radix-ui.com/primitives/docs/components/${a.docsSlug}`;return w.useEffect(()=>{e&&(document.getElementById(e)||console.error(t))},[t,e]),null},kr="DialogDescriptionWarning",yr=({contentRef:e,descriptionId:a})=>{let o=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${Gt(kr).contentName}}.`;return w.useEffect(()=>{let r=e.current?.getAttribute("aria-describedby");a&&r&&(document.getElementById(a)||console.warn(o))},[o,e,a]),null},Vt=At;var zt=Mt,_t=Ft,Xt=Tt,Kt=qt,jt=Ut,Zt=Wt;var _=require("react/jsx-runtime");function ve({className:e="",...a}){return(0,_.jsx)("button",{className:`dswt-button ${e}`,...a})}function Jt({className:e="",...a}){return(0,_.jsx)("input",{className:`dswt-input ${e}`,...a})}function $t({children:e,...a}){return(0,_.jsx)(Vt,{...a,children:e})}function Qt({children:e}){let a=de();return(0,_.jsxs)(zt,{children:[(0,_.jsx)(_t,{className:"dswt-dialog-overlay"}),(0,_.jsxs)(Xt,{className:"dswt-dialog-content",children:[e,(0,_.jsx)(Zt,{className:"dswt-dialog-close","aria-label":a("close"),children:(0,_.jsx)(Le,{size:16})})]})]})}var Yt=Kt,eo=jt;var S=require("react/jsx-runtime");function ao({target:e,api:a,workspaces:t,sessions:o,defaultBaseChoice:r="current",onCreated:u,onClose:d}){let l=de(),[n,f]=(0,Y.useState)(null),[c,p]=(0,Y.useState)(""),[L,m]=(0,Y.useState)(r),[x,s]=(0,Y.useState)(""),[i,h]=(0,Y.useState)(!1);(0,Y.useEffect)(()=>{let D=!0;return f(null),s(""),p(""),m(r),a.list(e.path).then(F=>{D&&f(F)}).catch(F=>{D&&s(String(F?.message??F))}),()=>{D=!1}},[a,r,e.path]);let C=n?.repoPath,v=Ba(c),R=`task/${v}`,b=C?Ma(C,v):"",A=n?.worktrees.find(D=>E(D.path)===E(e.path))?.branch??"HEAD",I=n?.defaultBranch??n?.worktrees.find(D=>D.isMain)?.branch??A,W=L==="main"?n?.defaultRef??I:A,j=async()=>{if(!C||!c.trim()){s(l("fillTaskName"));return}h(!0),s("");let D,F;try{let X=await a.create({repoPath:C,path:b,branch:R,baseRef:W});D=X.path,F=await t.create({path:X.path}),await t.rename(F.workspaceId,`${e.title}/${v}`);let lo=await t.connectWorkspace(F.workspaceId);u(X.path),o.open(lo),d()}catch(X){F?.workspaceId&&t.delete(F.workspaceId).catch(()=>{}),D&&a.remove({repoPath:C,path:D}).catch(()=>{}),s(`${l("operationFailed")}${String(X?.message??X)}`)}finally{h(!1)}};return(0,S.jsx)($t,{open:!0,onOpenChange:D=>{!D&&!i&&d()},children:(0,S.jsxs)(Qt,{children:[(0,S.jsx)(Yt,{className:"dswt-dialog-title",children:Da(l("dialogTitle"),{name:e.title})}),(0,S.jsx)(eo,{className:"dswt-visually-hidden",children:e.title}),x?(0,S.jsxs)("div",{className:"dswt-error",role:"alert",children:[(0,S.jsx)(Z,{size:14})," ",x]}):null,(0,S.jsxs)("label",{className:"dswt-field",children:[(0,S.jsx)("span",{className:"dswt-field-label",children:l("taskName")}),(0,S.jsx)(Jt,{"aria-label":l("taskName"),value:c,disabled:i,onChange:D=>p(D.target.value),placeholder:l("taskNamePlaceholder"),autoFocus:!0})]}),(0,S.jsxs)("fieldset",{className:"dswt-field dswt-base-fieldset",disabled:i||!n,children:[(0,S.jsx)("legend",{className:"dswt-field-label",children:l("basedOn")}),(0,S.jsxs)("div",{className:"dswt-radio-group",role:"radiogroup","aria-label":l("basedOn"),children:[(0,S.jsxs)("label",{className:"dswt-radio-option","data-selected":L==="current"?"true":void 0,children:[(0,S.jsx)("input",{className:"dswt-radio-input",type:"radio",name:"dswt-base-branch",value:"current",checked:L==="current",onChange:()=>m("current")}),(0,S.jsxs)("span",{className:"dswt-radio-copy",children:[(0,S.jsx)("span",{className:"dswt-radio-label",children:l("currentBranch")}),(0,S.jsx)("span",{className:"dswt-radio-branch",children:A})]})]}),(0,S.jsxs)("label",{className:"dswt-radio-option","data-selected":L==="main"?"true":void 0,children:[(0,S.jsx)("input",{className:"dswt-radio-input",type:"radio",name:"dswt-base-branch",value:"main",checked:L==="main",onChange:()=>m("main")}),(0,S.jsxs)("span",{className:"dswt-radio-copy",children:[(0,S.jsx)("span",{className:"dswt-radio-label",children:l("mainBranch")}),(0,S.jsx)("span",{className:"dswt-radio-branch",children:I})]})]})]})]}),(0,S.jsxs)("div",{className:"dswt-dialog-actions",children:[(0,S.jsx)(ve,{type:"button",disabled:i,onClick:d,children:l("cancel")}),(0,S.jsxs)(ve,{type:"button",className:"dswt-button-primary",disabled:i||!c.trim()||!n,onClick:j,children:[i?(0,S.jsx)(J,{size:14,className:"dswt-spin"}):null,l(i?"creating":"createAndOpen")]})]})]})})}var ue=require("react/jsx-runtime");function Pe(){return(0,ue.jsxs)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[(0,ue.jsx)("path",{d:"M4 2.25v8.5a2.25 2.25 0 1 0 1.5 0V7.75h4v3a2.25 2.25 0 1 0 1.5 0V6.25H5.5v-4H4Z",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"4.75",cy:"12.75",r:"1.5",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"10.25",cy:"12.75",r:"1.5",fill:"currentColor"}),(0,ue.jsx)("circle",{cx:"4.75",cy:"2.25",r:"1.5",fill:"currentColor"})]})}var ke=require("react/jsx-runtime");function to({session:e,useWorkspaces:a,onOpen:t}){let o=de(),r=a(u=>u.items.find(d=>d.sessionIds?.includes(e.sessionId)));return!e.blank||!r?null:(0,ke.jsx)("div",{className:"dswt-new-session-action",children:(0,ke.jsxs)(ve,{type:"button",className:"dswt-new-session-button",onClick:()=>t(r),children:[(0,ke.jsx)(Pe,{}),o("createWorktree")]})})}var Rr="/dsh-simple-worktree";function oo(e){async function a(t,o){let r=await e.rpc.call(Rr,t,o);if(!r?.ok){let u=new Error(r?.error?.message??"worktree operation failed");throw u.code=r?.error?.code,u}return r.value}return{list:t=>a("worktree.list",{path:t}),classify:t=>a("worktree.classify",{path:t}),create:t=>a("worktree.create",t),remove:t=>a("worktree.remove",t)}}var ye=require("react/jsx-runtime"),ro="data-dsh-simple-worktree-style";function Ar(){if(typeof document>"u"||document.querySelector(`style[${ro}]`))return;let e=document.createElement("style");return e.setAttribute(ro,""),e.textContent=wa,document.head.appendChild(e),()=>e.remove()}var uo={name:"@alpacachen/dsh-simple-worktree",inject:["slots","connection","locale","workspaces","sessions","workspaceExtensions"],apply(e){e.effect(Ar,"dsh-simple-worktree styles"),e.effect(()=>Aa(e),"dsh-simple-worktree locale");let a=oo(e.connection),t=e.workspaces,o=e.sessions,r=e.get("locale"),u=e.workspaceExtensions,d=new Set;e.effect(()=>{if(!(!r||typeof r.subscribe!="function"))return r.subscribe(()=>u.invalidate())},"dsh-simple-worktree locale refresh");let l=new Set,n=!0,f=()=>{},c=0,p=async()=>{let m=++c,x=t.list.getSnapshot().items,s=await Promise.all(x.map(async i=>{try{return await a.classify(i.path)}catch{return}}));if(!(!n||m!==c)){d.clear(),l.clear();for(let i of s)i?.isGit&&i.path&&d.add(E(i.path)),i?.isWorktree&&i.path&&l.add(E(i.path));u.invalidate()}};e.effect(()=>u.register({id:"dsh-simple-worktree",menuItem(x){let s=E(x.path);if(!(!d.has(s)||l.has(s)))return{id:"dsh-simple-worktree.create",label:Ie("createWorktree"),icon:(0,ye.jsx)(Pe,{}),order:30,onSelect:()=>f(x)}},deleteWorkspace(x){let s=E(x.path);if(l.has(s))return(async()=>{let i=await a.classify(x.path);!i.isWorktree||!i.repoPath||(await a.remove({repoPath:i.repoPath,path:x.path}),await t.delete(x.workspaceId),d.delete(s),l.delete(s),u.invalidate())})()},icon(x){return l.has(E(x.path))?(0,ye.jsx)(Pe,{}):void 0}}),"dsh-simple-worktree workspace extensions"),e.effect(()=>{n=!0;let m=t.list.subscribe(()=>{p()});return p(),()=>{n=!1,c+=1,m()}},"dsh-simple-worktree workspace classification");function L(){let[m,x]=(0,ze.useState)(null);return(0,ze.useEffect)(()=>(f=(s,i="current")=>x({target:s,defaultBaseChoice:i}),()=>{f=()=>{}}),[]),m?(0,ye.jsx)(ao,{target:m.target,api:a,workspaces:t,sessions:o,defaultBaseChoice:m.defaultBaseChoice,onCreated:s=>{d.add(E(s)),l.add(E(s)),u.invalidate()},onClose:()=>x(null)}):null}e.slots.inject("conversation.input.dock",()=>e.slots.register({name:"conversation.input.dock",id:"dsh-simple-worktree-new-session",order:-30,locale:xe,label:()=>Ie("createWorktree")},m=>(0,ye.jsx)(to,{session:m.session,useWorkspaces:m.useWorkspaces,onOpen:x=>f(x,"main")}))),e.slots.inject("shell.overlay",()=>e.slots.register({name:"shell.overlay",id:"dsh-simple-worktree-create",order:30,locale:xe,label:()=>Ie("createWorktree")},L))}};var Dr=uo;
|
|
152
152
|
/*! Bundled license information:
|
|
153
153
|
|
|
154
154
|
lucide-react/dist/esm/shared/src/utils.js:
|
package/docs/preview.png
ADDED
|
Binary file
|
package/lib/index.js
CHANGED
|
@@ -42,18 +42,24 @@ async function tryRunGit(subprocess, cwd, args) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export async function detectDefaultBranch(subprocess, repoPath, worktrees) {
|
|
45
|
-
const remoteHead = await
|
|
45
|
+
const [remoteHead, refsOutput] = await Promise.all([
|
|
46
|
+
tryRunGit(subprocess, repoPath, ['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD']),
|
|
47
|
+
tryRunGit(subprocess, repoPath, ['for-each-ref', '--format=%(refname:short)', 'refs/heads', 'refs/remotes/origin']),
|
|
48
|
+
])
|
|
49
|
+
const refs = new Set(refsOutput.split(/\r?\n/).filter(Boolean))
|
|
50
|
+
|
|
46
51
|
if (remoteHead) {
|
|
47
52
|
const separator = remoteHead.indexOf('/')
|
|
48
|
-
|
|
53
|
+
const name = separator >= 0 ? remoteHead.slice(separator + 1) : ''
|
|
54
|
+
if (name) return { name, ref: refs.has(name) ? name : remoteHead }
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (branches.includes(preferred)) return preferred
|
|
57
|
+
for (const name of ['main', 'master', 'trunk', 'develop']) {
|
|
58
|
+
if (refs.has(name)) return { name, ref: name }
|
|
59
|
+
if (refs.has(`origin/${name}`)) return { name, ref: `origin/${name}` }
|
|
55
60
|
}
|
|
56
|
-
|
|
61
|
+
const name = worktrees.find((worktree) => worktree.isMain)?.branch ?? worktrees.find((worktree) => worktree.branch)?.branch
|
|
62
|
+
return name ? { name, ref: name } : { name: 'HEAD', ref: 'HEAD' }
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
export function parseWorktrees(text) {
|
|
@@ -123,7 +129,7 @@ export function apply(ctx) {
|
|
|
123
129
|
const worktrees = parseWorktrees(porcelain)
|
|
124
130
|
const repoPath = worktrees.find((worktree) => worktree.isMain)?.path ?? topLevel
|
|
125
131
|
const defaultBranch = await detectDefaultBranch(ctx.subprocess, repoPath, worktrees)
|
|
126
|
-
|
|
132
|
+
return { repoPath, commonDir, defaultBranch: defaultBranch.name, defaultRef: defaultBranch.ref, worktrees }
|
|
127
133
|
}, classifyGitError)
|
|
128
134
|
|
|
129
135
|
if (endpoint === 'worktree.classify') return recover(async () => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alpacachen/dsh-simple-worktree",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "A Git worktree plugin for DeepSeek Harness that creates task branches, registers worktrees as DSH Workspaces, and opens isolated sessions.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"deepseek-harness",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"cordis.patch.yml",
|
|
36
36
|
"package.json",
|
|
37
37
|
"README.md",
|
|
38
|
-
"README.zh.md"
|
|
38
|
+
"README.zh.md",
|
|
39
|
+
"docs/preview.png"
|
|
39
40
|
],
|
|
40
41
|
"scripts": {
|
|
41
42
|
"build": "node build.mjs",
|