@hunan36/dsh-git-flow 0.0.0-stage → 0.4.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/LICENSE +21 -0
- package/README.md +253 -2
- package/README.zh.md +262 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +2138 -0
- package/lib/index.js +1347 -0
- package/lib/types/client/BranchChip.d.ts +8 -0
- package/lib/types/client/BranchMenu.d.ts +27 -0
- package/lib/types/client/CommitDialog.d.ts +45 -0
- package/lib/types/client/GitFlowDialog.d.ts +37 -0
- package/lib/types/client/api.d.ts +42 -0
- package/lib/types/client/index.d.ts +14 -0
- package/lib/types/client/locales.d.ts +236 -0
- package/lib/types/client/styles.d.ts +12 -0
- package/lib/types/contract.d.ts +207 -0
- package/lib/types/git.d.ts +86 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/message.d.ts +27 -0
- package/lib/types/routes.d.ts +14 -0
- package/lib/types/service.d.ts +178 -0
- package/package.json +92 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
/** Props the session-scoped slot delivers to this entry. */
|
|
3
|
+
export interface GitFlowChipProps {
|
|
4
|
+
sessionId: string;
|
|
5
|
+
t: TranslateNS<'gitFlow'>;
|
|
6
|
+
}
|
|
7
|
+
/** Branch chip for the session's workspace; renders nothing outside a repository. */
|
|
8
|
+
export declare function GitFlowChip({ sessionId, t }: GitFlowChipProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { GitBranchesView, GitFlowStateView, GitStatusView } from '../contract.ts';
|
|
3
|
+
/** Branch popover props. */
|
|
4
|
+
export interface BranchMenuProps {
|
|
5
|
+
t: TranslateNS<'gitFlow'>;
|
|
6
|
+
status: GitStatusView;
|
|
7
|
+
/** Branch table, loaded on first open. */
|
|
8
|
+
branches: GitBranchesView | undefined;
|
|
9
|
+
/** True while a load or switch is in flight; the chip shows a busy state. */
|
|
10
|
+
busy: boolean;
|
|
11
|
+
open: boolean;
|
|
12
|
+
onOpenChange: (open: boolean) => void;
|
|
13
|
+
onSelectBranch: (name: string) => void;
|
|
14
|
+
onNewBranch: () => void;
|
|
15
|
+
onCommit: () => void;
|
|
16
|
+
/** Push what is already committed, without opening the commit panel. */
|
|
17
|
+
onPush: () => void;
|
|
18
|
+
/** Pull the current branch's upstream (`--ff-only`). */
|
|
19
|
+
onPull: () => void;
|
|
20
|
+
onRefresh: () => void;
|
|
21
|
+
/** Flow state of the current branch; absent until it has been read. */
|
|
22
|
+
flow: GitFlowStateView | undefined;
|
|
23
|
+
onStartFlow: () => void;
|
|
24
|
+
onFinishFlow: () => void;
|
|
25
|
+
}
|
|
26
|
+
/** Pill plus anchored branch picker: pinned search, scrolling rows, pinned actions. */
|
|
27
|
+
export declare function BranchMenu(props: BranchMenuProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { GitStatusView } from '../contract.ts';
|
|
3
|
+
/** What a dialog reports back to the chip that owns it. */
|
|
4
|
+
export interface DialogHost {
|
|
5
|
+
t: TranslateNS<'gitFlow'>;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
/** Transient banner text; `failed` renders the warning glyph. */
|
|
8
|
+
notify: (text: string, failed?: boolean) => void;
|
|
9
|
+
/** Re-read status after the repository changed. */
|
|
10
|
+
refresh: () => void;
|
|
11
|
+
}
|
|
12
|
+
/** Commit composer: pick paths, draft or write the message, commit, optionally push. */
|
|
13
|
+
export declare function CommitDialog(props: CommitDialogProps): import("react").JSX.Element;
|
|
14
|
+
/**
|
|
15
|
+
* Confirmation for a destructive discard. Nothing is sent until the user picks
|
|
16
|
+
* the destructive action here.
|
|
17
|
+
*/
|
|
18
|
+
export declare function DiscardDialog(props: DiscardDialogProps): import("react").JSX.Element;
|
|
19
|
+
/** Discard dialog props. */
|
|
20
|
+
export interface DiscardDialogProps extends DialogHost {
|
|
21
|
+
files: string[];
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
}
|
|
24
|
+
/** Commit dialog props. */
|
|
25
|
+
export interface CommitDialogProps extends DialogHost {
|
|
26
|
+
status: GitStatusView;
|
|
27
|
+
onClose: () => void;
|
|
28
|
+
}
|
|
29
|
+
/** Ask for a branch name, create it from the current HEAD, and switch to it. */
|
|
30
|
+
export declare function CreateBranchDialog(props: CreateBranchDialogProps): import("react").JSX.Element;
|
|
31
|
+
/** New-branch dialog props. */
|
|
32
|
+
export interface CreateBranchDialogProps extends DialogHost {
|
|
33
|
+
status: GitStatusView;
|
|
34
|
+
onClose: () => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A switch that git refused because it would overwrite local edits. The first
|
|
38
|
+
* attempt runs without `force`; only this second confirmation sends it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function ForceCheckoutDialog(props: ForceCheckoutDialogProps): import("react").JSX.Element;
|
|
41
|
+
/** Forced-switch dialog props. */
|
|
42
|
+
export interface ForceCheckoutDialogProps extends DialogHost {
|
|
43
|
+
branch: string;
|
|
44
|
+
onClose: () => void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { GitFlowStateView, GitStatusView } from '../contract.ts';
|
|
2
|
+
import type { DialogHost } from './CommitDialog.tsx';
|
|
3
|
+
/** Start dialog props. */
|
|
4
|
+
export interface StartFlowDialogProps extends DialogHost {
|
|
5
|
+
state: GitFlowStateView;
|
|
6
|
+
status: GitStatusView;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
/** A start refused for a missing develop hands off to the init dialog. */
|
|
9
|
+
onNeedDevelop: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Name a flow branch and create it from the branch its family starts at.
|
|
13
|
+
* A missing develop is not an error the user can fix in this dialog, so it
|
|
14
|
+
* closes and hands off to the guided creation instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function StartFlowDialog(props: StartFlowDialogProps): import("react").JSX.Element;
|
|
17
|
+
/** Init-develop dialog props. */
|
|
18
|
+
export interface InitDevelopDialogProps extends DialogHost {
|
|
19
|
+
state: GitFlowStateView;
|
|
20
|
+
status: GitStatusView;
|
|
21
|
+
onClose: () => void;
|
|
22
|
+
/** Continue whatever asked for develop in the first place. */
|
|
23
|
+
onDone: () => void;
|
|
24
|
+
}
|
|
25
|
+
/** Create the integration branch from production (or HEAD when there is none). */
|
|
26
|
+
export declare function InitDevelopDialog(props: InitDevelopDialogProps): import("react").JSX.Element;
|
|
27
|
+
/** Finish dialog props. */
|
|
28
|
+
export interface FinishFlowDialogProps extends DialogHost {
|
|
29
|
+
state: GitFlowStateView;
|
|
30
|
+
status: GitStatusView;
|
|
31
|
+
onClose: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Confirm and run the finish sequence. The step list is generated from the same
|
|
35
|
+
* facts the host will act on, so what the user reads is what will happen.
|
|
36
|
+
*/
|
|
37
|
+
export declare function FinishFlowDialog(props: FinishFlowDialogProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed fetch wrapper for `/api/dsh-git-flow/*`. Every call names only the
|
|
3
|
+
* session; the host resolves the repository.
|
|
4
|
+
*/
|
|
5
|
+
import type { TranslateNS } from '@deepseek-ai/dsh-client-ui-slots';
|
|
6
|
+
import type { CheckoutRequest, DiscardRequest, CreateBranchRequest, CommitRequest, GenerateMessageRequest, GitBranchesView, GitCommitView, GitErrorCode, GitFlowFinishView, GitFlowStartRequest, GitFlowStateView, GitMessageView, GitPullView, GitPushView, GitStatusView } from '../contract.ts';
|
|
7
|
+
/** A git operation refused by the host, carrying its structured code. */
|
|
8
|
+
export declare class GitApiError extends Error {
|
|
9
|
+
readonly code: GitErrorCode;
|
|
10
|
+
constructor(code: GitErrorCode, message: string);
|
|
11
|
+
}
|
|
12
|
+
/** Whether an error should hide the branch chip instead of reporting itself. */
|
|
13
|
+
export declare function isSilentError(error: unknown): boolean;
|
|
14
|
+
/** Whether an error means the checked paths are out of date. */
|
|
15
|
+
export declare function isStaleSelection(error: unknown): boolean;
|
|
16
|
+
/** Human-readable failure text for any thrown value. */
|
|
17
|
+
export declare function errorText(t: TranslateNS<'gitFlow'>, error: unknown): string;
|
|
18
|
+
/** The browser-side git API. */
|
|
19
|
+
export declare const gitApi: {
|
|
20
|
+
status: (sessionId: string) => Promise<GitStatusView>;
|
|
21
|
+
branches: (sessionId: string) => Promise<GitBranchesView>;
|
|
22
|
+
checkout: (body: CheckoutRequest) => Promise<GitStatusView>;
|
|
23
|
+
createBranch: (body: CreateBranchRequest) => Promise<GitStatusView>;
|
|
24
|
+
commit: (body: CommitRequest) => Promise<GitCommitView>;
|
|
25
|
+
discard: (body: DiscardRequest) => Promise<GitStatusView>;
|
|
26
|
+
push: (body: {
|
|
27
|
+
sessionId: string;
|
|
28
|
+
}) => Promise<GitPushView>;
|
|
29
|
+
pull: (body: {
|
|
30
|
+
sessionId: string;
|
|
31
|
+
}) => Promise<GitPullView>;
|
|
32
|
+
generateMessage: (body: GenerateMessageRequest) => Promise<GitMessageView>;
|
|
33
|
+
gitflowState: (sessionId: string) => Promise<GitFlowStateView>;
|
|
34
|
+
startFlow: (body: GitFlowStartRequest) => Promise<GitStatusView>;
|
|
35
|
+
initDevelop: (body: {
|
|
36
|
+
sessionId: string;
|
|
37
|
+
}) => Promise<GitStatusView>;
|
|
38
|
+
finishFlow: (body: {
|
|
39
|
+
sessionId: string;
|
|
40
|
+
version?: string;
|
|
41
|
+
}) => Promise<GitFlowFinishView>;
|
|
42
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-git-flow, browser half. Registers the `gitFlow` dictionary and one
|
|
3
|
+
* `conversation.input.left` entry: the branch chip and everything it opens.
|
|
4
|
+
* Loaded by the harness module loader as `dsh-git-flow/client.js`.
|
|
5
|
+
* @module dsh-git-flow/client
|
|
6
|
+
*/
|
|
7
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
8
|
+
/** Services this fiber needs before it activates. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Mount the branch chip and its copy.
|
|
12
|
+
* @param ctx - client root context.
|
|
13
|
+
*/
|
|
14
|
+
export declare function apply(ctx: Context): void;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser copy for the git surface. Both dictionaries carry the same keys;
|
|
3
|
+
* `en` is typed against `zh` so a missing key is a compile error.
|
|
4
|
+
*/
|
|
5
|
+
export declare const GIT_FLOW_NS = "gitFlow";
|
|
6
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
7
|
+
interface LocaleNamespaceMap {
|
|
8
|
+
/** Branch, commit, and push copy owned by this plugin. */
|
|
9
|
+
gitFlow: GitFlowKey;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
declare const zh: {
|
|
13
|
+
readonly 'chip.tooltip': "当前分支 {branch},{count} 个未提交改动";
|
|
14
|
+
readonly 'chip.tooltip.clean': "当前分支 {branch},工作区干净";
|
|
15
|
+
readonly 'chip.aheadBehind': "领先 {ahead},落后 {behind}";
|
|
16
|
+
readonly 'chip.unpushed': "有 {count} 个提交未推送";
|
|
17
|
+
readonly 'menu.search': "搜索分支";
|
|
18
|
+
readonly 'menu.local': "本地分支";
|
|
19
|
+
readonly 'menu.remote': "仅在远端";
|
|
20
|
+
readonly 'menu.empty': "没有匹配的分支";
|
|
21
|
+
readonly 'menu.loading': "读取分支…";
|
|
22
|
+
readonly 'menu.newBranch': "新建分支…";
|
|
23
|
+
readonly 'menu.commit': "提交…";
|
|
24
|
+
readonly 'menu.push': "推送提交";
|
|
25
|
+
readonly 'menu.pull': "拉取远程代码";
|
|
26
|
+
readonly 'menu.refresh': "刷新状态";
|
|
27
|
+
readonly 'menu.startFlow': "启动 Git Flow 分支…";
|
|
28
|
+
readonly 'menu.finishFlow': "完成 Git Flow 分支…";
|
|
29
|
+
readonly 'flow.feature': "功能";
|
|
30
|
+
readonly 'flow.release': "发布";
|
|
31
|
+
readonly 'flow.hotfix': "热修复";
|
|
32
|
+
readonly 'flow.badge': "{kind}";
|
|
33
|
+
readonly 'start.title': "启动 Git Flow 分支";
|
|
34
|
+
readonly 'start.description': "功能与发布分支从 {develop} 切出,热修复从 {production} 切出。";
|
|
35
|
+
readonly 'start.kind': "分支类型";
|
|
36
|
+
readonly 'start.name': "名称";
|
|
37
|
+
readonly 'start.placeholder': "例如 login,将创建 {prefix}login";
|
|
38
|
+
readonly 'start.submit': "创建并切换";
|
|
39
|
+
readonly 'start.done': "已创建并切换到 {branch}";
|
|
40
|
+
readonly 'start.needName': "请先填写名称";
|
|
41
|
+
readonly 'start.base': "将从 {base} 切出";
|
|
42
|
+
readonly 'start.versionHint': "发布与热修复的名称建议带版本号,例如 0.4.0";
|
|
43
|
+
readonly 'initDevelop.title': "还没有 {develop} 分支";
|
|
44
|
+
readonly 'initDevelop.description': "Git Flow 需要一个集成分支。将从 {from} 创建 {develop} 并切换过去。";
|
|
45
|
+
readonly 'initDevelop.submit': "创建 {develop}";
|
|
46
|
+
readonly 'initDevelop.done': "已创建 {develop}";
|
|
47
|
+
readonly 'finish.title': "完成 {branch}";
|
|
48
|
+
readonly 'finish.description': "以下动作会依次执行,合并提交与标签一旦创建就不会回滚。";
|
|
49
|
+
readonly 'finish.mergeInto': "合并到 {targets}(--no-ff)";
|
|
50
|
+
readonly 'finish.tag': "创建标签 {tag}";
|
|
51
|
+
readonly 'finish.version': "把 package.json 版本改为 {version}";
|
|
52
|
+
readonly 'finish.push': "推送分支与标签到 origin";
|
|
53
|
+
readonly 'finish.delete': "删除已完成的本地分支";
|
|
54
|
+
readonly 'finish.versionLabel': "版本号";
|
|
55
|
+
readonly 'finish.submit': "完成并合并";
|
|
56
|
+
readonly 'finish.tagExists': "标签 {tag} 已存在,请先改用其它版本号";
|
|
57
|
+
readonly 'finish.done': "已完成 {branch}";
|
|
58
|
+
readonly 'finish.partial': "{branch} 已在本地完成,但推送失败:{detail}";
|
|
59
|
+
readonly 'finish.merged': "已合并到 {targets}";
|
|
60
|
+
readonly 'finish.tagCreated': "已创建标签 {tag}";
|
|
61
|
+
readonly 'finish.versionWritten': "已提交版本号 {version}";
|
|
62
|
+
readonly 'finish.deleted': "已删除本地分支";
|
|
63
|
+
readonly 'finish.pushFail': "推送失败:{detail}";
|
|
64
|
+
readonly 'checkout.done': "已切换到 {branch}";
|
|
65
|
+
readonly 'checkout.dirtyTitle': "工作区有未提交改动";
|
|
66
|
+
readonly 'checkout.dirtyBody': "切换到 {branch} 会覆盖本地改动。可以先提交,或者强制切换(`git switch --force` 会丢弃全部本地改动)。";
|
|
67
|
+
readonly 'checkout.force': "强制切换";
|
|
68
|
+
readonly 'create.title': "新建分支";
|
|
69
|
+
readonly 'create.description': "基于当前分支 {branch} 创建并切换。";
|
|
70
|
+
readonly 'create.name': "分支名称";
|
|
71
|
+
readonly 'create.placeholder': "例如 feature/git-flow";
|
|
72
|
+
readonly 'create.submit': "创建并切换";
|
|
73
|
+
readonly 'create.done': "已创建并切换到 {branch}";
|
|
74
|
+
readonly 'commit.title': "提交改动";
|
|
75
|
+
readonly 'commit.description': "只提交勾选的文件;提交信息可由模型生成,也可以自己写。";
|
|
76
|
+
readonly 'commit.files': "改动文件";
|
|
77
|
+
readonly 'commit.selectAll': "全部 {count} 个文件";
|
|
78
|
+
readonly 'commit.message': "提交信息";
|
|
79
|
+
readonly 'commit.messageLanguage': "提交信息语言";
|
|
80
|
+
readonly 'commit.messagePlaceholder': "第一行写成 feat: 描述,空一行后可以补充要点";
|
|
81
|
+
readonly 'commit.generate': "生成提交信息";
|
|
82
|
+
readonly 'commit.regenerate': "重新生成";
|
|
83
|
+
readonly 'commit.generating': "正在生成…";
|
|
84
|
+
readonly 'commit.push': "推送";
|
|
85
|
+
readonly 'commit.commit': "提交";
|
|
86
|
+
readonly 'commit.commitPush': "提交并推送";
|
|
87
|
+
readonly 'commit.cancel': "取消";
|
|
88
|
+
readonly 'commit.discard': "放弃更改";
|
|
89
|
+
readonly 'commit.discardTitle': "放弃这些文件的改动?";
|
|
90
|
+
readonly 'commit.discardBody': "将把 {count} 个文件恢复到 HEAD:已跟踪的改动被丢弃,未跟踪的文件会被删除。此操作无法撤销。";
|
|
91
|
+
readonly 'commit.discardDone': "已放弃 {count} 个文件的改动";
|
|
92
|
+
readonly 'commit.discardOne': "放弃「{path}」的改动";
|
|
93
|
+
readonly 'commit.resize': "拖动调整面板宽度";
|
|
94
|
+
readonly 'commit.none': "还没有勾选文件";
|
|
95
|
+
readonly 'commit.needMessage': "请先填写提交信息";
|
|
96
|
+
readonly 'commit.selected': "已选 {count} 个文件";
|
|
97
|
+
readonly 'commit.noUpstream': "当前分支还没有上游,首次推送会自动建立";
|
|
98
|
+
readonly 'commit.fallback': "模型没有给出可用信息,已填入模板,可自行修改";
|
|
99
|
+
readonly 'commit.staleHost': "语言选择没生效:宿主进程还是旧版本,重启 dsh web 后再试";
|
|
100
|
+
readonly 'commit.fallbackReason': "模型没有给出可用信息({detail}),已填入模板,可自行修改";
|
|
101
|
+
readonly 'commit.done': "已提交 {hash}";
|
|
102
|
+
readonly 'commit.pushDone': "已提交并推送 {hash}";
|
|
103
|
+
readonly 'commit.pushFail': "已提交 {hash},但推送失败";
|
|
104
|
+
readonly 'push.done': "已推送 {branch}";
|
|
105
|
+
readonly 'pull.done': "已拉取 {branch}";
|
|
106
|
+
readonly 'status.clean': "工作区干净";
|
|
107
|
+
readonly 'status.conflict': "有冲突文件";
|
|
108
|
+
readonly 'error.notRepository': "当前工作区不是 git 仓库";
|
|
109
|
+
readonly 'error.notInstalled': "本机没有可用的 git 命令";
|
|
110
|
+
readonly 'error.timeout': "git 命令超时";
|
|
111
|
+
readonly 'error.noRoute': "这个会话还没有模型路由,先发出一轮对话再试";
|
|
112
|
+
readonly 'error.detached': "当前处于游离 HEAD,先切到一个分支再操作";
|
|
113
|
+
readonly 'error.noFiles': "请至少勾选一个文件";
|
|
114
|
+
readonly 'error.invalid': "输入不合法:{detail}";
|
|
115
|
+
readonly 'error.failed': "操作失败:{detail}";
|
|
116
|
+
readonly 'error.developMissing': "仓库里还没有 develop 分支,请先创建";
|
|
117
|
+
readonly 'error.mergeConflict': "合并时出现冲突,请先解决冲突再完成分支";
|
|
118
|
+
readonly 'error.tagExists': "标签已经存在:{detail}";
|
|
119
|
+
readonly 'error.gitflowBranchRequired': "当前分支不是功能、发布或热修复分支";
|
|
120
|
+
};
|
|
121
|
+
/** Both locales, in the shape `ctx.locale.register` validates. */
|
|
122
|
+
export declare const gitFlowLocale: {
|
|
123
|
+
zh: {
|
|
124
|
+
readonly 'chip.tooltip': "当前分支 {branch},{count} 个未提交改动";
|
|
125
|
+
readonly 'chip.tooltip.clean': "当前分支 {branch},工作区干净";
|
|
126
|
+
readonly 'chip.aheadBehind': "领先 {ahead},落后 {behind}";
|
|
127
|
+
readonly 'chip.unpushed': "有 {count} 个提交未推送";
|
|
128
|
+
readonly 'menu.search': "搜索分支";
|
|
129
|
+
readonly 'menu.local': "本地分支";
|
|
130
|
+
readonly 'menu.remote': "仅在远端";
|
|
131
|
+
readonly 'menu.empty': "没有匹配的分支";
|
|
132
|
+
readonly 'menu.loading': "读取分支…";
|
|
133
|
+
readonly 'menu.newBranch': "新建分支…";
|
|
134
|
+
readonly 'menu.commit': "提交…";
|
|
135
|
+
readonly 'menu.push': "推送提交";
|
|
136
|
+
readonly 'menu.pull': "拉取远程代码";
|
|
137
|
+
readonly 'menu.refresh': "刷新状态";
|
|
138
|
+
readonly 'menu.startFlow': "启动 Git Flow 分支…";
|
|
139
|
+
readonly 'menu.finishFlow': "完成 Git Flow 分支…";
|
|
140
|
+
readonly 'flow.feature': "功能";
|
|
141
|
+
readonly 'flow.release': "发布";
|
|
142
|
+
readonly 'flow.hotfix': "热修复";
|
|
143
|
+
readonly 'flow.badge': "{kind}";
|
|
144
|
+
readonly 'start.title': "启动 Git Flow 分支";
|
|
145
|
+
readonly 'start.description': "功能与发布分支从 {develop} 切出,热修复从 {production} 切出。";
|
|
146
|
+
readonly 'start.kind': "分支类型";
|
|
147
|
+
readonly 'start.name': "名称";
|
|
148
|
+
readonly 'start.placeholder': "例如 login,将创建 {prefix}login";
|
|
149
|
+
readonly 'start.submit': "创建并切换";
|
|
150
|
+
readonly 'start.done': "已创建并切换到 {branch}";
|
|
151
|
+
readonly 'start.needName': "请先填写名称";
|
|
152
|
+
readonly 'start.base': "将从 {base} 切出";
|
|
153
|
+
readonly 'start.versionHint': "发布与热修复的名称建议带版本号,例如 0.4.0";
|
|
154
|
+
readonly 'initDevelop.title': "还没有 {develop} 分支";
|
|
155
|
+
readonly 'initDevelop.description': "Git Flow 需要一个集成分支。将从 {from} 创建 {develop} 并切换过去。";
|
|
156
|
+
readonly 'initDevelop.submit': "创建 {develop}";
|
|
157
|
+
readonly 'initDevelop.done': "已创建 {develop}";
|
|
158
|
+
readonly 'finish.title': "完成 {branch}";
|
|
159
|
+
readonly 'finish.description': "以下动作会依次执行,合并提交与标签一旦创建就不会回滚。";
|
|
160
|
+
readonly 'finish.mergeInto': "合并到 {targets}(--no-ff)";
|
|
161
|
+
readonly 'finish.tag': "创建标签 {tag}";
|
|
162
|
+
readonly 'finish.version': "把 package.json 版本改为 {version}";
|
|
163
|
+
readonly 'finish.push': "推送分支与标签到 origin";
|
|
164
|
+
readonly 'finish.delete': "删除已完成的本地分支";
|
|
165
|
+
readonly 'finish.versionLabel': "版本号";
|
|
166
|
+
readonly 'finish.submit': "完成并合并";
|
|
167
|
+
readonly 'finish.tagExists': "标签 {tag} 已存在,请先改用其它版本号";
|
|
168
|
+
readonly 'finish.done': "已完成 {branch}";
|
|
169
|
+
readonly 'finish.partial': "{branch} 已在本地完成,但推送失败:{detail}";
|
|
170
|
+
readonly 'finish.merged': "已合并到 {targets}";
|
|
171
|
+
readonly 'finish.tagCreated': "已创建标签 {tag}";
|
|
172
|
+
readonly 'finish.versionWritten': "已提交版本号 {version}";
|
|
173
|
+
readonly 'finish.deleted': "已删除本地分支";
|
|
174
|
+
readonly 'finish.pushFail': "推送失败:{detail}";
|
|
175
|
+
readonly 'checkout.done': "已切换到 {branch}";
|
|
176
|
+
readonly 'checkout.dirtyTitle': "工作区有未提交改动";
|
|
177
|
+
readonly 'checkout.dirtyBody': "切换到 {branch} 会覆盖本地改动。可以先提交,或者强制切换(`git switch --force` 会丢弃全部本地改动)。";
|
|
178
|
+
readonly 'checkout.force': "强制切换";
|
|
179
|
+
readonly 'create.title': "新建分支";
|
|
180
|
+
readonly 'create.description': "基于当前分支 {branch} 创建并切换。";
|
|
181
|
+
readonly 'create.name': "分支名称";
|
|
182
|
+
readonly 'create.placeholder': "例如 feature/git-flow";
|
|
183
|
+
readonly 'create.submit': "创建并切换";
|
|
184
|
+
readonly 'create.done': "已创建并切换到 {branch}";
|
|
185
|
+
readonly 'commit.title': "提交改动";
|
|
186
|
+
readonly 'commit.description': "只提交勾选的文件;提交信息可由模型生成,也可以自己写。";
|
|
187
|
+
readonly 'commit.files': "改动文件";
|
|
188
|
+
readonly 'commit.selectAll': "全部 {count} 个文件";
|
|
189
|
+
readonly 'commit.message': "提交信息";
|
|
190
|
+
readonly 'commit.messageLanguage': "提交信息语言";
|
|
191
|
+
readonly 'commit.messagePlaceholder': "第一行写成 feat: 描述,空一行后可以补充要点";
|
|
192
|
+
readonly 'commit.generate': "生成提交信息";
|
|
193
|
+
readonly 'commit.regenerate': "重新生成";
|
|
194
|
+
readonly 'commit.generating': "正在生成…";
|
|
195
|
+
readonly 'commit.push': "推送";
|
|
196
|
+
readonly 'commit.commit': "提交";
|
|
197
|
+
readonly 'commit.commitPush': "提交并推送";
|
|
198
|
+
readonly 'commit.cancel': "取消";
|
|
199
|
+
readonly 'commit.discard': "放弃更改";
|
|
200
|
+
readonly 'commit.discardTitle': "放弃这些文件的改动?";
|
|
201
|
+
readonly 'commit.discardBody': "将把 {count} 个文件恢复到 HEAD:已跟踪的改动被丢弃,未跟踪的文件会被删除。此操作无法撤销。";
|
|
202
|
+
readonly 'commit.discardDone': "已放弃 {count} 个文件的改动";
|
|
203
|
+
readonly 'commit.discardOne': "放弃「{path}」的改动";
|
|
204
|
+
readonly 'commit.resize': "拖动调整面板宽度";
|
|
205
|
+
readonly 'commit.none': "还没有勾选文件";
|
|
206
|
+
readonly 'commit.needMessage': "请先填写提交信息";
|
|
207
|
+
readonly 'commit.selected': "已选 {count} 个文件";
|
|
208
|
+
readonly 'commit.noUpstream': "当前分支还没有上游,首次推送会自动建立";
|
|
209
|
+
readonly 'commit.fallback': "模型没有给出可用信息,已填入模板,可自行修改";
|
|
210
|
+
readonly 'commit.staleHost': "语言选择没生效:宿主进程还是旧版本,重启 dsh web 后再试";
|
|
211
|
+
readonly 'commit.fallbackReason': "模型没有给出可用信息({detail}),已填入模板,可自行修改";
|
|
212
|
+
readonly 'commit.done': "已提交 {hash}";
|
|
213
|
+
readonly 'commit.pushDone': "已提交并推送 {hash}";
|
|
214
|
+
readonly 'commit.pushFail': "已提交 {hash},但推送失败";
|
|
215
|
+
readonly 'push.done': "已推送 {branch}";
|
|
216
|
+
readonly 'pull.done': "已拉取 {branch}";
|
|
217
|
+
readonly 'status.clean': "工作区干净";
|
|
218
|
+
readonly 'status.conflict': "有冲突文件";
|
|
219
|
+
readonly 'error.notRepository': "当前工作区不是 git 仓库";
|
|
220
|
+
readonly 'error.notInstalled': "本机没有可用的 git 命令";
|
|
221
|
+
readonly 'error.timeout': "git 命令超时";
|
|
222
|
+
readonly 'error.noRoute': "这个会话还没有模型路由,先发出一轮对话再试";
|
|
223
|
+
readonly 'error.detached': "当前处于游离 HEAD,先切到一个分支再操作";
|
|
224
|
+
readonly 'error.noFiles': "请至少勾选一个文件";
|
|
225
|
+
readonly 'error.invalid': "输入不合法:{detail}";
|
|
226
|
+
readonly 'error.failed': "操作失败:{detail}";
|
|
227
|
+
readonly 'error.developMissing': "仓库里还没有 develop 分支,请先创建";
|
|
228
|
+
readonly 'error.mergeConflict': "合并时出现冲突,请先解决冲突再完成分支";
|
|
229
|
+
readonly 'error.tagExists': "标签已经存在:{detail}";
|
|
230
|
+
readonly 'error.gitflowBranchRequired': "当前分支不是功能、发布或热修复分支";
|
|
231
|
+
};
|
|
232
|
+
en: Record<"chip.tooltip" | "chip.tooltip.clean" | "chip.aheadBehind" | "chip.unpushed" | "menu.search" | "menu.local" | "menu.remote" | "menu.empty" | "menu.loading" | "menu.newBranch" | "menu.commit" | "menu.push" | "menu.pull" | "menu.refresh" | "menu.startFlow" | "menu.finishFlow" | "flow.feature" | "flow.release" | "flow.hotfix" | "flow.badge" | "start.title" | "start.description" | "start.kind" | "start.name" | "start.placeholder" | "start.submit" | "start.done" | "start.needName" | "start.base" | "start.versionHint" | "initDevelop.title" | "initDevelop.description" | "initDevelop.submit" | "initDevelop.done" | "finish.title" | "finish.description" | "finish.mergeInto" | "finish.tag" | "finish.version" | "finish.push" | "finish.delete" | "finish.versionLabel" | "finish.submit" | "finish.tagExists" | "finish.done" | "finish.partial" | "finish.merged" | "finish.tagCreated" | "finish.versionWritten" | "finish.deleted" | "finish.pushFail" | "checkout.done" | "checkout.dirtyTitle" | "checkout.dirtyBody" | "checkout.force" | "create.title" | "create.description" | "create.name" | "create.placeholder" | "create.submit" | "create.done" | "commit.title" | "commit.description" | "commit.files" | "commit.selectAll" | "commit.message" | "commit.messageLanguage" | "commit.messagePlaceholder" | "commit.generate" | "commit.regenerate" | "commit.generating" | "commit.push" | "commit.commit" | "commit.commitPush" | "commit.cancel" | "commit.discard" | "commit.discardTitle" | "commit.discardBody" | "commit.discardDone" | "commit.discardOne" | "commit.resize" | "commit.none" | "commit.needMessage" | "commit.selected" | "commit.noUpstream" | "commit.fallback" | "commit.staleHost" | "commit.fallbackReason" | "commit.done" | "commit.pushDone" | "commit.pushFail" | "push.done" | "pull.done" | "status.clean" | "status.conflict" | "error.notRepository" | "error.notInstalled" | "error.timeout" | "error.noRoute" | "error.detached" | "error.noFiles" | "error.invalid" | "error.failed" | "error.developMissing" | "error.mergeConflict" | "error.tagExists" | "error.gitflowBranchRequired", string>;
|
|
233
|
+
};
|
|
234
|
+
/** Every copy key of the `gitFlow` namespace. */
|
|
235
|
+
export type GitFlowKey = keyof typeof zh;
|
|
236
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one stylesheet this plugin needs. Inline styles cannot reach inside the
|
|
3
|
+
* primitive components (the checkbox labels its own text, the modal card owns
|
|
4
|
+
* its width), so the few rules that must cross that boundary live here and are
|
|
5
|
+
* installed once per client fiber.
|
|
6
|
+
* @module dsh-git-flow/client/styles
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Install the stylesheet for this fiber.
|
|
10
|
+
* @returns a disposer removing the style element.
|
|
11
|
+
*/
|
|
12
|
+
export declare function installStyles(): () => void;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract shared by the node half (implementations) and the browser half
|
|
3
|
+
* (fetch calls). Types only — importing this module never pulls runtime code
|
|
4
|
+
* into either bundle.
|
|
5
|
+
* @module dsh-git-flow/contract
|
|
6
|
+
*/
|
|
7
|
+
/** Structured failure codes, mirrored by the browser dictionary. */
|
|
8
|
+
export type GitErrorCode = 'git/not-installed' | 'git/not-a-repository' | 'git/timeout' | 'git/failed' | 'git/dirty-worktree' | 'git/detached-head' | 'git/invalid-input' | 'git/no-files-selected' | 'git/no-route' | 'git/develop-missing' | 'git/merge-conflict' | 'git/tag-exists' | 'git/gitflow-branch-required';
|
|
9
|
+
/** One changed path, as rendered in the commit panel. */
|
|
10
|
+
export interface GitFileView {
|
|
11
|
+
/** Repository-relative path; the new name for a rename. */
|
|
12
|
+
path: string;
|
|
13
|
+
/** Previous name, present only for a rename. */
|
|
14
|
+
oldPath?: string;
|
|
15
|
+
/** Index-vs-HEAD status code, `'.'` when clean there. */
|
|
16
|
+
indexStatus: string;
|
|
17
|
+
/** Worktree-vs-index status code, `'.'` when clean there. */
|
|
18
|
+
worktreeStatus: string;
|
|
19
|
+
/** True when the path already has staged content. */
|
|
20
|
+
staged: boolean;
|
|
21
|
+
/** True for untracked paths. */
|
|
22
|
+
untracked: boolean;
|
|
23
|
+
/** True for unresolved conflicts. */
|
|
24
|
+
conflicted: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** `GET /api/dsh-git-flow/status`. */
|
|
27
|
+
export interface GitStatusView {
|
|
28
|
+
/** Repository top level, display only. */
|
|
29
|
+
repo: string;
|
|
30
|
+
/** Branch name, or `'(detached)'` / `'(unknown)'`. */
|
|
31
|
+
head: string;
|
|
32
|
+
detached: boolean;
|
|
33
|
+
upstream?: string;
|
|
34
|
+
ahead: number;
|
|
35
|
+
behind: number;
|
|
36
|
+
dirty: boolean;
|
|
37
|
+
files: GitFileView[];
|
|
38
|
+
}
|
|
39
|
+
/** One local branch row. */
|
|
40
|
+
export interface GitBranchView {
|
|
41
|
+
name: string;
|
|
42
|
+
current: boolean;
|
|
43
|
+
upstream?: string;
|
|
44
|
+
/** True when only a remote-tracking ref carries this name. */
|
|
45
|
+
remoteOnly: boolean;
|
|
46
|
+
}
|
|
47
|
+
/** `GET /api/dsh-git-flow/branches`. */
|
|
48
|
+
export interface GitBranchesView {
|
|
49
|
+
head: string;
|
|
50
|
+
local: GitBranchView[];
|
|
51
|
+
/** Remote-tracking branches, minus the symbolic `HEAD` pointers. */
|
|
52
|
+
remote: string[];
|
|
53
|
+
}
|
|
54
|
+
/** `POST /api/dsh-git-flow/commit`. */
|
|
55
|
+
export interface GitCommitView {
|
|
56
|
+
hash: string;
|
|
57
|
+
shortHash: string;
|
|
58
|
+
branch: string;
|
|
59
|
+
files: number;
|
|
60
|
+
pushed: boolean;
|
|
61
|
+
pushNote?: string;
|
|
62
|
+
}
|
|
63
|
+
/** `POST /api/dsh-git-flow/push`. */
|
|
64
|
+
export interface GitPushView {
|
|
65
|
+
pushed: boolean;
|
|
66
|
+
/** git's own summary, trimmed to its last lines. */
|
|
67
|
+
pushNote: string;
|
|
68
|
+
}
|
|
69
|
+
/** `POST /api/dsh-git-flow/pull`. */
|
|
70
|
+
export interface GitPullView {
|
|
71
|
+
pulled: boolean;
|
|
72
|
+
/** git's own summary, trimmed to its last lines. */
|
|
73
|
+
pullNote: string;
|
|
74
|
+
}
|
|
75
|
+
/** `POST /api/dsh-git-flow/generate-message`. */
|
|
76
|
+
export interface GitMessageView {
|
|
77
|
+
message: string;
|
|
78
|
+
/** True when the model produced nothing usable and the template was used. */
|
|
79
|
+
fallback: boolean;
|
|
80
|
+
/** Why the model answer was unusable: its failure, or a rejected shape. */
|
|
81
|
+
reason?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Language the message was actually written in. Absent on a host older than
|
|
84
|
+
* the language option, which is how the panel notices a stale host process.
|
|
85
|
+
*/
|
|
86
|
+
language?: MessageLanguage;
|
|
87
|
+
/** Route used, so a stale model choice is diagnosable. */
|
|
88
|
+
route?: string;
|
|
89
|
+
}
|
|
90
|
+
/** Language of an AI-written commit message. */
|
|
91
|
+
export type MessageLanguage = 'zh' | 'en';
|
|
92
|
+
/** The three branch families of a git-flow workflow. */
|
|
93
|
+
export type GitFlowKind = 'feature' | 'release' | 'hotfix';
|
|
94
|
+
/** Where the flow branches live and what they are called. */
|
|
95
|
+
export interface GitFlowConfigView {
|
|
96
|
+
production: string;
|
|
97
|
+
develop: string;
|
|
98
|
+
featurePrefix: string;
|
|
99
|
+
releasePrefix: string;
|
|
100
|
+
hotfixPrefix: string;
|
|
101
|
+
tagPrefix: string;
|
|
102
|
+
}
|
|
103
|
+
/** `GET /api/dsh-git-flow/gitflow`. */
|
|
104
|
+
export interface GitFlowStateView {
|
|
105
|
+
/** Branch facts the panel needs to decide what is offered. */
|
|
106
|
+
head: string;
|
|
107
|
+
detached: boolean;
|
|
108
|
+
/** Flow family the current branch belongs to, when its name matches a prefix. */
|
|
109
|
+
kind?: GitFlowKind;
|
|
110
|
+
/** The current branch's own name within its family, e.g. `login` for `feature/login`. */
|
|
111
|
+
slug?: string;
|
|
112
|
+
/** Version parsed from a release/hotfix branch name, when it carries one. */
|
|
113
|
+
version?: string;
|
|
114
|
+
/** True when the develop branch exists locally or on a remote. */
|
|
115
|
+
hasDevelop: boolean;
|
|
116
|
+
/** True when a production branch exists locally or on a remote. */
|
|
117
|
+
hasProduction: boolean;
|
|
118
|
+
/** Commits the current branch has that its finish target lacks. */
|
|
119
|
+
ahead: number;
|
|
120
|
+
/** Name a release/hotfix finish would tag, e.g. `v0.4.0`. */
|
|
121
|
+
tagName?: string;
|
|
122
|
+
/** True when that tag already exists, in which case finish must refuse. */
|
|
123
|
+
tagExists: boolean;
|
|
124
|
+
branches: GitFlowConfigView;
|
|
125
|
+
}
|
|
126
|
+
/** `POST /api/dsh-git-flow/gitflow/start`. */
|
|
127
|
+
export interface GitFlowStartRequest {
|
|
128
|
+
sessionId: string;
|
|
129
|
+
kind: GitFlowKind;
|
|
130
|
+
/** Branch name inside the family; the prefix is added by the host. */
|
|
131
|
+
name: string;
|
|
132
|
+
}
|
|
133
|
+
/** `POST /api/dsh-git-flow/gitflow/init-develop`. */
|
|
134
|
+
export interface GitFlowInitRequest {
|
|
135
|
+
sessionId: string;
|
|
136
|
+
}
|
|
137
|
+
/** `POST /api/dsh-git-flow/gitflow/finish`. */
|
|
138
|
+
export interface GitFlowFinishRequest {
|
|
139
|
+
sessionId: string;
|
|
140
|
+
/** Release/hotfix only: set `package.json` to this version before tagging. */
|
|
141
|
+
version?: string;
|
|
142
|
+
}
|
|
143
|
+
/** One step of a finish run, so the panel can report exactly what landed. */
|
|
144
|
+
export interface GitFlowStepView {
|
|
145
|
+
/** Stable step id: `merge`, `tag`, `version`, `push`, `delete`. */
|
|
146
|
+
id: string;
|
|
147
|
+
/** Human-readable outcome, already localized on the host side by the caller. */
|
|
148
|
+
detail: string;
|
|
149
|
+
ok: boolean;
|
|
150
|
+
}
|
|
151
|
+
/** `POST /api/dsh-git-flow/gitflow/finish`. */
|
|
152
|
+
export interface GitFlowFinishView {
|
|
153
|
+
kind: GitFlowKind;
|
|
154
|
+
branch: string;
|
|
155
|
+
/** Branches the finished branch was merged into, in order. */
|
|
156
|
+
mergedInto: string[];
|
|
157
|
+
/** Annotated tag created, for release and hotfix. */
|
|
158
|
+
tag?: string;
|
|
159
|
+
/** Version written to `package.json`, when one exists at the root. */
|
|
160
|
+
version?: string;
|
|
161
|
+
/** Commits and tags git confirmed as pushed. */
|
|
162
|
+
pushed: string[];
|
|
163
|
+
/** True when the finished branch was deleted. */
|
|
164
|
+
deleted: boolean;
|
|
165
|
+
/** Steps that did not complete; the run stops at the first one. */
|
|
166
|
+
failure?: GitFlowStepView;
|
|
167
|
+
}
|
|
168
|
+
/** Envelope every route answers with. */
|
|
169
|
+
export type GitResponse<T> = {
|
|
170
|
+
ok: true;
|
|
171
|
+
data: T;
|
|
172
|
+
} | {
|
|
173
|
+
ok: false;
|
|
174
|
+
code: GitErrorCode;
|
|
175
|
+
message: string;
|
|
176
|
+
};
|
|
177
|
+
/** Request bodies. */
|
|
178
|
+
export interface CheckoutRequest {
|
|
179
|
+
sessionId: string;
|
|
180
|
+
name: string;
|
|
181
|
+
force?: boolean;
|
|
182
|
+
}
|
|
183
|
+
export interface CreateBranchRequest {
|
|
184
|
+
sessionId: string;
|
|
185
|
+
name: string;
|
|
186
|
+
base?: string;
|
|
187
|
+
}
|
|
188
|
+
export interface CommitRequest {
|
|
189
|
+
sessionId: string;
|
|
190
|
+
files: string[];
|
|
191
|
+
message: string;
|
|
192
|
+
push?: boolean;
|
|
193
|
+
}
|
|
194
|
+
/** `POST /api/dsh-git-flow/discard`: throw the selected paths back to HEAD. */
|
|
195
|
+
export interface DiscardRequest {
|
|
196
|
+
sessionId: string;
|
|
197
|
+
files: string[];
|
|
198
|
+
}
|
|
199
|
+
export interface GenerateMessageRequest {
|
|
200
|
+
sessionId: string;
|
|
201
|
+
files: string[];
|
|
202
|
+
/** Overrides the configured `messageLanguage` for this call. */
|
|
203
|
+
language?: MessageLanguage;
|
|
204
|
+
}
|
|
205
|
+
export interface PushRequest {
|
|
206
|
+
sessionId: string;
|
|
207
|
+
}
|