@deepseek-harness-tui/dsh-tui 0.11.2 → 0.12.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/README.md +21 -5
- package/bin/dsh-tui.js +30 -3
- package/cordis.patch.yml +24 -5
- package/guide/dsh-tui-guide/SKILL.md +37 -0
- package/guide/dsh-tui-guide/configuration.en.md +410 -0
- package/guide/dsh-tui-guide/configuration.md +349 -0
- package/guide/dsh-tui-guide/getting-started.en.md +398 -0
- package/guide/dsh-tui-guide/getting-started.md +397 -0
- package/guide/dsh-tui-guide/interaction.en.md +674 -0
- package/guide/dsh-tui-guide/interaction.md +747 -0
- package/guide/dsh-tui-guide/migrate.en.md +166 -0
- package/guide/dsh-tui-guide/migrate.md +132 -0
- package/guide/dsh-tui-guide/plugins.en.md +68 -0
- package/guide/dsh-tui-guide/plugins.md +56 -0
- package/guide/dsh-tui-guide/themes.en.md +192 -0
- package/guide/dsh-tui-guide/themes.md +185 -0
- package/guide/dsh-tui-guide/user-guide.en.md +608 -0
- package/guide/dsh-tui-guide/user-guide.md +586 -0
- package/guide/dsh-tui-guide/vscode.en.md +301 -0
- package/guide/dsh-tui-guide/vscode.md +272 -0
- package/lib/settings.json +5 -5
- package/lib/types/adapter/channel/ui-policy.d.ts +3 -2
- package/lib/types/adapter/channel/ui-policy.d.ts.map +1 -1
- package/lib/types/adapter/channel/ui-policy.js +4 -0
- package/lib/types/adapter/ports/channel-settings.d.ts +2 -1
- package/lib/types/adapter/ports/channel-settings.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-ui.d.ts +29 -2
- package/lib/types/adapter/ports/channel-ui.d.ts.map +1 -1
- package/lib/types/adapter/ports/channel-view.d.ts +43 -9
- package/lib/types/adapter/ports/channel-view.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.d.ts +9 -0
- package/lib/types/components/Chat/JobCard.d.ts.map +1 -1
- package/lib/types/components/Chat/JobCard.js +42 -15
- package/lib/types/components/Chat/SubagentMessage.js +6 -6
- package/lib/types/components/JobsPanel.d.ts.map +1 -1
- package/lib/types/components/JobsPanel.js +80 -33
- package/lib/types/components/MessageList.js +3 -3
- package/lib/types/components/PresetPicker.d.ts +4 -0
- package/lib/types/components/PresetPicker.d.ts.map +1 -1
- package/lib/types/components/PresetPicker.js +5 -1
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +12 -1
- package/lib/types/components/StarPrompt.d.ts +6 -0
- package/lib/types/components/StarPrompt.d.ts.map +1 -1
- package/lib/types/components/StarPrompt.js +45 -0
- package/lib/types/components/SubagentCard.d.ts.map +1 -1
- package/lib/types/components/SubagentCard.js +8 -8
- package/lib/types/components/SubagentDetailScene.d.ts.map +1 -1
- package/lib/types/components/SubagentDetailScene.js +108 -10
- package/lib/types/components/WhaleGirl.d.ts +6 -0
- package/lib/types/components/WhaleGirl.d.ts.map +1 -1
- package/lib/types/components/WhaleGirl.js +18 -0
- package/lib/types/components/messages/AssistantThinkingMessage.js +4 -4
- package/lib/types/components/trajectory/MiniWake.d.ts +11 -1
- package/lib/types/components/trajectory/MiniWake.d.ts.map +1 -1
- package/lib/types/components/trajectory/MiniWake.js +9 -3
- package/lib/types/dsh-adapter/channel/external-commands.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/external-commands.js +8 -2
- package/lib/types/dsh-adapter/channel/job-projection.d.ts +1 -0
- package/lib/types/dsh-adapter/channel/job-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/job-projection.js +88 -3
- package/lib/types/dsh-adapter/channel/mode-actions.d.ts +13 -0
- package/lib/types/dsh-adapter/channel/mode-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/mode-actions.js +48 -7
- package/lib/types/dsh-adapter/channel/mode-permission-actions.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/mode-permission-actions.js +25 -9
- package/lib/types/dsh-adapter/channel/preferences.d.ts +1 -1
- package/lib/types/dsh-adapter/channel/preferences.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/preferences.js +17 -7
- package/lib/types/dsh-adapter/channel/state.d.ts +4 -2
- package/lib/types/dsh-adapter/channel/state.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/state.js +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel/subagent-projection.js +5 -0
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +16 -1
- package/lib/types/dsh-adapter/contract.d.ts +5 -4
- package/lib/types/dsh-adapter/contract.d.ts.map +1 -1
- package/lib/types/dsh-adapter/contract.js +9 -3
- package/lib/types/dsh-adapter/jobs.d.ts +82 -16
- package/lib/types/dsh-adapter/jobs.d.ts.map +1 -1
- package/lib/types/dsh-adapter/jobs.js +104 -9
- package/lib/types/dsh-adapter/oauth/bonus.d.ts +27 -0
- package/lib/types/dsh-adapter/oauth/bonus.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/bonus.js +69 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.d.ts +2 -1
- package/lib/types/dsh-adapter/oauth/command.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/command.js +7 -4
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.d.ts +13 -10
- package/lib/types/dsh-adapter/oauth/credentials.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/credentials.js +61 -23
- package/lib/types/dsh-adapter/oauth/deepseek.d.ts +39 -0
- package/lib/types/dsh-adapter/oauth/deepseek.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/deepseek.js +189 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.d.ts +24 -16
- package/lib/types/dsh-adapter/oauth/index.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.js +34 -20
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/interaction.d.ts +14 -12
- package/lib/types/dsh-adapter/oauth/interaction.d.ts.map +1 -0
- package/lib/types/dsh-adapter/oauth/interaction.js +283 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.d.ts +2 -1
- package/lib/types/dsh-adapter/oauth/opener.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/opener.js +1 -1
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.d.ts +10 -3
- package/lib/types/dsh-adapter/oauth/pi-ai.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/pi-ai.js +8 -3
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.d.ts +6 -3
- package/lib/types/dsh-adapter/oauth/profiles.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/profiles.js +11 -3
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.d.ts +14 -7
- package/lib/types/dsh-adapter/oauth/service.d.ts.map +1 -0
- package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/service.js +82 -17
- package/lib/types/dsh-adapter/plugin.d.ts +8 -1
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +72 -12
- package/lib/types/dsh-adapter/presets.d.ts +6 -4
- package/lib/types/dsh-adapter/presets.d.ts.map +1 -1
- package/lib/types/dsh-adapter/presets.js +6 -4
- package/lib/types/dsh-adapter/providerWizard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/providerWizard.js +6 -2
- package/lib/types/dsh-adapter/subagents.d.ts +1 -0
- package/lib/types/dsh-adapter/subagents.d.ts.map +1 -1
- package/lib/types/dsh-adapter/subagents.js +10 -1
- package/lib/types/i18n.d.ts +174 -18
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +53 -11
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +10 -1
- package/lib/types/ink/parse-keypress.d.ts +35 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +611 -83
- package/lib/types/ink/terminal-querier.d.ts +25 -0
- package/lib/types/ink/terminal-querier.d.ts.map +1 -1
- package/lib/types/ink/terminal-querier.js +42 -0
- package/lib/types/ink/update-overflow-guard.d.ts +24 -0
- package/lib/types/ink/update-overflow-guard.d.ts.map +1 -1
- package/lib/types/ink/update-overflow-guard.js +25 -3
- package/lib/types/minimalUiMode.d.ts +19 -0
- package/lib/types/minimalUiMode.d.ts.map +1 -0
- package/lib/types/minimalUiMode.js +23 -0
- package/lib/types/oauth.d.ts +5 -10
- package/lib/types/oauth.d.ts.map +1 -1
- package/lib/types/oauth.js +5 -10
- package/lib/types/screens/Chat.d.ts +4 -1
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +27 -7
- package/lib/types/screens/StatusLine.d.ts +4 -0
- package/lib/types/screens/StatusLine.d.ts.map +1 -1
- package/lib/types/screens/StatusLine.js +12 -12
- package/lib/types/settings/definitions.js +4 -4
- package/lib/types/tips.d.ts.map +1 -1
- package/lib/types/tips.js +10 -4
- package/lib/types/update.js +2 -2
- package/lib/types/utils/pastedImagePath.d.ts +8 -0
- package/lib/types/utils/pastedImagePath.d.ts.map +1 -1
- package/lib/types/utils/pastedImagePath.js +29 -5
- package/package.json +111 -100
- package/presets/liangshen/agent.cordis.yml +4 -1
- package/presets/liangshen/preset.yml +1 -1
- package/lib/types/minimalMode.d.ts +0 -13
- package/lib/types/minimalMode.d.ts.map +0 -1
- package/lib/types/minimalMode.js +0 -17
- package/node_modules/@deepseek-harness-tui/dsh-auth/LICENSE +0 -21
- package/node_modules/@deepseek-harness-tui/dsh-auth/README.md +0 -143
- package/node_modules/@deepseek-harness-tui/dsh-auth/cordis.patch.yml +0 -11
- package/node_modules/@deepseek-harness-tui/dsh-auth/dsh-plugin.json +0 -44
- package/node_modules/@deepseek-harness-tui/dsh-auth/lib/interaction.js +0 -193
- package/node_modules/@deepseek-harness-tui/dsh-auth/package.json +0 -69
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TUI interaction for the Host-owned DeepSeek account authorization flow.
|
|
3
|
+
*
|
|
4
|
+
* The Host owns PKCE, its callback route, credential persistence, and the
|
|
5
|
+
* `deepseek-account` LLM route. This module supplies a loopback callback
|
|
6
|
+
* origin, mounts the official Host listener when an older bundle patch omits
|
|
7
|
+
* it, and displays the Host's safe attempt state through the existing question
|
|
8
|
+
* panel. It never reads or writes the account grant.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from 'node:fs';
|
|
11
|
+
import { getLang } from '../../i18n.js';
|
|
12
|
+
import { QuestionBridge } from './interaction.js';
|
|
13
|
+
export const DEEPSEEK_ACCOUNT_PROVIDER = 'deepseek-account';
|
|
14
|
+
/** Resolve late: the account provider is absent on older DSH hosts. */
|
|
15
|
+
export function deepSeekAccountFrom(ctx) {
|
|
16
|
+
return ctx.get('deepseekAccount');
|
|
17
|
+
}
|
|
18
|
+
/** The Host webServer may be shared, supplied by the TUI row, or mounted as a fallback. */
|
|
19
|
+
export function deepSeekCallbackOrigin(ctx) {
|
|
20
|
+
const server = ctx.get('webServer');
|
|
21
|
+
const port = server?.port;
|
|
22
|
+
if (port === undefined || !Number.isInteger(port) || port < 1 || port > 65535) {
|
|
23
|
+
throw new Error('DeepSeek sign-in needs an active Host webServer for the browser callback');
|
|
24
|
+
}
|
|
25
|
+
return `http://127.0.0.1:${port}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Keep DeepSeek login usable after a profile-only update from a global TUI
|
|
29
|
+
* whose older bundle patch still mounts `dsh-tui-auth` but has no webserver
|
|
30
|
+
* row. The official Host listener is mounted only on the first login that
|
|
31
|
+
* needs it; an existing Web or user-owned listener is never replaced.
|
|
32
|
+
*/
|
|
33
|
+
export function createDeepSeekCallbackOriginResolver(ctx) {
|
|
34
|
+
let fallback;
|
|
35
|
+
let mounting;
|
|
36
|
+
let disposed = false;
|
|
37
|
+
const mountFallback = async () => {
|
|
38
|
+
const { WebServer } = await import('@deepseek-ai/dsh-host-webserver');
|
|
39
|
+
if (disposed)
|
|
40
|
+
throw new Error('dsh-auth: callback listener owner was disposed');
|
|
41
|
+
// Another Host row may have become available while the import resolved.
|
|
42
|
+
if (ctx.get('webServer') !== undefined)
|
|
43
|
+
return;
|
|
44
|
+
const fiber = ctx.root.plugin(WebServer, { host: '127.0.0.1', port: 0 });
|
|
45
|
+
fallback = fiber;
|
|
46
|
+
try {
|
|
47
|
+
await fiber;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
fallback = undefined;
|
|
51
|
+
try {
|
|
52
|
+
await fiber.dispose();
|
|
53
|
+
}
|
|
54
|
+
catch (disposeError) {
|
|
55
|
+
throw new AggregateError([error, disposeError], 'DeepSeek callback listener failed to start and dispose');
|
|
56
|
+
}
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
resolve: async () => {
|
|
62
|
+
if (disposed)
|
|
63
|
+
throw new Error('dsh-auth: callback listener owner was disposed');
|
|
64
|
+
if (ctx.get('webServer') === undefined) {
|
|
65
|
+
// A declared but unavailable listener is a composition decision or
|
|
66
|
+
// failure, not the missing row of an older global TUI patch.
|
|
67
|
+
const loader = ctx.get('loader');
|
|
68
|
+
for (const entry of loader?.entries() ?? []) {
|
|
69
|
+
if (entry.options.id === 'dsh-tui-webserver'
|
|
70
|
+
|| entry.options.name === '@deepseek-ai/dsh-host-webserver') {
|
|
71
|
+
return deepSeekCallbackOrigin(ctx);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
mounting ??= mountFallback().finally(() => { mounting = undefined; });
|
|
75
|
+
try {
|
|
76
|
+
await mounting;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
80
|
+
throw new Error(`DeepSeek sign-in could not start a Host webServer callback listener: ${message}`, { cause: error });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (disposed)
|
|
84
|
+
throw new Error('dsh-auth: callback listener owner was disposed');
|
|
85
|
+
return deepSeekCallbackOrigin(ctx);
|
|
86
|
+
},
|
|
87
|
+
dispose: async () => {
|
|
88
|
+
disposed = true;
|
|
89
|
+
await mounting?.catch(() => undefined);
|
|
90
|
+
await fallback?.dispose();
|
|
91
|
+
fallback = undefined;
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const tuiVersion = (() => {
|
|
96
|
+
try {
|
|
97
|
+
const manifest = JSON.parse(readFileSync(new URL(import.meta.resolve('@deepseek-harness-tui/dsh-tui/package.json')), 'utf8'));
|
|
98
|
+
return typeof manifest.version === 'string' ? manifest.version : '0.0.0';
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return '0.0.0';
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
104
|
+
/** Platform request identity is supplied by the current TUI, not cached by the Host. */
|
|
105
|
+
export function deepSeekClientMetadata() {
|
|
106
|
+
return {
|
|
107
|
+
version: tuiVersion,
|
|
108
|
+
locale: getLang() === 'zh' ? 'zh-CN' : 'en-US',
|
|
109
|
+
timezoneOffsetSeconds: -new Date().getTimezoneOffset() * 60,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function succeeded(state, id) {
|
|
113
|
+
return state.attempt?.id === id && state.attempt.phase === 'succeeded' && state.status === 'credential-stored';
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Start (or join) the upstream browser attempt, display its URL, and wait for
|
|
117
|
+
* the upstream state stream. Esc/external abort cancels the exact attempt;
|
|
118
|
+
* a commit that won that race is reported as success instead of a false
|
|
119
|
+
* cancellation. The question panel is always retired before returning.
|
|
120
|
+
*/
|
|
121
|
+
export async function loginDeepSeekAccount(account, callbackOrigin, ask, signal, helpers = {}) {
|
|
122
|
+
const runAbort = new AbortController();
|
|
123
|
+
const forwardAbort = () => runAbort.abort(signal?.reason);
|
|
124
|
+
if (signal !== undefined) {
|
|
125
|
+
if (signal.aborted)
|
|
126
|
+
forwardAbort();
|
|
127
|
+
else
|
|
128
|
+
signal.addEventListener('abort', forwardAbort, { once: true });
|
|
129
|
+
}
|
|
130
|
+
const bridge = new QuestionBridge(ask, runAbort, helpers);
|
|
131
|
+
let id;
|
|
132
|
+
let active = false;
|
|
133
|
+
try {
|
|
134
|
+
runAbort.signal.throwIfAborted();
|
|
135
|
+
// Match Desktop's login_source for Platform-side promotion eligibility.
|
|
136
|
+
const initial = await account.startSignIn(deepSeekClientMetadata(), callbackOrigin, 'desktop');
|
|
137
|
+
id = initial.attempt?.id;
|
|
138
|
+
if (id === undefined)
|
|
139
|
+
throw new Error('DeepSeek sign-in returned no attempt');
|
|
140
|
+
active = true;
|
|
141
|
+
runAbort.signal.throwIfAborted();
|
|
142
|
+
let shownUrl;
|
|
143
|
+
try {
|
|
144
|
+
for await (const state of account.watch(runAbort.signal)) {
|
|
145
|
+
const attempt = state.attempt;
|
|
146
|
+
if (attempt?.id !== id)
|
|
147
|
+
throw new Error('DeepSeek sign-in attempt was replaced');
|
|
148
|
+
if (attempt.phase === 'waiting-browser' && attempt.authorizeUrl !== undefined
|
|
149
|
+
&& attempt.authorizeUrl !== shownUrl) {
|
|
150
|
+
shownUrl = attempt.authorizeUrl;
|
|
151
|
+
bridge.notify({ type: 'auth_url', url: shownUrl });
|
|
152
|
+
}
|
|
153
|
+
if (attempt.phase === 'succeeded') {
|
|
154
|
+
active = false;
|
|
155
|
+
if (!succeeded(state, id))
|
|
156
|
+
throw new Error('DeepSeek sign-in succeeded without a stored credential');
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (attempt.phase === 'failed' || attempt.phase === 'expired' || attempt.phase === 'cancelled') {
|
|
160
|
+
active = false;
|
|
161
|
+
throw new Error(`DeepSeek sign-in ${attempt.phase}${attempt.errorCode === undefined ? '' : ` (${attempt.errorCode})`}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (!runAbort.signal.aborted)
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
if (runAbort.signal.aborted) {
|
|
170
|
+
const afterCancel = await account.cancelSignIn(id);
|
|
171
|
+
active = false;
|
|
172
|
+
if (succeeded(afterCancel, id))
|
|
173
|
+
return;
|
|
174
|
+
throw new Error('DeepSeek sign-in cancelled');
|
|
175
|
+
}
|
|
176
|
+
throw new Error('DeepSeek sign-in state stream ended before completion');
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
signal?.removeEventListener('abort', forwardAbort);
|
|
180
|
+
runAbort.abort();
|
|
181
|
+
try {
|
|
182
|
+
if (active && id !== undefined)
|
|
183
|
+
await account.cancelSignIn(id);
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
await bridge.settle();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.d.ts
RENAMED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Built-in subscription OAuth sign-in as LLM provider routes.
|
|
3
3
|
*
|
|
4
|
-
* One
|
|
5
|
-
* (ChatGPT/Codex, Claude
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* One internal Cordis module mounts supported subscription routes from the
|
|
5
|
+
* installed pi-ai catalog (ChatGPT/Codex, Claude, Grok, and newer flows when
|
|
6
|
+
* available) as `llm` registry routes. Signed-in models appear in model
|
|
7
|
+
* pickers; unsigned routes remain addressable for saved sessions. When the
|
|
8
|
+
* Host supplies `deepseekAccount`, the same sign-in surface also delegates
|
|
9
|
+
* DeepSeek browser authorization to that service; the Host owns its model
|
|
10
|
+
* route, callback, and credential store.
|
|
11
|
+
* `PiAiAdapter` runs with this
|
|
12
|
+
* module's file-backed pi-ai `CredentialStore` injected
|
|
9
13
|
* (`PiAiAuthInjection`): requests resolve the stored OAuth credential through
|
|
10
14
|
* the provider's own auth and rotate refresh tokens under the store's lock.
|
|
11
15
|
* Login/logout run over the `userQuestions` seam, so they work on any
|
|
12
16
|
* interactive surface and refuse cleanly where none exists (TUI-RUN-001).
|
|
13
17
|
*
|
|
14
18
|
* ```yaml
|
|
15
|
-
* - id: dsh-auth
|
|
16
|
-
* name: 'dsh-
|
|
19
|
+
* - id: dsh-tui-auth
|
|
20
|
+
* name: '@deepseek-harness-tui/dsh-tui/oauth'
|
|
21
|
+
* inject: [llm, commands]
|
|
17
22
|
* config:
|
|
18
|
-
* providers: [openai-codex, anthropic, xai]
|
|
23
|
+
* # providers: [openai-codex, anthropic, xai] # optional catalog subset;
|
|
24
|
+
* # newer pi-ai also offers openai and meta
|
|
19
25
|
* # credentialsFile: /secure/path/credentials.json # default $DSH_HOME/dsh-auth/
|
|
20
26
|
* # Per-provider catalog overrides, keyed by provider id then model id:
|
|
21
27
|
* # any optional field keeps the installed catalog's value. The example
|
|
@@ -30,7 +36,7 @@
|
|
|
30
36
|
* (an llm-pi-ai settings profile for the same provider) is refused by the
|
|
31
37
|
* registry — that refusal is logged and the remaining routes still mount.
|
|
32
38
|
*
|
|
33
|
-
* @module dsh-
|
|
39
|
+
* @module @deepseek-harness-tui/dsh-tui/oauth
|
|
34
40
|
*/
|
|
35
41
|
import type { Context } from '@deepseek-ai/cordis';
|
|
36
42
|
import z from '@deepseek-ai/schemastery';
|
|
@@ -43,15 +49,14 @@ export declare const name = "dsh-auth";
|
|
|
43
49
|
* Deliberately empty. A hard code-level inject would deadlock any
|
|
44
50
|
* composition lacking the `llm`/`commands` services at boot ("pending
|
|
45
51
|
* (waiting for service: …)") — the failure mode dsh-tui documented for its
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* *entry* level, where a stale patch cannot deadlock a newer boot.
|
|
52
|
+
* optional rows (#183). Both services resolve per call through `ctx.get` in
|
|
53
|
+
* {@link apply}; the profile patch declares the inject at the *entry* level,
|
|
54
|
+
* where a stale patch cannot deadlock a newer boot.
|
|
50
55
|
*/
|
|
51
56
|
export declare const inject: readonly string[];
|
|
52
57
|
/** Plugin configuration. */
|
|
53
58
|
export interface Config {
|
|
54
|
-
/** Provider routes to mount;
|
|
59
|
+
/** Provider routes to mount; omitted means every supported flow in the installed pi-ai catalog. */
|
|
55
60
|
providers?: string[];
|
|
56
61
|
/** Credential file override; default `$DSH_HOME/dsh-auth/credentials.json`. */
|
|
57
62
|
credentialsFile?: string;
|
|
@@ -70,7 +75,9 @@ export { QuestionBridge, describeEvent } from './interaction.js';
|
|
|
70
75
|
export type { AskFn, QuestionBridgeHelpers } from './interaction.js';
|
|
71
76
|
export { copyToClipboard, openInBrowser, openerFor } from './opener.js';
|
|
72
77
|
export { CredentialFile, defaultCredentialsFile } from './credentials.js';
|
|
73
|
-
export { OAUTH_PROVIDER_IDS, buildOAuthProfile, type ModelOverride } from './profiles.js';
|
|
78
|
+
export { OAUTH_PROVIDER_IDS, availableOAuthProviderIds, buildOAuthProfile, type ModelOverride } from './profiles.js';
|
|
79
|
+
export { DEEPSEEK_ACCOUNT_PROVIDER, deepSeekAccountFrom, deepSeekCallbackOrigin, deepSeekClientMetadata, loginDeepSeekAccount } from './deepseek.js';
|
|
80
|
+
export { WhaleCouponStore } from './bonus.js';
|
|
74
81
|
/**
|
|
75
82
|
* The adapter the plugin registers: a {@link PiAiAdapter} whose *advisory
|
|
76
83
|
* catalog* is credential-gated. A provider with no stored OAuth credential
|
|
@@ -92,3 +99,4 @@ export declare class CredentialGatedAdapter extends PiAiAdapter {
|
|
|
92
99
|
}
|
|
93
100
|
/** Mount the routes, the service, and the command. */
|
|
94
101
|
export declare function apply(ctx: Context, config: Config): void;
|
|
102
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAEpE,OAAO,EAAoE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAOpH,eAAO,MAAM,IAAI,aAAa,CAAA;AAC9B;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAAE,SAAS,MAAM,EAAO,CAAA;AAgB3C,4BAA4B;AAC5B,MAAM,WAAW,MAAM;IACrB,mGAAmG;IACnG,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;CAC/D;AAOD,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAI3B,CAAA;AAEF,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChE,YAAY,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AACpH,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AACpJ,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAkB7C;;;;;;;;;;;;;GAaG;AACH,qBAAa,sBAAuB,SAAQ,WAAW;IAGnD,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAD9B,OAAO,EAAE,kBAAkB,EACV,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC;IAKzD,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,YAAY,EAAE,CAAC;CAI9E;AAED,sDAAsD;AACtD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAuHxD"}
|
package/{node_modules/@deepseek-harness-tui/dsh-auth/lib → lib/types/dsh-adapter/oauth}/index.js
RENAMED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Built-in subscription OAuth sign-in as LLM provider routes.
|
|
3
3
|
*
|
|
4
|
-
* One
|
|
5
|
-
* (ChatGPT/Codex, Claude
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* One internal Cordis module mounts supported subscription routes from the
|
|
5
|
+
* installed pi-ai catalog (ChatGPT/Codex, Claude, Grok, and newer flows when
|
|
6
|
+
* available) as `llm` registry routes. Signed-in models appear in model
|
|
7
|
+
* pickers; unsigned routes remain addressable for saved sessions. When the
|
|
8
|
+
* Host supplies `deepseekAccount`, the same sign-in surface also delegates
|
|
9
|
+
* DeepSeek browser authorization to that service; the Host owns its model
|
|
10
|
+
* route, callback, and credential store.
|
|
11
|
+
* `PiAiAdapter` runs with this
|
|
12
|
+
* module's file-backed pi-ai `CredentialStore` injected
|
|
9
13
|
* (`PiAiAuthInjection`): requests resolve the stored OAuth credential through
|
|
10
14
|
* the provider's own auth and rotate refresh tokens under the store's lock.
|
|
11
15
|
* Login/logout run over the `userQuestions` seam, so they work on any
|
|
12
16
|
* interactive surface and refuse cleanly where none exists (TUI-RUN-001).
|
|
13
17
|
*
|
|
14
18
|
* ```yaml
|
|
15
|
-
* - id: dsh-auth
|
|
16
|
-
* name: 'dsh-
|
|
19
|
+
* - id: dsh-tui-auth
|
|
20
|
+
* name: '@deepseek-harness-tui/dsh-tui/oauth'
|
|
21
|
+
* inject: [llm, commands]
|
|
17
22
|
* config:
|
|
18
|
-
* providers: [openai-codex, anthropic, xai]
|
|
23
|
+
* # providers: [openai-codex, anthropic, xai] # optional catalog subset;
|
|
24
|
+
* # newer pi-ai also offers openai and meta
|
|
19
25
|
* # credentialsFile: /secure/path/credentials.json # default $DSH_HOME/dsh-auth/
|
|
20
26
|
* # Per-provider catalog overrides, keyed by provider id then model id:
|
|
21
27
|
* # any optional field keeps the installed catalog's value. The example
|
|
@@ -30,7 +36,7 @@
|
|
|
30
36
|
* (an llm-pi-ai settings profile for the same provider) is refused by the
|
|
31
37
|
* registry — that refusal is logged and the remaining routes still mount.
|
|
32
38
|
*
|
|
33
|
-
* @module dsh-
|
|
39
|
+
* @module @deepseek-harness-tui/dsh-tui/oauth
|
|
34
40
|
*/
|
|
35
41
|
import { existsSync } from 'node:fs';
|
|
36
42
|
import { homedir } from 'node:os';
|
|
@@ -38,18 +44,18 @@ import { join } from 'node:path';
|
|
|
38
44
|
import z from '@deepseek-ai/schemastery';
|
|
39
45
|
import { PiAiAdapter } from '@deepseek-ai/dsh-llm-pi-ai';
|
|
40
46
|
import { CredentialFile, defaultCredentialsFile } from './credentials.js';
|
|
41
|
-
import { buildOAuthProfile, OAUTH_PROVIDER_IDS } from './profiles.js';
|
|
47
|
+
import { availableOAuthProviderIds, buildOAuthProfile, OAUTH_PROVIDER_IDS } from './profiles.js';
|
|
42
48
|
import { createDshAuthApi, DshAuthService } from './service.js';
|
|
43
49
|
import { createAuthCommandHandler } from './command.js';
|
|
50
|
+
import { createDeepSeekCallbackOriginResolver, deepSeekAccountFrom } from './deepseek.js';
|
|
44
51
|
export const name = 'dsh-auth';
|
|
45
52
|
/**
|
|
46
53
|
* Deliberately empty. A hard code-level inject would deadlock any
|
|
47
54
|
* composition lacking the `llm`/`commands` services at boot ("pending
|
|
48
55
|
* (waiting for service: …)") — the failure mode dsh-tui documented for its
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* *entry* level, where a stale patch cannot deadlock a newer boot.
|
|
56
|
+
* optional rows (#183). Both services resolve per call through `ctx.get` in
|
|
57
|
+
* {@link apply}; the profile patch declares the inject at the *entry* level,
|
|
58
|
+
* where a stale patch cannot deadlock a newer boot.
|
|
53
59
|
*/
|
|
54
60
|
export const inject = [];
|
|
55
61
|
const modelOverride = z.object({
|
|
@@ -57,7 +63,7 @@ const modelOverride = z.object({
|
|
|
57
63
|
maxTokens: z.number().step(1).min(1),
|
|
58
64
|
});
|
|
59
65
|
export const Config = z.object({
|
|
60
|
-
providers: z.array(z.string()).default(
|
|
66
|
+
providers: z.array(z.string()).default(availableOAuthProviderIds()),
|
|
61
67
|
credentialsFile: z.string(),
|
|
62
68
|
modelOverrides: z.dict(z.dict(modelOverride)),
|
|
63
69
|
});
|
|
@@ -65,7 +71,9 @@ export { createDshAuthApi } from './service.js';
|
|
|
65
71
|
export { QuestionBridge, describeEvent } from './interaction.js';
|
|
66
72
|
export { copyToClipboard, openInBrowser, openerFor } from './opener.js';
|
|
67
73
|
export { CredentialFile, defaultCredentialsFile } from './credentials.js';
|
|
68
|
-
export { OAUTH_PROVIDER_IDS, buildOAuthProfile } from './profiles.js';
|
|
74
|
+
export { OAUTH_PROVIDER_IDS, availableOAuthProviderIds, buildOAuthProfile } from './profiles.js';
|
|
75
|
+
export { DEEPSEEK_ACCOUNT_PROVIDER, deepSeekAccountFrom, deepSeekCallbackOrigin, deepSeekClientMetadata, loginDeepSeekAccount } from './deepseek.js';
|
|
76
|
+
export { WhaleCouponStore } from './bonus.js';
|
|
69
77
|
/**
|
|
70
78
|
* The ambient auth context providers may consult while resolving their own
|
|
71
79
|
* auth. `env()` answers from the process environment; `fileExists()` answers
|
|
@@ -107,7 +115,7 @@ export class CredentialGatedAdapter extends PiAiAdapter {
|
|
|
107
115
|
}
|
|
108
116
|
/** Mount the routes, the service, and the command. */
|
|
109
117
|
export function apply(ctx, config) {
|
|
110
|
-
const configured = config.providers ??
|
|
118
|
+
const configured = config.providers ?? availableOAuthProviderIds();
|
|
111
119
|
const unknown = configured.filter(id => !OAUTH_PROVIDER_IDS.includes(id));
|
|
112
120
|
if (unknown.length > 0 || configured.length === 0) {
|
|
113
121
|
throw new Error(`dsh-auth: providers must be a non-empty subset of [${OAUTH_PROVIDER_IDS.join(', ')}]; got [${configured.join(', ')}]`);
|
|
@@ -156,17 +164,23 @@ export function apply(ctx, config) {
|
|
|
156
164
|
// the plugin module; the defensive get-then-create matches how the TUI
|
|
157
165
|
// mounts userQuestions.
|
|
158
166
|
const service = ctx.get('dshAuth') ?? new DshAuthService(ctx);
|
|
167
|
+
const callbackOrigin = createDeepSeekCallbackOriginResolver(ctx);
|
|
159
168
|
const api = createDshAuthApi({
|
|
160
169
|
profiles,
|
|
161
170
|
store,
|
|
171
|
+
resolveDeepSeekAccount: () => deepSeekAccountFrom(ctx),
|
|
172
|
+
coupons: service.coupons,
|
|
173
|
+
resolveCallbackOrigin: callbackOrigin.resolve,
|
|
162
174
|
resolveAsk: () => {
|
|
163
175
|
const questions = ctx.get('userQuestions');
|
|
164
176
|
return questions === undefined ? undefined : request => questions.ask(request);
|
|
165
177
|
},
|
|
166
|
-
logger: ctx.logger,
|
|
167
178
|
});
|
|
168
179
|
service.api = api;
|
|
169
180
|
ctx.effect(function* () {
|
|
181
|
+
// LIFO disposal: release command registration, drain started logins, then
|
|
182
|
+
// close a fallback callback listener only this module mounted.
|
|
183
|
+
yield () => callbackOrigin.dispose();
|
|
170
184
|
const releases = [];
|
|
171
185
|
// Runtime service resolution (never a code-level inject — see `inject`):
|
|
172
186
|
// absent services keep this plugin inert and logged, not the whole boot
|
|
@@ -197,7 +211,7 @@ export function apply(ctx, config) {
|
|
|
197
211
|
const handler = createAuthCommandHandler(api);
|
|
198
212
|
releases.push(commands.register({
|
|
199
213
|
name: 'auth',
|
|
200
|
-
description: 'Provider
|
|
214
|
+
description: 'Provider account sign-in (OAuth): status, login, logout',
|
|
201
215
|
handler: invocation => {
|
|
202
216
|
const operation = handler(invocation);
|
|
203
217
|
active.add(operation);
|
|
@@ -6,19 +6,17 @@
|
|
|
6
6
|
* their options, text/secret/manual-code prompts expect the custom-answer
|
|
7
7
|
* input row.
|
|
8
8
|
*
|
|
9
|
-
* `notify()`
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* path gets the same treatment: its short code is the thing to copy, and
|
|
17
|
-
* the verification page is auto-opened too.
|
|
9
|
+
* `notify()` opens browser/device URLs for pi-ai. Browser flows immediately
|
|
10
|
+
* race a callback server against a `manual_code` prompt; the URL and
|
|
11
|
+
* copy/reopen/cancel actions therefore share that SAME question with the
|
|
12
|
+
* paste field. A separate waiting question would claim the FIFO question
|
|
13
|
+
* surface first and make remote/headless callback fallback unreachable.
|
|
14
|
+
* Browser flows without a manual prompt still get a waiting panel. Device
|
|
15
|
+
* flows use that panel to show/copy the short code until polling settles.
|
|
18
16
|
*
|
|
19
17
|
* One `AbortController` owns the whole run: pi-ai reads `interaction.signal`
|
|
20
|
-
* to abort the flow,
|
|
21
|
-
*
|
|
18
|
+
* to abort the flow, ask requests compose it with per-prompt cancellation,
|
|
19
|
+
* and the waiting panel's cancel action fires it.
|
|
22
20
|
*
|
|
23
21
|
* Nothing here assumes a browser or GUI *exists* (TUI-RUN-001): when no
|
|
24
22
|
* opener or clipboard helper is available the panel degrades to showing the
|
|
@@ -26,7 +24,7 @@
|
|
|
26
24
|
* registered at all, `ask` rejects and the login command turns that into a
|
|
27
25
|
* clear refusal.
|
|
28
26
|
*
|
|
29
|
-
* @module dsh-
|
|
27
|
+
* @module @deepseek-harness-tui/dsh-tui/oauth/interaction
|
|
30
28
|
*/
|
|
31
29
|
import type { AskUserQuestionItem, AskUserQuestionAnswer } from '@deepseek-ai/dsh-user-questions';
|
|
32
30
|
import type { PiAiAuthEvent, PiAiAuthInteraction, PiAiAuthPrompt } from './pi-ai.js';
|
|
@@ -54,15 +52,19 @@ export declare class QuestionBridge implements PiAiAuthInteraction {
|
|
|
54
52
|
private readonly openUrl;
|
|
55
53
|
private readonly copy;
|
|
56
54
|
private waiting;
|
|
55
|
+
private pendingBrowserView;
|
|
56
|
+
private notice;
|
|
57
57
|
private waitingClosed;
|
|
58
58
|
constructor(ask: AskFn, runAbort: AbortController, helpers?: QuestionBridgeHelpers);
|
|
59
59
|
prompt(prompt: PiAiAuthPrompt): Promise<string>;
|
|
60
60
|
notify(event: PiAiAuthEvent): void;
|
|
61
61
|
/** Close the waiting panel (if any) and stop answering for this run. */
|
|
62
62
|
settle(): Promise<void>;
|
|
63
|
+
private retireWaiting;
|
|
63
64
|
/**
|
|
64
65
|
* Show the waiting panel until the flow settles or the user cancels,
|
|
65
66
|
* re-asking after a copy/reopen action with a one-line status prefix.
|
|
66
67
|
*/
|
|
67
68
|
private runWaitingPanel;
|
|
68
69
|
}
|
|
70
|
+
//# sourceMappingURL=interaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction.d.ts","sourceRoot":"","sources":["../../../../src/dsh-adapter/oauth/interaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAGjG,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEpF,4EAA4E;AAC5E,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE;IAC5B,SAAS,EAAE,mBAAmB,EAAE,CAAA;IAChC,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAEpC,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAA;IAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC9C;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAU1D;AA6CD;;;;GAIG;AACH,qBAAa,cAAe,YAAW,mBAAmB;IAatD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAb3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,OAAO,CAGF;IACb,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,aAAa,CAAQ;gBAGV,GAAG,EAAE,KAAK,EACV,QAAQ,EAAE,eAAe,EAC1C,OAAO,GAAE,qBAA0B;IAO/B,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAqFrD,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAgClC,wEAAwE;IAClE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;YAOf,aAAa;IAM3B;;;OAGG;YACW,eAAe;CAgD9B"}
|