Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qjclaw-dmg
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qjclaw-dmg
Commits
a4d243ae
Commit
a4d243ae
authored
Mar 30, 2026
by
AI-甘富林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(desktop): unify startup setup flow and runtime cloud prewarm
parent
f9e6de26
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
824 additions
and
124 deletions
+824
-124
index.ts
apps/desktop/src/main/index.ts
+122
-10
ipc.ts
apps/desktop/src/main/ipc.ts
+333
-57
app-config.ts
apps/desktop/src/main/services/app-config.ts
+83
-34
cloud-api.ts
apps/desktop/src/main/services/cloud-api.ts
+159
-18
index.ts
apps/desktop/src/preload/index.ts
+4
-3
startup-prewarm-plan.zh-CN.md
docs/startup-prewarm-plan.zh-CN.md
+92
-0
index.ts
packages/shared-types/src/index.ts
+31
-2
No files found.
apps/desktop/src/main/index.ts
View file @
a4d243ae
This diff is collapsed.
Click to expand it.
apps/desktop/src/main/ipc.ts
View file @
a4d243ae
This diff is collapsed.
Click to expand it.
apps/desktop/src/main/services/app-config.ts
View file @
a4d243ae
import
{
mkdir
,
readFile
,
writeFile
}
from
"node:fs/promises"
;
import
{
mkdir
,
readFile
,
rename
,
rm
,
writeFile
}
from
"node:fs/promises"
;
import
path
from
"node:path"
;
import
path
from
"node:path"
;
import
type
{
AppConfig
,
RuntimeModePreference
,
SaveConfigInput
}
from
"@qjclaw/shared-types"
;
import
type
{
AppConfig
,
RuntimeModePreference
,
SaveConfigInput
,
SetupMode
}
from
"@qjclaw/shared-types"
;
const
CONFIG_DIR
=
"config"
;
const
CONFIG_DIR
=
"config"
;
const
CONFIG_FILE
=
"app-config.json"
;
const
CONFIG_FILE
=
"app-config.json"
;
...
@@ -23,6 +23,7 @@ const UI_ROUTE_NAMES = new Set([
...
@@ -23,6 +23,7 @@ const UI_ROUTE_NAMES = new Set([
]);
]);
interface
LegacyConfig
{
interface
LegacyConfig
{
setupMode
?:
SetupMode
;
provider
?:
string
;
provider
?:
string
;
baseUrl
?:
string
;
baseUrl
?:
string
;
apiKeyConfigured
?:
boolean
;
apiKeyConfigured
?:
boolean
;
...
@@ -79,6 +80,10 @@ function normalizeRuntimeMode(raw?: string): RuntimeModePreference {
...
@@ -79,6 +80,10 @@ function normalizeRuntimeMode(raw?: string): RuntimeModePreference {
return
raw
===
"bundled-runtime"
||
raw
===
"external-gateway"
?
raw
:
"bundled-runtime"
;
return
raw
===
"bundled-runtime"
||
raw
===
"external-gateway"
?
raw
:
"bundled-runtime"
;
}
}
function
normalizeSetupMode
(
raw
?:
string
):
SetupMode
{
return
raw
===
"direct-provider"
?
raw
:
"employee-key"
;
}
function
resolveRuntimeCloudApiBaseUrl
(
raw
?:
string
):
string
{
function
resolveRuntimeCloudApiBaseUrl
(
raw
?:
string
):
string
{
const
normalized
=
normalizeCloudApiBaseUrl
(
raw
??
""
);
const
normalized
=
normalizeCloudApiBaseUrl
(
raw
??
""
);
if
(
normalized
)
{
if
(
normalized
)
{
...
@@ -91,48 +96,41 @@ function resolveRuntimeCloudApiBaseUrl(raw?: string): string {
...
@@ -91,48 +96,41 @@ function resolveRuntimeCloudApiBaseUrl(raw?: string): string {
export
class
AppConfigService
{
export
class
AppConfigService
{
private
readonly
userDataPath
:
string
;
private
readonly
userDataPath
:
string
;
private
ioChain
:
Promise
<
void
>
=
Promise
.
resolve
();
constructor
(
userDataPath
:
string
)
{
constructor
(
userDataPath
:
string
)
{
this
.
userDataPath
=
userDataPath
;
this
.
userDataPath
=
userDataPath
;
}
}
async
load
():
Promise
<
AppConfig
>
{
async
load
():
Promise
<
AppConfig
>
{
const
filePath
=
this
.
getConfigPath
();
return
this
.
runExclusive
(()
=>
this
.
loadUnlocked
());
await
mkdir
(
path
.
dirname
(
filePath
),
{
recursive
:
true
});
try
{
const
raw
=
await
readFile
(
filePath
,
"utf8"
);
const
parsed
=
JSON
.
parse
(
raw
)
as
LegacyConfig
;
const
config
=
this
.
normalizeConfig
(
parsed
);
await
writeFile
(
filePath
,
JSON
.
stringify
(
config
,
null
,
2
),
"utf8"
);
return
config
;
}
catch
{
const
defaults
=
this
.
createDefaultConfig
();
await
writeFile
(
filePath
,
JSON
.
stringify
(
defaults
,
null
,
2
),
"utf8"
);
return
defaults
;
}
}
}
async
save
(
input
:
SaveConfigInput
):
Promise
<
AppConfig
>
{
async
save
(
input
:
SaveConfigInput
):
Promise
<
AppConfig
>
{
const
current
=
await
this
.
load
();
return
this
.
runExclusive
(
async
()
=>
{
const
config
:
AppConfig
=
{
const
current
=
await
this
.
loadUnlocked
();
provider
:
input
.
provider
,
const
config
:
AppConfig
=
{
baseUrl
:
input
.
baseUrl
,
setupMode
:
normalizeSetupMode
(
input
.
setupMode
),
apiKeyConfigured
:
Boolean
(
input
.
apiKey
)
||
current
.
apiKeyConfigured
,
provider
:
input
.
provider
,
gatewayTokenConfigured
:
Boolean
(
input
.
gatewayToken
)
||
current
.
gatewayTokenConfigured
,
baseUrl
:
input
.
baseUrl
,
authTokenConfigured
:
typeof
input
.
authToken
===
"string"
?
Boolean
(
input
.
authToken
)
:
current
.
authTokenConfigured
,
apiKeyConfigured
:
Boolean
(
input
.
apiKey
)
||
current
.
apiKeyConfigured
,
defaultModel
:
input
.
defaultModel
,
gatewayTokenConfigured
:
Boolean
(
input
.
gatewayToken
)
||
current
.
gatewayTokenConfigured
,
workspacePath
:
input
.
workspacePath
,
authTokenConfigured
:
typeof
input
.
authToken
===
"string"
?
Boolean
(
input
.
authToken
)
:
current
.
authTokenConfigured
,
gatewayUrl
:
normalizeGatewayUrl
(
input
.
gatewayUrl
),
defaultModel
:
input
.
defaultModel
,
cloudApiBaseUrl
:
normalizeCloudApiBaseUrl
(
input
.
cloudApiBaseUrl
),
workspacePath
:
input
.
workspacePath
,
runtimeCloudApiBaseUrl
:
resolveRuntimeCloudApiBaseUrl
(
input
.
runtimeCloudApiBaseUrl
),
gatewayUrl
:
normalizeGatewayUrl
(
input
.
gatewayUrl
),
runtimeMode
:
normalizeRuntimeMode
(
input
.
runtimeMode
)
cloudApiBaseUrl
:
normalizeCloudApiBaseUrl
(
input
.
cloudApiBaseUrl
),
};
runtimeCloudApiBaseUrl
:
resolveRuntimeCloudApiBaseUrl
(
input
.
runtimeCloudApiBaseUrl
),
runtimeMode
:
normalizeRuntimeMode
(
input
.
runtimeMode
)
};
await
this
.
writeConfig
(
config
);
return
config
;
});
}
const
filePath
=
this
.
getConfigPath
();
getDataPath
(...
segments
:
string
[]):
string
{
await
mkdir
(
path
.
dirname
(
filePath
),
{
recursive
:
true
});
return
path
.
join
(
this
.
userDataPath
,
...
segments
);
await
writeFile
(
filePath
,
JSON
.
stringify
(
config
,
null
,
2
),
"utf8"
);
return
config
;
}
}
private
getConfigPath
():
string
{
private
getConfigPath
():
string
{
...
@@ -141,6 +139,7 @@ export class AppConfigService {
...
@@ -141,6 +139,7 @@ export class AppConfigService {
private
createDefaultConfig
():
AppConfig
{
private
createDefaultConfig
():
AppConfig
{
return
{
return
{
setupMode
:
"employee-key"
,
provider
:
"openai"
,
provider
:
"openai"
,
baseUrl
:
"https://api.openai.com/v1"
,
baseUrl
:
"https://api.openai.com/v1"
,
apiKeyConfigured
:
false
,
apiKeyConfigured
:
false
,
...
@@ -157,6 +156,7 @@ export class AppConfigService {
...
@@ -157,6 +156,7 @@ export class AppConfigService {
private
normalizeConfig
(
config
:
LegacyConfig
):
AppConfig
{
private
normalizeConfig
(
config
:
LegacyConfig
):
AppConfig
{
return
{
return
{
setupMode
:
normalizeSetupMode
(
config
.
setupMode
),
provider
:
config
.
provider
??
"openai"
,
provider
:
config
.
provider
??
"openai"
,
baseUrl
:
config
.
baseUrl
??
"https://api.openai.com/v1"
,
baseUrl
:
config
.
baseUrl
??
"https://api.openai.com/v1"
,
apiKeyConfigured
:
Boolean
(
config
.
apiKeyConfigured
),
apiKeyConfigured
:
Boolean
(
config
.
apiKeyConfigured
),
...
@@ -170,4 +170,53 @@ export class AppConfigService {
...
@@ -170,4 +170,53 @@ export class AppConfigService {
runtimeMode: normalizeRuntimeMode(config.runtimeMode ?? process.env.QJCLAW_RUNTIME_MODE)
runtimeMode: normalizeRuntimeMode(config.runtimeMode ?? process.env.QJCLAW_RUNTIME_MODE)
};
};
}
}
private async runExclusive<T>(operation: () => Promise<T>): Promise<T> {
const next = this.ioChain.then(operation, operation);
this.ioChain = next.then(() => undefined, () => undefined);
return next;
}
private async loadUnlocked(): Promise<AppConfig> {
const filePath = this.getConfigPath();
await mkdir(path.dirname(filePath), { recursive: true });
try {
const raw = await readFile(filePath, "utf8");
const parsed = JSON.parse(raw) as LegacyConfig;
const config = this.normalizeConfig(parsed);
await this.writeConfig(config);
return config;
} catch (error) {
if (!this.shouldResetToDefaults(error)) {
throw error;
}
const defaults = this.createDefaultConfig();
await this.writeConfig(defaults);
return defaults;
}
}
private shouldResetToDefaults(error: unknown): boolean {
if (!error || typeof error !== "object") {
return false;
}
const candidate = error as NodeJS.ErrnoException;
if (candidate.code === "ENOENT") {
return true;
}
return error instanceof SyntaxError;
}
private async writeConfig(config: AppConfig): Promise<void> {
const filePath = this.getConfigPath();
const tempPath = `
$
{
filePath
}.
tmp
`;
await mkdir(path.dirname(filePath), { recursive: true });
await writeFile(tempPath, JSON.stringify(config, null, 2), "utf8");
await rm(filePath, { force: true });
await rename(tempPath, filePath);
}
}
}
apps/desktop/src/main/services/cloud-api.ts
View file @
a4d243ae
This diff is collapsed.
Click to expand it.
apps/desktop/src/preload/index.ts
View file @
a4d243ae
import
{
contextBridge
,
ipcRenderer
}
from
"electron"
;
import
{
contextBridge
,
ipcRenderer
}
from
"electron"
;
import
{
import
{
IPC_CHANNELS
,
IPC_CHANNELS
,
type
ChatStreamListener
,
type
ChatStreamListener
,
...
@@ -10,7 +10,8 @@ import {
...
@@ -10,7 +10,8 @@ import {
const
desktopApi
:
DesktopApi
=
{
const
desktopApi
:
DesktopApi
=
{
workspace
:
{
workspace
:
{
getSummary
:
()
=>
ipcRenderer
.
invoke
(
IPC_CHANNELS
.
workspaceGetSummary
)
getSummary
:
()
=>
ipcRenderer
.
invoke
(
IPC_CHANNELS
.
workspaceGetSummary
),
warmup
:
()
=>
ipcRenderer
.
invoke
(
IPC_CHANNELS
.
workspaceWarmup
)
},
},
gateway
:
{
gateway
:
{
status
:
()
=>
ipcRenderer
.
invoke
(
IPC_CHANNELS
.
gatewayStatus
),
status
:
()
=>
ipcRenderer
.
invoke
(
IPC_CHANNELS
.
gatewayStatus
),
...
@@ -83,4 +84,4 @@ const desktopApi: DesktopApi = {
...
@@ -83,4 +84,4 @@ const desktopApi: DesktopApi = {
const
smokeEnabled
=
process
.
argv
.
includes
(
"--qjc-smoke"
);
const
smokeEnabled
=
process
.
argv
.
includes
(
"--qjc-smoke"
);
contextBridge
.
exposeInMainWorld
(
"qjcDesktop"
,
desktopApi
);
contextBridge
.
exposeInMainWorld
(
"qjcDesktop"
,
desktopApi
);
contextBridge
.
exposeInMainWorld
(
"qjcSmokeEnabled"
,
smokeEnabled
);
contextBridge
.
exposeInMainWorld
(
"qjcSmokeEnabled"
,
smokeEnabled
);
\ No newline at end of file
docs/startup-prewarm-plan.zh-CN.md
0 → 100644
View file @
a4d243ae
# 启动页预热方案(适配当前代码)
## 背景
当前代码已经把一部分冷启动前移到了主进程,但聊天页仍然会在服务未 ready 时提前打开,并通过发送区禁发来暴露启动过程。用户感知上会变成“聊天窗口已经打开,但发送按钮是灰的,还要等待准备环境”。
这次方案的目标是把初始化完整收拢到启动页,聊天页只在
`chatReady === true`
后进入;同时对云配置增加“缓存优先 + 后台增量同步”,缩短二次启动时间。
## 当前代码问题定位
-
主进程已经有预热链路:
`apps/desktop/src/main/index.ts`
-
启动时会拉取员工配置、启动 bundled runtime、连接 gateway。
-
状态聚合已经存在:
`apps/desktop/src/main/ipc.ts`
-
`WorkspaceSummary`
已包含
`chatReady`
、
`chatLaunchState`
、
`startupPhase`
、
`startupMessage`
。
-
问题主要出在渲染层:
`apps/ui/src/App.tsx`
-
聊天页在未 ready 时提前进入。
-
发送按钮和提示文案绑定到运行时 ready 状态,导致界面像“卡住”。
## 本次适配
### 1. 主进程预热保留,但改成缓存优先
-
在
`OpenClawConfigClient`
中加入运行时云配置缓存。
-
缓存内容包含:
-
上次成功的员工配置 payload
-
配置摘要
-
当前员工密钥指纹
-
启动时优先尝试读取缓存:
-
如果缓存命中且密钥未变,bundled runtime 直接基于缓存配置启动。
-
启动完成后再后台执行一次云端刷新。
-
如果缓存不存在或密钥变更:
-
仍按原始链路阻塞拉取
`fetchConfig("init")`
。
### 2. 缓存失效策略
-
当用户更换或清空员工密钥时,立即清理旧缓存。
-
缓存只在密钥指纹一致时复用,避免把上一位员工的配置拿来启动。
### 3. 启动页成为聊天入口
-
聊天视图新增启动页门禁:
-
服务未 ready 时,只展示启动页,不渲染聊天消息区和发送区。
-
服务 ready 后,自动进入聊天页。
-
启动页展示:
-
主状态文案
-
进度条
-
四段步骤:读取本地配置、准备本地助手、连接聊天服务、进入对话
-
失败时保留“重新准备”和“打开设置”入口
### 4. 聊天页恢复正常可发状态
-
聊天页不再把发送按钮绑定到启动期状态。
-
进入聊天页后:
-
发送按钮只受“已绑定、输入非空、未发送中、未保存中”控制。
-
`ensureChatAvailable()`
保留,但只用于异常恢复:
-
理论上不再承担首开冷启动主路径。
### 5. 现有优化继续保留
-
只展示
`user`
/
`assistant`
主消息。
-
保留可折叠“思考过程”面板。
-
保留
`completed`
无
`delta`
的兜底显示逻辑。
## 涉及文件
-
`apps/desktop/src/main/index.ts`
-
`apps/desktop/src/main/ipc.ts`
-
`apps/desktop/src/main/services/cloud-api.ts`
-
`apps/desktop/src/main/services/app-config.ts`
-
`apps/ui/src/App.tsx`
-
`apps/ui/src/styles.css`
## 验收标准
-
已绑定情况下,打开应用先看到启动页,而不是灰按钮聊天页。
-
二次启动且缓存可用时,启动页等待明显短于首次启动。
-
启动完成后进入聊天页,发送按钮默认可用。
-
更换员工密钥后,不复用旧员工缓存。
-
runtime 或 gateway 异常掉线时,仍能通过恢复逻辑重新可用。
## 测试建议
1.
首次启动,无缓存
-
应显示启动页并完成完整预热。
2.
再次启动,有缓存
-
应明显更快进入聊天页。
3.
更换员工密钥
-
旧缓存应失效,不应沿用旧员工配置。
4.
断网启动
-
有缓存时可继续进入;无缓存时停留在启动失败页。
5.
聊天页回归
-
进入聊天页后首条消息不应再承担完整冷启动链路。
packages/shared-types/src/index.ts
View file @
a4d243ae
export
const
IPC_CHANNELS
=
{
export
const
IPC_CHANNELS
=
{
workspaceGetSummary
:
"workspace:get-summary"
,
workspaceGetSummary
:
"workspace:get-summary"
,
workspaceWarmup
:
"workspace:warmup"
,
gatewayStatus
:
"gateway:status"
,
gatewayStatus
:
"gateway:status"
,
gatewayConnect
:
"gateway:connect"
,
gatewayConnect
:
"gateway:connect"
,
gatewayDisconnect
:
"gateway:disconnect"
,
gatewayDisconnect
:
"gateway:disconnect"
,
...
@@ -36,7 +37,7 @@
...
@@ -36,7 +37,7 @@
export
type
GatewayState
=
"unknown"
|
"connecting"
|
"connected"
|
"disconnected"
|
"error"
;
export
type
GatewayState
=
"unknown"
|
"connecting"
|
"connected"
|
"disconnected"
|
"error"
;
export
type
LogLevel
=
"info"
|
"warn"
|
"error"
;
export
type
LogLevel
=
"info"
|
"warn"
|
"error"
;
export
type
MessageRole
=
"system"
|
"user"
|
"assistant"
;
export
type
MessageRole
=
"system"
|
"user"
|
"assistant"
|
"tool"
|
"toolResult"
;
export
type
AuthSessionState
=
"authenticated"
|
"anonymous"
|
"expired"
|
"error"
;
export
type
AuthSessionState
=
"authenticated"
|
"anonymous"
|
"expired"
|
"error"
;
export
type
CreditStatus
=
"ok"
|
"low"
|
"empty"
;
export
type
CreditStatus
=
"ok"
|
"low"
|
"empty"
;
export
type
RuntimeMode
=
"external-gateway"
|
"bundled-runtime"
;
export
type
RuntimeMode
=
"external-gateway"
|
"bundled-runtime"
;
...
@@ -53,10 +54,18 @@ export type RuntimeCloudState = "unconfigured" | "loading" | "ready" | "error";
...
@@ -53,10 +54,18 @@ export type RuntimeCloudState = "unconfigured" | "loading" | "ready" | "error";
export
type
RuntimeTelemetryState
=
"idle"
|
"running"
|
"stopped"
|
"error"
;
export
type
RuntimeTelemetryState
=
"idle"
|
"running"
|
"stopped"
|
"error"
;
export
type
RuntimeCloudEventType
=
"startup"
|
"shutdown"
|
"message_sent"
|
"message_received"
|
"error"
|
"config_updated"
;
export
type
RuntimeCloudEventType
=
"startup"
|
"shutdown"
|
"message_sent"
|
"message_received"
|
"error"
|
"config_updated"
;
export
type
PluginStatus
=
"included"
|
"extension"
|
"unavailable"
;
export
type
PluginStatus
=
"included"
|
"extension"
|
"unavailable"
;
export
type
SetupMode
=
"employee-key"
|
"direct-provider"
;
export
type
ChatLaunchState
=
"unbound"
|
"starting"
|
"ready"
|
"error"
;
export
type
ChatLaunchState
=
"unbound"
|
"starting"
|
"ready"
|
"error"
;
export
type
WorkspaceStartupPhase
=
"idle"
|
"syncing-config"
|
"starting-runtime"
|
"connecting-gateway"
|
"ready"
|
"error"
;
export
type
SkillDownloadState
=
"pending"
|
"downloading"
|
"ready"
|
"failed"
|
"removed"
;
export
type
SkillDownloadState
=
"pending"
|
"downloading"
|
"ready"
|
"failed"
|
"removed"
;
export
type
DailyReportDeliveryState
=
"draft"
|
"sent"
|
"failed"
;
export
type
DailyReportDeliveryState
=
"draft"
|
"sent"
|
"failed"
;
export
interface
WorkspaceWarmupResult
{
accepted
:
boolean
;
state
:
"scheduled"
|
"skipped"
;
message
:
string
;
}
export
interface
GatewayStatus
{
export
interface
GatewayStatus
{
state
:
GatewayState
;
state
:
GatewayState
;
url
:
string
;
url
:
string
;
...
@@ -246,9 +255,13 @@ export interface PluginSummary {
...
@@ -246,9 +255,13 @@ export interface PluginSummary {
export
interface
WorkspaceSummary
{
export
interface
WorkspaceSummary
{
apiKeyConfigured
:
boolean
;
apiKeyConfigured
:
boolean
;
bindingRequired
:
boolean
;
bindingRequired
:
boolean
;
setupRequired
:
boolean
;
setupMode
:
SetupMode
;
chatReady
:
boolean
;
chatReady
:
boolean
;
chatLaunchState
:
ChatLaunchState
;
chatLaunchState
:
ChatLaunchState
;
chatStatusMessage
?:
string
;
chatStatusMessage
?:
string
;
startupPhase
:
WorkspaceStartupPhase
;
startupMessage
?:
string
;
employeeId
?:
string
;
employeeId
?:
string
;
employeeName
?:
string
;
employeeName
?:
string
;
welcomeMessage
?:
string
;
welcomeMessage
?:
string
;
...
@@ -322,6 +335,16 @@ export interface ChatStreamDeltaEvent {
...
@@ -322,6 +335,16 @@ export interface ChatStreamDeltaEvent {
fullText
?:
string
;
fullText
?:
string
;
}
}
export
interface
ChatStreamStatusEvent
{
type
:
"status"
;
requestId
:
string
;
sessionId
:
string
;
runId
?:
string
;
stage
:
string
;
label
:
string
;
detail
?:
string
;
}
export
interface
ChatStreamCompletedEvent
{
export
interface
ChatStreamCompletedEvent
{
type
:
"completed"
;
type
:
"completed"
;
requestId
:
string
;
requestId
:
string
;
...
@@ -339,7 +362,7 @@ export interface ChatStreamErrorEvent {
...
@@ -339,7 +362,7 @@ export interface ChatStreamErrorEvent {
message
:
string
;
message
:
string
;
}
}
export
type
ChatStreamEvent
=
ChatStreamStartedEvent
|
ChatStreamDeltaEvent
|
ChatStreamCompletedEvent
|
ChatStreamErrorEvent
;
export
type
ChatStreamEvent
=
ChatStreamStartedEvent
|
ChatStream
StatusEvent
|
ChatStream
DeltaEvent
|
ChatStreamCompletedEvent
|
ChatStreamErrorEvent
;
export
type
ChatStreamListener
=
(
event
:
ChatStreamEvent
)
=>
void
;
export
type
ChatStreamListener
=
(
event
:
ChatStreamEvent
)
=>
void
;
...
@@ -350,6 +373,7 @@ export interface PromptResult {
...
@@ -350,6 +373,7 @@ export interface PromptResult {
}
}
export
interface
AppConfig
{
export
interface
AppConfig
{
setupMode
:
SetupMode
;
provider
:
string
;
provider
:
string
;
baseUrl
:
string
;
baseUrl
:
string
;
apiKeyConfigured
:
boolean
;
apiKeyConfigured
:
boolean
;
...
@@ -369,6 +393,7 @@ export interface DiagnosticsExportResult {
...
@@ -369,6 +393,7 @@ export interface DiagnosticsExportResult {
}
}
export
interface
SaveConfigInput
{
export
interface
SaveConfigInput
{
setupMode
:
SetupMode
;
provider
:
string
;
provider
:
string
;
baseUrl
:
string
;
baseUrl
:
string
;
apiKey
?:
string
;
apiKey
?:
string
;
...
@@ -482,6 +507,7 @@ export interface SystemSummary {
...
@@ -482,6 +507,7 @@ export interface SystemSummary {
export
interface
DesktopApi
{
export
interface
DesktopApi
{
workspace
:
{
workspace
:
{
getSummary
():
Promise
<
WorkspaceSummary
>
;
getSummary
():
Promise
<
WorkspaceSummary
>
;
warmup
():
Promise
<
WorkspaceWarmupResult
>
;
};
};
gateway
:
{
gateway
:
{
status
():
Promise
<
GatewayStatus
>
;
status
():
Promise
<
GatewayStatus
>
;
...
@@ -545,3 +571,6 @@ export interface DesktopApi {
...
@@ -545,3 +571,6 @@ export interface DesktopApi {
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment