@dungsil/dsh-plugin-ui-vcs 0.2.0 → 0.3.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/dist/client.js +443 -136
- package/dist/index.js +339 -14
- package/package.json +6 -1
package/dist/client.js
CHANGED
|
@@ -12,9 +12,9 @@ var __exportAll = (all, no_symbols) => {
|
|
|
12
12
|
return target;
|
|
13
13
|
};
|
|
14
14
|
let react = require("react");
|
|
15
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
15
16
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
16
17
|
let react_dom = require("react-dom");
|
|
17
|
-
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
18
18
|
// ../../tools/ui/src/icons/git-pull-request.svg
|
|
19
19
|
var git_pull_request_default = "<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\" aria-hidden=\"true\">\n <circle cx=\"5\" cy=\"5\" r=\"2\"/>\n <circle cx=\"5\" cy=\"19\" r=\"2\"/>\n <circle cx=\"19\" cy=\"19\" r=\"2\"/>\n <path d=\"M5 7v10M19 17V7a2 2 0 0 0-2-2h-5m3-3-3 3 3 3\"/>\n</svg>\n";
|
|
20
20
|
// ../../tools/ui/src/icons/git-pull-request-draft.svg
|
|
@@ -23,6 +23,40 @@ var git_pull_request_draft_default = "<svg xmlns=\"http://www.w3.org/2000/svg\"
|
|
|
23
23
|
var git_pull_request_closed_default = "<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\" aria-hidden=\"true\">\n <circle cx=\"5\" cy=\"5\" r=\"2\"/>\n <circle cx=\"5\" cy=\"19\" r=\"2\"/>\n <circle cx=\"19\" cy=\"19\" r=\"2\"/>\n <path d=\"M5 7v10M19 17v-5M16 3l6 6m0-6-6 6\"/>\n</svg>\n";
|
|
24
24
|
// ../../tools/ui/src/icons/git-merge.svg
|
|
25
25
|
var git_merge_default = "<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\" aria-hidden=\"true\">\n <circle cx=\"5\" cy=\"5\" r=\"2\"/>\n <circle cx=\"5\" cy=\"19\" r=\"2\"/>\n <circle cx=\"19\" cy=\"19\" r=\"2\"/>\n <path d=\"M5 7v10M5 7a12 12 0 0 0 12 12\"/>\n</svg>\n";
|
|
26
|
+
// ../../tools/ui/src/client.ts
|
|
27
|
+
function useLocaleSnapshot(locale) {
|
|
28
|
+
const subscribe = (0, react.useCallback)((listener) => locale.subscribe(listener), [locale]);
|
|
29
|
+
const getSnapshot = (0, react.useCallback)(() => locale.getSnapshot(), [locale]);
|
|
30
|
+
return (0, react.useSyncExternalStore)(subscribe, getSnapshot);
|
|
31
|
+
}
|
|
32
|
+
/** Each effect owns its sheet, even when another plugin installs the same defaults. */
|
|
33
|
+
function installStyles(css) {
|
|
34
|
+
const style = document.createElement("style");
|
|
35
|
+
style.textContent = css;
|
|
36
|
+
document.head.append(style);
|
|
37
|
+
return () => style.remove();
|
|
38
|
+
}
|
|
39
|
+
// ../../tools/ui/src/settings.tsx
|
|
40
|
+
const settingsStyles = `
|
|
41
|
+
.dsh-plugin-settings-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 0; border-bottom: .5px solid var(--dsw-alias-border-l2); }
|
|
42
|
+
.dsh-plugin-settings-text { flex: 1; min-width: 0; }
|
|
43
|
+
.dsh-plugin-settings-picker { min-width: 0; }
|
|
44
|
+
.dsh-plugin-settings-selector { box-sizing: border-box; display: inline-flex; align-items: center; gap: 12px; max-width: 100%; height: 36px; padding: 0 14px; border: none; border-radius: var(--dsw-radius-md); background: var(--dsw-alias-bg-module-platform); color: inherit; font: inherit; cursor: pointer; }
|
|
45
|
+
.dsh-plugin-settings-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
46
|
+
.dsh-plugin-settings-selector svg { flex: none; }
|
|
47
|
+
.dsh-plugin-settings-selector:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }
|
|
48
|
+
.dsh-plugin-settings-selector:disabled { opacity: .5; cursor: default; }
|
|
49
|
+
.dsh-plugin-settings-selector:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary-new-colorprimary-new-color); outline-offset: 2px; }
|
|
50
|
+
`;
|
|
51
|
+
function SettingsRow({ label, children }) {
|
|
52
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
53
|
+
className: "dsh-plugin-settings-row",
|
|
54
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
55
|
+
className: "dsh-plugin-settings-text",
|
|
56
|
+
children: label
|
|
57
|
+
}), children]
|
|
58
|
+
});
|
|
59
|
+
}
|
|
26
60
|
// locale/en.json
|
|
27
61
|
var en_default = {
|
|
28
62
|
meta: {
|
|
@@ -13322,7 +13356,7 @@ function bindPullRequestLinks(root, open) {
|
|
|
13322
13356
|
}
|
|
13323
13357
|
// src/pull-requests-client.tsx
|
|
13324
13358
|
var pull_requests_client_exports = /* @__PURE__ */ __exportAll({
|
|
13325
|
-
apply: () => apply$
|
|
13359
|
+
apply: () => apply$2,
|
|
13326
13360
|
checksState: () => checksState,
|
|
13327
13361
|
inject: () => inject$1,
|
|
13328
13362
|
name: () => name$1
|
|
@@ -13427,7 +13461,7 @@ function Choice({ label, value, items, onChange, disabled }) {
|
|
|
13427
13461
|
})
|
|
13428
13462
|
});
|
|
13429
13463
|
}
|
|
13430
|
-
function apply$
|
|
13464
|
+
function apply$2(ctx) {
|
|
13431
13465
|
const connection = ctx.get("connection");
|
|
13432
13466
|
const sessions = ctx.get("sessions");
|
|
13433
13467
|
const views = /* @__PURE__ */ new Map();
|
|
@@ -14209,6 +14243,15 @@ function apply$1(ctx) {
|
|
|
14209
14243
|
const channel = "/api";
|
|
14210
14244
|
const describeMethod = "dungsil-vcs/describe";
|
|
14211
14245
|
const executeMethod = "dungsil-vcs/execute";
|
|
14246
|
+
function validCommitSettings(value) {
|
|
14247
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
14248
|
+
const input = value;
|
|
14249
|
+
return Object.keys(input).every((key) => [
|
|
14250
|
+
"authorName",
|
|
14251
|
+
"authorEmail",
|
|
14252
|
+
"noSign"
|
|
14253
|
+
].includes(key)) && typeof input.authorName === "string" && input.authorName.length <= 200 && !/[<>]/.test(input.authorName) && !Array.from(input.authorName).some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) && typeof input.authorEmail === "string" && input.authorEmail.length <= 254 && (input.authorEmail === "" || /^[^\s<>@]+@[^\s<>@]+$/.test(input.authorEmail)) && !Array.from(input.authorEmail).some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) && (input.authorName === "" ? input.authorEmail === "" : !!input.authorName.trim() && !!input.authorEmail) && typeof input.noSign === "boolean";
|
|
14254
|
+
}
|
|
14212
14255
|
function isGitActionResult(value) {
|
|
14213
14256
|
if (!value || typeof value !== "object") return false;
|
|
14214
14257
|
const result = value;
|
|
@@ -14218,6 +14261,337 @@ function isGitActionResult(value) {
|
|
|
14218
14261
|
"pr"
|
|
14219
14262
|
].includes(result.operation) && typeof result.branch === "string" && (result.commit === void 0 || /^[a-f0-9]{40,64}$/.test(result.commit)) && (result.url === void 0 || /^https?:\/\//.test(result.url)) && Array.isArray(result.checks) && result.checks.every((check) => typeof check === "string");
|
|
14220
14263
|
}
|
|
14264
|
+
// src/settings-client.tsx
|
|
14265
|
+
var settings_client_exports = /* @__PURE__ */ __exportAll({ apply: () => apply$1 });
|
|
14266
|
+
const copy$1 = {
|
|
14267
|
+
ko: {
|
|
14268
|
+
nav: "버전 관리",
|
|
14269
|
+
scope: "DSH의 Git 버튼이 생성하는 커밋에만 적용합니다. 저장소와 사용자 Git 설정은 변경하지 않습니다.",
|
|
14270
|
+
author: "커밋 작성자",
|
|
14271
|
+
name: "이름",
|
|
14272
|
+
email: "이메일",
|
|
14273
|
+
authorHint: "이름과 이메일을 모두 비우면 기존 Git 작성자를 사용합니다. 커미터는 변경하지 않습니다.",
|
|
14274
|
+
noSign: "항상 커밋 서명 비활성화",
|
|
14275
|
+
noSignHint: "활성화하면 이 UI에서 생성하는 커밋에 --no-gpg-sign을 적용합니다. 비활성화하면 기존 Git 서명 설정을 따릅니다.",
|
|
14276
|
+
loading: "불러오는 중…",
|
|
14277
|
+
error: "결과를 확인하지 못했습니다. 새로고침한 뒤 다시 시도하세요.",
|
|
14278
|
+
conflict: "다른 곳에서 설정을 변경했습니다. 새로고침한 뒤 다시 입력하세요.",
|
|
14279
|
+
invalid: "이름과 올바른 이메일을 함께 입력하거나 두 항목을 모두 비우세요.",
|
|
14280
|
+
cli: "CLI 인증 상태",
|
|
14281
|
+
refresh: "새로고침",
|
|
14282
|
+
selectSession: "CLI 상태를 확인하려면 세션을 먼저 여세요.",
|
|
14283
|
+
authenticated: "인증됨",
|
|
14284
|
+
unauthenticated: "인증되지 않음",
|
|
14285
|
+
unavailable: "설치되지 않음",
|
|
14286
|
+
errorStatus: "확인 실패",
|
|
14287
|
+
environment: "환경 변수",
|
|
14288
|
+
keyring: "키링",
|
|
14289
|
+
"config-file": "CLI 설정 파일"
|
|
14290
|
+
},
|
|
14291
|
+
en: {
|
|
14292
|
+
nav: "Version control",
|
|
14293
|
+
scope: "Only applies to commits created by DSH Git buttons. Repository and user Git configuration are never changed.",
|
|
14294
|
+
author: "Commit author",
|
|
14295
|
+
name: "Name",
|
|
14296
|
+
email: "Email",
|
|
14297
|
+
authorHint: "Leave both fields empty to use the existing Git author. The committer is not changed.",
|
|
14298
|
+
noSign: "Always disable commit signing",
|
|
14299
|
+
noSignHint: "When enabled, commits created by this UI use --no-gpg-sign. Otherwise, existing Git signing settings apply.",
|
|
14300
|
+
loading: "Loading…",
|
|
14301
|
+
error: "Could not confirm the result. Refresh before retrying.",
|
|
14302
|
+
conflict: "Settings changed elsewhere. Refresh and enter your changes again.",
|
|
14303
|
+
invalid: "Enter both a name and a valid email, or leave both fields empty.",
|
|
14304
|
+
cli: "CLI authentication",
|
|
14305
|
+
refresh: "Refresh",
|
|
14306
|
+
selectSession: "Open a session to check CLI status.",
|
|
14307
|
+
authenticated: "Authenticated",
|
|
14308
|
+
unauthenticated: "Not authenticated",
|
|
14309
|
+
unavailable: "Not installed",
|
|
14310
|
+
errorStatus: "Check failed",
|
|
14311
|
+
environment: "Environment variable",
|
|
14312
|
+
keyring: "Keyring",
|
|
14313
|
+
"config-file": "CLI config file"
|
|
14314
|
+
},
|
|
14315
|
+
zh: {
|
|
14316
|
+
nav: "版本控制",
|
|
14317
|
+
scope: "仅适用于 DSH Git 按钮创建的提交,不会修改仓库或用户 Git 配置。",
|
|
14318
|
+
author: "提交作者",
|
|
14319
|
+
name: "姓名",
|
|
14320
|
+
email: "邮箱",
|
|
14321
|
+
authorHint: "将两个字段都留空以使用现有 Git 作者,不更改提交者。",
|
|
14322
|
+
noSign: "始终禁用提交签名",
|
|
14323
|
+
noSignHint: "启用时,此 UI 创建的提交使用 --no-gpg-sign;否则遵循现有 Git 签名设置。",
|
|
14324
|
+
loading: "正在加载…",
|
|
14325
|
+
error: "无法确认结果,请刷新后重试。",
|
|
14326
|
+
conflict: "设置已在其他位置更改,请刷新后重新输入。",
|
|
14327
|
+
invalid: "请输入姓名和有效邮箱,或将两个字段都留空。",
|
|
14328
|
+
cli: "CLI 认证状态",
|
|
14329
|
+
refresh: "刷新",
|
|
14330
|
+
selectSession: "请先打开会话以检查 CLI 状态。",
|
|
14331
|
+
authenticated: "已认证",
|
|
14332
|
+
unauthenticated: "未认证",
|
|
14333
|
+
unavailable: "未安装",
|
|
14334
|
+
errorStatus: "检查失败",
|
|
14335
|
+
environment: "环境变量",
|
|
14336
|
+
keyring: "密钥环",
|
|
14337
|
+
"config-file": "CLI 配置文件"
|
|
14338
|
+
}
|
|
14339
|
+
};
|
|
14340
|
+
const localized = (language) => copy$1[language.startsWith("ko") ? "ko" : language.startsWith("zh") ? "zh" : "en"];
|
|
14341
|
+
function VcsSettings({ ctx }) {
|
|
14342
|
+
const { active } = useLocaleSnapshot(ctx.locale);
|
|
14343
|
+
const text = localized(active);
|
|
14344
|
+
const id = (0, react.useId)();
|
|
14345
|
+
const connection = ctx.get("connection");
|
|
14346
|
+
const sessionId = (0, react.useSyncExternalStore)((listener) => ctx.sidebarRight.mounted.subscribe(listener), () => ctx.sidebarRight.mounted.getSnapshot());
|
|
14347
|
+
const [view, setView] = (0, react.useState)();
|
|
14348
|
+
const [draft, setDraft] = (0, react.useState)();
|
|
14349
|
+
const [busy, setBusy] = (0, react.useState)(false);
|
|
14350
|
+
const [blocked, setBlocked] = (0, react.useState)(false);
|
|
14351
|
+
const [notice, setNotice] = (0, react.useState)();
|
|
14352
|
+
const [cli, setCli] = (0, react.useState)();
|
|
14353
|
+
const [checking, setChecking] = (0, react.useState)(false);
|
|
14354
|
+
const [cliError, setCliError] = (0, react.useState)(false);
|
|
14355
|
+
const pending = (0, react.useRef)(false);
|
|
14356
|
+
const lifetime = (0, react.useRef)(null);
|
|
14357
|
+
const load = async (signal) => {
|
|
14358
|
+
setBusy(true);
|
|
14359
|
+
try {
|
|
14360
|
+
const result = await connection.rpc.call(channel, "dungsil-vcs/settings", {}, signal);
|
|
14361
|
+
if (signal.aborted) return;
|
|
14362
|
+
if (!result.ok) throw new Error("unavailable");
|
|
14363
|
+
const next = result.value;
|
|
14364
|
+
setView(next);
|
|
14365
|
+
setDraft(next.settings);
|
|
14366
|
+
setBlocked(false);
|
|
14367
|
+
setNotice(void 0);
|
|
14368
|
+
} catch {
|
|
14369
|
+
if (!signal.aborted) {
|
|
14370
|
+
setBlocked(true);
|
|
14371
|
+
setNotice("error");
|
|
14372
|
+
}
|
|
14373
|
+
} finally {
|
|
14374
|
+
if (!signal.aborted) setBusy(false);
|
|
14375
|
+
}
|
|
14376
|
+
};
|
|
14377
|
+
(0, react.useEffect)(() => {
|
|
14378
|
+
const controller = new AbortController();
|
|
14379
|
+
lifetime.current = controller;
|
|
14380
|
+
load(controller.signal);
|
|
14381
|
+
return () => controller.abort();
|
|
14382
|
+
}, []);
|
|
14383
|
+
(0, react.useEffect)(() => {
|
|
14384
|
+
const controller = new AbortController();
|
|
14385
|
+
setCli(void 0);
|
|
14386
|
+
setCliError(false);
|
|
14387
|
+
setChecking(false);
|
|
14388
|
+
if (sessionId) check(controller.signal);
|
|
14389
|
+
return () => controller.abort();
|
|
14390
|
+
}, [sessionId]);
|
|
14391
|
+
const check = async (signal) => {
|
|
14392
|
+
setChecking(true);
|
|
14393
|
+
setCliError(false);
|
|
14394
|
+
try {
|
|
14395
|
+
const result = await connection.rpc.call(channel, "dungsil-vcs/cli-status", { sessionId }, signal);
|
|
14396
|
+
if (signal.aborted) return;
|
|
14397
|
+
if (!result.ok) throw new Error("unavailable");
|
|
14398
|
+
setCli(result.value);
|
|
14399
|
+
} catch {
|
|
14400
|
+
if (!signal.aborted) {
|
|
14401
|
+
setCli(void 0);
|
|
14402
|
+
setCliError(true);
|
|
14403
|
+
}
|
|
14404
|
+
} finally {
|
|
14405
|
+
if (!signal.aborted) setChecking(false);
|
|
14406
|
+
}
|
|
14407
|
+
};
|
|
14408
|
+
const save = async () => {
|
|
14409
|
+
const signal = lifetime.current?.signal;
|
|
14410
|
+
if (!signal || signal.aborted || pending.current || !view || !validCommitSettings(draft) || blocked) return;
|
|
14411
|
+
if (JSON.stringify(view.settings) === JSON.stringify(draft)) return;
|
|
14412
|
+
const settings = draft;
|
|
14413
|
+
pending.current = true;
|
|
14414
|
+
setBusy(true);
|
|
14415
|
+
setNotice(void 0);
|
|
14416
|
+
try {
|
|
14417
|
+
const result = await connection.rpc.call(channel, "dungsil-vcs/save-settings", {
|
|
14418
|
+
revision: view.revision,
|
|
14419
|
+
settings
|
|
14420
|
+
}, signal);
|
|
14421
|
+
if (signal.aborted) return;
|
|
14422
|
+
if (!result.ok) {
|
|
14423
|
+
setBlocked(true);
|
|
14424
|
+
setNotice(result.error.code === "conflict" ? "conflict" : "error");
|
|
14425
|
+
return;
|
|
14426
|
+
}
|
|
14427
|
+
const next = result.value;
|
|
14428
|
+
setView(next);
|
|
14429
|
+
setDraft((current) => JSON.stringify(current) === JSON.stringify(settings) ? next.settings : current);
|
|
14430
|
+
} catch {
|
|
14431
|
+
if (!signal.aborted) {
|
|
14432
|
+
setBlocked(true);
|
|
14433
|
+
setNotice("error");
|
|
14434
|
+
}
|
|
14435
|
+
} finally {
|
|
14436
|
+
pending.current = false;
|
|
14437
|
+
if (!signal.aborted) setBusy(false);
|
|
14438
|
+
}
|
|
14439
|
+
};
|
|
14440
|
+
(0, react.useEffect)(() => {
|
|
14441
|
+
if (busy || blocked || !view || !validCommitSettings(draft)) return;
|
|
14442
|
+
if (JSON.stringify(view.settings) === JSON.stringify(draft)) return;
|
|
14443
|
+
const timer = setTimeout(() => void save(), 600);
|
|
14444
|
+
return () => clearTimeout(timer);
|
|
14445
|
+
}, [
|
|
14446
|
+
draft,
|
|
14447
|
+
view,
|
|
14448
|
+
busy,
|
|
14449
|
+
blocked
|
|
14450
|
+
]);
|
|
14451
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
14452
|
+
className: "dsh-vcs-settings",
|
|
14453
|
+
"aria-label": text.nav,
|
|
14454
|
+
children: [
|
|
14455
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: text.scope }),
|
|
14456
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
14457
|
+
onSubmit: (event) => {
|
|
14458
|
+
event.preventDefault();
|
|
14459
|
+
save();
|
|
14460
|
+
},
|
|
14461
|
+
children: [
|
|
14462
|
+
draft && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
14463
|
+
disabled: blocked,
|
|
14464
|
+
children: [
|
|
14465
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: text.author }),
|
|
14466
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: text.authorHint }),
|
|
14467
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsRow, {
|
|
14468
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
14469
|
+
htmlFor: `${id}-name`,
|
|
14470
|
+
children: text.name
|
|
14471
|
+
}),
|
|
14472
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
14473
|
+
className: "dsh-vcs-settings-input",
|
|
14474
|
+
id: `${id}-name`,
|
|
14475
|
+
value: draft.authorName,
|
|
14476
|
+
maxLength: 200,
|
|
14477
|
+
autoComplete: "off",
|
|
14478
|
+
onChange: (event) => {
|
|
14479
|
+
setDraft({
|
|
14480
|
+
...draft,
|
|
14481
|
+
authorName: event.target.value
|
|
14482
|
+
});
|
|
14483
|
+
setNotice(void 0);
|
|
14484
|
+
}
|
|
14485
|
+
})
|
|
14486
|
+
}),
|
|
14487
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsRow, {
|
|
14488
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
14489
|
+
htmlFor: `${id}-email`,
|
|
14490
|
+
children: text.email
|
|
14491
|
+
}),
|
|
14492
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
14493
|
+
className: "dsh-vcs-settings-input",
|
|
14494
|
+
id: `${id}-email`,
|
|
14495
|
+
type: "email",
|
|
14496
|
+
value: draft.authorEmail,
|
|
14497
|
+
maxLength: 254,
|
|
14498
|
+
autoComplete: "off",
|
|
14499
|
+
onChange: (event) => {
|
|
14500
|
+
setDraft({
|
|
14501
|
+
...draft,
|
|
14502
|
+
authorEmail: event.target.value
|
|
14503
|
+
});
|
|
14504
|
+
setNotice(void 0);
|
|
14505
|
+
}
|
|
14506
|
+
})
|
|
14507
|
+
}),
|
|
14508
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsRow, {
|
|
14509
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: text.noSign }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: text.noSignHint })] }),
|
|
14510
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
14511
|
+
label: text.noSign,
|
|
14512
|
+
checked: draft.noSign,
|
|
14513
|
+
disabled: blocked,
|
|
14514
|
+
onChange: (noSign) => {
|
|
14515
|
+
setDraft({
|
|
14516
|
+
...draft,
|
|
14517
|
+
noSign
|
|
14518
|
+
});
|
|
14519
|
+
setNotice(void 0);
|
|
14520
|
+
}
|
|
14521
|
+
})
|
|
14522
|
+
}),
|
|
14523
|
+
!validCommitSettings(draft) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14524
|
+
role: "alert",
|
|
14525
|
+
children: text.invalid
|
|
14526
|
+
})
|
|
14527
|
+
]
|
|
14528
|
+
}),
|
|
14529
|
+
busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14530
|
+
role: "status",
|
|
14531
|
+
children: text.loading
|
|
14532
|
+
}),
|
|
14533
|
+
notice && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14534
|
+
role: "alert",
|
|
14535
|
+
children: text[notice]
|
|
14536
|
+
}),
|
|
14537
|
+
blocked && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
14538
|
+
type: "button",
|
|
14539
|
+
disabled: busy,
|
|
14540
|
+
onClick: () => {
|
|
14541
|
+
if (lifetime.current) load(lifetime.current.signal);
|
|
14542
|
+
},
|
|
14543
|
+
children: text.refresh
|
|
14544
|
+
})
|
|
14545
|
+
]
|
|
14546
|
+
}),
|
|
14547
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: text.cli }),
|
|
14548
|
+
!sessionId ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14549
|
+
role: "status",
|
|
14550
|
+
children: text.selectSession
|
|
14551
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
14552
|
+
checking && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14553
|
+
role: "status",
|
|
14554
|
+
children: text.loading
|
|
14555
|
+
}),
|
|
14556
|
+
cliError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
14557
|
+
role: "alert",
|
|
14558
|
+
children: text.error
|
|
14559
|
+
}),
|
|
14560
|
+
cli?.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14561
|
+
className: "dsh-vcs-settings-cli",
|
|
14562
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsRow, {
|
|
14563
|
+
label: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: item.cli }),
|
|
14564
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text[item.status === "error" ? "errorStatus" : item.status] })
|
|
14565
|
+
}), item.accounts.map((account, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", { children: [
|
|
14566
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: account.host }),
|
|
14567
|
+
" · ",
|
|
14568
|
+
account.login,
|
|
14569
|
+
account.method && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [" · ", text[account.method]] })
|
|
14570
|
+
] }, index))]
|
|
14571
|
+
}, item.cli))
|
|
14572
|
+
] })
|
|
14573
|
+
]
|
|
14574
|
+
});
|
|
14575
|
+
}
|
|
14576
|
+
function apply$1(ctx) {
|
|
14577
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
14578
|
+
name: "settings.section",
|
|
14579
|
+
id: "dungsil-ui-vcs",
|
|
14580
|
+
order: 17,
|
|
14581
|
+
label: () => localized(ctx.locale.getSnapshot().active).nav,
|
|
14582
|
+
inject: () => ({ ctx })
|
|
14583
|
+
}, VcsSettings));
|
|
14584
|
+
ctx.effect(() => installStyles(`${settingsStyles}
|
|
14585
|
+
.dsh-vcs-settings { color: var(--dsw-alias-label-primary); font: 14px/22px var(--dsw-font-family, system-ui); }
|
|
14586
|
+
.dsh-vcs-settings fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }
|
|
14587
|
+
.dsh-vcs-settings h3 { font: inherit; font-weight: 600; margin: 24px 0 8px; }
|
|
14588
|
+
.dsh-vcs-settings p { color: var(--dsw-alias-label-secondary); margin: 8px 0; overflow-wrap: anywhere; }
|
|
14589
|
+
.dsh-vcs-settings .dsh-plugin-settings-text p { font-size: 12px; line-height: 20px; margin: 4px 0 0; }
|
|
14590
|
+
.dsh-vcs-settings-input { box-sizing: border-box; width: 240px; max-width: 65%; flex: 0 1 240px; min-width: 0; }
|
|
14591
|
+
.dsh-vcs-settings [role=alert] { color: var(--dsw-alias-state-error-primary); }
|
|
14592
|
+
.dsh-vcs-settings-cli .dsh-plugin-settings-row { padding: 8px 0; }
|
|
14593
|
+
`), "ui-vcs: settings styles");
|
|
14594
|
+
}
|
|
14221
14595
|
// src/client.tsx
|
|
14222
14596
|
const name = "dungsil-ui-vcs";
|
|
14223
14597
|
const inject = [
|
|
@@ -14235,17 +14609,8 @@ const copy = {
|
|
|
14235
14609
|
push: "Push",
|
|
14236
14610
|
commit: "Commit only",
|
|
14237
14611
|
menu: "More Git actions",
|
|
14238
|
-
loading: "Checking branch…",
|
|
14239
|
-
lookupError: "Could not determine the default branch. Refocus this window to retry. Commit only is still available.",
|
|
14240
14612
|
hint: "Commit and push changes, and create or update a PR on a feature branch or worktree.",
|
|
14241
|
-
sending: "Running Git action…"
|
|
14242
|
-
sent: "Git action completed.",
|
|
14243
|
-
noChanges: "No task changes to commit.",
|
|
14244
|
-
error: "Could not confirm the Git action. Check Git and remote state before retrying.",
|
|
14245
|
-
partialStage: "A selected file has staged and unstaged changes. Finish staging that file before retrying.",
|
|
14246
|
-
readOnly: "Git actions are unavailable in read-only mode.",
|
|
14247
|
-
conflict: "The repository changed. Check Git state before retrying.",
|
|
14248
|
-
busy: "Another task is active. Wait for it to finish."
|
|
14613
|
+
sending: "Running Git action…"
|
|
14249
14614
|
},
|
|
14250
14615
|
ko: {
|
|
14251
14616
|
pr: "PR 생성",
|
|
@@ -14254,17 +14619,8 @@ const copy = {
|
|
|
14254
14619
|
push: "푸시",
|
|
14255
14620
|
commit: "커밋만",
|
|
14256
14621
|
menu: "다른 Git 작업",
|
|
14257
|
-
loading: "브랜치 확인 중…",
|
|
14258
|
-
lookupError: "기본 브랜치를 확인하지 못했습니다. 창으로 돌아오면 다시 확인합니다. 커밋만 요청할 수 있습니다.",
|
|
14259
14622
|
hint: "변경 사항을 커밋·푸시하고, 기능 브랜치나 worktree에서는 PR을 생성하거나 업데이트합니다.",
|
|
14260
|
-
sending: "Git 작업 실행 중…"
|
|
14261
|
-
sent: "Git 작업을 완료했습니다.",
|
|
14262
|
-
noChanges: "커밋할 작업 변경 사항이 없습니다.",
|
|
14263
|
-
error: "Git 작업 결과를 확인하지 못했습니다. 다시 시도하기 전에 Git과 원격 저장소 상태를 확인하세요.",
|
|
14264
|
-
partialStage: "선택한 파일에 스테이징한 변경과 하지 않은 변경이 함께 있습니다. 해당 파일의 스테이징을 마친 뒤 다시 시도하세요.",
|
|
14265
|
-
readOnly: "읽기 전용 모드에서는 Git 작업을 실행할 수 없습니다.",
|
|
14266
|
-
conflict: "저장소 상태가 바뀌었습니다. Git 상태를 확인한 뒤 다시 시도하세요.",
|
|
14267
|
-
busy: "다른 작업을 실행 중입니다. 작업이 끝날 때까지 기다리세요."
|
|
14623
|
+
sending: "Git 작업 실행 중…"
|
|
14268
14624
|
},
|
|
14269
14625
|
zh: {
|
|
14270
14626
|
pr: "创建 PR",
|
|
@@ -14273,21 +14629,13 @@ const copy = {
|
|
|
14273
14629
|
push: "推送",
|
|
14274
14630
|
commit: "仅提交",
|
|
14275
14631
|
menu: "更多 Git 操作",
|
|
14276
|
-
loading: "正在检查分支…",
|
|
14277
|
-
lookupError: "无法确定默认分支。重新聚焦窗口以重试。仍可选择仅提交。",
|
|
14278
14632
|
hint: "提交并推送更改,在功能分支或 worktree 中创建或更新 PR。",
|
|
14279
|
-
sending: "正在执行 Git 操作…"
|
|
14280
|
-
sent: "Git 操作已完成。",
|
|
14281
|
-
noChanges: "没有可提交的任务更改。",
|
|
14282
|
-
error: "无法确认 Git 操作结果。请先检查 Git 和远程仓库状态,再决定是否重试。",
|
|
14283
|
-
partialStage: "所选文件同时包含已暂存和未暂存的更改。请完成该文件的暂存后重试。",
|
|
14284
|
-
readOnly: "只读模式下无法执行 Git 操作。",
|
|
14285
|
-
conflict: "仓库状态已更改。请检查 Git 状态后重试。",
|
|
14286
|
-
busy: "另一个任务正在运行。请等待任务结束。"
|
|
14633
|
+
sending: "正在执行 Git 操作…"
|
|
14287
14634
|
}
|
|
14288
14635
|
};
|
|
14289
14636
|
function apply(ctx) {
|
|
14290
14637
|
ctx.plugin(pull_requests_client_exports);
|
|
14638
|
+
ctx.plugin(settings_client_exports);
|
|
14291
14639
|
const connection = ctx.get("connection");
|
|
14292
14640
|
function Action({ sessionId, useSession, useAccess, useProjection }) {
|
|
14293
14641
|
const language = (0, react.useSyncExternalStore)((listener) => ctx.locale.subscribe(listener), () => ctx.locale.getSnapshot().active);
|
|
@@ -14306,9 +14654,7 @@ function apply(ctx) {
|
|
|
14306
14654
|
const [lookup, setLookup] = (0, react.useState)("loading");
|
|
14307
14655
|
const [open, setOpen] = (0, react.useState)(false);
|
|
14308
14656
|
const [hasChanges, setHasChanges] = (0, react.useState)(false);
|
|
14309
|
-
const [
|
|
14310
|
-
const [result, setResult] = (0, react.useState)();
|
|
14311
|
-
const [errorCode, setErrorCode] = (0, react.useState)("");
|
|
14657
|
+
const [sending, setSending] = (0, react.useState)(false);
|
|
14312
14658
|
const mounted = (0, react.useRef)(true);
|
|
14313
14659
|
(0, react.useEffect)(() => {
|
|
14314
14660
|
mounted.current = true;
|
|
@@ -14316,8 +14662,7 @@ function apply(ctx) {
|
|
|
14316
14662
|
mounted.current = false;
|
|
14317
14663
|
};
|
|
14318
14664
|
}, []);
|
|
14319
|
-
const
|
|
14320
|
-
const disabled = !canPrompt || unavailable || status === "sending" || typeof cwd !== "string";
|
|
14665
|
+
const disabled = !canPrompt || unavailable || sending || typeof cwd !== "string";
|
|
14321
14666
|
const viewOnly = hasRequest && !needsUpdate;
|
|
14322
14667
|
const ciState = ciRequest ? checksState(ciRequest) : "warning";
|
|
14323
14668
|
const ciLabel = {
|
|
@@ -14401,9 +14746,7 @@ function apply(ctx) {
|
|
|
14401
14746
|
if (disabled || pending.current || typeof cwd !== "string") return;
|
|
14402
14747
|
pending.current = true;
|
|
14403
14748
|
setOpen(false);
|
|
14404
|
-
|
|
14405
|
-
setErrorCode("");
|
|
14406
|
-
setStatus("sending");
|
|
14749
|
+
setSending(true);
|
|
14407
14750
|
try {
|
|
14408
14751
|
const response = await connection.rpc.call(channel, executeMethod, {
|
|
14409
14752
|
sessionId,
|
|
@@ -14412,110 +14755,79 @@ function apply(ctx) {
|
|
|
14412
14755
|
requestId: crypto.randomUUID()
|
|
14413
14756
|
}, AbortSignal.timeout(3e5));
|
|
14414
14757
|
if (!mounted.current) return;
|
|
14415
|
-
if (!response.ok)
|
|
14416
|
-
setErrorCode(response.error.code);
|
|
14417
|
-
setStatus("error");
|
|
14418
|
-
return;
|
|
14419
|
-
}
|
|
14758
|
+
if (!response.ok) return;
|
|
14420
14759
|
if (!isGitActionResult(response.value) || response.value.operation !== selected) throw new Error("Invalid Git response");
|
|
14421
|
-
setResult(response.value);
|
|
14422
14760
|
if (response.value.operation === "pr" && response.value.url) {
|
|
14423
14761
|
setHasRequest(true);
|
|
14424
14762
|
setNeedsUpdate(false);
|
|
14425
14763
|
}
|
|
14426
|
-
|
|
14427
|
-
} catch {
|
|
14428
|
-
if (mounted.current) setStatus("error");
|
|
14429
|
-
} finally {
|
|
14764
|
+
} catch {} finally {
|
|
14430
14765
|
pending.current = false;
|
|
14766
|
+
if (mounted.current) setSending(false);
|
|
14431
14767
|
}
|
|
14432
14768
|
};
|
|
14433
|
-
if (hidden || !hasChanges) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14769
|
+
if (hidden || !hasChanges || lookup !== "ready" || !operation) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14434
14770
|
ref: anchor,
|
|
14435
14771
|
hidden: true
|
|
14436
14772
|
});
|
|
14437
14773
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14438
14774
|
className: "dsh-vcs",
|
|
14439
|
-
children: [
|
|
14440
|
-
|
|
14441
|
-
|
|
14442
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14443
|
-
className: "dsh-vcs-trigger",
|
|
14444
|
-
disabled: !viewOnly && disabled || !operation || lookup !== "ready",
|
|
14445
|
-
title: viewOnly ? text.viewPr : text.hint,
|
|
14446
|
-
"aria-describedby": statusId,
|
|
14447
|
-
"aria-busy": status === "sending",
|
|
14448
|
-
onClick: () => {
|
|
14449
|
-
if (viewOnly) ctx.sidebarRight.openTab(name$1);
|
|
14450
|
-
else if (operation) send(operation);
|
|
14451
|
-
},
|
|
14452
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { "aria-hidden": "true" }), viewOnly ? text.viewPr : status === "sending" ? text.sending : operation === "push" ? text.push : hasRequest ? text.updatePr : text.pr]
|
|
14453
|
-
}), !viewOnly && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
14454
|
-
open,
|
|
14455
|
-
side: "top",
|
|
14456
|
-
portal: true,
|
|
14457
|
-
compact: true,
|
|
14458
|
-
items: [...hasRequest ? [{
|
|
14459
|
-
id: "view",
|
|
14460
|
-
label: text.viewPr
|
|
14461
|
-
}] : [], {
|
|
14462
|
-
id: "commit",
|
|
14463
|
-
label: text.commit
|
|
14464
|
-
}],
|
|
14465
|
-
onClose: () => setOpen(false),
|
|
14466
|
-
onSelect: (id) => {
|
|
14467
|
-
if (id === "view") {
|
|
14468
|
-
setOpen(false);
|
|
14469
|
-
ctx.sidebarRight.openTab("dungsil-vcs-pull-requests");
|
|
14470
|
-
} else send("commit");
|
|
14471
|
-
},
|
|
14472
|
-
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14473
|
-
className: "dsh-vcs-trigger dsh-vcs-menu",
|
|
14474
|
-
disabled,
|
|
14475
|
-
"aria-label": text.menu,
|
|
14476
|
-
"aria-haspopup": "menu",
|
|
14477
|
-
"aria-expanded": open,
|
|
14478
|
-
onClick: () => setOpen((value) => !value),
|
|
14479
|
-
onKeyDown: (event) => {
|
|
14480
|
-
if (!open && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
14481
|
-
event.preventDefault();
|
|
14482
|
-
setOpen(true);
|
|
14483
|
-
}
|
|
14484
|
-
},
|
|
14485
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { "aria-hidden": "true" })
|
|
14486
|
-
})
|
|
14487
|
-
})]
|
|
14488
|
-
}),
|
|
14489
|
-
hasRequest && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14775
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
14776
|
+
className: "dsh-vcs-actions",
|
|
14777
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14490
14778
|
className: "dsh-vcs-trigger",
|
|
14491
|
-
|
|
14492
|
-
|
|
14493
|
-
|
|
14494
|
-
|
|
14495
|
-
|
|
14496
|
-
|
|
14497
|
-
|
|
14498
|
-
|
|
14499
|
-
|
|
14500
|
-
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14779
|
+
disabled: !viewOnly && disabled,
|
|
14780
|
+
title: viewOnly ? text.viewPr : text.hint,
|
|
14781
|
+
"aria-busy": sending,
|
|
14782
|
+
onClick: () => {
|
|
14783
|
+
if (viewOnly) ctx.sidebarRight.openTab(name$1);
|
|
14784
|
+
else if (operation) send(operation);
|
|
14785
|
+
},
|
|
14786
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, { "aria-hidden": "true" }), viewOnly ? text.viewPr : sending ? text.sending : operation === "push" ? text.push : hasRequest ? text.updatePr : text.pr]
|
|
14787
|
+
}), !viewOnly && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
14788
|
+
open,
|
|
14789
|
+
side: "top",
|
|
14790
|
+
portal: true,
|
|
14791
|
+
compact: true,
|
|
14792
|
+
items: [...hasRequest ? [{
|
|
14793
|
+
id: "view",
|
|
14794
|
+
label: text.viewPr
|
|
14795
|
+
}] : [], {
|
|
14796
|
+
id: "commit",
|
|
14797
|
+
label: text.commit
|
|
14798
|
+
}],
|
|
14799
|
+
onClose: () => setOpen(false),
|
|
14800
|
+
onSelect: (id) => {
|
|
14801
|
+
if (id === "view") {
|
|
14802
|
+
setOpen(false);
|
|
14803
|
+
ctx.sidebarRight.openTab("dungsil-vcs-pull-requests");
|
|
14804
|
+
} else send("commit");
|
|
14805
|
+
},
|
|
14806
|
+
anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14807
|
+
className: "dsh-vcs-trigger dsh-vcs-menu",
|
|
14808
|
+
disabled,
|
|
14809
|
+
"aria-label": text.menu,
|
|
14810
|
+
"aria-haspopup": "menu",
|
|
14811
|
+
"aria-expanded": open,
|
|
14812
|
+
onClick: () => setOpen((value) => !value),
|
|
14813
|
+
onKeyDown: (event) => {
|
|
14814
|
+
if (!open && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
|
|
14815
|
+
event.preventDefault();
|
|
14816
|
+
setOpen(true);
|
|
14817
|
+
}
|
|
14818
|
+
},
|
|
14819
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { "aria-hidden": "true" })
|
|
14820
|
+
})
|
|
14821
|
+
})]
|
|
14822
|
+
}), hasRequest && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Pill, {
|
|
14823
|
+
className: "dsh-vcs-trigger",
|
|
14824
|
+
title: `${labels.checks}: ${ciLabel}`,
|
|
14825
|
+
onClick: () => ctx.sidebarRight.openTab("dungsil-vcs-pull-requests", { params: { section: "checks" } }),
|
|
14826
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
|
|
14827
|
+
state: ciState,
|
|
14828
|
+
appearance: "step"
|
|
14829
|
+
}), `${labels.checks}: ${ciLabel}`]
|
|
14830
|
+
})]
|
|
14519
14831
|
});
|
|
14520
14832
|
}
|
|
14521
14833
|
ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
|
|
@@ -14531,15 +14843,10 @@ function apply(ctx) {
|
|
|
14531
14843
|
.dsh-vcs-actions > .dsh-vcs-trigger { border-radius: 14px 0 0 14px; }
|
|
14532
14844
|
.dsh-vcs-actions > .dsh-vcs-trigger:only-child { border-radius: 14px; }
|
|
14533
14845
|
.dsh-vcs-actions .dsh-vcs-menu { border-radius: 0 14px 14px 0; border-left: 0; padding: 0 7px; }
|
|
14534
|
-
.dsh-vcs-notice { font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }
|
|
14535
14846
|
.dsh-vcs-trigger { height: 28px; max-width: 100%; padding: 0 10px; border: 1px solid var(--dsw-alias-border-l2); font: inherit; font-size: 12px; line-height: 18px; }
|
|
14536
14847
|
.dsh-vcs-trigger svg { flex: none; width: 14px; height: 14px; }
|
|
14537
14848
|
.dsh-vcs-trigger:disabled { background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-dimmed); cursor: default; }
|
|
14538
14849
|
.dsh-vcs-trigger:focus-visible { outline: 2px solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); outline-offset: 0; }
|
|
14539
|
-
.dsh-vcs-status { flex-basis: 100%; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); }
|
|
14540
|
-
.dsh-vcs-status:empty { display: none; }
|
|
14541
|
-
.dsh-vcs-status { overflow-wrap: anywhere; }
|
|
14542
|
-
.dsh-vcs-status[role=alert] { color: var(--dsw-alias-state-error-primary); }
|
|
14543
14850
|
.dsh-vcs-session-request svg { width: 100%; height: 100%; }
|
|
14544
14851
|
`;
|
|
14545
14852
|
document.head.append(style);
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { clientRequestSchema } from "@deepseek-ai/dsh-client-connection";
|
|
|
3
3
|
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
4
4
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
5
5
|
import { Context, Service } from "@deepseek-ai/cordis";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
6
7
|
// \0rolldown/runtime.js
|
|
7
8
|
var __defProp = Object.defineProperty;
|
|
8
9
|
var __exportAll = (all, no_symbols) => {
|
|
@@ -905,13 +906,13 @@ const method = "dungsil-vcs/pull-requests/list";
|
|
|
905
906
|
const actionMethod = "dungsil-vcs/pull-requests/action";
|
|
906
907
|
// src/pull-requests.ts
|
|
907
908
|
var pull_requests_exports = /* @__PURE__ */ __exportAll({
|
|
908
|
-
Config: () => Config,
|
|
909
|
-
apply: () => apply$
|
|
910
|
-
inject: () => inject$
|
|
911
|
-
name: () => name$
|
|
909
|
+
Config: () => Config$1,
|
|
910
|
+
apply: () => apply$3,
|
|
911
|
+
inject: () => inject$3,
|
|
912
|
+
name: () => name$3
|
|
912
913
|
});
|
|
913
|
-
const name$
|
|
914
|
-
const inject$
|
|
914
|
+
const name$3 = "dungsil-vcs-pull-requests";
|
|
915
|
+
const inject$3 = [
|
|
915
916
|
"connection",
|
|
916
917
|
"sessionController",
|
|
917
918
|
"workingDirectory",
|
|
@@ -919,7 +920,7 @@ const inject$2 = [
|
|
|
919
920
|
"sandbox",
|
|
920
921
|
"sandboxPolicy"
|
|
921
922
|
];
|
|
922
|
-
const Config = Schema.object({ provider: Schema.union([
|
|
923
|
+
const Config$1 = Schema.object({ provider: Schema.union([
|
|
923
924
|
"auto",
|
|
924
925
|
"github",
|
|
925
926
|
"gitlab",
|
|
@@ -971,7 +972,7 @@ function actionInput$1(value) {
|
|
|
971
972
|
].includes(input.strategy)) || input.action === "merge" && input.body !== void 0) throw new Error("invalid_payload");
|
|
972
973
|
return input;
|
|
973
974
|
}
|
|
974
|
-
function apply$
|
|
975
|
+
function apply$3(ctx, config) {
|
|
975
976
|
const lifetime = new AbortController();
|
|
976
977
|
const actionsInFlight = /* @__PURE__ */ new Set();
|
|
977
978
|
ctx.effect(() => () => lifetime.abort());
|
|
@@ -4514,14 +4515,23 @@ async function generateTexts(ctx, agent, operation, context, signal) {
|
|
|
4514
4515
|
// src/protocol.ts
|
|
4515
4516
|
const channel = "/api";
|
|
4516
4517
|
const executeMethod = "dungsil-vcs/execute";
|
|
4518
|
+
function validCommitSettings(value) {
|
|
4519
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
4520
|
+
const input = value;
|
|
4521
|
+
return Object.keys(input).every((key) => [
|
|
4522
|
+
"authorName",
|
|
4523
|
+
"authorEmail",
|
|
4524
|
+
"noSign"
|
|
4525
|
+
].includes(key)) && typeof input.authorName === "string" && input.authorName.length <= 200 && !/[<>]/.test(input.authorName) && !Array.from(input.authorName).some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) && typeof input.authorEmail === "string" && input.authorEmail.length <= 254 && (input.authorEmail === "" || /^[^\s<>@]+@[^\s<>@]+$/.test(input.authorEmail)) && !Array.from(input.authorEmail).some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127) && (input.authorName === "" ? input.authorEmail === "" : !!input.authorName.trim() && !!input.authorEmail) && typeof input.noSign === "boolean";
|
|
4526
|
+
}
|
|
4517
4527
|
// src/commands.ts
|
|
4518
4528
|
var commands_exports = /* @__PURE__ */ __exportAll({
|
|
4519
|
-
apply: () => apply$
|
|
4520
|
-
inject: () => inject$
|
|
4521
|
-
name: () => name$
|
|
4529
|
+
apply: () => apply$2,
|
|
4530
|
+
inject: () => inject$2,
|
|
4531
|
+
name: () => name$2
|
|
4522
4532
|
});
|
|
4523
|
-
const name$
|
|
4524
|
-
const inject$
|
|
4533
|
+
const name$2 = "dungsil-vcs-commands";
|
|
4534
|
+
const inject$2 = [
|
|
4525
4535
|
"connection",
|
|
4526
4536
|
"sessionController",
|
|
4527
4537
|
"workingDirectory",
|
|
@@ -4546,7 +4556,7 @@ function actionInput(value) {
|
|
|
4546
4556
|
].includes(input.operation) || typeof input.requestId !== "string" || !/^[a-zA-Z0-9-]{16,100}$/.test(input.requestId)) throw new Error("invalid");
|
|
4547
4557
|
return input;
|
|
4548
4558
|
}
|
|
4549
|
-
function apply$
|
|
4559
|
+
function apply$2(ctx, config) {
|
|
4550
4560
|
const lifetime = new AbortController();
|
|
4551
4561
|
const pending = /* @__PURE__ */ new Set();
|
|
4552
4562
|
const repositories = /* @__PURE__ */ new Set();
|
|
@@ -4561,6 +4571,12 @@ function apply$1(ctx, config) {
|
|
|
4561
4571
|
}
|
|
4562
4572
|
});
|
|
4563
4573
|
const execute = async (agent, input, signal) => {
|
|
4574
|
+
const settings = {
|
|
4575
|
+
authorName: config.authorName ?? "",
|
|
4576
|
+
authorEmail: config.authorEmail ?? "",
|
|
4577
|
+
noSign: config.noSign ?? false
|
|
4578
|
+
};
|
|
4579
|
+
if (!validCommitSettings(settings)) throw new Error("invalid");
|
|
4564
4580
|
if (ctx.sandboxPolicy.resolve({ session: agent.session }).mode === "read-only") throw new Error("read_only");
|
|
4565
4581
|
const cwd = await ctx.workingDirectory.ensure(agent, signal);
|
|
4566
4582
|
if (cwd !== input.cwd) throw new Error("conflict");
|
|
@@ -4810,6 +4826,8 @@ function apply$1(ctx, config) {
|
|
|
4810
4826
|
]);
|
|
4811
4827
|
await git([
|
|
4812
4828
|
"commit",
|
|
4829
|
+
...settings.authorName ? [`--author=${settings.authorName} <${settings.authorEmail}>`] : [],
|
|
4830
|
+
...settings.noSign ? ["--no-gpg-sign"] : [],
|
|
4813
4831
|
"--only",
|
|
4814
4832
|
"-m",
|
|
4815
4833
|
texts.commitMessage,
|
|
@@ -4906,6 +4924,312 @@ function apply$1(ctx, config) {
|
|
|
4906
4924
|
}
|
|
4907
4925
|
}), "ui-vcs: owner-only commands");
|
|
4908
4926
|
}
|
|
4927
|
+
// src/cli-status.ts
|
|
4928
|
+
function object(value) {
|
|
4929
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("invalid_status");
|
|
4930
|
+
return value;
|
|
4931
|
+
}
|
|
4932
|
+
function parse(output) {
|
|
4933
|
+
if (output.length > 1048576) throw new Error("invalid_status");
|
|
4934
|
+
return JSON.parse(output);
|
|
4935
|
+
}
|
|
4936
|
+
function safe(value) {
|
|
4937
|
+
return typeof value === "string" && !/(?:gh[pousr]_|github_pat_|gl(?:pat|oas|rt|cbt|ptt|ft|soat|dt)-|Bearer|eyJ)/i.test(value) && !/[a-f0-9]{20,}/i.test(value) && !/[a-z0-9_+-]{32,}/i.test(value);
|
|
4938
|
+
}
|
|
4939
|
+
function host(value) {
|
|
4940
|
+
if (!safe(value) || value.length > 253 || !/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?::[0-9]{1,5})?$/i.test(value)) throw new Error("invalid_identity");
|
|
4941
|
+
return value.toLowerCase();
|
|
4942
|
+
}
|
|
4943
|
+
function account(hostname, login, source) {
|
|
4944
|
+
if (!safe(login) || !/^[a-z0-9][a-z0-9_.-]{0,99}$/i.test(login)) throw new Error("invalid_identity");
|
|
4945
|
+
const result = {
|
|
4946
|
+
host: host(hostname),
|
|
4947
|
+
login
|
|
4948
|
+
};
|
|
4949
|
+
if ([
|
|
4950
|
+
"GH_TOKEN",
|
|
4951
|
+
"GITHUB_TOKEN",
|
|
4952
|
+
"GH_ENTERPRISE_TOKEN",
|
|
4953
|
+
"GITHUB_ENTERPRISE_TOKEN",
|
|
4954
|
+
"environment"
|
|
4955
|
+
].includes(String(source))) result.method = "environment";
|
|
4956
|
+
else if (source === "keyring") result.method = "keyring";
|
|
4957
|
+
else if (source === "config_file" || typeof source === "string" && /(?:^|[/\\])hosts\.yml$/.test(source)) result.method = "config-file";
|
|
4958
|
+
return result;
|
|
4959
|
+
}
|
|
4960
|
+
async function inspectAuth(cli, run) {
|
|
4961
|
+
const data = object(parse(await run(cli, cli === "gh" ? [
|
|
4962
|
+
"auth",
|
|
4963
|
+
"status",
|
|
4964
|
+
"--json",
|
|
4965
|
+
"hosts"
|
|
4966
|
+
] : [
|
|
4967
|
+
"auth",
|
|
4968
|
+
"status",
|
|
4969
|
+
"--all",
|
|
4970
|
+
"--output",
|
|
4971
|
+
"json"
|
|
4972
|
+
])));
|
|
4973
|
+
const rows = cli === "gh" ? Object.values(object(data.hosts)).flatMap((entries) => {
|
|
4974
|
+
if (!Array.isArray(entries)) throw new Error("invalid_status");
|
|
4975
|
+
return entries;
|
|
4976
|
+
}) : data.hosts;
|
|
4977
|
+
if (!Array.isArray(rows)) throw new Error("invalid_status");
|
|
4978
|
+
const accounts = [];
|
|
4979
|
+
let failed = false;
|
|
4980
|
+
for (const row of rows) {
|
|
4981
|
+
const entry = object(row);
|
|
4982
|
+
if (entry.state === "success") try {
|
|
4983
|
+
accounts.push(account(entry.host, cli === "gh" ? entry.login : entry.user, cli === "gh" ? entry.tokenSource : entry.token_source));
|
|
4984
|
+
} catch {
|
|
4985
|
+
failed = true;
|
|
4986
|
+
}
|
|
4987
|
+
else if (entry.state !== "refresh_expired") failed = true;
|
|
4988
|
+
}
|
|
4989
|
+
return {
|
|
4990
|
+
cli,
|
|
4991
|
+
status: failed ? "error" : accounts.length ? "authenticated" : "unauthenticated",
|
|
4992
|
+
accounts
|
|
4993
|
+
};
|
|
4994
|
+
}
|
|
4995
|
+
async function inspectTea(run) {
|
|
4996
|
+
const logins = parse(await run("tea", [
|
|
4997
|
+
"login",
|
|
4998
|
+
"list",
|
|
4999
|
+
"--output",
|
|
5000
|
+
"json"
|
|
5001
|
+
]));
|
|
5002
|
+
if (!Array.isArray(logins)) throw new Error("invalid_status");
|
|
5003
|
+
const accounts = [];
|
|
5004
|
+
let failed = false;
|
|
5005
|
+
for (const row of logins) try {
|
|
5006
|
+
const entry = object(row);
|
|
5007
|
+
if (typeof entry.name !== "string" || !entry.name || entry.name.length > 256 || entry.name.split("").some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new Error("invalid_status");
|
|
5008
|
+
if (typeof entry.url !== "string") throw new Error("invalid_status");
|
|
5009
|
+
const url = new URL(entry.url);
|
|
5010
|
+
if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new Error("invalid_identity");
|
|
5011
|
+
const hostname = host(url.host);
|
|
5012
|
+
const user = object(parse(await run("tea", [
|
|
5013
|
+
"api",
|
|
5014
|
+
"--method",
|
|
5015
|
+
"GET",
|
|
5016
|
+
"--login",
|
|
5017
|
+
entry.name,
|
|
5018
|
+
"user"
|
|
5019
|
+
])));
|
|
5020
|
+
if (typeof user.id !== "number" || !Number.isSafeInteger(user.id) || user.id <= 0) throw new Error("invalid_user");
|
|
5021
|
+
accounts.push(account(hostname, user.login));
|
|
5022
|
+
} catch (error) {
|
|
5023
|
+
if (error instanceof Error && error.message === "cli_missing") throw error;
|
|
5024
|
+
failed = true;
|
|
5025
|
+
}
|
|
5026
|
+
return {
|
|
5027
|
+
cli: "tea",
|
|
5028
|
+
status: failed ? "error" : accounts.length ? "authenticated" : "unauthenticated",
|
|
5029
|
+
accounts
|
|
5030
|
+
};
|
|
5031
|
+
}
|
|
5032
|
+
/** The runner must reject resolution failures with Error('cli_missing'), and
|
|
5033
|
+
* reject nonzero exits, policy failures and timeouts with any other error.
|
|
5034
|
+
* It must bound execution/output and disable prompts. No stdout/stderr is ever
|
|
5035
|
+
* returned, including when older CLIs do not support these structured queries.
|
|
5036
|
+
*/
|
|
5037
|
+
async function inspectCliStatus(run) {
|
|
5038
|
+
return Promise.all([
|
|
5039
|
+
"gh",
|
|
5040
|
+
"glab",
|
|
5041
|
+
"tea"
|
|
5042
|
+
].map(async (cli) => {
|
|
5043
|
+
try {
|
|
5044
|
+
return await (cli === "tea" ? inspectTea(run) : inspectAuth(cli, run));
|
|
5045
|
+
} catch (error) {
|
|
5046
|
+
return {
|
|
5047
|
+
cli,
|
|
5048
|
+
status: error instanceof Error && error.message === "cli_missing" ? "unavailable" : "error",
|
|
5049
|
+
accounts: []
|
|
5050
|
+
};
|
|
5051
|
+
}
|
|
5052
|
+
}));
|
|
5053
|
+
}
|
|
5054
|
+
// src/settings.ts
|
|
5055
|
+
var settings_exports = /* @__PURE__ */ __exportAll({
|
|
5056
|
+
Config: () => Config,
|
|
5057
|
+
apply: () => apply$1,
|
|
5058
|
+
inject: () => inject$1,
|
|
5059
|
+
name: () => name$1
|
|
5060
|
+
});
|
|
5061
|
+
const name$1 = "dungsil-vcs-settings";
|
|
5062
|
+
const inject$1 = [
|
|
5063
|
+
"connection",
|
|
5064
|
+
"configEditor",
|
|
5065
|
+
"sessionController",
|
|
5066
|
+
"workingDirectory",
|
|
5067
|
+
"subprocess",
|
|
5068
|
+
"sandbox",
|
|
5069
|
+
"sandboxPolicy"
|
|
5070
|
+
];
|
|
5071
|
+
const Config = Schema.object({
|
|
5072
|
+
provider: Schema.union([
|
|
5073
|
+
"auto",
|
|
5074
|
+
"github",
|
|
5075
|
+
"gitlab",
|
|
5076
|
+
"gitea",
|
|
5077
|
+
"forgejo"
|
|
5078
|
+
]).default("auto"),
|
|
5079
|
+
authorName: Schema.string().default(""),
|
|
5080
|
+
authorEmail: Schema.string().default(""),
|
|
5081
|
+
noSign: Schema.boolean().default(false)
|
|
5082
|
+
});
|
|
5083
|
+
function apply$1(ctx) {
|
|
5084
|
+
const editor = ctx.configEditor;
|
|
5085
|
+
const lifetime = new AbortController();
|
|
5086
|
+
ctx.effect(() => () => lifetime.abort());
|
|
5087
|
+
const entry = () => {
|
|
5088
|
+
const entries = editor.entries().filter((item) => item.options.name === "@dungsil/dsh-plugin-ui-vcs");
|
|
5089
|
+
if (entries.length !== 1) throw new Error("unavailable");
|
|
5090
|
+
return entries[0];
|
|
5091
|
+
};
|
|
5092
|
+
const snapshot = () => {
|
|
5093
|
+
const current = entry().options.config;
|
|
5094
|
+
return {
|
|
5095
|
+
revision: createHash("sha256").update(JSON.stringify(current ?? {})).digest("hex"),
|
|
5096
|
+
settings: {
|
|
5097
|
+
authorName: current?.authorName ?? "",
|
|
5098
|
+
authorEmail: current?.authorEmail ?? "",
|
|
5099
|
+
noSign: current?.noSign ?? false
|
|
5100
|
+
}
|
|
5101
|
+
};
|
|
5102
|
+
};
|
|
5103
|
+
for (const endpoint of [
|
|
5104
|
+
"settings",
|
|
5105
|
+
"save-settings",
|
|
5106
|
+
"cli-status"
|
|
5107
|
+
]) {
|
|
5108
|
+
const method = `dungsil-vcs/${endpoint}`;
|
|
5109
|
+
ctx.effect(() => ctx.connection.fetch.register({
|
|
5110
|
+
path: `${channel}/${method}`,
|
|
5111
|
+
methods: ["POST"],
|
|
5112
|
+
requestBody: "buffered",
|
|
5113
|
+
async fetch(request) {
|
|
5114
|
+
let rpcId = "";
|
|
5115
|
+
let result;
|
|
5116
|
+
try {
|
|
5117
|
+
const body = clientRequestSchema.parse(await request.json());
|
|
5118
|
+
rpcId = body.rpcId;
|
|
5119
|
+
if (body.method !== method) throw new Error("invalid");
|
|
5120
|
+
const signal = AbortSignal.any([
|
|
5121
|
+
request.signal,
|
|
5122
|
+
lifetime.signal,
|
|
5123
|
+
AbortSignal.timeout(3e4)
|
|
5124
|
+
]);
|
|
5125
|
+
signal.throwIfAborted();
|
|
5126
|
+
if (endpoint === "settings") result = {
|
|
5127
|
+
ok: true,
|
|
5128
|
+
value: snapshot()
|
|
5129
|
+
};
|
|
5130
|
+
else if (endpoint === "save-settings") {
|
|
5131
|
+
const input = body.payload;
|
|
5132
|
+
if (!input || typeof input.revision !== "string" || !validCommitSettings(input.settings)) throw new Error("invalid");
|
|
5133
|
+
const settings = input.settings;
|
|
5134
|
+
await editor.edit(entry(), (current) => {
|
|
5135
|
+
if (snapshot().revision !== input.revision) throw new Error("conflict");
|
|
5136
|
+
return {
|
|
5137
|
+
...current,
|
|
5138
|
+
...settings
|
|
5139
|
+
};
|
|
5140
|
+
});
|
|
5141
|
+
result = {
|
|
5142
|
+
ok: true,
|
|
5143
|
+
value: snapshot()
|
|
5144
|
+
};
|
|
5145
|
+
} else {
|
|
5146
|
+
const sessionId = body.payload?.sessionId;
|
|
5147
|
+
if (typeof sessionId !== "string" || !sessionId || sessionId.length > 256) throw new Error("invalid");
|
|
5148
|
+
const resolved = await ctx.sessionController.resolveAgent(SessionId(sessionId));
|
|
5149
|
+
if ("error" in resolved) throw new Error("unavailable");
|
|
5150
|
+
const { agent } = resolved;
|
|
5151
|
+
const cwd = await ctx.workingDirectory.ensure(agent, signal);
|
|
5152
|
+
const value = await inspectCliStatus(async (executable, args) => {
|
|
5153
|
+
const bounded = AbortSignal.any([signal, AbortSignal.timeout(1e4)]);
|
|
5154
|
+
let path;
|
|
5155
|
+
try {
|
|
5156
|
+
path = await ctx.subprocess.resolveExecutable(executable, void 0, bounded);
|
|
5157
|
+
} catch (error) {
|
|
5158
|
+
if (error instanceof Error && error.name === "SubprocessExecutableNotFoundError") throw new Error("cli_missing");
|
|
5159
|
+
throw error;
|
|
5160
|
+
}
|
|
5161
|
+
const argv = [path, ...args];
|
|
5162
|
+
const policy = ctx.sandboxPolicy.resolve({ session: agent.session });
|
|
5163
|
+
const command = policy.mode === "danger-full-access" ? argv : (await ctx.sandbox.confine(argv, {
|
|
5164
|
+
...policy,
|
|
5165
|
+
mode: policy.mode
|
|
5166
|
+
}, bounded)).argv;
|
|
5167
|
+
const child = ctx.subprocess.spawn({
|
|
5168
|
+
argv: command,
|
|
5169
|
+
cwd,
|
|
5170
|
+
signal: bounded,
|
|
5171
|
+
graceMs: 1e3,
|
|
5172
|
+
env: {
|
|
5173
|
+
GH_PROMPT_DISABLED: "1",
|
|
5174
|
+
GLAB_PROMPT_DISABLED: "1",
|
|
5175
|
+
NO_COLOR: "1",
|
|
5176
|
+
GH_HOST: void 0,
|
|
5177
|
+
GH_REPO: void 0,
|
|
5178
|
+
GITLAB_HOST: void 0,
|
|
5179
|
+
GITLAB_REPO: void 0,
|
|
5180
|
+
TEA_LOGIN: void 0,
|
|
5181
|
+
TEA_REPO: void 0,
|
|
5182
|
+
...executable === "tea" ? {
|
|
5183
|
+
GH_TOKEN: void 0,
|
|
5184
|
+
GITEA_TOKEN: void 0,
|
|
5185
|
+
GITEA_INSTANCE_URL: void 0,
|
|
5186
|
+
GITEA_INSTANCE_SSH_HOST: void 0,
|
|
5187
|
+
GITEA_INSTANCE_INSECURE: void 0
|
|
5188
|
+
} : {}
|
|
5189
|
+
},
|
|
5190
|
+
stdio: {
|
|
5191
|
+
stdin: "ignore",
|
|
5192
|
+
stdout: { maxBytes: 131072 },
|
|
5193
|
+
stderr: { maxBytes: 16384 }
|
|
5194
|
+
}
|
|
5195
|
+
});
|
|
5196
|
+
try {
|
|
5197
|
+
const outcome = await child.done;
|
|
5198
|
+
bounded.throwIfAborted();
|
|
5199
|
+
const output = child.collected.stdout.readFrom(0);
|
|
5200
|
+
if (outcome.exitCode !== 0 || output.lossy) throw new Error("command_failed");
|
|
5201
|
+
return output.text;
|
|
5202
|
+
} finally {
|
|
5203
|
+
child.terminate();
|
|
5204
|
+
await child.waitForExit();
|
|
5205
|
+
}
|
|
5206
|
+
});
|
|
5207
|
+
signal.throwIfAborted();
|
|
5208
|
+
if (ctx.workingDirectory.get(agent.session) !== cwd) throw new Error("conflict");
|
|
5209
|
+
result = {
|
|
5210
|
+
ok: true,
|
|
5211
|
+
value
|
|
5212
|
+
};
|
|
5213
|
+
}
|
|
5214
|
+
} catch (error) {
|
|
5215
|
+
result = {
|
|
5216
|
+
ok: false,
|
|
5217
|
+
error: {
|
|
5218
|
+
code: error instanceof Error && ["invalid", "conflict"].includes(error.message) ? error.message : "unavailable",
|
|
5219
|
+
message: "Could not confirm VCS settings.",
|
|
5220
|
+
details: {}
|
|
5221
|
+
}
|
|
5222
|
+
};
|
|
5223
|
+
}
|
|
5224
|
+
return Response.json({
|
|
5225
|
+
type: "server-response",
|
|
5226
|
+
rpcId,
|
|
5227
|
+
result
|
|
5228
|
+
}, { headers: { "Cache-Control": "no-store" } });
|
|
5229
|
+
}
|
|
5230
|
+
}), `ui-vcs: owner-only ${endpoint}`);
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
4909
5233
|
// src/index.ts
|
|
4910
5234
|
const name = "dungsil-ui-vcs";
|
|
4911
5235
|
const inject = [
|
|
@@ -4919,6 +5243,7 @@ const inject = [
|
|
|
4919
5243
|
function apply(ctx, config) {
|
|
4920
5244
|
ctx.plugin(pull_requests_exports, config);
|
|
4921
5245
|
ctx.plugin(commands_exports, config);
|
|
5246
|
+
ctx.plugin(settings_exports);
|
|
4922
5247
|
ctx.effect(() => ctx.connection.fetch.register({
|
|
4923
5248
|
path: "/api/dungsil-vcs/describe",
|
|
4924
5249
|
methods: ["POST"],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dungsil/dsh-plugin-ui-vcs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Git actions and PR/MR review for GitHub, GitLab, Gitea and Forgejo.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,15 +29,18 @@
|
|
|
29
29
|
"@deepseek-ai/dsh-agent": "0.2.1-rc.5",
|
|
30
30
|
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-rc.5",
|
|
31
31
|
"@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.5",
|
|
32
|
+
"@deepseek-ai/dsh-app-boot": "0.2.1-rc.5",
|
|
32
33
|
"@deepseek-ai/dsh-client-connection": "0.2.1-rc.5",
|
|
33
34
|
"@deepseek-ai/dsh-client-locale": "0.2.1-rc.5",
|
|
34
35
|
"@deepseek-ai/dsh-client-store": "0.2.1-rc.5",
|
|
35
36
|
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.5",
|
|
36
37
|
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.5",
|
|
37
38
|
"@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.5",
|
|
39
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-rc.5",
|
|
38
40
|
"@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.1-rc.5",
|
|
39
41
|
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.5",
|
|
40
42
|
"@deepseek-ai/dsh-client-ui-workspace": "0.2.1-rc.5",
|
|
43
|
+
"@deepseek-ai/dsh-config-editor": "0.2.1-rc.5",
|
|
41
44
|
"@deepseek-ai/dsh-credentials-local": "0.2.1-rc.5",
|
|
42
45
|
"@deepseek-ai/dsh-fs": "0.2.1-rc.5",
|
|
43
46
|
"@deepseek-ai/dsh-llm": "0.2.1-rc.5",
|
|
@@ -66,6 +69,7 @@
|
|
|
66
69
|
"@deepseek-ai/cordis": "^4.0.5",
|
|
67
70
|
"@deepseek-ai/dsh-client-connection": "^0.2.1-rc.5",
|
|
68
71
|
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-rc.5",
|
|
72
|
+
"@deepseek-ai/dsh-config-editor": "0.2.1-rc.5",
|
|
69
73
|
"@deepseek-ai/dsh-session": "^0.2.1-rc.5"
|
|
70
74
|
},
|
|
71
75
|
"engines": {
|
|
@@ -83,6 +87,7 @@
|
|
|
83
87
|
"@deepseek-ai/dsh-client-connection",
|
|
84
88
|
"@deepseek-ai/dsh-client-locale",
|
|
85
89
|
"@deepseek-ai/dsh-client-ui-session",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
86
91
|
"@deepseek-ai/dsh-client-ui-sidebar-right",
|
|
87
92
|
"@deepseek-ai/dsh-client-ui-workspace"
|
|
88
93
|
]
|