@steerable/agent-shell 0.6.34 → 0.6.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-update-electron.d.ts +5 -0
- package/dist/app-update-electron.js +66 -0
- package/dist/app-update.d.ts +82 -0
- package/dist/app-update.js +199 -0
- package/dist/main.js +48 -2
- package/dist/product-config.d.ts +12 -0
- package/package.json +11 -8
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* electron-updater 适配。只在桌面主进程启用更新时加载。
|
|
3
|
+
*/
|
|
4
|
+
import log from 'electron-log';
|
|
5
|
+
import electronUpdater from 'electron-updater';
|
|
6
|
+
export function createElectronAppUpdater() {
|
|
7
|
+
const { autoUpdater } = electronUpdater;
|
|
8
|
+
autoUpdater.logger = log;
|
|
9
|
+
return {
|
|
10
|
+
get autoDownload() {
|
|
11
|
+
return autoUpdater.autoDownload;
|
|
12
|
+
},
|
|
13
|
+
set autoDownload(value) {
|
|
14
|
+
autoUpdater.autoDownload = value;
|
|
15
|
+
},
|
|
16
|
+
get autoInstallOnAppQuit() {
|
|
17
|
+
return autoUpdater.autoInstallOnAppQuit;
|
|
18
|
+
},
|
|
19
|
+
set autoInstallOnAppQuit(value) {
|
|
20
|
+
autoUpdater.autoInstallOnAppQuit = value;
|
|
21
|
+
},
|
|
22
|
+
get allowDowngrade() {
|
|
23
|
+
return autoUpdater.allowDowngrade;
|
|
24
|
+
},
|
|
25
|
+
set allowDowngrade(value) {
|
|
26
|
+
autoUpdater.allowDowngrade = value;
|
|
27
|
+
},
|
|
28
|
+
setFeedURL(options) {
|
|
29
|
+
autoUpdater.setFeedURL(options);
|
|
30
|
+
},
|
|
31
|
+
async checkForUpdates() {
|
|
32
|
+
const result = await autoUpdater.checkForUpdates();
|
|
33
|
+
if (!result)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
updateInfo: { version: result.updateInfo.version },
|
|
37
|
+
isUpdateAvailable: result.isUpdateAvailable,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
quitAndInstall(isSilent, isForceRunAfter) {
|
|
41
|
+
autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
|
|
42
|
+
},
|
|
43
|
+
on(event, listener) {
|
|
44
|
+
if (event === 'download-progress') {
|
|
45
|
+
autoUpdater.on('download-progress', listener);
|
|
46
|
+
}
|
|
47
|
+
else if (event === 'update-downloaded') {
|
|
48
|
+
autoUpdater.on('update-downloaded', listener);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
autoUpdater.on('error', listener);
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
off(event, listener) {
|
|
55
|
+
if (event === 'download-progress') {
|
|
56
|
+
autoUpdater.off('download-progress', listener);
|
|
57
|
+
}
|
|
58
|
+
else if (event === 'update-downloaded') {
|
|
59
|
+
autoUpdater.off('update-downloaded', listener);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
autoUpdater.off('error', listener);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 桌面自动更新。产品经 `ProductConfig.updates.feedUrl` 注入 generic 通道;
|
|
3
|
+
* 本模块只编排检查、下载和安装,具体传输交给 `AppUpdaterPort`
|
|
4
|
+
* (生产环境是 electron-updater)。
|
|
5
|
+
*/
|
|
6
|
+
export declare const APP_UPDATE_CHECK_INTERVAL_MS: number;
|
|
7
|
+
export type AppUpdatePhase = 'disabled' | 'idle' | 'checking' | 'downloading' | 'ready' | 'installing' | 'error';
|
|
8
|
+
export interface AppUpdateState {
|
|
9
|
+
phase: AppUpdatePhase;
|
|
10
|
+
version?: string;
|
|
11
|
+
percent?: number;
|
|
12
|
+
message?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AppUpdateCheckResult {
|
|
15
|
+
updateInfo: {
|
|
16
|
+
version: string;
|
|
17
|
+
};
|
|
18
|
+
isUpdateAvailable: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface AppUpdaterPort {
|
|
21
|
+
autoDownload: boolean;
|
|
22
|
+
autoInstallOnAppQuit: boolean;
|
|
23
|
+
allowDowngrade: boolean;
|
|
24
|
+
setFeedURL(options: {
|
|
25
|
+
provider: 'generic';
|
|
26
|
+
url: string;
|
|
27
|
+
}): void;
|
|
28
|
+
checkForUpdates(): Promise<AppUpdateCheckResult | null>;
|
|
29
|
+
quitAndInstall(isSilent?: boolean, isForceRunAfter?: boolean): void;
|
|
30
|
+
on(event: 'download-progress', listener: (progress: {
|
|
31
|
+
percent: number;
|
|
32
|
+
}) => void): void;
|
|
33
|
+
on(event: 'update-downloaded', listener: (info: {
|
|
34
|
+
version: string;
|
|
35
|
+
}) => void): void;
|
|
36
|
+
on(event: 'error', listener: (error: Error) => void): void;
|
|
37
|
+
off(event: 'download-progress', listener: (progress: {
|
|
38
|
+
percent: number;
|
|
39
|
+
}) => void): void;
|
|
40
|
+
off(event: 'update-downloaded', listener: (info: {
|
|
41
|
+
version: string;
|
|
42
|
+
}) => void): void;
|
|
43
|
+
off(event: 'error', listener: (error: Error) => void): void;
|
|
44
|
+
}
|
|
45
|
+
export interface AppUpdateOptions {
|
|
46
|
+
feedUrl?: string;
|
|
47
|
+
packaged: boolean;
|
|
48
|
+
currentVersion: string;
|
|
49
|
+
env: NodeJS.ProcessEnv;
|
|
50
|
+
updater: AppUpdaterPort;
|
|
51
|
+
onState?: (state: AppUpdateState) => void;
|
|
52
|
+
/** 测试注入。缺省写 `env.DEEPPATH_UPDATE_STATUS_FILE`。 */
|
|
53
|
+
statusFile?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function appUpdateMenuAction(state: AppUpdateState): 'none' | 'check' | 'install';
|
|
56
|
+
export declare function shouldNotifyUpdateReady(previous: AppUpdatePhase, next: AppUpdateState): boolean;
|
|
57
|
+
export declare class AppUpdateController {
|
|
58
|
+
private readonly options;
|
|
59
|
+
private current;
|
|
60
|
+
private enabled;
|
|
61
|
+
private started;
|
|
62
|
+
private disposed;
|
|
63
|
+
private bound;
|
|
64
|
+
private candidate;
|
|
65
|
+
private downloadedVersion;
|
|
66
|
+
private checkPromise;
|
|
67
|
+
private cancelTimer;
|
|
68
|
+
private readonly statusFile;
|
|
69
|
+
constructor(options: AppUpdateOptions);
|
|
70
|
+
get state(): AppUpdateState;
|
|
71
|
+
start(): Promise<AppUpdateState>;
|
|
72
|
+
checkNow(): Promise<AppUpdateState>;
|
|
73
|
+
installNow(): AppUpdateState;
|
|
74
|
+
dispose(): void;
|
|
75
|
+
private bind;
|
|
76
|
+
private readonly onProgress;
|
|
77
|
+
private readonly onDownloaded;
|
|
78
|
+
private readonly onError;
|
|
79
|
+
private doCheck;
|
|
80
|
+
private isNewer;
|
|
81
|
+
private publish;
|
|
82
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 桌面自动更新。产品经 `ProductConfig.updates.feedUrl` 注入 generic 通道;
|
|
3
|
+
* 本模块只编排检查、下载和安装,具体传输交给 `AppUpdaterPort`
|
|
4
|
+
* (生产环境是 electron-updater)。
|
|
5
|
+
*/
|
|
6
|
+
import { appendFileSync } from 'node:fs';
|
|
7
|
+
import { gt, valid } from 'semver';
|
|
8
|
+
export const APP_UPDATE_CHECK_INTERVAL_MS = 4 * 60 * 60 * 1000;
|
|
9
|
+
export function appUpdateMenuAction(state) {
|
|
10
|
+
if (state.phase === 'disabled')
|
|
11
|
+
return 'none';
|
|
12
|
+
if (state.phase === 'ready' || state.phase === 'installing')
|
|
13
|
+
return 'install';
|
|
14
|
+
return 'check';
|
|
15
|
+
}
|
|
16
|
+
export function shouldNotifyUpdateReady(previous, next) {
|
|
17
|
+
return previous !== 'ready' && next.phase === 'ready' && Boolean(next.version);
|
|
18
|
+
}
|
|
19
|
+
function resolveFeed(options) {
|
|
20
|
+
const override = options.env.DEEPPATH_UPDATE_FEED_URL?.trim() ?? '';
|
|
21
|
+
const feedUrl = override || options.feedUrl?.trim() || '';
|
|
22
|
+
const forceUnpackaged = options.env.DEEPPATH_APP_UPDATE === '1';
|
|
23
|
+
if (!feedUrl || (!options.packaged && !forceUnpackaged))
|
|
24
|
+
return { enabled: false };
|
|
25
|
+
return { enabled: true, feedUrl };
|
|
26
|
+
}
|
|
27
|
+
function clampPercent(percent) {
|
|
28
|
+
if (!Number.isFinite(percent))
|
|
29
|
+
return 0;
|
|
30
|
+
return Math.min(100, Math.max(0, percent));
|
|
31
|
+
}
|
|
32
|
+
function defaultSchedule(fn, ms) {
|
|
33
|
+
const timer = setInterval(fn, ms);
|
|
34
|
+
timer.unref();
|
|
35
|
+
return () => clearInterval(timer);
|
|
36
|
+
}
|
|
37
|
+
export class AppUpdateController {
|
|
38
|
+
options;
|
|
39
|
+
current = { phase: 'disabled' };
|
|
40
|
+
enabled = false;
|
|
41
|
+
started = false;
|
|
42
|
+
disposed = false;
|
|
43
|
+
bound = false;
|
|
44
|
+
candidate;
|
|
45
|
+
downloadedVersion;
|
|
46
|
+
checkPromise;
|
|
47
|
+
cancelTimer;
|
|
48
|
+
statusFile;
|
|
49
|
+
constructor(options) {
|
|
50
|
+
this.options = options;
|
|
51
|
+
this.statusFile = options.statusFile ?? options.env.DEEPPATH_UPDATE_STATUS_FILE;
|
|
52
|
+
}
|
|
53
|
+
get state() {
|
|
54
|
+
return this.current;
|
|
55
|
+
}
|
|
56
|
+
async start() {
|
|
57
|
+
if (this.started)
|
|
58
|
+
return this.checkPromise ?? this.state;
|
|
59
|
+
this.started = true;
|
|
60
|
+
const target = resolveFeed(this.options);
|
|
61
|
+
if (!target.enabled)
|
|
62
|
+
return this.publish({ phase: 'disabled' });
|
|
63
|
+
this.enabled = true;
|
|
64
|
+
this.options.updater.autoDownload = true;
|
|
65
|
+
this.options.updater.autoInstallOnAppQuit = true;
|
|
66
|
+
this.options.updater.allowDowngrade = false;
|
|
67
|
+
this.options.updater.setFeedURL({ provider: 'generic', url: target.feedUrl });
|
|
68
|
+
this.bind();
|
|
69
|
+
const first = this.checkNow();
|
|
70
|
+
this.cancelTimer = defaultSchedule(() => {
|
|
71
|
+
void this.checkNow();
|
|
72
|
+
}, APP_UPDATE_CHECK_INTERVAL_MS);
|
|
73
|
+
return first;
|
|
74
|
+
}
|
|
75
|
+
checkNow() {
|
|
76
|
+
if (this.disposed || !this.enabled)
|
|
77
|
+
return Promise.resolve(this.state);
|
|
78
|
+
if (this.state.phase === 'downloading' || this.state.phase === 'ready' || this.state.phase === 'installing') {
|
|
79
|
+
return Promise.resolve(this.state);
|
|
80
|
+
}
|
|
81
|
+
if (this.checkPromise)
|
|
82
|
+
return this.checkPromise;
|
|
83
|
+
this.checkPromise = this.doCheck().finally(() => {
|
|
84
|
+
this.checkPromise = undefined;
|
|
85
|
+
});
|
|
86
|
+
return this.checkPromise;
|
|
87
|
+
}
|
|
88
|
+
installNow() {
|
|
89
|
+
if (this.disposed || this.state.phase !== 'ready' || !this.downloadedVersion)
|
|
90
|
+
return this.state;
|
|
91
|
+
const version = this.downloadedVersion;
|
|
92
|
+
this.publish({ phase: 'installing', version });
|
|
93
|
+
try {
|
|
94
|
+
this.options.updater.quitAndInstall(false, true);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return this.publish({
|
|
98
|
+
phase: 'error',
|
|
99
|
+
version,
|
|
100
|
+
message: error instanceof Error ? error.message : String(error),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return this.state;
|
|
104
|
+
}
|
|
105
|
+
dispose() {
|
|
106
|
+
this.disposed = true;
|
|
107
|
+
this.cancelTimer?.();
|
|
108
|
+
this.cancelTimer = undefined;
|
|
109
|
+
if (!this.bound)
|
|
110
|
+
return;
|
|
111
|
+
this.options.updater.off('download-progress', this.onProgress);
|
|
112
|
+
this.options.updater.off('update-downloaded', this.onDownloaded);
|
|
113
|
+
this.options.updater.off('error', this.onError);
|
|
114
|
+
this.bound = false;
|
|
115
|
+
}
|
|
116
|
+
bind() {
|
|
117
|
+
if (this.bound)
|
|
118
|
+
return;
|
|
119
|
+
this.bound = true;
|
|
120
|
+
this.options.updater.on('download-progress', this.onProgress);
|
|
121
|
+
this.options.updater.on('update-downloaded', this.onDownloaded);
|
|
122
|
+
this.options.updater.on('error', this.onError);
|
|
123
|
+
}
|
|
124
|
+
onProgress = (progress) => {
|
|
125
|
+
if (this.downloadedVersion)
|
|
126
|
+
return;
|
|
127
|
+
this.publish({
|
|
128
|
+
phase: 'downloading',
|
|
129
|
+
...(this.candidate ? { version: this.candidate } : {}),
|
|
130
|
+
percent: clampPercent(progress.percent),
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
onDownloaded = (info) => {
|
|
134
|
+
if (!this.isNewer(info.version))
|
|
135
|
+
return;
|
|
136
|
+
this.downloadedVersion = info.version;
|
|
137
|
+
this.candidate = info.version;
|
|
138
|
+
this.publish({ phase: 'ready', version: info.version });
|
|
139
|
+
};
|
|
140
|
+
onError = (error) => {
|
|
141
|
+
const version = this.candidate ?? this.state.version;
|
|
142
|
+
this.publish({
|
|
143
|
+
phase: 'error',
|
|
144
|
+
...(version ? { version } : {}),
|
|
145
|
+
message: error instanceof Error ? error.message : String(error),
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
async doCheck() {
|
|
149
|
+
this.downloadedVersion = undefined;
|
|
150
|
+
this.candidate = undefined;
|
|
151
|
+
this.publish({ phase: 'checking' });
|
|
152
|
+
try {
|
|
153
|
+
const result = await this.options.updater.checkForUpdates();
|
|
154
|
+
if (this.disposed)
|
|
155
|
+
return this.state;
|
|
156
|
+
if (this.downloadedVersion && this.isNewer(this.downloadedVersion)) {
|
|
157
|
+
if (this.state.phase === 'ready' && this.state.version === this.downloadedVersion)
|
|
158
|
+
return this.state;
|
|
159
|
+
return this.publish({ phase: 'ready', version: this.downloadedVersion });
|
|
160
|
+
}
|
|
161
|
+
if (!result)
|
|
162
|
+
return this.publish({ phase: 'error', message: 'app update: no check result' });
|
|
163
|
+
const version = result.updateInfo.version;
|
|
164
|
+
if (!result.isUpdateAvailable)
|
|
165
|
+
return this.publish({ phase: 'idle' });
|
|
166
|
+
if (valid(version) === null) {
|
|
167
|
+
return this.publish({ phase: 'error', message: 'app update: feed version is invalid' });
|
|
168
|
+
}
|
|
169
|
+
if (!this.isNewer(version))
|
|
170
|
+
return this.publish({ phase: 'idle' });
|
|
171
|
+
this.candidate = version;
|
|
172
|
+
if (this.state.phase === 'downloading') {
|
|
173
|
+
return this.publish({ phase: 'downloading', version, percent: this.state.percent ?? 0 });
|
|
174
|
+
}
|
|
175
|
+
return this.publish({ phase: 'downloading', version, percent: 0 });
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (this.disposed)
|
|
179
|
+
return this.state;
|
|
180
|
+
return this.publish({
|
|
181
|
+
phase: 'error',
|
|
182
|
+
...(this.candidate ? { version: this.candidate } : {}),
|
|
183
|
+
message: error instanceof Error ? error.message : String(error),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
isNewer(version) {
|
|
188
|
+
return valid(version) !== null && valid(this.options.currentVersion) !== null && gt(version, this.options.currentVersion);
|
|
189
|
+
}
|
|
190
|
+
publish(state) {
|
|
191
|
+
if (this.disposed)
|
|
192
|
+
return this.current;
|
|
193
|
+
this.current = state;
|
|
194
|
+
if (this.statusFile)
|
|
195
|
+
appendFileSync(this.statusFile, `${JSON.stringify(state)}\n`);
|
|
196
|
+
this.options.onState?.(state);
|
|
197
|
+
return state;
|
|
198
|
+
}
|
|
199
|
+
}
|
package/dist/main.js
CHANGED
|
@@ -11,6 +11,8 @@ import log from 'electron-log';
|
|
|
11
11
|
import { getBrand } from './brand.js';
|
|
12
12
|
import { getPreloadPath } from './runtime.js';
|
|
13
13
|
import { getProductConfig } from './product-config.js';
|
|
14
|
+
import { AppUpdateController, appUpdateMenuAction, shouldNotifyUpdateReady, } from './app-update.js';
|
|
15
|
+
import { createElectronAppUpdater } from './app-update-electron.js';
|
|
14
16
|
import { assertHostIpcAllowed, getResolvedHostTools } from './host-tools-runtime.js';
|
|
15
17
|
import { createJsonStore } from './json-store.js';
|
|
16
18
|
import { getUserDataDir } from './runtime.js';
|
|
@@ -471,11 +473,25 @@ function createMenu() {
|
|
|
471
473
|
},
|
|
472
474
|
]
|
|
473
475
|
: []),
|
|
474
|
-
//
|
|
475
|
-
//
|
|
476
|
+
// 帮助菜单:更新动作来自自动更新状态;链接是产品注入配置
|
|
477
|
+
// (3.1,product.json links)。都没有则不渲染「帮助」。
|
|
476
478
|
...(() => {
|
|
477
479
|
const links = getProductConfig().links ?? {};
|
|
478
480
|
const submenu = [];
|
|
481
|
+
const updateAction = appUpdates ? appUpdateMenuAction(appUpdates.state) : 'none';
|
|
482
|
+
if (updateAction !== 'none') {
|
|
483
|
+
submenu.push({
|
|
484
|
+
label: updateAction === 'install' ? '重启并安装更新' : '检查更新',
|
|
485
|
+
click: () => {
|
|
486
|
+
if (!appUpdates)
|
|
487
|
+
return;
|
|
488
|
+
if (appUpdateMenuAction(appUpdates.state) === 'install')
|
|
489
|
+
appUpdates.installNow();
|
|
490
|
+
else
|
|
491
|
+
void appUpdates.checkNow();
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
}
|
|
479
495
|
if (links.releasePage) {
|
|
480
496
|
submenu.push({
|
|
481
497
|
label: '打开发布页',
|
|
@@ -817,7 +833,37 @@ function setupIpcHandlers() {
|
|
|
817
833
|
}
|
|
818
834
|
});
|
|
819
835
|
}
|
|
836
|
+
let appUpdates = null;
|
|
837
|
+
function startDesktopUpdates() {
|
|
838
|
+
let previous = 'disabled';
|
|
839
|
+
appUpdates = new AppUpdateController({
|
|
840
|
+
feedUrl: getProductConfig().updates?.feedUrl,
|
|
841
|
+
packaged: app.isPackaged,
|
|
842
|
+
currentVersion: app.getVersion(),
|
|
843
|
+
env: process.env,
|
|
844
|
+
updater: createElectronAppUpdater(),
|
|
845
|
+
onState: state => {
|
|
846
|
+
log.info('[app-update]', state.phase, state.version ?? '', state.message ?? '');
|
|
847
|
+
if (shouldNotifyUpdateReady(previous, state) && state.version) {
|
|
848
|
+
const notification = new ElectronNotification({
|
|
849
|
+
title: getBrand().displayName,
|
|
850
|
+
body: `新版本 ${state.version} 已下载,点击重启并安装`,
|
|
851
|
+
});
|
|
852
|
+
notification.on('click', () => {
|
|
853
|
+
appUpdates?.installNow();
|
|
854
|
+
});
|
|
855
|
+
notification.show();
|
|
856
|
+
}
|
|
857
|
+
const actionChanged = appUpdateMenuAction({ phase: previous }) !== appUpdateMenuAction(state);
|
|
858
|
+
previous = state.phase;
|
|
859
|
+
if (actionChanged)
|
|
860
|
+
createMenu();
|
|
861
|
+
},
|
|
862
|
+
});
|
|
863
|
+
void appUpdates.start();
|
|
864
|
+
}
|
|
820
865
|
app.whenReady().then(async () => {
|
|
866
|
+
startDesktopUpdates();
|
|
821
867
|
applyStrictCsp();
|
|
822
868
|
runtime = await createHostRuntime({
|
|
823
869
|
broadcast: (channel, payload) => broadcastTerminalEvent(channel, payload),
|
package/dist/product-config.d.ts
CHANGED
|
@@ -15,6 +15,13 @@ export interface ProductLinks {
|
|
|
15
15
|
/** 帮助菜单「访问官网」URL。 */
|
|
16
16
|
website?: string;
|
|
17
17
|
}
|
|
18
|
+
export interface ProductUpdates {
|
|
19
|
+
/**
|
|
20
|
+
* electron-updater generic 通道根地址(目录,不含 latest*.yml)。
|
|
21
|
+
* 打包配置里的 publishUrl 由产品组装根注入到这里。空则不检查更新。
|
|
22
|
+
*/
|
|
23
|
+
feedUrl?: string;
|
|
24
|
+
}
|
|
18
25
|
export interface ProductConfig {
|
|
19
26
|
/**
|
|
20
27
|
* 云端遥测端点(insights flush 的 API base)。空 = 不上报(中性默认);
|
|
@@ -23,6 +30,11 @@ export interface ProductConfig {
|
|
|
23
30
|
insightsApiBase?: string;
|
|
24
31
|
/** 帮助菜单链接;缺省的项不渲染。 */
|
|
25
32
|
links?: ProductLinks;
|
|
33
|
+
/**
|
|
34
|
+
* 桌面自动更新。缺省不检查。只在已打包的应用里生效,除非
|
|
35
|
+
* `DEEPPATH_APP_UPDATE=1`。`DEEPPATH_UPDATE_FEED_URL` 可覆盖 feedUrl。
|
|
36
|
+
*/
|
|
37
|
+
updates?: ProductUpdates;
|
|
26
38
|
/**
|
|
27
39
|
* BS 模式的 userData 目录名(~/ 下)。CS 模式由 Electron 按
|
|
28
40
|
* productName 分目录,不经此字段。
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steerable/agent-shell",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.36",
|
|
4
4
|
"description": "Steerable framework — product-neutral desktop/headless agent host (Tier 5). Electron main + preload + headless HTTP server (BS) sharing one storage/sidecar/tooling core; scenario packs extend it through the @steerable/pack-sdk contract and are composed at build time by the consuming product.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://steerableframework.com/",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/pathlyapp/
|
|
9
|
+
"url": "git+https://github.com/pathlyapp/opensteerable.git",
|
|
10
10
|
"directory": "packages/agent-shell/ts"
|
|
11
11
|
},
|
|
12
12
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/pathlyapp/
|
|
13
|
+
"url": "https://github.com/pathlyapp/opensteerable/issues"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"main": "dist/runtime.js",
|
|
@@ -51,20 +51,23 @@
|
|
|
51
51
|
"dotenv": "^17.4.2",
|
|
52
52
|
"electron-log": "^5.4.3",
|
|
53
53
|
"electron-store": "^8.1.0",
|
|
54
|
+
"electron-updater": "^6.8.9",
|
|
54
55
|
"he": "^1.2.0",
|
|
55
56
|
"node-pty": "^1.1.0",
|
|
56
|
-
"
|
|
57
|
-
"@steerable/
|
|
58
|
-
"@steerable/
|
|
57
|
+
"semver": "^7.8.0",
|
|
58
|
+
"@steerable/agent-protocol": "0.6.36",
|
|
59
|
+
"@steerable/pack-sdk": "0.6.36",
|
|
60
|
+
"@steerable/agent-harness": "0.6.36"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|
|
61
63
|
"@types/better-sqlite3": "^7.6.13",
|
|
62
64
|
"@types/he": "^1.2.3",
|
|
63
65
|
"@types/node": "^22.10.5",
|
|
66
|
+
"@types/semver": "^7.8.0",
|
|
64
67
|
"electron": "^28.3.3",
|
|
68
|
+
"esbuild": "^0.25.0",
|
|
65
69
|
"typescript": "^5.8.3",
|
|
66
|
-
"vitest": "^3.2.4"
|
|
67
|
-
"esbuild": "^0.25.0"
|
|
70
|
+
"vitest": "^3.2.4"
|
|
68
71
|
},
|
|
69
72
|
"scripts": {
|
|
70
73
|
"gen": "echo agent-shell-ts",
|