@jingyi0605/codingns4dsh 0.1.0 → 0.1.2
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.en.md +306 -0
- package/README.md +190 -993
- package/data/build/dist/client/account-bar.d.ts +2 -2
- package/data/build/dist/client/account-bar.js +96 -39
- package/data/build/dist/client/bundle.js +13722 -3611
- package/data/build/dist/client/cli-catalog.js +20 -3
- package/data/build/dist/client/cli-slots.d.ts +5 -0
- package/data/build/dist/client/cli-slots.js +57 -7
- package/data/build/dist/client/debug/ui.d.ts +1 -1
- package/data/build/dist/client/debug/ui.js +62 -32
- package/data/build/dist/client/dsh-runtime-version.d.ts +9 -2
- package/data/build/dist/client/dsh-runtime-version.js +24 -2
- package/data/build/dist/client/features/cli-adapters.d.ts +1 -1
- package/data/build/dist/client/features/cli-adapters.js +19 -16
- package/data/build/dist/client/features/debug.js +2 -2
- package/data/build/dist/client/features/index.d.ts +2 -1
- package/data/build/dist/client/features/index.js +3 -1
- package/data/build/dist/client/features/lan-access-panel.d.ts +1 -1
- package/data/build/dist/client/features/lan-access-panel.js +8 -10
- package/data/build/dist/client/features/lan-access.js +1 -1
- package/data/build/dist/client/features/login-protection-panel.d.ts +1 -1
- package/data/build/dist/client/features/login-protection-panel.js +7 -9
- package/data/build/dist/client/features/reverse-proxy-panel.d.ts +1 -1
- package/data/build/dist/client/features/reverse-proxy-panel.js +99 -11
- package/data/build/dist/client/features/reverse-proxy.d.ts +1 -1
- package/data/build/dist/client/features/reverse-proxy.js +19 -18
- package/data/build/dist/client/features/terminal-enhancement-panel.d.ts +1 -1
- package/data/build/dist/client/features/terminal-enhancement-panel.js +62 -55
- package/data/build/dist/client/features/terminal-enhancement.d.ts +1 -1
- package/data/build/dist/client/features/terminal-enhancement.js +3 -3
- package/data/build/dist/client/features/types.d.ts +14 -3
- package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts +1 -1
- package/data/build/dist/client/features/workspace-session-enhancement-panel.js +31 -9
- package/data/build/dist/client/features/workspace-session-enhancement.js +72 -11
- package/data/build/dist/client/git-management.d.ts +16 -0
- package/data/build/dist/client/git-management.js +757 -0
- package/data/build/dist/client/index.d.ts +3 -2
- package/data/build/dist/client/index.js +152 -27
- package/data/build/dist/client/locale.js +91 -29
- package/data/build/dist/client/quick-phrase-layout.d.ts +49 -0
- package/data/build/dist/client/quick-phrase-layout.js +95 -0
- package/data/build/dist/client/quick-phrase-slot.d.ts +7 -0
- package/data/build/dist/client/quick-phrase-slot.js +370 -0
- package/data/build/dist/client/remote-web-context.js +1 -1
- package/data/build/dist/client/settings-bridge.d.ts +9 -6
- package/data/build/dist/client/settings-bridge.js +51 -27
- package/data/build/dist/client/settings-section.d.ts +3 -2
- package/data/build/dist/client/settings-section.js +33 -19
- package/data/build/dist/client/subscription-slot.d.ts +3 -0
- package/data/build/dist/client/subscription-slot.js +108 -16
- package/data/build/dist/client/terminal/model.d.ts +14 -2
- package/data/build/dist/client/terminal/model.js +109 -21
- package/data/build/dist/client/terminal/recovery.d.ts +50 -0
- package/data/build/dist/client/terminal/recovery.js +101 -0
- package/data/build/dist/client/terminal/ui.d.ts +2 -2
- package/data/build/dist/client/terminal/ui.js +49 -11
- package/data/build/dist/client/terminal/xterm-view.d.ts +2 -2
- package/data/build/dist/client/terminal/xterm-view.js +2 -1
- package/data/build/dist/client/theme.d.ts +6 -1
- package/data/build/dist/client/theme.js +32 -1
- package/data/build/dist/client/workspace-session-archive-dom.d.ts +12 -0
- package/data/build/dist/client/workspace-session-archive-dom.js +27 -5
- package/data/build/dist/client/workspace-session-visibility-dom.d.ts +30 -0
- package/data/build/dist/client/workspace-session-visibility-dom.js +604 -0
- package/data/build/dist/dsh-capabilities/client/config-forms-adapter.d.ts +50 -0
- package/data/build/dist/dsh-capabilities/client/config-forms-adapter.js +139 -0
- package/data/build/dist/dsh-capabilities/client/conversation-adapter.d.ts +7 -0
- package/data/build/dist/dsh-capabilities/client/conversation-adapter.js +6 -0
- package/data/build/dist/dsh-capabilities/client/locale-adapter.d.ts +9 -0
- package/data/build/dist/dsh-capabilities/client/locale-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +10 -0
- package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +14 -0
- package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.d.ts +8 -0
- package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.js +16 -0
- package/data/build/dist/dsh-capabilities/client/sidebar-adapter.d.ts +7 -0
- package/data/build/dist/dsh-capabilities/client/sidebar-adapter.js +5 -0
- package/data/build/dist/dsh-capabilities/client/theme-adapter.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/client/theme-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/client/typert-adapter.d.ts +5 -0
- package/data/build/dist/dsh-capabilities/client/typert-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/host/config-forms-adapter.d.ts +19 -0
- package/data/build/dist/dsh-capabilities/host/config-forms-adapter.js +45 -0
- package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.d.ts +19 -0
- package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.js +13 -0
- package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.d.ts +8 -0
- package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.js +47 -0
- package/data/build/dist/dsh-capabilities/host/typert-adapter.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/host/typert-adapter.js +4 -0
- package/data/build/dist/dsh-capabilities/index.d.ts +6 -0
- package/data/build/dist/dsh-capabilities/index.js +6 -0
- package/data/build/dist/dsh-capabilities/matrix.d.ts +15 -0
- package/data/build/dist/dsh-capabilities/matrix.js +32 -0
- package/data/build/dist/dsh-capabilities/registry.d.ts +22 -0
- package/data/build/dist/dsh-capabilities/registry.js +196 -0
- package/data/build/dist/dsh-capabilities/routes.d.ts +10 -0
- package/data/build/dist/dsh-capabilities/routes.js +34 -0
- package/data/build/dist/dsh-capabilities/settings-store.d.ts +29 -0
- package/data/build/dist/dsh-capabilities/settings-store.js +5 -0
- package/data/build/dist/dsh-capabilities/types.d.ts +50 -0
- package/data/build/dist/dsh-capabilities/types.js +23 -0
- package/data/build/dist/features/registry.d.ts +8 -2
- package/data/build/dist/features/registry.js +104 -1
- package/data/build/dist/host/auth-session.d.ts +8 -1
- package/data/build/dist/host/auth-session.js +28 -6
- package/data/build/dist/host/cli-adapters/claude-driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/claude-driver.js +19 -4
- package/data/build/dist/host/cli-adapters/claude-model-options.d.ts +14 -0
- package/data/build/dist/host/cli-adapters/claude-model-options.js +157 -0
- package/data/build/dist/host/cli-adapters/codex-driver.d.ts +11 -0
- package/data/build/dist/host/cli-adapters/codex-driver.js +166 -14
- package/data/build/dist/host/cli-adapters/driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts +15 -0
- package/data/build/dist/host/cli-adapters/dsh-message-projector.js +120 -29
- package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts +4 -1
- package/data/build/dist/host/cli-adapters/dsh-tool-history.js +25 -7
- package/data/build/dist/host/cli-adapters/feature.js +74 -8
- package/data/build/dist/host/cli-adapters/gemini-driver.js +2 -2
- package/data/build/dist/host/cli-adapters/grok-driver.js +2 -2
- package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +4 -2
- package/data/build/dist/host/cli-adapters/json-rpc-process.js +8 -9
- package/data/build/dist/host/cli-adapters/kimi-driver.js +1 -1
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +17 -0
- package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +88 -0
- package/data/build/dist/host/cli-adapters/legacy-session-settings.d.ts +24 -0
- package/data/build/dist/host/cli-adapters/legacy-session-settings.js +162 -0
- package/data/build/dist/host/cli-adapters/official-provider-subscription.d.ts +29 -0
- package/data/build/dist/host/cli-adapters/official-provider-subscription.js +361 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +2 -0
- package/data/build/dist/host/cli-adapters/opencode-driver.js +97 -12
- package/data/build/dist/host/cli-adapters/pi-driver.js +69 -23
- package/data/build/dist/host/cli-adapters/provider-registry.d.ts +33 -0
- package/data/build/dist/host/cli-adapters/provider-registry.js +83 -0
- package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +25 -3
- package/data/build/dist/host/cli-adapters/provider-subscription.js +346 -30
- package/data/build/dist/host/cli-adapters/registry.d.ts +6 -0
- package/data/build/dist/host/cli-adapters/registry.js +170 -13
- package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +10 -0
- package/data/build/dist/host/cli-adapters/session-store.d.ts +7 -0
- package/data/build/dist/host/cli-adapters/session-store.js +39 -1
- package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +3 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts +3 -0
- package/data/build/dist/host/cli-adapters/stream-normalizer.js +22 -2
- package/data/build/dist/host/control-api-client.d.ts +3 -3
- package/data/build/dist/host/control-api-client.js +2 -1
- package/data/build/dist/host/credential-store.js +11 -1
- package/data/build/dist/host/dsh-device-runtime.d.ts +4 -0
- package/data/build/dist/host/dsh-device-runtime.js +20 -9
- package/data/build/dist/host/features/auth.js +8 -5
- package/data/build/dist/host/features/debug.js +1 -1
- package/data/build/dist/host/features/git-management.d.ts +5 -0
- package/data/build/dist/host/features/git-management.js +290 -0
- package/data/build/dist/host/features/host-status.js +1 -1
- package/data/build/dist/host/features/index.d.ts +1 -0
- package/data/build/dist/host/features/index.js +3 -0
- package/data/build/dist/host/features/terminal-process.js +1 -1
- package/data/build/dist/host/features/terminal-status.d.ts +3 -1
- package/data/build/dist/host/features/terminal-status.js +3 -1
- package/data/build/dist/host/index.d.ts +7 -3
- package/data/build/dist/host/index.js +76 -11
- package/data/build/dist/host/lan-access-dsh.js +18 -5
- package/data/build/dist/host/native-session-bridge.d.ts +23 -1
- package/data/build/dist/host/native-session-bridge.js +157 -10
- package/data/build/dist/host/rpc-table.d.ts +1 -1
- package/data/build/dist/host/rpc.js +60 -10
- package/data/build/dist/host/session-migration-repair.d.ts +19 -0
- package/data/build/dist/host/session-migration-repair.js +395 -0
- package/data/build/dist/host/settings.d.ts +8 -1
- package/data/build/dist/host/settings.js +94 -3
- package/data/build/dist/host/terminal/backends/tmux-backend.d.ts +1 -0
- package/data/build/dist/host/terminal/backends/tmux-backend.js +4 -2
- package/data/build/dist/host/terminal/controller-factory.d.ts +4 -0
- package/data/build/dist/host/terminal/controller-factory.js +26 -7
- package/data/build/dist/host/terminal/runtime-manager.d.ts +2 -1
- package/data/build/dist/host/terminal/runtime-manager.js +3 -0
- package/data/build/dist/host/terminal/startup.d.ts +2 -0
- package/data/build/dist/host/terminal/startup.js +2 -1
- package/data/build/dist/host/terminal/terminal-controller.d.ts +10 -3
- package/data/build/dist/host/terminal/terminal-controller.js +101 -15
- package/data/build/dist/host/terminal/terminal-process-service.js +3 -1
- package/data/build/dist/host/terminal/terminal-service.d.ts +2 -0
- package/data/build/dist/host/terminal/terminal-service.js +10 -0
- package/data/build/dist/index.d.ts +6 -2
- package/data/build/dist/index.js +8 -2
- package/data/build/dist/shared/contracts/cli-adapter.d.ts +14 -0
- package/data/build/dist/shared/contracts/config.d.ts +31 -1
- package/data/build/dist/shared/contracts/config.js +25 -0
- package/data/build/dist/shared/contracts/dsh-device.d.ts +13 -1
- package/data/build/dist/shared/contracts/errors.d.ts +1 -1
- package/data/build/dist/shared/contracts/feature.d.ts +6 -0
- package/data/build/dist/shared/contracts/git.d.ts +82 -0
- package/data/build/dist/shared/contracts/git.js +3 -0
- package/data/build/dist/shared/contracts/subscription.d.ts +46 -0
- package/data/build/dist/shared/contracts/terminal.d.ts +4 -1
- package/data/build/dist/shared/contracts/version.d.ts +2 -2
- package/data/build/dist/shared/contracts/version.js +4 -6
- package/data/build/dist/shared/debug.d.ts +14 -0
- package/data/build/dist/shared/debug.js +53 -0
- package/data/build/dist/shared/index.d.ts +7 -4
- package/data/build/dist/shared/index.js +2 -1
- package/data/build/dist/transport/debug.d.ts +1 -1
- package/data/build/dist/transport/debug.js +3 -30
- package/data/build/dist/transport/dsh-session.js +3 -3
- package/data/build/dist/typert.host.js +4 -2
- package/data/build/dist/typert.remote-client.d.ts +11 -0
- package/data/build/dist/typert.remote-client.js +7 -0
- package/dsh.bundle.patch +1 -1
- package/package.json +17 -5
- package/profile/README.md +4 -4
- package/profile/package.json +6 -4
- package/profile/scripts/check-dsh-install.mjs +2 -2
- package/profile/version.json +2 -2
- package/scripts/check-dsh-install.mjs +2 -2
- package/version.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { homedir } from 'node:os';
|
|
1
|
+
import { homedir, hostname } from 'node:os';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { DSH_VERSION } from '../shared/contracts/version.js';
|
|
3
4
|
import { FileDshDeviceCredentialStore, } from './credential-store.js';
|
|
4
5
|
import { ensureHostDtlsIdentity, FileHostDtlsIdentityStore, startHostRelayRuntime, } from './relay-tunnel-runtime.js';
|
|
5
6
|
/**
|
|
@@ -15,20 +16,26 @@ export async function startDshHostDeviceRuntime(options) {
|
|
|
15
16
|
throw new Error('DSH Host accessToken 已失效');
|
|
16
17
|
return token;
|
|
17
18
|
};
|
|
19
|
+
const withAccessToken = (operation) => options.withAccessToken === undefined ? operation(getAccessToken()) : options.withAccessToken(operation);
|
|
18
20
|
const credentialStore = options.credentialStore ?? new FileDshDeviceCredentialStore(defaultDshCredentialPath());
|
|
19
21
|
const dtlsStore = options.dtlsStore ?? new FileHostDtlsIdentityStore(defaultDtlsPath());
|
|
20
22
|
const identity = await ensureHostDtlsIdentity(dtlsStore);
|
|
23
|
+
const dshVersion = options.dshVersion?.trim() || DSH_VERSION;
|
|
24
|
+
const computerName = options.computerName?.trim() || hostname().trim() || 'unknown';
|
|
25
|
+
const heartbeatDetails = { dshVersion, computerName };
|
|
21
26
|
let credential = await credentialStore.read();
|
|
22
27
|
let device;
|
|
23
28
|
if (credential === null || credential.dtlsFingerprint !== identity.fingerprint) {
|
|
24
29
|
const request = {
|
|
25
30
|
displayName: options.displayName?.trim() || 'DSH Host',
|
|
31
|
+
dshVersion,
|
|
32
|
+
computerName,
|
|
26
33
|
devicePublicKey: identity.certPem,
|
|
27
34
|
dtlsFingerprint: identity.fingerprint,
|
|
28
35
|
protocolVersion: options.protocolVersion ?? 'dsh-envelope-v1',
|
|
29
36
|
capabilities: [...(options.capabilities ?? ['rpc', 'pty', 'file', 'web'])],
|
|
30
37
|
};
|
|
31
|
-
const registered = await options.controlClient.registerDshDevice(
|
|
38
|
+
const registered = await withAccessToken((accessToken) => options.controlClient.registerDshDevice(accessToken, request));
|
|
32
39
|
credential = {
|
|
33
40
|
deviceId: registered.device.dshDeviceId ?? registered.device.deviceId ?? (() => { throw new Error('DSH 注册响应缺少设备标识'); })(),
|
|
34
41
|
deviceCredential: registered.deviceCredential,
|
|
@@ -36,17 +43,21 @@ export async function startDshHostDeviceRuntime(options) {
|
|
|
36
43
|
dtlsFingerprint: identity.fingerprint,
|
|
37
44
|
tunnelDomain: registered.device.tunnelDomain ?? null,
|
|
38
45
|
displayName: registered.device.displayName,
|
|
46
|
+
dshVersion: registered.device.dshVersion ?? dshVersion,
|
|
47
|
+
computerName: registered.device.computerName ?? computerName,
|
|
39
48
|
savedAt: new Date().toISOString(),
|
|
40
49
|
};
|
|
41
50
|
await credentialStore.write(credential);
|
|
42
51
|
device = registered.device;
|
|
43
52
|
}
|
|
44
53
|
else {
|
|
45
|
-
const listed = await options.controlClient.listDshDevices(
|
|
54
|
+
const listed = await withAccessToken((accessToken) => options.controlClient.listDshDevices(accessToken));
|
|
46
55
|
device = listed.devices.find((candidate) => (candidate.dshDeviceId ?? candidate.deviceId) === credential.deviceId) ?? {
|
|
47
56
|
dshDeviceId: credential.deviceId,
|
|
48
57
|
deviceId: credential.deviceId,
|
|
49
58
|
displayName: credential.displayName,
|
|
59
|
+
dshVersion: credential.dshVersion ?? dshVersion,
|
|
60
|
+
computerName: credential.computerName ?? computerName,
|
|
50
61
|
protocolVersion: options.protocolVersion ?? 'dsh-envelope-v1',
|
|
51
62
|
capabilities: [...(options.capabilities ?? [])],
|
|
52
63
|
dtlsFingerprint: credential.dtlsFingerprint,
|
|
@@ -61,10 +72,10 @@ export async function startDshHostDeviceRuntime(options) {
|
|
|
61
72
|
if (credential === null)
|
|
62
73
|
throw new Error('DSH 设备凭据初始化失败');
|
|
63
74
|
const savedCredential = credential;
|
|
64
|
-
await options.controlClient.heartbeatDshDevice(
|
|
75
|
+
await withAccessToken((accessToken) => options.controlClient.heartbeatDshDevice(accessToken, savedCredential.deviceId, savedCredential.deviceCredential, heartbeatDetails));
|
|
65
76
|
const runtimeOptions = {
|
|
66
77
|
controlClient: { createSignalingTicket: async () => { throw new Error('DSH runtime 必须使用 DSH ticket'); } },
|
|
67
|
-
createTicket: ({ identity: material, credentialVersion }) => requestDshTicket(options.controlClient,
|
|
78
|
+
createTicket: ({ identity: material, credentialVersion }) => requestDshTicket(withAccessToken, options.controlClient, savedCredential, material.fingerprint, credentialVersion),
|
|
68
79
|
accessToken: options.accessToken,
|
|
69
80
|
bindingId: savedCredential.deviceId,
|
|
70
81
|
credentialVersion: savedCredential.credentialVersion,
|
|
@@ -83,7 +94,7 @@ export async function startDshHostDeviceRuntime(options) {
|
|
|
83
94
|
if (stopped)
|
|
84
95
|
return;
|
|
85
96
|
void Promise.resolve()
|
|
86
|
-
.then(() => options.controlClient.heartbeatDshDevice(
|
|
97
|
+
.then(() => withAccessToken((accessToken) => options.controlClient.heartbeatDshDevice(accessToken, savedCredential.deviceId, savedCredential.deviceCredential, heartbeatDetails)))
|
|
87
98
|
.catch(() => undefined);
|
|
88
99
|
}, options.heartbeatIntervalMs ?? 30_000);
|
|
89
100
|
const stop = async () => {
|
|
@@ -98,14 +109,14 @@ export async function startDshHostDeviceRuntime(options) {
|
|
|
98
109
|
await options.onRuntime?.(runtime);
|
|
99
110
|
return { credential: savedCredential, device, runtime, stop };
|
|
100
111
|
}
|
|
101
|
-
async function requestDshTicket(
|
|
102
|
-
const response = await client.createDshRelayTicket(accessToken, {
|
|
112
|
+
async function requestDshTicket(withAccessToken, client, credential, fingerprint, credentialVersion) {
|
|
113
|
+
const response = await withAccessToken((accessToken) => client.createDshRelayTicket(accessToken, {
|
|
103
114
|
dshDeviceId: credential.deviceId,
|
|
104
115
|
deviceCredential: credential.deviceCredential,
|
|
105
116
|
hostDtlsFingerprint: fingerprint,
|
|
106
117
|
credentialVersion: credentialVersion ?? credential.credentialVersion,
|
|
107
118
|
role: 'host',
|
|
108
|
-
});
|
|
119
|
+
}));
|
|
109
120
|
return {
|
|
110
121
|
...response,
|
|
111
122
|
bindingId: response.dshDeviceId,
|
|
@@ -29,7 +29,7 @@ export function createAuthFeature() {
|
|
|
29
29
|
return {
|
|
30
30
|
descriptor: {
|
|
31
31
|
name: 'auth',
|
|
32
|
-
version: '0.1.
|
|
32
|
+
version: '0.1.1',
|
|
33
33
|
enabledByDefault: true,
|
|
34
34
|
dependencies: [],
|
|
35
35
|
runtime: 'host',
|
|
@@ -89,6 +89,7 @@ export function createAuthFeature() {
|
|
|
89
89
|
accessToken,
|
|
90
90
|
credentialStore: dshCredentials,
|
|
91
91
|
accessTokenProvider: () => target.getAccessToken(),
|
|
92
|
+
withAccessToken: (operation) => target.withAccessToken(operation),
|
|
92
93
|
...(context.services.dshVersion === undefined ? {} : { dshVersion: context.services.dshVersion }),
|
|
93
94
|
resources: context.resources,
|
|
94
95
|
gatewayFeatures,
|
|
@@ -131,7 +132,10 @@ export function createAuthFeature() {
|
|
|
131
132
|
bind: (payload) => requireSession().bindHost(parseHostBind(payload)),
|
|
132
133
|
unbind: (payload) => requireSession().unbindHost(parseStringField(payload, 'bindingId')),
|
|
133
134
|
signalingTicket: (payload) => requireSession().createClientSignalingTicket(parseOptionalStringField(payload, 'tunnelDomain')),
|
|
134
|
-
'dsh/device/list': () =>
|
|
135
|
+
'dsh/device/list': () => {
|
|
136
|
+
const target = requireSession();
|
|
137
|
+
return target.withAccessToken((accessToken) => target.getControlClient().listDshDevices(accessToken));
|
|
138
|
+
},
|
|
135
139
|
'dsh/device/start': async () => { await startDsh(requireSession()); return dshRuntime?.device ?? null; },
|
|
136
140
|
'dsh/device/stop': async () => { await dshRuntime?.stop(); dshRuntime = null; return { stopped: true }; },
|
|
137
141
|
'dsh/device/status': () => dshRuntime ? { device: dshRuntime.device, online: true } : { device: null, online: false },
|
|
@@ -148,8 +152,7 @@ export function createAuthFeature() {
|
|
|
148
152
|
const input = isRecord(payload) && typeof payload.dshDeviceId === 'string' ? payload.dshDeviceId.trim() : '';
|
|
149
153
|
if (!input || input !== dshRuntime.credential.deviceId)
|
|
150
154
|
throw new CodingNsRpcError('DSH_DEVICE_NOT_FOUND', '请求的 DSH 设备不是当前 Host');
|
|
151
|
-
|
|
152
|
-
if (!accessToken)
|
|
155
|
+
if (!target.getAccessToken())
|
|
153
156
|
throw new CodingNsRpcError('CODINGNS_RPC_UNAUTHENTICATED', 'Codingns4DSH 尚未登录');
|
|
154
157
|
const request = {
|
|
155
158
|
dshDeviceId: dshRuntime.credential.deviceId,
|
|
@@ -158,7 +161,7 @@ export function createAuthFeature() {
|
|
|
158
161
|
credentialVersion: dshRuntime.credential.credentialVersion,
|
|
159
162
|
role: 'client',
|
|
160
163
|
};
|
|
161
|
-
return target.getControlClient().createDshRelayTicket(accessToken, request);
|
|
164
|
+
return target.withAccessToken((accessToken) => target.getControlClient().createDshRelayTicket(accessToken, request));
|
|
162
165
|
},
|
|
163
166
|
};
|
|
164
167
|
context.resources.add(context.services.rpc.register('auth', (action, payload) => {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
+
import type { CodingNsHostServices } from './types.js';
|
|
3
|
+
/** Host 侧 Git 工作区服务;所有路径都由 resolveWorkspaceRoot 权威解析。 */
|
|
4
|
+
export declare function createGitManagementFeature(): FeatureModule<CodingNsHostServices>;
|
|
5
|
+
//# sourceMappingURL=git-management.d.ts.map
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
4
|
+
import { CodingNsRpcError } from '../rpc-table.js';
|
|
5
|
+
const execFile = promisify(execFileCallback);
|
|
6
|
+
const MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
7
|
+
const MAX_DIFF_BYTES = 60_000;
|
|
8
|
+
/** Host 侧 Git 工作区服务;所有路径都由 resolveWorkspaceRoot 权威解析。 */
|
|
9
|
+
export function createGitManagementFeature() {
|
|
10
|
+
return {
|
|
11
|
+
descriptor: {
|
|
12
|
+
name: 'gitManagement',
|
|
13
|
+
version: '0.1.0',
|
|
14
|
+
enabledByDefault: true,
|
|
15
|
+
dependencies: [],
|
|
16
|
+
runtime: 'host',
|
|
17
|
+
},
|
|
18
|
+
start(context) {
|
|
19
|
+
context.resources.add(context.services.rpc.register('git', async (action, payload) => {
|
|
20
|
+
const input = record(payload);
|
|
21
|
+
const workspaceId = requiredString(input.workspaceId, 'workspaceId');
|
|
22
|
+
const root = context.services.resolveWorkspaceRoot?.(workspaceId);
|
|
23
|
+
if (root === null || root === undefined)
|
|
24
|
+
throw new CodingNsRpcError('GIT_WORKSPACE_UNAVAILABLE', '当前 Workspace 没有可用的本地目录');
|
|
25
|
+
switch (action) {
|
|
26
|
+
case 'status': return readStatus(workspaceId, root);
|
|
27
|
+
case 'init': return runGit(root, ['init']).then(() => readStatus(workspaceId, root));
|
|
28
|
+
case 'diff': return readDiff(workspaceId, root, requiredString(input.path, 'path'), input.staged === true);
|
|
29
|
+
case 'stage': return mutateTargets(workspaceId, root, input.targets, 'add');
|
|
30
|
+
case 'unstage': return mutateTargets(workspaceId, root, input.targets, 'reset');
|
|
31
|
+
case 'discard': return discardTargets(workspaceId, root, input.targets);
|
|
32
|
+
case 'commit': return commit(workspaceId, root, requiredString(input.subject, 'subject'));
|
|
33
|
+
case 'commit-diff': return readCommitDiff(root, requiredString(input.commitHash, 'commitHash'));
|
|
34
|
+
case 'history': return readHistory(workspaceId, root, input.limit, input.offset);
|
|
35
|
+
case 'branches': return readBranches(root);
|
|
36
|
+
case 'switch': return switchBranch(root, requiredString(input.branchName, 'branchName'), input.create === true);
|
|
37
|
+
case 'fetch': return syncRemote(workspaceId, root, ['fetch', '--all', '--prune']);
|
|
38
|
+
case 'pull': return syncRemote(workspaceId, root, ['pull', '--ff-only']);
|
|
39
|
+
case 'push': return syncRemote(workspaceId, root, ['push']);
|
|
40
|
+
case 'undo': return undoLastCommit(workspaceId, root);
|
|
41
|
+
default: throw new CodingNsRpcError('CODINGNS_RPC_NOT_FOUND', `未知 Git RPC: git/${action}`);
|
|
42
|
+
}
|
|
43
|
+
}));
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function readStatus(workspaceId, root) {
|
|
48
|
+
let result;
|
|
49
|
+
try {
|
|
50
|
+
result = await runGit(root, ['status', '--porcelain=v1', '-z', '--branch']);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (!isNotGitRepositoryError(error))
|
|
54
|
+
throw error;
|
|
55
|
+
return {
|
|
56
|
+
snapshot: { workspaceId, repoRoot: root, enabled: false, branch: 'HEAD', ahead: 0, behind: 0, hasRemote: false, isDirty: false, lastFetchedAt: null },
|
|
57
|
+
changes: [],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const tokens = result.stdout.split('\0');
|
|
61
|
+
const changes = [];
|
|
62
|
+
let branch = 'HEAD';
|
|
63
|
+
let ahead = 0;
|
|
64
|
+
let behind = 0;
|
|
65
|
+
let hasRemote = false;
|
|
66
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
67
|
+
const token = tokens[index];
|
|
68
|
+
if (!token)
|
|
69
|
+
continue;
|
|
70
|
+
if (token.startsWith('## ')) {
|
|
71
|
+
const tracking = parseBranchLine(token.slice(3));
|
|
72
|
+
branch = tracking.branch;
|
|
73
|
+
ahead = tracking.ahead;
|
|
74
|
+
behind = tracking.behind;
|
|
75
|
+
hasRemote = tracking.hasRemote;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (token.length < 3)
|
|
79
|
+
continue;
|
|
80
|
+
const stagedStatus = token[0] === ' ' || token[0] === '?' || token[0] === '!' ? null : token[0] ?? null;
|
|
81
|
+
const worktreeStatus = token[1] === ' ' || token[1] === '?' || token[1] === '!' ? null : token[1] ?? null;
|
|
82
|
+
const status = `${token[0] ?? ' '}${token[1] ?? ' '}`.trim() || '?';
|
|
83
|
+
const path = normalizeGitPath(token.slice(3));
|
|
84
|
+
let oldPath = null;
|
|
85
|
+
if ((token[0] === 'R' || token[0] === 'C' || token[1] === 'R' || token[1] === 'C') && tokens[index + 1]) {
|
|
86
|
+
oldPath = normalizeGitPath(tokens[index + 1] ?? '');
|
|
87
|
+
index += 1;
|
|
88
|
+
}
|
|
89
|
+
changes.push({ path, status, staged: stagedStatus !== null, oldPath, binary: false, stagedStatus, worktreeStatus });
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
snapshot: { workspaceId, repoRoot: root, enabled: true, branch, ahead, behind, hasRemote, isDirty: changes.length > 0, lastFetchedAt: null },
|
|
93
|
+
changes,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function parseBranchLine(value) {
|
|
97
|
+
const [rawBranch, rawTracking] = value.split('...');
|
|
98
|
+
const branch = (rawBranch ?? 'HEAD').replace(/^No commits yet on /u, '').trim() || 'HEAD';
|
|
99
|
+
const tracking = rawTracking ?? '';
|
|
100
|
+
const ahead = Number(/\[ahead (\d+)/u.exec(tracking)?.[1] ?? 0);
|
|
101
|
+
const behind = Number(/\[behind (\d+)/u.exec(tracking)?.[1] ?? 0);
|
|
102
|
+
return { branch, ahead, behind, hasRemote: rawTracking !== undefined };
|
|
103
|
+
}
|
|
104
|
+
async function readDiff(workspaceId, root, target, staged) {
|
|
105
|
+
const path = safeTarget(root, target);
|
|
106
|
+
try {
|
|
107
|
+
const result = await runGit(root, [...(staged ? ['diff', '--cached'] : ['diff']), '--binary', '--', path]);
|
|
108
|
+
const content = result.stdout.slice(0, MAX_DIFF_BYTES);
|
|
109
|
+
return { workspaceId, path: normalizeGitPath(target), staged, binary: /Binary files /u.test(result.stdout), truncated: result.stdout.length > content.length, content };
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error instanceof GitCommandError && error.stderr.includes('unknown revision'))
|
|
113
|
+
throw error;
|
|
114
|
+
return { workspaceId, path: normalizeGitPath(target), staged, binary: false, truncated: false, content: '' };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function mutateTargets(workspaceId, root, rawTargets, action) {
|
|
118
|
+
const targets = safeTargets(root, rawTargets);
|
|
119
|
+
if (targets.length > 0)
|
|
120
|
+
await runGit(root, action === 'add' ? ['add', '--', ...targets] : ['reset', '--', ...targets]);
|
|
121
|
+
return readStatus(workspaceId, root);
|
|
122
|
+
}
|
|
123
|
+
async function discardTargets(workspaceId, root, rawTargets) {
|
|
124
|
+
const targets = safeTargets(root, rawTargets);
|
|
125
|
+
if (targets.length > 0) {
|
|
126
|
+
await runGit(root, ['restore', '--worktree', '--staged', '--', ...targets]).catch(() => undefined);
|
|
127
|
+
await runGit(root, ['clean', '-f', '--', ...targets]).catch(() => undefined);
|
|
128
|
+
}
|
|
129
|
+
return readStatus(workspaceId, root);
|
|
130
|
+
}
|
|
131
|
+
async function commit(workspaceId, root, subject) {
|
|
132
|
+
if (subject.length > 200)
|
|
133
|
+
throw new TypeError('subject 不能超过 200 个字符');
|
|
134
|
+
const result = await runGit(root, ['commit', '-m', subject]);
|
|
135
|
+
const hash = (await runGit(root, ['rev-parse', 'HEAD'])).stdout.trim();
|
|
136
|
+
return { commitHash: hash, summary: result.stdout.trim() || `已提交 ${hash.slice(0, 8)}`, status: await readStatus(workspaceId, root) };
|
|
137
|
+
}
|
|
138
|
+
async function readCommitDiff(root, rawCommitHash) {
|
|
139
|
+
const commitHash = rawCommitHash.trim();
|
|
140
|
+
if (!/^[0-9a-f]{7,40}$/iu.test(commitHash))
|
|
141
|
+
throw new TypeError('commitHash 无效');
|
|
142
|
+
const [result, filesResult] = await Promise.all([
|
|
143
|
+
runGit(root, ['-c', 'core.quotePath=false', 'show', '--format=', '--binary', '--no-ext-diff', '-M', commitHash, '--']),
|
|
144
|
+
runGit(root, ['-c', 'core.quotePath=false', 'show', '--format=', '--name-status', '-M', commitHash, '--']),
|
|
145
|
+
]);
|
|
146
|
+
const content = result.stdout.slice(0, MAX_DIFF_BYTES);
|
|
147
|
+
return { commitHash, files: parseCommitChangedFiles(filesResult.stdout, result.stdout), content, truncated: result.stdout.length > content.length };
|
|
148
|
+
}
|
|
149
|
+
function parseCommitChangedFiles(value, diffContent) {
|
|
150
|
+
const binaryPaths = new Set();
|
|
151
|
+
for (const line of diffContent.split(/\r?\n/u)) {
|
|
152
|
+
const match = /^Binary files .* and .* differ$/u.exec(line);
|
|
153
|
+
if (match !== null) {
|
|
154
|
+
const paths = line.match(/(?:a|b)\/([^\s]+?)(?: differ)?$/u);
|
|
155
|
+
if (paths?.[1] !== undefined)
|
|
156
|
+
binaryPaths.add(paths[1]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return value.split(/\r?\n/u).flatMap((line) => {
|
|
160
|
+
const fields = line.split('\t');
|
|
161
|
+
const statusToken = fields[0]?.trim() ?? '';
|
|
162
|
+
if (statusToken === '' || fields.length < 2)
|
|
163
|
+
return [];
|
|
164
|
+
const status = statusToken[0] ?? '?';
|
|
165
|
+
const renamed = status === 'R' || status === 'C';
|
|
166
|
+
const oldPath = renamed ? fields[1] ?? null : null;
|
|
167
|
+
const path = (renamed ? fields[2] : fields[1])?.trim() ?? '';
|
|
168
|
+
if (path === '')
|
|
169
|
+
return [];
|
|
170
|
+
return [{ path, oldPath, status, binary: binaryPaths.has(path) }];
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
async function syncRemote(workspaceId, root, args) {
|
|
174
|
+
await runGit(root, args);
|
|
175
|
+
return readStatus(workspaceId, root);
|
|
176
|
+
}
|
|
177
|
+
async function undoLastCommit(workspaceId, root) {
|
|
178
|
+
await runGit(root, ['rev-parse', '--verify', 'HEAD']);
|
|
179
|
+
await runGit(root, ['reset', '--soft', 'HEAD~1']);
|
|
180
|
+
return readStatus(workspaceId, root);
|
|
181
|
+
}
|
|
182
|
+
async function readHistory(_workspaceId, root, rawLimit, rawOffset) {
|
|
183
|
+
const limit = Math.max(1, Math.min(100, Number.isSafeInteger(rawLimit) ? Number(rawLimit) : 50));
|
|
184
|
+
const offset = Math.max(0, Math.min(1_000_000, Number.isSafeInteger(rawOffset) ? Number(rawOffset) : 0));
|
|
185
|
+
let result;
|
|
186
|
+
try {
|
|
187
|
+
result = await runGit(root, ['log', `--skip=${String(offset)}`, `--max-count=${String(limit)}`, '--format=%H%x1f%an%x1f%aI%x1f%s%x1f%b%x1e']);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (isEmptyRepositoryError(error))
|
|
191
|
+
return { items: [], cursor: String(offset), nextCursor: null, totalCount: 0 };
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
const items = [];
|
|
195
|
+
for (const record of result.stdout.split('\x1e')) {
|
|
196
|
+
const fields = record.trim().split('\x1f');
|
|
197
|
+
if (fields.length < 5 || !fields[0])
|
|
198
|
+
continue;
|
|
199
|
+
items.push({ commitHash: fields[0], authorName: fields[1] ?? '', authoredAt: fields[2] ?? '', subject: fields[3] ?? '', body: fields[4] ?? '', refs: [] });
|
|
200
|
+
}
|
|
201
|
+
let total = 0;
|
|
202
|
+
try {
|
|
203
|
+
total = Number((await runGit(root, ['rev-list', '--count', 'HEAD'])).stdout.trim() || 0);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
if (!isEmptyRepositoryError(error))
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
return { items, cursor: String(offset), nextCursor: offset + items.length < total ? String(offset + items.length) : null, totalCount: total };
|
|
210
|
+
}
|
|
211
|
+
async function readBranches(root) {
|
|
212
|
+
const currentBranch = (await runGit(root, ['branch', '--show-current'])).stdout.trim() || 'HEAD';
|
|
213
|
+
// for-each-ref 不展开 %xNN;使用 Git 原生支持的 NUL 字段分隔符,避免分支名被污染。
|
|
214
|
+
const result = await runGit(root, ['for-each-ref', '--format=%(refname)%00%(refname:short)%00%(HEAD)%00%(upstream:short)', 'refs/heads', 'refs/remotes']);
|
|
215
|
+
const local = [];
|
|
216
|
+
const remote = [];
|
|
217
|
+
const fields = result.stdout.replace(/\r?\n$/u, '').split('\0');
|
|
218
|
+
for (let index = 0; index + 3 < fields.length; index += 4) {
|
|
219
|
+
const fullName = fields[index] ?? '';
|
|
220
|
+
const name = fields[index + 1] ?? '';
|
|
221
|
+
const head = fields[index + 2] ?? '';
|
|
222
|
+
const upstream = fields[index + 3] ?? '';
|
|
223
|
+
if (!name)
|
|
224
|
+
continue;
|
|
225
|
+
const item = { name, current: head === '*', upstream: upstream || null, remote: fullName.startsWith('refs/remotes/') };
|
|
226
|
+
(item.remote ? remote : local).push(item);
|
|
227
|
+
}
|
|
228
|
+
return { currentBranch, local, remote };
|
|
229
|
+
}
|
|
230
|
+
async function switchBranch(root, branchName, create) {
|
|
231
|
+
if (!/^[A-Za-z0-9._/-]+$/u.test(branchName) || branchName.startsWith('-'))
|
|
232
|
+
throw new TypeError('branchName 无效');
|
|
233
|
+
await runGit(root, create ? ['switch', '-c', branchName] : ['switch', branchName]);
|
|
234
|
+
return readBranches(root);
|
|
235
|
+
}
|
|
236
|
+
async function runGit(cwd, args) {
|
|
237
|
+
try {
|
|
238
|
+
return await execFile('git', [...args], { cwd, encoding: 'utf8', maxBuffer: MAX_OUTPUT_BYTES, timeout: 30_000 });
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
const detail = error;
|
|
242
|
+
throw new GitCommandError(`git ${args.join(' ')} 执行失败`, detail.stderr ?? detail.stdout ?? String(error), detail.code);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
class GitCommandError extends Error {
|
|
246
|
+
stderr;
|
|
247
|
+
commandCode;
|
|
248
|
+
constructor(message, stderr, commandCode) {
|
|
249
|
+
super(message);
|
|
250
|
+
this.stderr = stderr;
|
|
251
|
+
this.commandCode = commandCode;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function safeTargets(root, value) {
|
|
255
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string'))
|
|
256
|
+
throw new TypeError('targets 必须是字符串数组');
|
|
257
|
+
return value.map((item) => safeTarget(root, item)).filter((item, index, list) => list.indexOf(item) === index);
|
|
258
|
+
}
|
|
259
|
+
function safeTarget(root, value) {
|
|
260
|
+
const target = normalizeGitPath(value);
|
|
261
|
+
if (!target || target.includes('\0') || isAbsolute(target) || target === '.' || target.split('/').includes('..'))
|
|
262
|
+
throw new TypeError('Git 路径无效');
|
|
263
|
+
const absolute = resolve(root, target);
|
|
264
|
+
const escaped = relative(root, absolute);
|
|
265
|
+
if (escaped.startsWith('..') || isAbsolute(escaped))
|
|
266
|
+
throw new TypeError('Git 路径超出 Workspace');
|
|
267
|
+
return target;
|
|
268
|
+
}
|
|
269
|
+
function normalizeGitPath(value) { return value.replaceAll('\\', '/').replace(/^\.\//u, '').trim(); }
|
|
270
|
+
function isNotGitRepositoryError(error) {
|
|
271
|
+
if (!(error instanceof GitCommandError))
|
|
272
|
+
return false;
|
|
273
|
+
return error.commandCode === 128 && /not a git repository|not a git repository/u.test(error.stderr);
|
|
274
|
+
}
|
|
275
|
+
function isEmptyRepositoryError(error) {
|
|
276
|
+
if (!(error instanceof GitCommandError))
|
|
277
|
+
return false;
|
|
278
|
+
return error.commandCode === 128 && /does not have any commits yet|your current branch/u.test(error.stderr);
|
|
279
|
+
}
|
|
280
|
+
function record(value) {
|
|
281
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
282
|
+
throw new TypeError('Git RPC 参数必须是对象');
|
|
283
|
+
return value;
|
|
284
|
+
}
|
|
285
|
+
function requiredString(value, field) {
|
|
286
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
287
|
+
throw new TypeError(`${field} 必须是非空字符串`);
|
|
288
|
+
return value.trim();
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=git-management.js.map
|
|
@@ -15,5 +15,6 @@ export { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
|
15
15
|
export { createTerminalProcessFeature } from './terminal-process.js';
|
|
16
16
|
export { createDebugFeature } from './debug.js';
|
|
17
17
|
export { createHostStatusFeature } from './host-status.js';
|
|
18
|
+
export { createGitManagementFeature } from './git-management.js';
|
|
18
19
|
export type { CodingNsHostServices } from './types.js';
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -5,6 +5,7 @@ import { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
|
5
5
|
import { createTerminalProcessFeature } from './terminal-process.js';
|
|
6
6
|
import { createDebugFeature } from './debug.js';
|
|
7
7
|
import { createHostStatusFeature } from './host-status.js';
|
|
8
|
+
import { createGitManagementFeature } from './git-management.js';
|
|
8
9
|
/** 生产启动可把实际 controller 模式注入状态模块,避免向设置页报告默认占位值。 */
|
|
9
10
|
export function createHostFeatures(options = {}) {
|
|
10
11
|
return [
|
|
@@ -15,6 +16,7 @@ export function createHostFeatures(options = {}) {
|
|
|
15
16
|
createTerminalProcessFeature(),
|
|
16
17
|
createDebugFeature(),
|
|
17
18
|
createHostStatusFeature(),
|
|
19
|
+
createGitManagementFeature(),
|
|
18
20
|
];
|
|
19
21
|
}
|
|
20
22
|
/** Host 侧功能模块清单:新增模块在这里登记一行,不需要改动入口或 RPC 分发。 */
|
|
@@ -26,4 +28,5 @@ export { createCliAdaptersFeature } from '../cli-adapters/feature.js';
|
|
|
26
28
|
export { createTerminalProcessFeature } from './terminal-process.js';
|
|
27
29
|
export { createDebugFeature } from './debug.js';
|
|
28
30
|
export { createHostStatusFeature } from './host-status.js';
|
|
31
|
+
export { createGitManagementFeature } from './git-management.js';
|
|
29
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { FeatureModule } from '../../shared/contracts/feature.js';
|
|
2
|
-
import type { CodingNsTerminalStatus } from '../../shared/contracts/terminal.js';
|
|
2
|
+
import type { CodingNsTerminalRuntimeType, CodingNsTerminalStatus } from '../../shared/contracts/terminal.js';
|
|
3
3
|
import { type DetectedTerminalShell } from '../terminal/shell-detection.js';
|
|
4
4
|
import type { CodingNsHostServices } from './types.js';
|
|
5
5
|
export interface TerminalStatusFeatureOptions {
|
|
6
6
|
readonly platform?: string;
|
|
7
7
|
readonly controllerMode?: CodingNsTerminalStatus['controllerMode'];
|
|
8
8
|
readonly effectiveEnabled?: boolean;
|
|
9
|
+
readonly runtimeTypes?: readonly CodingNsTerminalRuntimeType[];
|
|
10
|
+
readonly runtimeWarning?: string;
|
|
9
11
|
readonly detectShells?: () => readonly DetectedTerminalShell[];
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
@@ -14,7 +14,7 @@ export function createTerminalStatusFeature(options = {}) {
|
|
|
14
14
|
return {
|
|
15
15
|
descriptor: {
|
|
16
16
|
name: 'terminalStatus',
|
|
17
|
-
version: '0.1.
|
|
17
|
+
version: '0.1.1',
|
|
18
18
|
enabledByDefault: true,
|
|
19
19
|
dependencies: [],
|
|
20
20
|
runtime: 'host',
|
|
@@ -38,6 +38,8 @@ export function createTerminalStatusFeature(options = {}) {
|
|
|
38
38
|
platform: normalizePlatform(platform),
|
|
39
39
|
controllerMode,
|
|
40
40
|
effectiveEnabled,
|
|
41
|
+
...(options.runtimeTypes === undefined ? {} : { runtimeTypes: options.runtimeTypes }),
|
|
42
|
+
...(options.runtimeWarning === undefined ? {} : { runtimeWarning: options.runtimeWarning }),
|
|
41
43
|
profiles: available.map((shell) => ({
|
|
42
44
|
profileId: shell.profileId,
|
|
43
45
|
name: shell.displayName,
|
|
@@ -7,17 +7,21 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { Context } from '@deepseek-ai/cordis';
|
|
9
9
|
export declare function apply(ctx?: Context): void;
|
|
10
|
-
export { HOST_FEATURES, createAuthFeature, createLanAccessDshFeature, createTerminalStatusFeature, createHostFeatures, createCliAdaptersFeature, createTerminalProcessFeature, } from './features/index.js';
|
|
10
|
+
export { HOST_FEATURES, createAuthFeature, createLanAccessDshFeature, createTerminalStatusFeature, createHostFeatures, createCliAdaptersFeature, createTerminalProcessFeature, createGitManagementFeature, } from './features/index.js';
|
|
11
11
|
export type { CodingNsHostServices } from './features/index.js';
|
|
12
12
|
export { CodingNsSettingsSchema, registerCodingNsSettings } from './settings.js';
|
|
13
13
|
export { createCodingNsRpcHandler, createCodingNsSettingsRpcHandler, registerCodingNsRpc } from './rpc.js';
|
|
14
14
|
export { DebugWorkspaceService, NodeDebugPortInspector, type DebugPortCheck, type DebugPortInspector, type DebugPortProcess, type DebugProxyBinding, } from './debug.js';
|
|
15
15
|
export { CodingNsRpcError, CodingNsRpcTable, type CodingNsRpcHandler, type CodingNsRpcTarget, } from './rpc-table.js';
|
|
16
16
|
export { CodingNsAuthSession } from './auth-session.js';
|
|
17
|
-
export { createCodingNsNativeSessionBridge, type CodingNsNativeSessionBridge, type CodingNsNativeSessionController, type CodingNsNativeSessionStore, type CodingNsNativeWorkspaceController, type CodingNsNativeRequestContext, } from './native-session-bridge.js';
|
|
17
|
+
export { createCodingNsNativeSessionBridge, type CodingNsNativeSessionBridge, type CodingNsNativeSessionController, type CodingNsNativeSessionStore, type CodingNsNativeWorkspaceController, type CodingNsNativeRequestContext, type CodingNsNativeUsageSample, } from './native-session-bridge.js';
|
|
18
|
+
export { repairLegacySessionLog, repairLegacySessionLogs, type LegacySessionRepairOptions, type LegacySessionRepairReport, } from './session-migration-repair.js';
|
|
19
|
+
export { defaultLegacySettingsPath, parseLegacyImportedSessionRecords, readLegacyImportedSessionRecords, } from './cli-adapters/legacy-session-settings.js';
|
|
18
20
|
export { CommandCodeDriver } from './cli-adapters/command-code-driver.js';
|
|
19
21
|
export { CommandCodeSubscriptionService, readCommandCodeApiKey } from './cli-adapters/command-code-subscription.js';
|
|
20
|
-
export { ProviderSubscriptionService, CodexSubscriptionService, ClaudeCodeSubscriptionService, Sub2ApiUsageService, OpenCodeSubscriptionService, type Sub2ApiSource, type Sub2ApiUsageOptions, } from './cli-adapters/provider-subscription.js';
|
|
22
|
+
export { ProviderSubscriptionService, CodexSubscriptionService, ClaudeCodeSubscriptionService, DeepseekSubscriptionService, Sub2ApiUsageService, OpenCodeSubscriptionService, type DeepseekSubscriptionOptions, type Sub2ApiSource, type Sub2ApiUsageOptions, } from './cli-adapters/provider-subscription.js';
|
|
23
|
+
export { OfficialProviderSubscriptionService, type OfficialProviderSubscriptionOptions } from './cli-adapters/official-provider-subscription.js';
|
|
24
|
+
export { MODEL_PROVIDER_DEFINITIONS, identifyModelProvider, normalizeProviderBaseUrl, normalizeProviderName, thirdPartyProvider, type ProviderDefinition, type ProviderIdentity, type ProviderSubscriptionCapability, type ProviderSubscriptionReader, } from './cli-adapters/provider-registry.js';
|
|
21
25
|
export { ClaudeCodeDriver } from './cli-adapters/claude-driver.js';
|
|
22
26
|
export { KimiCliDriver } from './cli-adapters/kimi-driver.js';
|
|
23
27
|
export { GeminiCliDriver } from './cli-adapters/gemini-driver.js';
|