@modesto_ma/dsh-guanxiang 0.2.0-beta.2 → 0.2.0-beta.4
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 +25 -35
- package/lib/client.js +173 -151
- package/lib/client.js.map +1 -1
- package/lib/index.js +493 -891
- package/lib/index.js.map +1 -1
- package/package.json +3 -1
- package/src/client/api.ts +43 -6
- package/src/client/page.tsx +64 -99
- package/src/config.ts +28 -45
- package/src/index.ts +11 -4
- package/src/repos/lookup.ts +92 -0
- package/src/repos/registry.ts +57 -295
- package/src/service.ts +166 -59
- package/src/settings/contract.ts +50 -26
- package/src/settings/routes.ts +19 -1
- package/src/skill-update/change.ts +81 -0
- package/src/skill-update/tool.ts +74 -49
- package/src/repos/credentials.ts +0 -104
- package/src/repos/git.ts +0 -74
- package/src/skill-update/git.ts +0 -157
package/lib/client.js
CHANGED
|
@@ -48,8 +48,12 @@ window.__ModuleLoader__.load({
|
|
|
48
48
|
const SETTINGS_ROUTE = "/guanxiang/settings";
|
|
49
49
|
/** POST:立即重新拉取全部仓库,或 body `{ url }` 指定的一个仓库。 */
|
|
50
50
|
const SYNC_ROUTE = "/guanxiang/sync";
|
|
51
|
-
/** PUT:body `{ tokenEnv, value }`
|
|
51
|
+
/** PUT:body `{ tokenEnv, value }` 把分析接口令牌存入 DSH 凭据库;DELETE:body `{ tokenEnv }` 删除已存的值。只接受分析接口令牌的名称。 */
|
|
52
52
|
const TOKEN_ROUTE = "/guanxiang/token";
|
|
53
|
+
/** POST:body {@link HostAddRequest} 经 dsh-repo 添加主机;DELETE:body `{ url }` 删除面板添加的主机。 */
|
|
54
|
+
const HOSTS_ROUTE = "/guanxiang/hosts";
|
|
55
|
+
/** PUT:body `{ url, value }` 经 dsh-repo 保存主机令牌;DELETE:body `{ url }` 清除已存的令牌。 */
|
|
56
|
+
const HOST_TOKEN_ROUTE = "/guanxiang/host-token";
|
|
53
57
|
//#endregion
|
|
54
58
|
//#region src/client/api.ts
|
|
55
59
|
/**
|
|
@@ -129,8 +133,8 @@ window.__ModuleLoader__.load({
|
|
|
129
133
|
})).state;
|
|
130
134
|
}
|
|
131
135
|
/**
|
|
132
|
-
* Store
|
|
133
|
-
* @param tokenEnv -
|
|
136
|
+
* Store the analyze token in DSH's credential store.
|
|
137
|
+
* @param tokenEnv - the analyze token's credential reference.
|
|
134
138
|
* @param value - token value.
|
|
135
139
|
* @returns the new state, which reports only whether the token is set.
|
|
136
140
|
*/
|
|
@@ -144,8 +148,8 @@ window.__ModuleLoader__.load({
|
|
|
144
148
|
})).state;
|
|
145
149
|
}
|
|
146
150
|
/**
|
|
147
|
-
* Remove
|
|
148
|
-
* @param tokenEnv -
|
|
151
|
+
* Remove the stored analyze token.
|
|
152
|
+
* @param tokenEnv - the analyze token's credential reference.
|
|
149
153
|
* @returns the new state.
|
|
150
154
|
*/
|
|
151
155
|
async function clearToken(tokenEnv) {
|
|
@@ -154,11 +158,60 @@ window.__ModuleLoader__.load({
|
|
|
154
158
|
body: JSON.stringify({ tokenEnv })
|
|
155
159
|
})).state;
|
|
156
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Add a dsh-repo host, with its token.
|
|
163
|
+
* @param host - kind, address, alias, and token.
|
|
164
|
+
* @returns the new state.
|
|
165
|
+
*/
|
|
166
|
+
async function addHost(host) {
|
|
167
|
+
return (await request(HOSTS_ROUTE, {
|
|
168
|
+
method: "POST",
|
|
169
|
+
body: JSON.stringify(host)
|
|
170
|
+
})).state;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Remove a host added from a panel.
|
|
174
|
+
* @param url - host address.
|
|
175
|
+
* @returns the new state.
|
|
176
|
+
*/
|
|
177
|
+
async function removeHost(url) {
|
|
178
|
+
return (await request(HOSTS_ROUTE, {
|
|
179
|
+
method: "DELETE",
|
|
180
|
+
body: JSON.stringify({ url })
|
|
181
|
+
})).state;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Store a host's token.
|
|
185
|
+
* @param url - host address.
|
|
186
|
+
* @param value - token value.
|
|
187
|
+
* @returns the new state, which reports only whether the token is set.
|
|
188
|
+
*/
|
|
189
|
+
async function saveHostToken(url, value) {
|
|
190
|
+
return (await request(HOST_TOKEN_ROUTE, {
|
|
191
|
+
method: "PUT",
|
|
192
|
+
body: JSON.stringify({
|
|
193
|
+
url,
|
|
194
|
+
value
|
|
195
|
+
})
|
|
196
|
+
})).state;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Remove a host's stored token.
|
|
200
|
+
* @param url - host address.
|
|
201
|
+
* @returns the new state.
|
|
202
|
+
*/
|
|
203
|
+
async function clearHostToken(url) {
|
|
204
|
+
return (await request(HOST_TOKEN_ROUTE, {
|
|
205
|
+
method: "DELETE",
|
|
206
|
+
body: JSON.stringify({ url })
|
|
207
|
+
})).state;
|
|
208
|
+
}
|
|
157
209
|
//#endregion
|
|
158
210
|
//#region src/client/page.tsx
|
|
159
211
|
/**
|
|
160
212
|
* 左侧栏「观象」主区页面:应用仓库、访问令牌、日志下载、分析接口、高级(含 SKILL 改进)五个
|
|
161
|
-
*
|
|
213
|
+
* 分页,共用一份草稿和底部保存条。访问令牌分页管理 dsh-repo 的主机,改动立即
|
|
214
|
+
* 生效,不进草稿;令牌值存入 DSH 凭据库。
|
|
162
215
|
* 仓库拉取中时每 2 秒刷新状态。
|
|
163
216
|
*
|
|
164
217
|
* @module dsh-guanxiang/client/page
|
|
@@ -195,9 +248,7 @@ window.__ModuleLoader__.load({
|
|
|
195
248
|
}
|
|
196
249
|
function toDraft(settings) {
|
|
197
250
|
return {
|
|
198
|
-
reposDir: settings.reposDir,
|
|
199
251
|
repos: settings.repos.map((repo) => ({ ...repo })),
|
|
200
|
-
gitCredentials: settings.gitCredentials.map((credential) => ({ ...credential })),
|
|
201
252
|
fetchIntervalMin: trimNumber(settings.fetchIntervalMs / MINUTE),
|
|
202
253
|
maxAppsPerRequest: String(settings.maxAppsPerRequest),
|
|
203
254
|
dispatchTimeoutMin: trimNumber(settings.dispatchTimeoutMs / MINUTE),
|
|
@@ -221,17 +272,10 @@ window.__ModuleLoader__.load({
|
|
|
221
272
|
const maxFiles = positive(draft.skillMaxFiles, "提议文件数上限");
|
|
222
273
|
if (!Number.isInteger(maxFiles)) throw new Error("提议文件数上限必须是整数");
|
|
223
274
|
return {
|
|
224
|
-
reposDir: draft.reposDir.trim(),
|
|
225
275
|
repos: draft.repos.map((repo) => repo.branch === void 0 || repo.branch.trim() === "" ? { url: repo.url.trim() } : {
|
|
226
276
|
url: repo.url.trim(),
|
|
227
277
|
branch: repo.branch.trim()
|
|
228
278
|
}),
|
|
229
|
-
gitCredentials: draft.gitCredentials.map((credential) => ({
|
|
230
|
-
url: credential.url.trim(),
|
|
231
|
-
...credential.alias === void 0 || credential.alias.trim() === "" ? {} : { alias: credential.alias.trim() },
|
|
232
|
-
username: credential.username.trim(),
|
|
233
|
-
tokenEnv: credential.tokenEnv.trim()
|
|
234
|
-
})),
|
|
235
279
|
fetchIntervalMs: Math.round(positive(draft.fetchIntervalMin, "更新间隔", true) * MINUTE),
|
|
236
280
|
maxAppsPerRequest: maxApps,
|
|
237
281
|
dispatchTimeoutMs: Math.round(positive(draft.dispatchTimeoutMin, "派发超时") * MINUTE),
|
|
@@ -465,25 +509,15 @@ window.__ModuleLoader__.load({
|
|
|
465
509
|
}
|
|
466
510
|
}) : null,
|
|
467
511
|
tab === "tokens" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TokensTab, {
|
|
468
|
-
draft,
|
|
469
|
-
setDraft,
|
|
470
512
|
state,
|
|
471
513
|
busy,
|
|
472
|
-
onAdd: async (
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
}), token === "" ? `已添加 ${credential.url},请填入令牌` : `已添加 ${credential.url}`, false))?.settings.gitCredentials[state.settings.gitCredentials.length];
|
|
477
|
-
if (added === void 0) return false;
|
|
478
|
-
setDraft((current) => current === void 0 || current.gitCredentials.some((item) => item.url === added.url) ? current : {
|
|
479
|
-
...current,
|
|
480
|
-
gitCredentials: [...current.gitCredentials, added]
|
|
481
|
-
});
|
|
482
|
-
return token === "" || await run(() => saveToken(added.tokenEnv, token), `已添加 ${added.url} 并保存令牌,使用它的仓库会重新拉取`, false) !== void 0;
|
|
514
|
+
onAdd: async (host) => await run(() => addHost(host), `已添加 ${host.url},仓库会重新拉取`, false) !== void 0,
|
|
515
|
+
onSave: async (url, value) => await run(() => saveHostToken(url, value), `已保存 ${url} 的令牌,仓库会重新拉取`, false) !== void 0,
|
|
516
|
+
onClear: (url) => {
|
|
517
|
+
run(() => clearHostToken(url), `已清除面板保存的 ${url} 令牌`, false);
|
|
483
518
|
},
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
run(() => clearToken(tokenEnv), `已清除面板保存的 ${tokenEnv}`, false);
|
|
519
|
+
onRemove: (url) => {
|
|
520
|
+
run(() => removeHost(url), `已删除 ${url}`, false);
|
|
487
521
|
}
|
|
488
522
|
}) : null,
|
|
489
523
|
tab === "download" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DownloadTab, {
|
|
@@ -495,7 +529,7 @@ window.__ModuleLoader__.load({
|
|
|
495
529
|
draft,
|
|
496
530
|
setDraft,
|
|
497
531
|
analyze: state.analyze,
|
|
498
|
-
credentialsAvailable: state.
|
|
532
|
+
credentialsAvailable: state.credentialsAvailable,
|
|
499
533
|
overridden: state.overridden,
|
|
500
534
|
busy,
|
|
501
535
|
onSave: async (value) => await run(() => saveToken(state.analyze.tokenEnv, value), "已保存分析接口令牌,下一个请求起生效", false) !== void 0,
|
|
@@ -636,11 +670,10 @@ window.__ModuleLoader__.load({
|
|
|
636
670
|
formatTime(current.commitTime),
|
|
637
671
|
")· 拉取于 ",
|
|
638
672
|
formatTime(current.syncedAt),
|
|
639
|
-
" · ",
|
|
640
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
673
|
+
current.dir === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [" · ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
641
674
|
className: "gx__mono",
|
|
642
675
|
children: current.dir
|
|
643
|
-
})
|
|
676
|
+
})] })
|
|
644
677
|
]
|
|
645
678
|
}) : null,
|
|
646
679
|
saved && current.error !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -708,15 +741,21 @@ window.__ModuleLoader__.load({
|
|
|
708
741
|
})
|
|
709
742
|
]
|
|
710
743
|
}),
|
|
744
|
+
state.hosts.availability === "ready" ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
745
|
+
className: "gx__notice gx__notice--error",
|
|
746
|
+
children: state.hosts.availability === "missing" ? "没有加载 dsh-repo 插件,仓库无法拉取。请安装 dsh-repo。" : "dsh-repo 版本过旧,仓库无法拉取。请升级 dsh-repo。"
|
|
747
|
+
}),
|
|
711
748
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
712
749
|
className: "gx__secFoot",
|
|
713
750
|
children: [
|
|
714
|
-
"
|
|
751
|
+
"由 dsh-repo 拉取到它的镜像目录",
|
|
752
|
+
state.hosts.mirrorDir === void 0 ? "" : `(${state.hosts.mirrorDir})`,
|
|
753
|
+
"。https 地址使用「访问令牌」中对应主机的令牌,ssh 地址和其他主机使用本机已有的 git 凭据(SSH key 或 credential helper)。不留分支时跟随远端默认分支。每个仓库需包含 ",
|
|
715
754
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
716
755
|
className: "gx__mono",
|
|
717
756
|
children: ".dsh/guanxiang.yaml"
|
|
718
757
|
}),
|
|
719
|
-
" 与其中声明的日志分析 SKILL
|
|
758
|
+
" 与其中声明的日志分析 SKILL。删除地址不会删除本地镜像。"
|
|
720
759
|
]
|
|
721
760
|
}),
|
|
722
761
|
state.repos.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -731,15 +770,19 @@ window.__ModuleLoader__.load({
|
|
|
731
770
|
]
|
|
732
771
|
});
|
|
733
772
|
}
|
|
734
|
-
const DEFAULT_USERNAME = "oauth2";
|
|
735
|
-
/** Prefix of the credential keys the panel allocates; namespaced so an unrelated `GITLAB_TOKEN` in the environment is not picked up. */
|
|
736
|
-
const DEFAULT_TOKEN_ENV = "GUANXIANG_GITLAB_TOKEN";
|
|
737
773
|
/** Credential store layers of `@deepseek-ai/dsh-credentials-local` other than its own file. */
|
|
738
774
|
const TOKEN_SOURCES = {
|
|
739
775
|
"env": "启动环境变量",
|
|
740
776
|
"project-env": "项目 .env",
|
|
741
777
|
"user-env": "$DSH_HOME/.env"
|
|
742
778
|
};
|
|
779
|
+
const HOST_KINDS = [{
|
|
780
|
+
id: "gitlab",
|
|
781
|
+
label: "GitLab"
|
|
782
|
+
}, {
|
|
783
|
+
id: "github",
|
|
784
|
+
label: "GitHub"
|
|
785
|
+
}];
|
|
743
786
|
function tokenPill(token) {
|
|
744
787
|
if (token === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
745
788
|
className: "gx__pill",
|
|
@@ -763,89 +806,75 @@ window.__ModuleLoader__.load({
|
|
|
763
806
|
]
|
|
764
807
|
});
|
|
765
808
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
* saved or drafted entry uses.
|
|
769
|
-
* @param used - keys already in use.
|
|
770
|
-
* @returns a free key.
|
|
771
|
-
*/
|
|
772
|
-
function freeTokenEnv(used) {
|
|
773
|
-
if (!used.has(DEFAULT_TOKEN_ENV)) return DEFAULT_TOKEN_ENV;
|
|
774
|
-
let index = 2;
|
|
775
|
-
while (used.has(`${DEFAULT_TOKEN_ENV}_${index}`)) index += 1;
|
|
776
|
-
return `${DEFAULT_TOKEN_ENV}_${index}`;
|
|
777
|
-
}
|
|
778
|
-
function TokensTab({ draft, setDraft, state, busy, onAdd, onSave, onClear }) {
|
|
809
|
+
function TokensTab({ state, busy, onAdd, onSave, onClear, onRemove }) {
|
|
810
|
+
const [kind, setKind] = (0, react.useState)("gitlab");
|
|
779
811
|
const [url, setUrl] = (0, react.useState)("");
|
|
780
812
|
const [alias, setAlias] = (0, react.useState)("");
|
|
781
813
|
const [token, setToken] = (0, react.useState)("");
|
|
782
|
-
const [addError, setAddError] = (0, react.useState)();
|
|
783
|
-
const [adding, setAdding] = (0, react.useState)(false);
|
|
784
814
|
const [values, setValues] = (0, react.useState)({});
|
|
785
|
-
const
|
|
786
|
-
const saved = (0, react.useMemo)(() => new Set(state.settings.gitCredentials.map((credential) => credential.tokenEnv)), [state.settings.gitCredentials]);
|
|
815
|
+
const { availability, hosts, error } = state.hosts;
|
|
787
816
|
const complete = url.trim() !== "" && alias.trim() !== "" && token.trim() !== "";
|
|
788
817
|
const add = () => {
|
|
789
|
-
if (!complete || busy
|
|
790
|
-
const address = url.trim();
|
|
791
|
-
if (state.settings.gitCredentials.some((credential) => credential.url === address)) {
|
|
792
|
-
setAddError("这个地址已经添加过了,请在上面的列表里更新它的令牌。");
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
setAddError(void 0);
|
|
796
|
-
setAdding(true);
|
|
797
|
-
const tokenEnv = freeTokenEnv(/* @__PURE__ */ new Set([...saved, ...draft.gitCredentials.map((credential) => credential.tokenEnv)]));
|
|
818
|
+
if (!complete || busy) return;
|
|
798
819
|
onAdd({
|
|
799
|
-
|
|
820
|
+
kind,
|
|
821
|
+
url: url.trim(),
|
|
800
822
|
alias: alias.trim(),
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}, token.trim()).then((ok) => {
|
|
823
|
+
token: token.trim()
|
|
824
|
+
}).then((ok) => {
|
|
804
825
|
if (!ok) return;
|
|
805
826
|
setUrl("");
|
|
806
827
|
setAlias("");
|
|
807
828
|
setToken("");
|
|
808
|
-
}).finally(() => {
|
|
809
|
-
setAdding(false);
|
|
810
829
|
});
|
|
811
830
|
};
|
|
812
|
-
const save = (
|
|
813
|
-
const value = values[
|
|
814
|
-
if (value === "" || busy
|
|
815
|
-
onSave(
|
|
831
|
+
const save = (address) => {
|
|
832
|
+
const value = values[address]?.trim() ?? "";
|
|
833
|
+
if (value === "" || busy) return;
|
|
834
|
+
onSave(address, value).then((ok) => {
|
|
816
835
|
if (ok) setValues((current) => ({
|
|
817
836
|
...current,
|
|
818
|
-
[
|
|
837
|
+
[address]: ""
|
|
819
838
|
}));
|
|
820
839
|
});
|
|
821
840
|
};
|
|
822
841
|
const submitOnEnter = (event) => {
|
|
823
842
|
if (event.key === "Enter") add();
|
|
824
843
|
};
|
|
844
|
+
if (availability !== "ready") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
845
|
+
className: "gx__sec",
|
|
846
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
847
|
+
className: "gx__secTitle",
|
|
848
|
+
children: "访问令牌"
|
|
849
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
850
|
+
className: "gx__notice gx__notice--error",
|
|
851
|
+
children: availability === "missing" ? "访问令牌由 dsh-repo 插件管理,当前没有加载 dsh-repo。请安装 dsh-repo。" : "dsh-repo 版本过旧,不能在这里管理访问令牌。请升级 dsh-repo。"
|
|
852
|
+
})]
|
|
853
|
+
});
|
|
825
854
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
826
855
|
className: "gx__sec",
|
|
827
856
|
children: [
|
|
828
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
857
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
829
858
|
className: "gx__secTitle",
|
|
830
|
-
children:
|
|
831
|
-
keys: state.overridden,
|
|
832
|
-
name: "gitCredentials"
|
|
833
|
-
})]
|
|
859
|
+
children: "访问令牌"
|
|
834
860
|
}),
|
|
835
|
-
state.
|
|
861
|
+
state.credentialsAvailable ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
836
862
|
className: "gx__notice gx__notice--error",
|
|
837
863
|
children: "当前 DSH 组合没有加载凭据服务(@deepseek-ai/dsh-credentials-local),无法保存或读取令牌。"
|
|
838
864
|
}),
|
|
865
|
+
error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
866
|
+
className: "gx__notice gx__notice--error",
|
|
867
|
+
children: ["无法读取 dsh-repo 的主机:", error]
|
|
868
|
+
}),
|
|
839
869
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
840
870
|
className: "gx__list",
|
|
841
871
|
children: [
|
|
842
|
-
|
|
872
|
+
hosts.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
843
873
|
className: "gx__emptyRow",
|
|
844
|
-
children: "
|
|
874
|
+
children: "还没有主机。用 https 地址拉取私有仓库时,在下面填入 GitLab 或 GitHub 地址、别名和令牌。"
|
|
845
875
|
}) : null,
|
|
846
|
-
|
|
847
|
-
const
|
|
848
|
-
const value = values[credential.tokenEnv] ?? "";
|
|
876
|
+
hosts.map((host) => {
|
|
877
|
+
const value = values[host.url] ?? "";
|
|
849
878
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
850
879
|
className: "gx__row gx__row--top",
|
|
851
880
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -853,17 +882,28 @@ window.__ModuleLoader__.load({
|
|
|
853
882
|
children: [
|
|
854
883
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
855
884
|
className: "gx__rowLabel",
|
|
856
|
-
children: [
|
|
885
|
+
children: [
|
|
886
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: host.alias ?? host.url }),
|
|
887
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
888
|
+
className: "gx__tag",
|
|
889
|
+
children: host.kind === "github" ? "GitHub" : "GitLab"
|
|
890
|
+
}),
|
|
891
|
+
host.origin === "config" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
892
|
+
className: "gx__tag",
|
|
893
|
+
children: "cordis.yml"
|
|
894
|
+
}) : null,
|
|
895
|
+
tokenPill(host.token)
|
|
896
|
+
]
|
|
857
897
|
}),
|
|
858
|
-
|
|
898
|
+
host.alias === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
859
899
|
className: "gx__rowSummary gx__mono",
|
|
860
|
-
children:
|
|
900
|
+
children: host.url
|
|
861
901
|
}),
|
|
862
|
-
|
|
902
|
+
host.token.error === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
863
903
|
className: "gx__rowError",
|
|
864
|
-
children:
|
|
904
|
+
children: host.token.error
|
|
865
905
|
}),
|
|
866
|
-
|
|
906
|
+
host.token.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
867
907
|
className: "gx__addRow gx__addRow--flush",
|
|
868
908
|
children: [
|
|
869
909
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
@@ -871,33 +911,33 @@ window.__ModuleLoader__.load({
|
|
|
871
911
|
type: "password",
|
|
872
912
|
autoComplete: "new-password",
|
|
873
913
|
spellCheck: false,
|
|
874
|
-
placeholder:
|
|
914
|
+
placeholder: host.token.configured ? "输入新令牌以替换" : "粘贴令牌",
|
|
875
915
|
value,
|
|
876
916
|
onChange: (event) => {
|
|
877
917
|
setValues({
|
|
878
918
|
...values,
|
|
879
|
-
[
|
|
919
|
+
[host.url]: event.target.value
|
|
880
920
|
});
|
|
881
921
|
},
|
|
882
922
|
onKeyDown: (event) => {
|
|
883
|
-
if (event.key === "Enter") save(
|
|
923
|
+
if (event.key === "Enter") save(host.url);
|
|
884
924
|
}
|
|
885
925
|
}),
|
|
886
926
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
887
927
|
type: "button",
|
|
888
928
|
className: "gx__btn",
|
|
889
|
-
disabled: busy ||
|
|
929
|
+
disabled: busy || value.trim() === "",
|
|
890
930
|
onClick: () => {
|
|
891
|
-
save(
|
|
931
|
+
save(host.url);
|
|
892
932
|
},
|
|
893
933
|
children: "保存令牌"
|
|
894
934
|
}),
|
|
895
|
-
|
|
935
|
+
host.token.configured && host.token.source === "file" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
896
936
|
type: "button",
|
|
897
937
|
className: "gx__btn gx__btn--ghost",
|
|
898
938
|
disabled: busy,
|
|
899
939
|
onClick: () => {
|
|
900
|
-
onClear(
|
|
940
|
+
onClear(host.url);
|
|
901
941
|
},
|
|
902
942
|
children: "清除"
|
|
903
943
|
}) : null
|
|
@@ -906,30 +946,42 @@ window.__ModuleLoader__.load({
|
|
|
906
946
|
]
|
|
907
947
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
908
948
|
className: "gx__rowCtl",
|
|
909
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
949
|
+
children: host.origin === "added" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
910
950
|
type: "button",
|
|
911
951
|
className: "gx__btn gx__btn--danger",
|
|
952
|
+
disabled: busy,
|
|
912
953
|
onClick: () => {
|
|
913
|
-
|
|
914
|
-
...draft,
|
|
915
|
-
gitCredentials: draft.gitCredentials.filter((_, position) => position !== index)
|
|
916
|
-
});
|
|
954
|
+
onRemove(host.url);
|
|
917
955
|
},
|
|
918
956
|
children: "删除"
|
|
919
|
-
})
|
|
957
|
+
}) : null
|
|
920
958
|
})]
|
|
921
|
-
},
|
|
959
|
+
}, host.url);
|
|
922
960
|
}),
|
|
923
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
961
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
924
962
|
className: "gx__addForm",
|
|
925
|
-
children:
|
|
963
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
926
964
|
className: "gx__addRow gx__addRow--flush",
|
|
927
965
|
children: [
|
|
928
966
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
929
967
|
className: "gx__field",
|
|
930
|
-
children: ["
|
|
968
|
+
children: ["类型", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
|
|
969
|
+
className: "gx__input",
|
|
970
|
+
value: kind,
|
|
971
|
+
onChange: (event) => {
|
|
972
|
+
setKind(event.target.value);
|
|
973
|
+
},
|
|
974
|
+
children: HOST_KINDS.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
975
|
+
value: item.id,
|
|
976
|
+
children: item.label
|
|
977
|
+
}, item.id))
|
|
978
|
+
})]
|
|
979
|
+
}),
|
|
980
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
981
|
+
className: "gx__field",
|
|
982
|
+
children: ["地址", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
931
983
|
className: "gx__input",
|
|
932
|
-
placeholder: "https://gitlab.example.com",
|
|
984
|
+
placeholder: kind === "github" ? "https://github.com" : "https://gitlab.example.com",
|
|
933
985
|
value: url,
|
|
934
986
|
onChange: (event) => {
|
|
935
987
|
setUrl(event.target.value);
|
|
@@ -939,9 +991,9 @@ window.__ModuleLoader__.load({
|
|
|
939
991
|
}),
|
|
940
992
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
941
993
|
className: "gx__field",
|
|
942
|
-
children: ["
|
|
994
|
+
children: ["别名", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
943
995
|
className: "gx__input",
|
|
944
|
-
placeholder: "例如
|
|
996
|
+
placeholder: "例如 公司 GitLab",
|
|
945
997
|
value: alias,
|
|
946
998
|
onChange: (event) => {
|
|
947
999
|
setAlias(event.target.value);
|
|
@@ -967,21 +1019,18 @@ window.__ModuleLoader__.load({
|
|
|
967
1019
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
968
1020
|
type: "button",
|
|
969
1021
|
className: "gx__btn gx__btn--end",
|
|
970
|
-
disabled: busy ||
|
|
1022
|
+
disabled: busy || !complete,
|
|
971
1023
|
onClick: add,
|
|
972
1024
|
children: "添加"
|
|
973
1025
|
})
|
|
974
1026
|
]
|
|
975
|
-
})
|
|
976
|
-
className: "gx__rowError",
|
|
977
|
-
children: addError
|
|
978
|
-
})]
|
|
1027
|
+
})
|
|
979
1028
|
})
|
|
980
1029
|
]
|
|
981
1030
|
}),
|
|
982
1031
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
983
1032
|
className: "gx__secFoot",
|
|
984
|
-
children: "
|
|
1033
|
+
children: "主机和令牌由 dsh-repo 管理,添加、删除和保存令牌立即生效,不需要点保存。该主机下的 https 仓库使用对应令牌,ssh 地址不受影响。GitLab 拉取需要 read_repository 权限,开启 SKILL 改进时需要 api 权限;GitHub 需要 Contents 与 Pull requests 读写权限。令牌保存在 DSH 凭据库(默认 $DSH_HOME/.credentials.yaml,仅本机用户可读),面板只显示是否已设置。cordis.yml 中配置的主机只能在这里更新令牌。"
|
|
985
1034
|
})
|
|
986
1035
|
]
|
|
987
1036
|
});
|
|
@@ -1320,36 +1369,9 @@ window.__ModuleLoader__.load({
|
|
|
1320
1369
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
1321
1370
|
className: "gx__secTitle",
|
|
1322
1371
|
children: "仓库"
|
|
1323
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1372
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1324
1373
|
className: "gx__list",
|
|
1325
|
-
children:
|
|
1326
|
-
className: "gx__row",
|
|
1327
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1328
|
-
className: "gx__rowText",
|
|
1329
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1330
|
-
className: "gx__rowLabel",
|
|
1331
|
-
children: ["拉取目录 ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Overridden, {
|
|
1332
|
-
keys: overridden,
|
|
1333
|
-
name: "reposDir"
|
|
1334
|
-
})]
|
|
1335
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1336
|
-
className: "gx__rowSummary",
|
|
1337
|
-
children: "每个仓库拉取到该目录下的同名子目录,观象只读使用。"
|
|
1338
|
-
})]
|
|
1339
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1340
|
-
className: "gx__rowCtl",
|
|
1341
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1342
|
-
className: "gx__input gx__input--wide gx__mono",
|
|
1343
|
-
value: draft.reposDir,
|
|
1344
|
-
onChange: (event) => {
|
|
1345
|
-
setDraft({
|
|
1346
|
-
...draft,
|
|
1347
|
-
reposDir: event.target.value
|
|
1348
|
-
});
|
|
1349
|
-
}
|
|
1350
|
-
})
|
|
1351
|
-
})]
|
|
1352
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NumberRow, {
|
|
1374
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NumberRow, {
|
|
1353
1375
|
label: "更新间隔",
|
|
1354
1376
|
summary: "输入 /guanxiang 时,距上次拉取超过该时间的仓库会先更新;0 表示每次都更新。",
|
|
1355
1377
|
unit: "分钟",
|
|
@@ -1361,7 +1383,7 @@ window.__ModuleLoader__.load({
|
|
|
1361
1383
|
fetchIntervalMin: value
|
|
1362
1384
|
});
|
|
1363
1385
|
}
|
|
1364
|
-
})
|
|
1386
|
+
})
|
|
1365
1387
|
})]
|
|
1366
1388
|
}),
|
|
1367
1389
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -1418,7 +1440,7 @@ window.__ModuleLoader__.load({
|
|
|
1418
1440
|
})]
|
|
1419
1441
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1420
1442
|
className: "gx__rowSummary",
|
|
1421
|
-
children: "子 Agent 发现应用的日志分析 SKILL
|
|
1443
|
+
children: "子 Agent 发现应用的日志分析 SKILL 有欠缺时可以写出修改提议;经用户授权后,观象经 dsh-repo 把它提交到新分支并创建合并请求(GitLab 或 GitHub,需要安装 dsh-repo 并配置该仓库主机的令牌)。"
|
|
1422
1444
|
})]
|
|
1423
1445
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1424
1446
|
className: "gx__rowCtl",
|