@klarkxy/dsh-git-commit 0.1.6 → 0.2.1
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 +34 -4
- package/docs/README.zh-CN.md +28 -2
- package/lib/client.inner.cjs +395 -79
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +396 -241
- package/lib/contracts.d.ts +45 -12
- package/lib/contracts.js +1 -27
- package/lib/contracts.js.map +1 -1
- package/lib/index.d.ts +14 -5
- package/lib/index.js +294 -82
- package/lib/index.js.map +1 -1
- package/package.json +16 -9
package/lib/client.js
CHANGED
|
@@ -1,168 +1,7 @@
|
|
|
1
|
-
function __createDshNodeShims() {
|
|
2
|
-
class EventEmitter {
|
|
3
|
-
constructor() {
|
|
4
|
-
this._e = Object.create(null)
|
|
5
|
-
}
|
|
6
|
-
on(type, fn) {
|
|
7
|
-
(this._e[type] ||= []).push(fn)
|
|
8
|
-
return this
|
|
9
|
-
}
|
|
10
|
-
addListener(type, fn) {
|
|
11
|
-
return this.on(type, fn)
|
|
12
|
-
}
|
|
13
|
-
once(type, fn) {
|
|
14
|
-
const wrap = (...args) => {
|
|
15
|
-
this.off(type, wrap)
|
|
16
|
-
fn(...args)
|
|
17
|
-
}
|
|
18
|
-
return this.on(type, wrap)
|
|
19
|
-
}
|
|
20
|
-
off(type, fn) {
|
|
21
|
-
const list = this._e[type]
|
|
22
|
-
if (list) this._e[type] = list.filter((item) => item !== fn)
|
|
23
|
-
return this
|
|
24
|
-
}
|
|
25
|
-
removeListener(type, fn) {
|
|
26
|
-
return this.off(type, fn)
|
|
27
|
-
}
|
|
28
|
-
emit(type, ...args) {
|
|
29
|
-
const list = this._e[type]
|
|
30
|
-
if (!list) return false
|
|
31
|
-
for (const fn of list.slice()) fn(...args)
|
|
32
|
-
return true
|
|
33
|
-
}
|
|
34
|
-
removeAllListeners(type) {
|
|
35
|
-
if (type) delete this._e[type]
|
|
36
|
-
else this._e = Object.create(null)
|
|
37
|
-
return this
|
|
38
|
-
}
|
|
39
|
-
listeners(type) {
|
|
40
|
-
return (this._e[type] || []).slice()
|
|
41
|
-
}
|
|
42
|
-
setMaxListeners() {
|
|
43
|
-
return this
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
class Buffer extends Uint8Array {
|
|
48
|
-
static from(value, encodingOrOffset, length) {
|
|
49
|
-
if (typeof value === 'string') return new Buffer(new TextEncoder().encode(value))
|
|
50
|
-
if (value instanceof ArrayBuffer) return new Buffer(new Uint8Array(value, encodingOrOffset, length))
|
|
51
|
-
if (ArrayBuffer.isView(value)) return new Buffer(new Uint8Array(value.buffer, value.byteOffset, value.byteLength))
|
|
52
|
-
if (Array.isArray(value) || value && typeof value.length === 'number') return new Buffer(Uint8Array.from(value))
|
|
53
|
-
return new Buffer(0)
|
|
54
|
-
}
|
|
55
|
-
static alloc(size, fill) {
|
|
56
|
-
const buf = new Buffer(size)
|
|
57
|
-
if (fill !== undefined && fill !== 0) {
|
|
58
|
-
if (typeof fill === 'string') {
|
|
59
|
-
const bytes = new TextEncoder().encode(fill)
|
|
60
|
-
for (let i = 0; i < size; i += 1) buf[i] = bytes[i % bytes.length]
|
|
61
|
-
} else buf.fill(fill)
|
|
62
|
-
}
|
|
63
|
-
return buf
|
|
64
|
-
}
|
|
65
|
-
static allocUnsafe(size) {
|
|
66
|
-
return new Buffer(size)
|
|
67
|
-
}
|
|
68
|
-
static allocUnsafeSlow(size) {
|
|
69
|
-
return new Buffer(size)
|
|
70
|
-
}
|
|
71
|
-
static concat(list, totalLength) {
|
|
72
|
-
const length = totalLength ?? list.reduce((sum, item) => sum + item.length, 0)
|
|
73
|
-
const out = new Buffer(length)
|
|
74
|
-
let offset = 0
|
|
75
|
-
for (const item of list) {
|
|
76
|
-
out.set(item, offset)
|
|
77
|
-
offset += item.length
|
|
78
|
-
}
|
|
79
|
-
return out
|
|
80
|
-
}
|
|
81
|
-
static isBuffer(value) {
|
|
82
|
-
return value instanceof Buffer
|
|
83
|
-
}
|
|
84
|
-
static byteLength(value) {
|
|
85
|
-
if (typeof value === 'string') return new TextEncoder().encode(value).length
|
|
86
|
-
return value?.byteLength ?? value?.length ?? 0
|
|
87
|
-
}
|
|
88
|
-
static isEncoding(encoding) {
|
|
89
|
-
return /^(utf8|utf-8|ascii|latin1|binary|hex|base64|base64url)$/i.test(String(encoding || ''))
|
|
90
|
-
}
|
|
91
|
-
toString(encoding) {
|
|
92
|
-
if (encoding === 'hex') return [...this].map((byte) => byte.toString(16).padStart(2, '0')).join('')
|
|
93
|
-
if (encoding === 'base64') {
|
|
94
|
-
let binary = ''
|
|
95
|
-
this.forEach((byte) => {
|
|
96
|
-
binary += String.fromCharCode(byte)
|
|
97
|
-
})
|
|
98
|
-
return btoa(binary)
|
|
99
|
-
}
|
|
100
|
-
return new TextDecoder().decode(this)
|
|
101
|
-
}
|
|
102
|
-
slice(start, end) {
|
|
103
|
-
return Buffer.from(super.subarray(start, end))
|
|
104
|
-
}
|
|
105
|
-
copy(target, targetStart = 0, start = 0, end = this.length) {
|
|
106
|
-
const sliced = this.subarray(start, end)
|
|
107
|
-
target.set(sliced, targetStart)
|
|
108
|
-
return sliced.length
|
|
109
|
-
}
|
|
110
|
-
write(string, offset = 0) {
|
|
111
|
-
const bytes = new TextEncoder().encode(string)
|
|
112
|
-
const written = Math.min(bytes.length, this.length - offset)
|
|
113
|
-
this.set(bytes.subarray(0, written), offset)
|
|
114
|
-
return written
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function inherits(ctor, superCtor) {
|
|
119
|
-
ctor.super_ = superCtor
|
|
120
|
-
ctor.prototype = Object.create(superCtor.prototype, {
|
|
121
|
-
constructor: { value: ctor, writable: true, configurable: true },
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (!globalThis.Buffer) globalThis.Buffer = Buffer
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
buffer: { Buffer, SlowBuffer: Buffer, INSPECT_MAX_BYTES: 50, kMaxLength: 0x7fffffff },
|
|
129
|
-
stream: {
|
|
130
|
-
Stream: EventEmitter,
|
|
131
|
-
Readable: EventEmitter,
|
|
132
|
-
Writable: EventEmitter,
|
|
133
|
-
Duplex: EventEmitter,
|
|
134
|
-
Transform: EventEmitter,
|
|
135
|
-
PassThrough: EventEmitter,
|
|
136
|
-
},
|
|
137
|
-
events: { EventEmitter },
|
|
138
|
-
util: {
|
|
139
|
-
deprecate(fn) {
|
|
140
|
-
return fn
|
|
141
|
-
},
|
|
142
|
-
inherits,
|
|
143
|
-
inspect() {
|
|
144
|
-
return ''
|
|
145
|
-
},
|
|
146
|
-
format(value) {
|
|
147
|
-
return String(value)
|
|
148
|
-
},
|
|
149
|
-
types: { isBuffer: Buffer.isBuffer },
|
|
150
|
-
},
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
1
|
window.__ModuleLoader__.load({
|
|
155
2
|
id: "@klarkxy/dsh-git-commit",
|
|
156
3
|
factory: (dshRequire) => {
|
|
157
|
-
var
|
|
158
|
-
var process = globalThis.process || { env: {}, nextTick: function (fn) { var args = [].slice.call(arguments, 1); queueMicrotask(function () { fn.apply(null, args); }); } };
|
|
159
|
-
var require = function (id) {
|
|
160
|
-
if (id === 'buffer' || id === 'stream' || id === 'util' || id === 'events') {
|
|
161
|
-
if (!__nodeShims) __nodeShims = __createDshNodeShims();
|
|
162
|
-
return __nodeShims[id];
|
|
163
|
-
}
|
|
164
|
-
return dshRequire(id);
|
|
165
|
-
};
|
|
4
|
+
var require = dshRequire;
|
|
166
5
|
var module = { exports: {} };
|
|
167
6
|
var exports = module.exports;
|
|
168
7
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
@@ -170,21 +9,14 @@ let react = require("react");
|
|
|
170
9
|
let react_dom = require("react-dom");
|
|
171
10
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
172
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
173
|
-
//#region ../dsh-
|
|
174
|
-
/**
|
|
175
|
-
* Shared plugin-page model menu.
|
|
176
|
-
*
|
|
177
|
-
* A feature plugin's own settings row exposes a model select. An empty
|
|
178
|
-
* selection means the host default chat model for that feature's own call.
|
|
179
|
-
*
|
|
180
|
-
* Browser-safe and React-optional: pure helpers live here so hosts and clients
|
|
181
|
-
* share one catalog contract without bundling React into the host build.
|
|
182
|
-
*/
|
|
12
|
+
//#region ../dsh-model-route/src/route.ts
|
|
183
13
|
const KEY_SEPARATOR = "";
|
|
184
|
-
|
|
14
|
+
/** Stable key for one route, safe to use as a select-option value. */
|
|
15
|
+
function modelRouteKey(provider, model) {
|
|
185
16
|
return provider && model ? `${provider}${KEY_SEPARATOR}${model}` : "";
|
|
186
17
|
}
|
|
187
|
-
|
|
18
|
+
/** Inverse of modelRouteKey; undefined for malformed keys. */
|
|
19
|
+
function parseModelRouteKey(value) {
|
|
188
20
|
const index = value.indexOf(KEY_SEPARATOR);
|
|
189
21
|
if (index <= 0) return void 0;
|
|
190
22
|
const provider = value.slice(0, index);
|
|
@@ -195,6 +27,8 @@ function parseModelMenuChoiceKey(value) {
|
|
|
195
27
|
model
|
|
196
28
|
};
|
|
197
29
|
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region ../dsh-model-route/src/catalog.ts
|
|
198
32
|
function asRecord(value) {
|
|
199
33
|
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
200
34
|
}
|
|
@@ -553,7 +387,7 @@ ${scope} {
|
|
|
553
387
|
border: 0.5px solid var(--dsw-alias-border-l3);
|
|
554
388
|
border-radius: var(--dsw-radius-md);
|
|
555
389
|
background: var(--dsw-alias-bg-layer-1);
|
|
556
|
-
font-family: var(--ds-font-family-code
|
|
390
|
+
font-family: var(--ds-font-family-code);
|
|
557
391
|
font-size: 12px;
|
|
558
392
|
line-height: 20px;
|
|
559
393
|
color: var(--dsw-alias-label-secondary);
|
|
@@ -629,6 +463,162 @@ ${scope} {
|
|
|
629
463
|
`.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?![+>~])/gm, (_match, className) => `&${className}, & ${className}`);
|
|
630
464
|
}
|
|
631
465
|
//#endregion
|
|
466
|
+
//#region ../dsh-plugin-kit/src/contracts.ts
|
|
467
|
+
/**
|
|
468
|
+
* Remote contribution for model-settings change notifications.
|
|
469
|
+
* Provided by `@klarkxy/dsh-model-hub` (`ModelSettingsChangesController`);
|
|
470
|
+
* subscribers degrade silently when that package is not installed.
|
|
471
|
+
* The stream carries invalidations only — `ready` is never a settings snapshot.
|
|
472
|
+
*/
|
|
473
|
+
const MODEL_SETTINGS_CHANGES_REMOTE = {
|
|
474
|
+
package: "@klarkxy/dsh-model-hub",
|
|
475
|
+
descriptors: [{
|
|
476
|
+
id: "modelSettingsChanges/watch",
|
|
477
|
+
service: "modelSettingsChangesController",
|
|
478
|
+
namespace: "modelSettingsChanges",
|
|
479
|
+
method: "watch",
|
|
480
|
+
mode: "stream",
|
|
481
|
+
invocation: { kind: "direct" },
|
|
482
|
+
parameters: [],
|
|
483
|
+
cancellation: { parameter: "signal" }
|
|
484
|
+
}]
|
|
485
|
+
};
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region ../dsh-plugin-kit/src/model-settings-client.ts
|
|
488
|
+
/** This stream carries invalidations only; ready is never a settings snapshot. */
|
|
489
|
+
function parseModelSettingsChangeFrame(value) {
|
|
490
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid model settings change frame");
|
|
491
|
+
const frame = value;
|
|
492
|
+
if (frame.kind === "ready" && Object.keys(frame).length === 1) return { kind: "ready" };
|
|
493
|
+
if (frame.kind === "changed" && Object.keys(frame).length === 3 && typeof frame.ns === "string" && frame.ns.length > 0 && typeof frame.revision === "number" && Number.isSafeInteger(frame.revision) && frame.revision >= 0) return {
|
|
494
|
+
kind: "changed",
|
|
495
|
+
ns: frame.ns,
|
|
496
|
+
revision: frame.revision
|
|
497
|
+
};
|
|
498
|
+
throw new Error("Invalid model settings change frame");
|
|
499
|
+
}
|
|
500
|
+
MODEL_SETTINGS_CHANGES_REMOTE.package, MODEL_SETTINGS_CHANGES_REMOTE.descriptors.map((descriptor) => ({
|
|
501
|
+
...descriptor,
|
|
502
|
+
result: {
|
|
503
|
+
mode: "strict",
|
|
504
|
+
typeSymbol: "ModelSettings.ChangeFrame",
|
|
505
|
+
create: () => ({ parse: parseModelSettingsChangeFrame })
|
|
506
|
+
}
|
|
507
|
+
}));
|
|
508
|
+
/** Native RemoteStream owns carrier reconnects; no timers or browser transport.
|
|
509
|
+
* A factory shares one logical stream while at least one subscriber remains. */
|
|
510
|
+
function createModelSettingsSubscriber(ctx, namespace) {
|
|
511
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
512
|
+
let injection;
|
|
513
|
+
let current;
|
|
514
|
+
let lifecycle = 0;
|
|
515
|
+
let failureMessage;
|
|
516
|
+
const report = (message) => {
|
|
517
|
+
failureMessage = message;
|
|
518
|
+
for (const listener of [...listeners]) try {
|
|
519
|
+
listener.error?.(message);
|
|
520
|
+
} catch {}
|
|
521
|
+
};
|
|
522
|
+
const invalidate = () => {
|
|
523
|
+
for (const listener of [...listeners]) {
|
|
524
|
+
if (!listeners.has(listener)) continue;
|
|
525
|
+
try {
|
|
526
|
+
listener.change();
|
|
527
|
+
} catch (error) {
|
|
528
|
+
try {
|
|
529
|
+
listener.error?.(error instanceof Error ? error.message : String(error));
|
|
530
|
+
} catch {}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
const start = () => {
|
|
535
|
+
const life = ++lifecycle;
|
|
536
|
+
injection = ctx.inject(["remote", "remote.modelSettingsChanges"], (injected) => {
|
|
537
|
+
if (life !== lifecycle || !listeners.size) return;
|
|
538
|
+
const scope = injected;
|
|
539
|
+
const stream = scope.remote.$stream({
|
|
540
|
+
name: "Model settings sync",
|
|
541
|
+
open: (signal) => scope.remote.modelSettingsChanges.watch(signal),
|
|
542
|
+
ended: (accepted) => /* @__PURE__ */ new Error(`Model settings sync stream ended ${accepted ? "after" : "before"} ready; refresh or reopen the page`)
|
|
543
|
+
});
|
|
544
|
+
const session = {
|
|
545
|
+
stream,
|
|
546
|
+
active: true
|
|
547
|
+
};
|
|
548
|
+
current = session;
|
|
549
|
+
scope.effect(() => () => {
|
|
550
|
+
session.active = false;
|
|
551
|
+
if (current === session) {
|
|
552
|
+
current = void 0;
|
|
553
|
+
if (life === lifecycle && listeners.size) report("Model settings sync service unavailable");
|
|
554
|
+
}
|
|
555
|
+
return stream.dispose();
|
|
556
|
+
});
|
|
557
|
+
(async () => {
|
|
558
|
+
let generation;
|
|
559
|
+
let ready = false;
|
|
560
|
+
try {
|
|
561
|
+
for await (const item of stream) {
|
|
562
|
+
if (!session.active || life !== lifecycle || !listeners.size) break;
|
|
563
|
+
if (item.signal.aborted) continue;
|
|
564
|
+
if (generation !== item.generation) {
|
|
565
|
+
generation = item.generation;
|
|
566
|
+
ready = false;
|
|
567
|
+
}
|
|
568
|
+
const frame = parseModelSettingsChangeFrame(item.value);
|
|
569
|
+
if (frame.kind === "ready") {
|
|
570
|
+
ready = true;
|
|
571
|
+
failureMessage = void 0;
|
|
572
|
+
item.accept();
|
|
573
|
+
invalidate();
|
|
574
|
+
} else {
|
|
575
|
+
if (!ready) throw new Error("Model settings sync change arrived before ready");
|
|
576
|
+
if (namespace === "*" || frame.ns === namespace) invalidate();
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
} catch (error) {
|
|
580
|
+
if (session.active && life === lifecycle) report(error instanceof Error ? error.message : String(error));
|
|
581
|
+
} finally {
|
|
582
|
+
if (current === session) current = void 0;
|
|
583
|
+
session.active = false;
|
|
584
|
+
await stream.dispose().catch(() => {});
|
|
585
|
+
}
|
|
586
|
+
})();
|
|
587
|
+
});
|
|
588
|
+
queueMicrotask(() => {
|
|
589
|
+
if (life === lifecycle && listeners.size && !current) report("Model settings sync service unavailable");
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
return Object.freeze({ subscribe(onChange, onError) {
|
|
593
|
+
const listener = {
|
|
594
|
+
change: onChange,
|
|
595
|
+
error: onError
|
|
596
|
+
};
|
|
597
|
+
listeners.add(listener);
|
|
598
|
+
if (!injection) start();
|
|
599
|
+
else if (failureMessage) queueMicrotask(() => {
|
|
600
|
+
if (listeners.has(listener) && failureMessage) try {
|
|
601
|
+
listener.error?.(failureMessage);
|
|
602
|
+
} catch {}
|
|
603
|
+
});
|
|
604
|
+
return () => {
|
|
605
|
+
if (!listeners.delete(listener) || listeners.size) return;
|
|
606
|
+
lifecycle++;
|
|
607
|
+
if (current) {
|
|
608
|
+
current.active = false;
|
|
609
|
+
current.stream.dispose().catch(() => {});
|
|
610
|
+
}
|
|
611
|
+
current = void 0;
|
|
612
|
+
failureMessage = void 0;
|
|
613
|
+
const previous = injection;
|
|
614
|
+
injection = void 0;
|
|
615
|
+
try {
|
|
616
|
+
Promise.resolve(previous?.dispose()).catch(() => {});
|
|
617
|
+
} catch {}
|
|
618
|
+
};
|
|
619
|
+
} });
|
|
620
|
+
}
|
|
621
|
+
//#endregion
|
|
632
622
|
//#region src/contracts.ts
|
|
633
623
|
const PLUGIN_NAME = "@klarkxy/dsh-git-commit";
|
|
634
624
|
const RPC_CHANNEL = "/dsh-git-commit";
|
|
@@ -659,6 +649,12 @@ const zh = {
|
|
|
659
649
|
loading: "正在读取仓库状态…",
|
|
660
650
|
running: "正在整理修改并分次提交…",
|
|
661
651
|
done: "已创建提交",
|
|
652
|
+
partial: "本次提交未全部完成;以下提交已保留",
|
|
653
|
+
stopped: "本次操作未确认完成",
|
|
654
|
+
uncertain: "以下提交组的结果不确定。请检查 Git 日志和状态,确认后再操作。",
|
|
655
|
+
hashUnavailable: "提交已创建,哈希未读取",
|
|
656
|
+
remaining: "尚未提交:{n} 组",
|
|
657
|
+
cancelled: "提交操作已取消",
|
|
662
658
|
fallback: "模型不可用,已合并为单个提交",
|
|
663
659
|
noWorkspace: "工作区没有修改",
|
|
664
660
|
unavailable: "不可用",
|
|
@@ -669,6 +665,12 @@ const zh = {
|
|
|
669
665
|
sessionRunning: "会话正在运行,提交已暂停",
|
|
670
666
|
refresh: "刷新",
|
|
671
667
|
failed: "操作失败",
|
|
668
|
+
disabled: "插件已停用",
|
|
669
|
+
busy: "已有提交操作正在进行",
|
|
670
|
+
stale: "设置已更新,请刷新后重试",
|
|
671
|
+
workspaceChanged: "工作区或分支已变更,请刷新后重试提交",
|
|
672
|
+
settingsUnavailable: "无法读取提交设置,请重新加载插件后重试",
|
|
673
|
+
invalidRequest: "提交请求无效,请刷新后重试",
|
|
672
674
|
planUnavailable: "模型没有给出可用的提交方案,已取消本次提交,工作区没有被改动。换一个模型重试,或在插件设置里开启兜底提交。",
|
|
673
675
|
close: "关闭"
|
|
674
676
|
};
|
|
@@ -687,6 +689,12 @@ const en = {
|
|
|
687
689
|
loading: "Reading repository status…",
|
|
688
690
|
running: "Organizing changes into commits…",
|
|
689
691
|
done: "Commits created",
|
|
692
|
+
partial: "This run stopped before completion; these commits were kept",
|
|
693
|
+
stopped: "This run did not finish with a confirmed result",
|
|
694
|
+
uncertain: "The outcome of these groups is uncertain. Check Git log and status before taking further action.",
|
|
695
|
+
hashUnavailable: "Commit created; hash unavailable",
|
|
696
|
+
remaining: "Groups not committed: {n}",
|
|
697
|
+
cancelled: "Commit run cancelled",
|
|
690
698
|
fallback: "Model unavailable; used a single commit",
|
|
691
699
|
noWorkspace: "No workspace changes",
|
|
692
700
|
unavailable: "Unavailable",
|
|
@@ -697,23 +705,31 @@ const en = {
|
|
|
697
705
|
sessionRunning: "Session is running; commits paused",
|
|
698
706
|
refresh: "Refresh",
|
|
699
707
|
failed: "Operation failed",
|
|
708
|
+
disabled: "Plugin disabled",
|
|
709
|
+
busy: "A commit run is already in progress",
|
|
710
|
+
stale: "Settings changed; refresh and retry",
|
|
711
|
+
workspaceChanged: "The workspace or branch changed; refresh and retry the commit",
|
|
712
|
+
settingsUnavailable: "Could not read commit settings; reload the plugin and retry",
|
|
713
|
+
invalidRequest: "Invalid commit request; refresh and retry",
|
|
700
714
|
planUnavailable: "The model returned no usable commit plan, so the run was cancelled and your workspace is untouched. Try another model, or turn on the fallback in plugin settings.",
|
|
701
715
|
close: "Close"
|
|
702
716
|
};
|
|
703
717
|
/** A failed RPC keeps its code so the panel can explain a rejection in its own words. */
|
|
704
718
|
var RpcError = class extends Error {
|
|
705
719
|
code;
|
|
706
|
-
|
|
720
|
+
partial;
|
|
721
|
+
constructor(code, message, partial) {
|
|
707
722
|
super(message);
|
|
708
723
|
this.name = "RpcError";
|
|
709
724
|
this.code = code;
|
|
725
|
+
this.partial = partial;
|
|
710
726
|
}
|
|
711
727
|
};
|
|
712
|
-
async function rpc(call, endpoint, payload = {}, fallback = "
|
|
728
|
+
async function rpc(call, endpoint, payload = {}, fallback = "") {
|
|
713
729
|
const result = await call(endpoint, payload);
|
|
714
730
|
if (!result || result.ok !== true) {
|
|
715
731
|
const failed = result && "error" in result ? result.error : void 0;
|
|
716
|
-
throw new RpcError(failed?.code ?? "unknown", failed?.message ? failed.message : fallback);
|
|
732
|
+
throw new RpcError(failed?.code ?? "unknown", failed?.message ? failed.message : fallback, failed && "partial" in failed ? failed.partial : void 0);
|
|
717
733
|
}
|
|
718
734
|
return result.value;
|
|
719
735
|
}
|
|
@@ -728,7 +744,25 @@ function reasonText(t, status) {
|
|
|
728
744
|
}
|
|
729
745
|
/** A refusal the plugin can name gets its own sentence; the rest stay verbatim. */
|
|
730
746
|
function errorText(t, error) {
|
|
731
|
-
|
|
747
|
+
const key = {
|
|
748
|
+
"plan-unavailable": "planUnavailable",
|
|
749
|
+
"no-session": "reasonNoSession",
|
|
750
|
+
"no-cwd": "reasonNoCwd",
|
|
751
|
+
"no-git": "reasonNoGit",
|
|
752
|
+
"not-a-repo": "reasonNoRepo",
|
|
753
|
+
"no-changes": "noWorkspace",
|
|
754
|
+
"session-running": "sessionRunning",
|
|
755
|
+
"session-changed": "workspaceChanged",
|
|
756
|
+
"workspace-changed": "workspaceChanged",
|
|
757
|
+
busy: "busy",
|
|
758
|
+
stale: "stale",
|
|
759
|
+
disposed: "disabled",
|
|
760
|
+
cancelled: "cancelled",
|
|
761
|
+
"settings-unavailable": "settingsUnavailable",
|
|
762
|
+
"bad-request": "invalidRequest",
|
|
763
|
+
"not-found": "invalidRequest"
|
|
764
|
+
}[error.code];
|
|
765
|
+
return key ? t(key) : error.message || t("failed");
|
|
732
766
|
}
|
|
733
767
|
function panelError(reason) {
|
|
734
768
|
return reason instanceof RpcError ? {
|
|
@@ -827,7 +861,7 @@ function GitCommitAction({ sessionId, useSession, call, t }) {
|
|
|
827
861
|
setLoading(true);
|
|
828
862
|
setError(null);
|
|
829
863
|
try {
|
|
830
|
-
const next = await rpc(call, "status", { sessionId }
|
|
864
|
+
const next = await rpc(call, "status", { sessionId });
|
|
831
865
|
if (generationRef.current !== generation) return;
|
|
832
866
|
setStatus(next);
|
|
833
867
|
} catch (reason) {
|
|
@@ -837,11 +871,7 @@ function GitCommitAction({ sessionId, useSession, call, t }) {
|
|
|
837
871
|
} finally {
|
|
838
872
|
if (generationRef.current === generation) setLoading(false);
|
|
839
873
|
}
|
|
840
|
-
}, [
|
|
841
|
-
call,
|
|
842
|
-
sessionId,
|
|
843
|
-
t
|
|
844
|
-
]);
|
|
874
|
+
}, [call, sessionId]);
|
|
845
875
|
(0, react.useEffect)(() => {
|
|
846
876
|
if (!open) return;
|
|
847
877
|
loadStatus();
|
|
@@ -864,23 +894,23 @@ function GitCommitAction({ sessionId, useSession, call, t }) {
|
|
|
864
894
|
setResult(null);
|
|
865
895
|
setError(null);
|
|
866
896
|
try {
|
|
867
|
-
const value = await rpc(call, "commit", { sessionId }
|
|
897
|
+
const value = await rpc(call, "commit", { sessionId });
|
|
868
898
|
if (generationRef.current !== generation) return;
|
|
869
899
|
setResult(value);
|
|
870
|
-
const next = await rpc(call, "status", { sessionId }).catch(() => void 0);
|
|
871
|
-
if (generationRef.current !== generation) return;
|
|
872
|
-
if (next) setStatus(next);
|
|
873
900
|
} catch (reason) {
|
|
874
901
|
if (generationRef.current !== generation) return;
|
|
902
|
+
if (reason instanceof RpcError && reason.partial) setResult(reason.partial);
|
|
875
903
|
setError(panelError(reason));
|
|
876
904
|
} finally {
|
|
877
|
-
if (generationRef.current === generation)
|
|
905
|
+
if (generationRef.current === generation) {
|
|
906
|
+
const next = await rpc(call, "status", { sessionId }).catch(() => void 0);
|
|
907
|
+
if (generationRef.current === generation) {
|
|
908
|
+
setStatus(next);
|
|
909
|
+
setRunning(false);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
878
912
|
}
|
|
879
|
-
}, [
|
|
880
|
-
call,
|
|
881
|
-
sessionId,
|
|
882
|
-
t
|
|
883
|
-
]);
|
|
913
|
+
}, [call, sessionId]);
|
|
884
914
|
const available = status?.available === true;
|
|
885
915
|
const workspaceCount = status?.workspace.files ?? 0;
|
|
886
916
|
const canCommit = available && !running && !sessionRunning && workspaceCount > 0;
|
|
@@ -1028,23 +1058,48 @@ function GitCommitAction({ sessionId, useSession, call, t }) {
|
|
|
1028
1058
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1029
1059
|
className: "dsh-ui-hint dsh-ui-wrap",
|
|
1030
1060
|
children: [
|
|
1031
|
-
t("done"),
|
|
1061
|
+
t("failure" in result ? result.commits.length ? "partial" : "stopped" : "done"),
|
|
1032
1062
|
" · ",
|
|
1033
1063
|
result.branch
|
|
1034
1064
|
]
|
|
1035
1065
|
}),
|
|
1036
1066
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1037
1067
|
className: "gcm-commits",
|
|
1038
|
-
children: result.commits.map((commit) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
|
|
1039
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: commit.hash }),
|
|
1068
|
+
children: result.commits.map((commit, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
|
|
1069
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: commit.hash || t("hashUnavailable") }),
|
|
1040
1070
|
" ",
|
|
1041
|
-
commit.message
|
|
1042
|
-
|
|
1071
|
+
commit.message,
|
|
1072
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1073
|
+
className: "dsh-ui-hint",
|
|
1074
|
+
children: commit.files.join(", ")
|
|
1075
|
+
})
|
|
1076
|
+
] }, `${index}:${commit.hash}`))
|
|
1043
1077
|
}),
|
|
1044
1078
|
result.fallback && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1045
1079
|
className: "dsh-ui-hint",
|
|
1046
1080
|
children: t("fallback")
|
|
1047
|
-
})
|
|
1081
|
+
}),
|
|
1082
|
+
"uncertain" in result && result.uncertain?.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1083
|
+
className: "dsh-ui-hint",
|
|
1084
|
+
role: "status",
|
|
1085
|
+
children: t("uncertain")
|
|
1086
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1087
|
+
className: "gcm-commits",
|
|
1088
|
+
children: result.uncertain.map((group, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [group.message, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1089
|
+
className: "dsh-ui-hint",
|
|
1090
|
+
children: group.files.join(", ")
|
|
1091
|
+
})] }, index))
|
|
1092
|
+
})] }) : null,
|
|
1093
|
+
"remaining" in result && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1094
|
+
className: "dsh-ui-hint",
|
|
1095
|
+
children: t("remaining").replace("{n}", String(result.remaining.length))
|
|
1096
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
1097
|
+
className: "gcm-commits",
|
|
1098
|
+
children: result.remaining.map((group, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [group.message, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1099
|
+
className: "dsh-ui-hint",
|
|
1100
|
+
children: group.files.join(", ")
|
|
1101
|
+
})] }, index))
|
|
1102
|
+
})] })
|
|
1048
1103
|
]
|
|
1049
1104
|
})
|
|
1050
1105
|
]
|
|
@@ -1071,10 +1126,10 @@ const clientCss = `${officialUiCss("gcm-root")}
|
|
|
1071
1126
|
.gcm-settings { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
|
|
1072
1127
|
.gcm-settings-status { display: flex; flex-direction: column; gap: 4px; }
|
|
1073
1128
|
`;
|
|
1074
|
-
/** Host UI language, following live switches
|
|
1129
|
+
/** Host UI language, following live switches with the host's English fallback. */
|
|
1075
1130
|
function useHostLocale(client) {
|
|
1076
1131
|
const subscribe = (0, react.useCallback)((listener) => client.locale.subscribe?.(listener) ?? (() => {}), [client]);
|
|
1077
|
-
const snapshot = (0, react.useCallback)(() => client.locale.getSnapshot?.().active ?? "
|
|
1132
|
+
const snapshot = (0, react.useCallback)(() => client.locale.getSnapshot?.().active ?? "en", [client]);
|
|
1078
1133
|
return (0, react.useSyncExternalStore)(subscribe, snapshot, snapshot);
|
|
1079
1134
|
}
|
|
1080
1135
|
const settingsZh = {
|
|
@@ -1089,7 +1144,9 @@ const settingsZh = {
|
|
|
1089
1144
|
saved: "已保存。",
|
|
1090
1145
|
stale: "设置已更新,请刷新后重试。",
|
|
1091
1146
|
failed: "无法读取提交设置。",
|
|
1092
|
-
retry: "重试"
|
|
1147
|
+
retry: "重试",
|
|
1148
|
+
refresh: "刷新设置",
|
|
1149
|
+
syncUnavailable: "自动刷新不可用,请手动刷新设置。"
|
|
1093
1150
|
};
|
|
1094
1151
|
const settingsEn = {
|
|
1095
1152
|
pageTitle: "Git Commit",
|
|
@@ -1103,7 +1160,9 @@ const settingsEn = {
|
|
|
1103
1160
|
saved: "Saved.",
|
|
1104
1161
|
stale: "Settings changed; refresh and retry.",
|
|
1105
1162
|
failed: "Could not load commit settings.",
|
|
1106
|
-
retry: "Retry"
|
|
1163
|
+
retry: "Retry",
|
|
1164
|
+
refresh: "Refresh settings",
|
|
1165
|
+
syncUnavailable: "Automatic refresh unavailable; refresh settings manually."
|
|
1107
1166
|
};
|
|
1108
1167
|
function settingsCopy(locale) {
|
|
1109
1168
|
return String(locale).startsWith("zh") ? settingsZh : settingsEn;
|
|
@@ -1115,23 +1174,77 @@ function GitCommitSettingsPanel(props) {
|
|
|
1115
1174
|
const [settings, setSettings] = (0, react.useState)(void 0);
|
|
1116
1175
|
const [choices, setChoices] = (0, react.useState)([]);
|
|
1117
1176
|
const [error, setError] = (0, react.useState)("");
|
|
1118
|
-
const [note, setNote] = (0, react.useState)(
|
|
1177
|
+
const [note, setNote] = (0, react.useState)(false);
|
|
1119
1178
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
1179
|
+
const [syncError, setSyncError] = (0, react.useState)("");
|
|
1180
|
+
const operation = (0, react.useRef)({
|
|
1181
|
+
epoch: 0,
|
|
1182
|
+
active: false,
|
|
1183
|
+
reading: false,
|
|
1184
|
+
writing: false,
|
|
1185
|
+
pending: false
|
|
1186
|
+
});
|
|
1187
|
+
const refreshRef = (0, react.useRef)(() => {});
|
|
1120
1188
|
const call = (0, react.useCallback)((endpoint, payload = {}) => props.client.connection.rpc.call(RPC_CHANNEL, endpoint, payload), [props.client]);
|
|
1121
|
-
|
|
1122
|
-
|
|
1189
|
+
const refresh = () => {
|
|
1190
|
+
const state = operation.current;
|
|
1191
|
+
if (!state.active) return;
|
|
1192
|
+
if (state.reading || state.writing) {
|
|
1193
|
+
state.pending = true;
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
state.pending = false;
|
|
1197
|
+
state.reading = true;
|
|
1198
|
+
setBusy(true);
|
|
1199
|
+
const epoch = state.epoch;
|
|
1123
1200
|
rpc(call, "settings", {}, text.failed).then((next) => {
|
|
1124
|
-
if (
|
|
1201
|
+
if (state.active && state.epoch === epoch && !state.pending) {
|
|
1125
1202
|
setSettings(next);
|
|
1126
1203
|
setError("");
|
|
1127
1204
|
}
|
|
1128
1205
|
}).catch(() => {
|
|
1129
|
-
if (
|
|
1206
|
+
if (state.active && state.epoch === epoch && !state.pending) setError("failed");
|
|
1207
|
+
}).finally(() => {
|
|
1208
|
+
if (!state.active || state.epoch !== epoch) return;
|
|
1209
|
+
state.reading = false;
|
|
1210
|
+
setBusy(false);
|
|
1211
|
+
if (state.pending) refreshRef.current();
|
|
1212
|
+
});
|
|
1213
|
+
};
|
|
1214
|
+
refreshRef.current = refresh;
|
|
1215
|
+
(0, react.useEffect)(() => {
|
|
1216
|
+
const state = operation.current;
|
|
1217
|
+
state.epoch++;
|
|
1218
|
+
state.active = true;
|
|
1219
|
+
state.reading = false;
|
|
1220
|
+
state.writing = false;
|
|
1221
|
+
state.pending = false;
|
|
1222
|
+
setBusy(false);
|
|
1223
|
+
setSettings(void 0);
|
|
1224
|
+
setError("");
|
|
1225
|
+
setNote(false);
|
|
1226
|
+
refreshRef.current();
|
|
1227
|
+
return () => {
|
|
1228
|
+
state.active = false;
|
|
1229
|
+
state.epoch++;
|
|
1230
|
+
};
|
|
1231
|
+
}, [call]);
|
|
1232
|
+
(0, react.useEffect)(() => {
|
|
1233
|
+
setSyncError("");
|
|
1234
|
+
let live = true;
|
|
1235
|
+
const stop = props.subscribeSettings?.(() => {
|
|
1236
|
+
if (live) {
|
|
1237
|
+
setSyncError("");
|
|
1238
|
+
refreshRef.current();
|
|
1239
|
+
}
|
|
1240
|
+
}, (message) => {
|
|
1241
|
+
if (live) setSyncError(message);
|
|
1130
1242
|
});
|
|
1131
1243
|
return () => {
|
|
1132
1244
|
live = false;
|
|
1245
|
+
stop?.();
|
|
1133
1246
|
};
|
|
1134
|
-
}, [
|
|
1247
|
+
}, [props.subscribeSettings, props.client]);
|
|
1135
1248
|
const boundProvider = settings?.model.provider ?? "";
|
|
1136
1249
|
const boundModel = settings?.model.model ?? "";
|
|
1137
1250
|
(0, react.useEffect)(() => {
|
|
@@ -1154,9 +1267,12 @@ function GitCommitSettingsPanel(props) {
|
|
|
1154
1267
|
boundModel
|
|
1155
1268
|
]);
|
|
1156
1269
|
const save = (0, react.useCallback)((patch) => {
|
|
1157
|
-
|
|
1270
|
+
const state = operation.current;
|
|
1271
|
+
if (!settings || !state.active || state.writing || state.reading) return;
|
|
1272
|
+
state.writing = true;
|
|
1273
|
+
const epoch = state.epoch;
|
|
1158
1274
|
setBusy(true);
|
|
1159
|
-
setNote(
|
|
1275
|
+
setNote(false);
|
|
1160
1276
|
setError("");
|
|
1161
1277
|
rpc(call, "settings.update", {
|
|
1162
1278
|
settings: {
|
|
@@ -1165,12 +1281,17 @@ function GitCommitSettingsPanel(props) {
|
|
|
1165
1281
|
},
|
|
1166
1282
|
expectedRevision: settings.revision
|
|
1167
1283
|
}, text.stale).then((next) => {
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1284
|
+
if (state.active && state.epoch === epoch) {
|
|
1285
|
+
setSettings(next);
|
|
1286
|
+
setNote(true);
|
|
1287
|
+
}
|
|
1171
1288
|
}).catch(() => {
|
|
1172
|
-
setError(
|
|
1289
|
+
if (state.active && state.epoch === epoch) setError("stale");
|
|
1290
|
+
}).finally(() => {
|
|
1291
|
+
if (!state.active || state.epoch !== epoch) return;
|
|
1292
|
+
state.writing = false;
|
|
1173
1293
|
setBusy(false);
|
|
1294
|
+
if (state.pending) refreshRef.current();
|
|
1174
1295
|
});
|
|
1175
1296
|
}, [
|
|
1176
1297
|
call,
|
|
@@ -1178,17 +1299,31 @@ function GitCommitSettingsPanel(props) {
|
|
|
1178
1299
|
text.saved,
|
|
1179
1300
|
text.stale
|
|
1180
1301
|
]);
|
|
1181
|
-
if (!settings) return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1302
|
+
if (!settings) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
1182
1303
|
className: "gcm-root gcm-settings",
|
|
1183
|
-
children:
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1304
|
+
children: [
|
|
1305
|
+
error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1306
|
+
role: "alert",
|
|
1307
|
+
className: "dsh-ui-error",
|
|
1308
|
+
children: text[error]
|
|
1309
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1310
|
+
role: "status",
|
|
1311
|
+
className: "dsh-ui-hint",
|
|
1312
|
+
children: text.loading
|
|
1313
|
+
}),
|
|
1314
|
+
syncError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1315
|
+
role: "status",
|
|
1316
|
+
className: "dsh-ui-hint",
|
|
1317
|
+
children: text.syncUnavailable
|
|
1318
|
+
}),
|
|
1319
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1320
|
+
variant: "ghost",
|
|
1321
|
+
size: "sm",
|
|
1322
|
+
disabled: busy,
|
|
1323
|
+
onClick: () => refreshRef.current(),
|
|
1324
|
+
children: text.retry
|
|
1325
|
+
})
|
|
1326
|
+
]
|
|
1192
1327
|
});
|
|
1193
1328
|
const current = settings.model;
|
|
1194
1329
|
const selected = choices.find((item) => item.provider === current.provider && item.model === current.model);
|
|
@@ -1199,15 +1334,30 @@ function GitCommitSettingsPanel(props) {
|
|
|
1199
1334
|
children: [
|
|
1200
1335
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1201
1336
|
className: "gcm-settings-status",
|
|
1202
|
-
children: [
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1337
|
+
children: [
|
|
1338
|
+
syncError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1339
|
+
role: "status",
|
|
1340
|
+
className: "dsh-ui-hint",
|
|
1341
|
+
children: text.syncUnavailable
|
|
1342
|
+
}),
|
|
1343
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1344
|
+
variant: "ghost",
|
|
1345
|
+
size: "sm",
|
|
1346
|
+
disabled: busy,
|
|
1347
|
+
onClick: () => refreshRef.current(),
|
|
1348
|
+
children: text.refresh
|
|
1349
|
+
}),
|
|
1350
|
+
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1351
|
+
role: "alert",
|
|
1352
|
+
className: "dsh-ui-error",
|
|
1353
|
+
children: text[error]
|
|
1354
|
+
}),
|
|
1355
|
+
note && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1356
|
+
role: "status",
|
|
1357
|
+
className: "dsh-ui-notice",
|
|
1358
|
+
children: text.saved
|
|
1359
|
+
})
|
|
1360
|
+
]
|
|
1211
1361
|
}),
|
|
1212
1362
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1213
1363
|
className: "dsh-ui-field",
|
|
@@ -1216,7 +1366,7 @@ function GitCommitSettingsPanel(props) {
|
|
|
1216
1366
|
children: text.model
|
|
1217
1367
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
1218
1368
|
className: "dsh-ui-select",
|
|
1219
|
-
value:
|
|
1369
|
+
value: modelRouteKey(current.provider, current.model),
|
|
1220
1370
|
disabled: busy,
|
|
1221
1371
|
onChange: (event) => {
|
|
1222
1372
|
const key = event.target.value;
|
|
@@ -1227,16 +1377,16 @@ function GitCommitSettingsPanel(props) {
|
|
|
1227
1377
|
} });
|
|
1228
1378
|
return;
|
|
1229
1379
|
}
|
|
1230
|
-
const parsed =
|
|
1380
|
+
const parsed = parseModelRouteKey(key);
|
|
1231
1381
|
if (parsed) save({ model: parsed });
|
|
1232
1382
|
},
|
|
1233
1383
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1234
1384
|
value: "",
|
|
1235
1385
|
children: text.modelDefault
|
|
1236
1386
|
}), choices.map((choice) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
1237
|
-
value:
|
|
1387
|
+
value: modelRouteKey(choice.provider, choice.model),
|
|
1238
1388
|
children: choice.label
|
|
1239
|
-
},
|
|
1389
|
+
}, modelRouteKey(choice.provider, choice.model)))]
|
|
1240
1390
|
})]
|
|
1241
1391
|
}),
|
|
1242
1392
|
selected && efforts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -1291,6 +1441,8 @@ function GitCommitSettingsPanel(props) {
|
|
|
1291
1441
|
}
|
|
1292
1442
|
function apply(ctx) {
|
|
1293
1443
|
const client = ctx;
|
|
1444
|
+
const settingsSubscriber = createModelSettingsSubscriber(ctx, PLUGIN_NAME);
|
|
1445
|
+
const subscribeSettings = (change, error) => settingsSubscriber.subscribe(change, error);
|
|
1294
1446
|
ctx.provide(GIT_COMMIT_CLIENT_SERVICE, { active: true });
|
|
1295
1447
|
ctx.effect(() => client.locale.register(NS, {
|
|
1296
1448
|
zh: { ...zh },
|
|
@@ -1307,7 +1459,10 @@ function apply(ctx) {
|
|
|
1307
1459
|
ctx.effect(() => client.slots.inject("plugins.bundle.config", () => client.slots.register({
|
|
1308
1460
|
name: "plugins.bundle.config",
|
|
1309
1461
|
key: PLUGIN_NAME
|
|
1310
|
-
}, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GitCommitSettingsPanel, {
|
|
1462
|
+
}, () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GitCommitSettingsPanel, {
|
|
1463
|
+
client,
|
|
1464
|
+
subscribeSettings
|
|
1465
|
+
}))), "git-commit.settings");
|
|
1311
1466
|
ctx.effect(() => client.slots.inject("conversation.session.header.actions", () => client.slots.register({
|
|
1312
1467
|
name: "conversation.session.header.actions",
|
|
1313
1468
|
id: "git-commit",
|