@agent-webui/ai-desk-daemon 1.0.24 → 1.0.29-beta1
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 +3 -1
- package/bin/cli.js +1 -2
- package/lib/daemon-manager.js +1 -2
- package/lib/harness-manager.js +178 -0
- package/lib/platform.js +71 -3
- package/lib/runtime-manager.js +320 -0
- package/lib/workspace-packages.js +172 -0
- package/package.json +18 -6
- package/scripts/postinstall.js +18 -4
- package/dist/darwin-arm64/ai-desk-daemon +0 -0
- package/dist/darwin-x64/ai-desk-daemon +0 -0
- package/dist/linux-arm64/ai-desk-daemon +0 -0
- package/dist/linux-x64/ai-desk-daemon +0 -0
- package/dist/win32-x64/ai-desk-daemon.exe +0 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
# 全局安装
|
|
27
|
-
npm install -g agent-webui/ai-desk
|
|
27
|
+
npm install -g @agent-webui/ai-desk
|
|
28
28
|
|
|
29
29
|
# 启动 daemon
|
|
30
30
|
aidesk start
|
|
@@ -36,6 +36,8 @@ aidesk status
|
|
|
36
36
|
**包含内容**:
|
|
37
37
|
- ✅ AI Desk Daemon 后台服务
|
|
38
38
|
- ✅ CLI 命令行管理工具
|
|
39
|
+
- ✅ 默认 harness 运行时与安装脚本
|
|
40
|
+
- ✅ 按平台分发的内置 Python runtime
|
|
39
41
|
- ✅ HTTP API (http://localhost:9527)
|
|
40
42
|
|
|
41
43
|
**不包含**:
|
package/bin/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ const { getLogPath } = require('../lib/platform');
|
|
|
12
12
|
const { VERSION } = require('../lib/platform');
|
|
13
13
|
|
|
14
14
|
program
|
|
15
|
-
.name('
|
|
15
|
+
.name('aidesk')
|
|
16
16
|
.description('AI Desk Daemon - CLI tool for managing the AI Desk daemon service')
|
|
17
17
|
.version(VERSION);
|
|
18
18
|
|
|
@@ -228,4 +228,3 @@ program.parse(process.argv);
|
|
|
228
228
|
if (!process.argv.slice(2).length) {
|
|
229
229
|
program.outputHelp();
|
|
230
230
|
}
|
|
231
|
-
|
package/lib/daemon-manager.js
CHANGED
|
@@ -80,7 +80,7 @@ function start() {
|
|
|
80
80
|
throw new Error(
|
|
81
81
|
`Daemon binary not found at: ${binaryPath}\n` +
|
|
82
82
|
`This might be a corrupted installation. Try reinstalling:\n` +
|
|
83
|
-
` npm install -g @
|
|
83
|
+
` npm install -g @agent-webui/ai-desk --force`
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -186,4 +186,3 @@ module.exports = {
|
|
|
186
186
|
restart,
|
|
187
187
|
status
|
|
188
188
|
};
|
|
189
|
-
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { ensureRuntime, readJSON, run, syncHarnessConfig, writeJSON } = require('./runtime-manager');
|
|
4
|
+
|
|
5
|
+
function listDependencyNames(packageRoot) {
|
|
6
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
7
|
+
const packageJson = readJSON(packageJsonPath);
|
|
8
|
+
|
|
9
|
+
const allDeps = {
|
|
10
|
+
...(packageJson.dependencies || {}),
|
|
11
|
+
...(packageJson.optionalDependencies || {}),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return Object.keys(allDeps).filter((name) => name.startsWith('@agent-webui/ai-desk-harness-'));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function findWorkspaceSiblingPackage(packageRoot, packageName) {
|
|
18
|
+
const packagesRoot = path.resolve(packageRoot, '..');
|
|
19
|
+
if (!fs.existsSync(packagesRoot)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const children = fs.readdirSync(packagesRoot, { withFileTypes: true });
|
|
24
|
+
for (const child of children) {
|
|
25
|
+
if (!child.isDirectory()) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const packageJsonPath = path.join(packagesRoot, child.name, 'package.json');
|
|
30
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const pkg = readJSON(packageJsonPath);
|
|
35
|
+
if (pkg.name === packageName) {
|
|
36
|
+
return path.dirname(packageJsonPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolveHarnessPackageDir(packageRoot, packageName) {
|
|
44
|
+
try {
|
|
45
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
|
46
|
+
paths: [packageRoot],
|
|
47
|
+
});
|
|
48
|
+
return path.dirname(packageJsonPath);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
const workspaceMatch = findWorkspaceSiblingPackage(packageRoot, packageName);
|
|
51
|
+
if (workspaceMatch) {
|
|
52
|
+
return workspaceMatch;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Failed to resolve harness package ${packageName} from ${packageRoot}: ${error.message}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveHarnesses(packageRoot) {
|
|
59
|
+
const harnessNames = listDependencyNames(packageRoot);
|
|
60
|
+
|
|
61
|
+
return harnessNames.map((packageName) => {
|
|
62
|
+
const packageDir = resolveHarnessPackageDir(packageRoot, packageName);
|
|
63
|
+
const packageJson = readJSON(path.join(packageDir, 'package.json'));
|
|
64
|
+
const manifestPath = path.join(packageDir, 'manifest.json');
|
|
65
|
+
const manifest = readJSON(manifestPath);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
packageDir,
|
|
69
|
+
packageJson,
|
|
70
|
+
packageName,
|
|
71
|
+
manifest,
|
|
72
|
+
manifestPath,
|
|
73
|
+
sourcePath: path.resolve(packageDir, manifest.source_path),
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function resolveCommandPath(binDir, command) {
|
|
79
|
+
const candidates = process.platform === 'win32'
|
|
80
|
+
? [
|
|
81
|
+
path.join(binDir, `${command}.exe`),
|
|
82
|
+
path.join(binDir, `${command}.cmd`),
|
|
83
|
+
path.join(binDir, `${command}.bat`),
|
|
84
|
+
path.join(binDir, command),
|
|
85
|
+
]
|
|
86
|
+
: [path.join(binDir, command)];
|
|
87
|
+
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
if (fs.existsSync(candidate)) {
|
|
90
|
+
return candidate;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return candidates[0];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function installHarnessPackage(runtimeInfo, harness) {
|
|
98
|
+
if (!fs.existsSync(harness.sourcePath)) {
|
|
99
|
+
throw new Error(`Harness source not found: ${harness.sourcePath}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const installResult = run(runtimeInfo.pythonPath, ['-m', 'pip', 'install', '--upgrade', harness.sourcePath]);
|
|
103
|
+
if (installResult.status !== 0) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
installResult.stderr ||
|
|
106
|
+
installResult.stdout ||
|
|
107
|
+
`Failed to install harness ${harness.packageName} from ${harness.sourcePath}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
for (const requirement of harness.manifest.python_requirements || []) {
|
|
112
|
+
const requirementResult = run(runtimeInfo.pythonPath, ['-m', 'pip', 'install', '--upgrade', requirement]);
|
|
113
|
+
if (requirementResult.status !== 0) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
requirementResult.stderr ||
|
|
116
|
+
requirementResult.stdout ||
|
|
117
|
+
`Failed to install Python requirement ${requirement} for ${harness.packageName}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
name: harness.manifest.name,
|
|
124
|
+
displayName: harness.manifest.display_name || harness.manifest.name,
|
|
125
|
+
module: harness.manifest.module,
|
|
126
|
+
commands: harness.manifest.commands || [],
|
|
127
|
+
capabilities: harness.manifest.capabilities || [],
|
|
128
|
+
commandPath: resolveCommandPath(runtimeInfo.binDir, (harness.manifest.commands || [])[0] || ''),
|
|
129
|
+
commandPaths: Object.fromEntries(
|
|
130
|
+
(harness.manifest.commands || []).map((command) => [command, resolveCommandPath(runtimeInfo.binDir, command)])
|
|
131
|
+
),
|
|
132
|
+
packageName: harness.packageName,
|
|
133
|
+
packageVersion: harness.packageJson.version || '',
|
|
134
|
+
version: harness.manifest.version || harness.packageJson.version || '',
|
|
135
|
+
sourcePath: harness.sourcePath,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function writeHarnessRegistry(runtimeInfo, harnesses) {
|
|
140
|
+
const registry = {
|
|
141
|
+
version: 1,
|
|
142
|
+
generated_at: new Date().toISOString(),
|
|
143
|
+
runtime: {
|
|
144
|
+
python_path: runtimeInfo.pythonPath,
|
|
145
|
+
venv_path: runtimeInfo.venvDir,
|
|
146
|
+
registry_path: runtimeInfo.registryPath,
|
|
147
|
+
source: runtimeInfo.source || '',
|
|
148
|
+
runtime_home: runtimeInfo.runtimeHomeDir || '',
|
|
149
|
+
package_name: runtimeInfo.packageName || '',
|
|
150
|
+
package_version: runtimeInfo.packageVersion || '',
|
|
151
|
+
archive_sha256: runtimeInfo.archiveSHA256 || '',
|
|
152
|
+
},
|
|
153
|
+
harnesses,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
writeJSON(runtimeInfo.registryPath, registry);
|
|
157
|
+
syncHarnessConfig(runtimeInfo, harnesses);
|
|
158
|
+
return registry;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function installHarnessesForPackageRoot(packageRoot) {
|
|
162
|
+
const runtimeInfo = ensureRuntime();
|
|
163
|
+
const harnessPackages = resolveHarnesses(packageRoot);
|
|
164
|
+
const installedHarnesses = harnessPackages.map((harness) => installHarnessPackage(runtimeInfo, harness));
|
|
165
|
+
const registry = writeHarnessRegistry(runtimeInfo, installedHarnesses);
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
harnessCount: installedHarnesses.length,
|
|
169
|
+
harnesses: installedHarnesses,
|
|
170
|
+
registry,
|
|
171
|
+
runtimeInfo,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
module.exports = {
|
|
176
|
+
installHarnessesForPackageRoot,
|
|
177
|
+
resolveHarnesses,
|
|
178
|
+
};
|
package/lib/platform.js
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
const os = require('os');
|
|
6
6
|
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { getBinaryPackageByPlatformKey, resolveInstalledPackageDir } = require('./workspace-packages');
|
|
7
9
|
|
|
8
|
-
const VERSION = '
|
|
10
|
+
const VERSION = require('../package.json').version;
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
* Detect current platform and architecture
|
|
@@ -39,9 +41,19 @@ function detectPlatform() {
|
|
|
39
41
|
*/
|
|
40
42
|
function getDaemonBinaryPath() {
|
|
41
43
|
const { platform, platformKey } = detectPlatform();
|
|
44
|
+
const binaryPackage = getBinaryPackageByPlatformKey(platformKey);
|
|
42
45
|
|
|
43
|
-
// Binary is in the npm package under dist/<platform>/
|
|
44
46
|
const binaryName = platform === 'win32' ? 'ai-desk-daemon.exe' : 'ai-desk-daemon';
|
|
47
|
+
if (binaryPackage) {
|
|
48
|
+
const packageDir = resolveInstalledPackageDir(binaryPackage.packageName);
|
|
49
|
+
if (packageDir) {
|
|
50
|
+
const packageBinaryPath = path.join(packageDir, 'bin', binaryName);
|
|
51
|
+
if (fs.existsSync(packageBinaryPath)) {
|
|
52
|
+
return packageBinaryPath;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
const binaryPath = path.join(__dirname, '..', 'dist', platformKey, binaryName);
|
|
46
58
|
|
|
47
59
|
return binaryPath;
|
|
@@ -54,6 +66,54 @@ function getConfigDir() {
|
|
|
54
66
|
return path.join(os.homedir(), '.aidesktop');
|
|
55
67
|
}
|
|
56
68
|
|
|
69
|
+
function getRuntimeDir() {
|
|
70
|
+
return path.join(getConfigDir(), 'runtime');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getManagedPythonDir() {
|
|
74
|
+
return path.join(getRuntimeDir(), 'python');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getManagedPythonBinDir() {
|
|
78
|
+
if (process.platform === 'win32') {
|
|
79
|
+
return getManagedPythonDir();
|
|
80
|
+
}
|
|
81
|
+
return path.join(getManagedPythonDir(), 'bin');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getManagedPythonPath() {
|
|
85
|
+
if (process.platform === 'win32') {
|
|
86
|
+
return path.join(getManagedPythonDir(), 'python.exe');
|
|
87
|
+
}
|
|
88
|
+
return path.join(getManagedPythonBinDir(), 'python3');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function getManagedPythonMetadataPath() {
|
|
92
|
+
return path.join(getManagedPythonDir(), '.ai-desk-runtime.json');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getRuntimeVenvDir() {
|
|
96
|
+
return path.join(getRuntimeDir(), 'venv');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function getRuntimeBinDir() {
|
|
100
|
+
if (process.platform === 'win32') {
|
|
101
|
+
return path.join(getRuntimeVenvDir(), 'Scripts');
|
|
102
|
+
}
|
|
103
|
+
return path.join(getRuntimeVenvDir(), 'bin');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getRuntimePythonPath() {
|
|
107
|
+
if (process.platform === 'win32') {
|
|
108
|
+
return path.join(getRuntimeBinDir(), 'python.exe');
|
|
109
|
+
}
|
|
110
|
+
return path.join(getRuntimeBinDir(), 'python3');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getHarnessRegistryPath() {
|
|
114
|
+
return path.join(getRuntimeDir(), 'installed-harnesses.json');
|
|
115
|
+
}
|
|
116
|
+
|
|
57
117
|
/**
|
|
58
118
|
* Get config file path
|
|
59
119
|
*/
|
|
@@ -79,9 +139,17 @@ module.exports = {
|
|
|
79
139
|
detectPlatform,
|
|
80
140
|
getDaemonBinaryPath,
|
|
81
141
|
getConfigDir,
|
|
142
|
+
getRuntimeDir,
|
|
143
|
+
getManagedPythonDir,
|
|
144
|
+
getManagedPythonBinDir,
|
|
145
|
+
getManagedPythonPath,
|
|
146
|
+
getManagedPythonMetadataPath,
|
|
147
|
+
getRuntimeVenvDir,
|
|
148
|
+
getRuntimeBinDir,
|
|
149
|
+
getRuntimePythonPath,
|
|
150
|
+
getHarnessRegistryPath,
|
|
82
151
|
getConfigPath,
|
|
83
152
|
getLogPath,
|
|
84
153
|
getPidPath,
|
|
85
154
|
VERSION
|
|
86
155
|
};
|
|
87
|
-
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { spawnSync } = require('child_process');
|
|
4
|
+
const {
|
|
5
|
+
getConfigDir,
|
|
6
|
+
getConfigPath,
|
|
7
|
+
getHarnessRegistryPath,
|
|
8
|
+
getManagedPythonBinDir,
|
|
9
|
+
getManagedPythonDir,
|
|
10
|
+
getManagedPythonMetadataPath,
|
|
11
|
+
getManagedPythonPath,
|
|
12
|
+
getRuntimeBinDir,
|
|
13
|
+
getRuntimeDir,
|
|
14
|
+
getRuntimePythonPath,
|
|
15
|
+
getRuntimeVenvDir,
|
|
16
|
+
detectPlatform,
|
|
17
|
+
} = require('./platform');
|
|
18
|
+
const {
|
|
19
|
+
getPythonRuntimePackageByPlatformKey,
|
|
20
|
+
resolveInstalledPackageDir,
|
|
21
|
+
} = require('./workspace-packages');
|
|
22
|
+
|
|
23
|
+
function readJSON(filePath) {
|
|
24
|
+
if (!fs.existsSync(filePath)) {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
30
|
+
} catch (error) {
|
|
31
|
+
throw new Error(`Failed to parse JSON at ${filePath}: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function writeJSON(filePath, value) {
|
|
36
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
37
|
+
fs.writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n', 'utf8');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function run(command, args, options = {}) {
|
|
41
|
+
const result = spawnSync(command, args, {
|
|
42
|
+
encoding: 'utf8',
|
|
43
|
+
stdio: 'pipe',
|
|
44
|
+
...options,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (result.error) {
|
|
48
|
+
throw result.error;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function findSystemPython() {
|
|
55
|
+
const candidates = [];
|
|
56
|
+
|
|
57
|
+
if (process.env.AI_DESK_PYTHON) {
|
|
58
|
+
candidates.push({ command: process.env.AI_DESK_PYTHON, args: [] });
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
candidates.push({ command: 'python3', args: [] });
|
|
62
|
+
candidates.push({ command: 'python', args: [] });
|
|
63
|
+
|
|
64
|
+
if (process.platform === 'win32') {
|
|
65
|
+
candidates.push({ command: 'py', args: ['-3'] });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
for (const candidate of candidates) {
|
|
69
|
+
try {
|
|
70
|
+
const result = run(candidate.command, [...candidate.args, '--version']);
|
|
71
|
+
if (result.status === 0) {
|
|
72
|
+
return candidate;
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
// Try next candidate.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw new Error('No usable Python interpreter found. Set AI_DESK_PYTHON to override.');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function ensureRuntimeDirectories() {
|
|
83
|
+
fs.mkdirSync(getConfigDir(), { recursive: true });
|
|
84
|
+
fs.mkdirSync(path.join(getConfigDir(), 'logs'), { recursive: true });
|
|
85
|
+
fs.mkdirSync(getRuntimeDir(), { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getBundledPythonRuntime() {
|
|
89
|
+
const { platformKey } = detectPlatform();
|
|
90
|
+
const runtimePackage = getPythonRuntimePackageByPlatformKey(platformKey);
|
|
91
|
+
if (!runtimePackage) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const packageDir = resolveInstalledPackageDir(runtimePackage.packageName, [path.join(__dirname, '..')]);
|
|
96
|
+
if (!packageDir) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const packageJson = readJSON(path.join(packageDir, 'package.json'));
|
|
101
|
+
const sourceRuntimeDir = path.join(packageDir, 'python');
|
|
102
|
+
const sourcePythonPath = path.join(packageDir, runtimePackage.pythonRelativePath);
|
|
103
|
+
const sourceBinDir = path.join(packageDir, runtimePackage.binDirRelativePath);
|
|
104
|
+
|
|
105
|
+
if (!fs.existsSync(sourceRuntimeDir) || !fs.existsSync(sourcePythonPath)) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
packageDir,
|
|
111
|
+
packageName: runtimePackage.packageName,
|
|
112
|
+
packageVersion: packageJson.version || '',
|
|
113
|
+
archiveName: runtimePackage.archiveName,
|
|
114
|
+
archiveSHA256: runtimePackage.sha256 || '',
|
|
115
|
+
sourceRuntimeDir,
|
|
116
|
+
sourcePythonPath,
|
|
117
|
+
sourceBinDir,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function copyDirectoryRecursive(sourceDir, targetDir) {
|
|
122
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
123
|
+
|
|
124
|
+
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
125
|
+
const sourcePath = path.join(sourceDir, entry.name);
|
|
126
|
+
const targetPath = path.join(targetDir, entry.name);
|
|
127
|
+
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
copyDirectoryRecursive(sourcePath, targetPath);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (entry.isSymbolicLink()) {
|
|
134
|
+
const linkTarget = fs.readlinkSync(sourcePath);
|
|
135
|
+
try {
|
|
136
|
+
fs.unlinkSync(targetPath);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error.code !== 'ENOENT') {
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
fs.symlinkSync(linkTarget, targetPath);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
147
|
+
try {
|
|
148
|
+
fs.chmodSync(targetPath, fs.statSync(sourcePath).mode);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
// Ignore chmod failures on platforms that do not preserve permissions.
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function packagedRuntimeLooksHealthy(pythonPath) {
|
|
156
|
+
if (!fs.existsSync(pythonPath)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
const result = run(pythonPath, ['-c', 'import sys; print(sys.executable)']);
|
|
162
|
+
return result.status === 0;
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function ensurePackagedRuntime(bundledRuntime) {
|
|
169
|
+
const targetRuntimeDir = getManagedPythonDir();
|
|
170
|
+
const metadataPath = getManagedPythonMetadataPath();
|
|
171
|
+
const expectedMetadata = {
|
|
172
|
+
package_name: bundledRuntime.packageName,
|
|
173
|
+
package_version: bundledRuntime.packageVersion,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const existingMetadata = readJSON(metadataPath);
|
|
177
|
+
const targetPythonPath = getManagedPythonPath();
|
|
178
|
+
const targetBinDir = getManagedPythonBinDir();
|
|
179
|
+
|
|
180
|
+
const metadataMatches =
|
|
181
|
+
existingMetadata.package_name === expectedMetadata.package_name &&
|
|
182
|
+
existingMetadata.package_version === expectedMetadata.package_version;
|
|
183
|
+
|
|
184
|
+
if (!metadataMatches || !packagedRuntimeLooksHealthy(targetPythonPath)) {
|
|
185
|
+
fs.rmSync(targetRuntimeDir, { recursive: true, force: true });
|
|
186
|
+
copyDirectoryRecursive(bundledRuntime.sourceRuntimeDir, targetRuntimeDir);
|
|
187
|
+
writeJSON(metadataPath, expectedMetadata);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
pythonPath: targetPythonPath,
|
|
192
|
+
binDir: targetBinDir,
|
|
193
|
+
runtimeHomeDir: targetRuntimeDir,
|
|
194
|
+
packageName: bundledRuntime.packageName,
|
|
195
|
+
packageVersion: bundledRuntime.packageVersion,
|
|
196
|
+
archiveSHA256: bundledRuntime.archiveSHA256,
|
|
197
|
+
source: 'packaged',
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function resolveRuntimePythonPath() {
|
|
202
|
+
const pythonPath = getRuntimePythonPath();
|
|
203
|
+
if (fs.existsSync(pythonPath)) {
|
|
204
|
+
return pythonPath;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const fallback = process.platform === 'win32'
|
|
208
|
+
? path.join(getRuntimeBinDir(), 'python.exe')
|
|
209
|
+
: path.join(getRuntimeBinDir(), 'python');
|
|
210
|
+
|
|
211
|
+
return fallback;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function venvLooksHealthy(pythonPath) {
|
|
215
|
+
if (!fs.existsSync(pythonPath)) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
const result = run(pythonPath, ['-c', 'import sys; print(sys.executable)']);
|
|
221
|
+
return result.status === 0;
|
|
222
|
+
} catch (error) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function ensureRuntime() {
|
|
228
|
+
ensureRuntimeDirectories();
|
|
229
|
+
|
|
230
|
+
const bundledRuntime = getBundledPythonRuntime();
|
|
231
|
+
if (bundledRuntime) {
|
|
232
|
+
const packagedRuntime = ensurePackagedRuntime(bundledRuntime);
|
|
233
|
+
const pipBootstrap = run(packagedRuntime.pythonPath, ['-m', 'pip', 'install', '--upgrade', 'pip', 'setuptools', 'wheel']);
|
|
234
|
+
if (pipBootstrap.status !== 0) {
|
|
235
|
+
throw new Error(pipBootstrap.stderr || pipBootstrap.stdout || 'Failed to bootstrap packaged Python runtime');
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
configPath: getConfigPath(),
|
|
240
|
+
pythonPath: packagedRuntime.pythonPath,
|
|
241
|
+
registryPath: getHarnessRegistryPath(),
|
|
242
|
+
runtimeDir: getRuntimeDir(),
|
|
243
|
+
runtimeHomeDir: packagedRuntime.runtimeHomeDir,
|
|
244
|
+
venvDir: '',
|
|
245
|
+
binDir: packagedRuntime.binDir,
|
|
246
|
+
packageName: packagedRuntime.packageName,
|
|
247
|
+
packageVersion: packagedRuntime.packageVersion,
|
|
248
|
+
archiveSHA256: packagedRuntime.archiveSHA256,
|
|
249
|
+
source: packagedRuntime.source,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const venvDir = getRuntimeVenvDir();
|
|
254
|
+
let pythonPath = resolveRuntimePythonPath();
|
|
255
|
+
|
|
256
|
+
if (!venvLooksHealthy(pythonPath)) {
|
|
257
|
+
const basePython = findSystemPython();
|
|
258
|
+
const createResult = run(basePython.command, [...basePython.args, '-m', 'venv', venvDir]);
|
|
259
|
+
if (createResult.status !== 0) {
|
|
260
|
+
throw new Error(createResult.stderr || createResult.stdout || 'Failed to create Python virtual environment');
|
|
261
|
+
}
|
|
262
|
+
pythonPath = resolveRuntimePythonPath();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const pipBootstrap = run(pythonPath, ['-m', 'pip', 'install', '--upgrade', 'pip', 'setuptools', 'wheel']);
|
|
266
|
+
if (pipBootstrap.status !== 0) {
|
|
267
|
+
throw new Error(pipBootstrap.stderr || pipBootstrap.stdout || 'Failed to bootstrap pip tooling');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return {
|
|
271
|
+
configPath: getConfigPath(),
|
|
272
|
+
pythonPath,
|
|
273
|
+
registryPath: getHarnessRegistryPath(),
|
|
274
|
+
runtimeDir: getRuntimeDir(),
|
|
275
|
+
runtimeHomeDir: venvDir,
|
|
276
|
+
venvDir,
|
|
277
|
+
binDir: getRuntimeBinDir(),
|
|
278
|
+
packageName: '',
|
|
279
|
+
packageVersion: '',
|
|
280
|
+
archiveSHA256: '',
|
|
281
|
+
source: 'system-venv',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function syncHarnessConfig(runtimeInfo, harnesses = []) {
|
|
286
|
+
const configPath = runtimeInfo.configPath || getConfigPath();
|
|
287
|
+
const config = readJSON(configPath);
|
|
288
|
+
|
|
289
|
+
config.harness_runtime = {
|
|
290
|
+
python_path: runtimeInfo.pythonPath,
|
|
291
|
+
venv_path: runtimeInfo.venvDir || '',
|
|
292
|
+
registry_path: runtimeInfo.registryPath,
|
|
293
|
+
source: runtimeInfo.source || '',
|
|
294
|
+
runtime_home: runtimeInfo.runtimeHomeDir || '',
|
|
295
|
+
package_name: runtimeInfo.packageName || '',
|
|
296
|
+
package_version: runtimeInfo.packageVersion || '',
|
|
297
|
+
archive_sha256: runtimeInfo.archiveSHA256 || '',
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
config.harnesses = {};
|
|
301
|
+
for (const harness of harnesses) {
|
|
302
|
+
config.harnesses[harness.name] = {
|
|
303
|
+
command: harness.commandPath || '',
|
|
304
|
+
module: harness.module,
|
|
305
|
+
package: harness.packageName,
|
|
306
|
+
version: harness.version,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
writeJSON(configPath, config);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
module.exports = {
|
|
314
|
+
ensureRuntime,
|
|
315
|
+
getBundledPythonRuntime,
|
|
316
|
+
readJSON,
|
|
317
|
+
run,
|
|
318
|
+
syncHarnessConfig,
|
|
319
|
+
writeJSON,
|
|
320
|
+
};
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
const DAEMON_BINARY_PACKAGES = [
|
|
2
|
+
{
|
|
3
|
+
dirName: 'ai-desk-daemon-darwin-arm64',
|
|
4
|
+
packageName: '@agent-webui/ai-desk-daemon-darwin-arm64',
|
|
5
|
+
platformKey: 'darwin-arm64',
|
|
6
|
+
os: ['darwin'],
|
|
7
|
+
cpu: ['arm64'],
|
|
8
|
+
binaryName: 'ai-desk-daemon',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
dirName: 'ai-desk-daemon-darwin-x64',
|
|
12
|
+
packageName: '@agent-webui/ai-desk-daemon-darwin-x64',
|
|
13
|
+
platformKey: 'darwin-x64',
|
|
14
|
+
os: ['darwin'],
|
|
15
|
+
cpu: ['x64'],
|
|
16
|
+
binaryName: 'ai-desk-daemon',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
dirName: 'ai-desk-daemon-linux-arm64',
|
|
20
|
+
packageName: '@agent-webui/ai-desk-daemon-linux-arm64',
|
|
21
|
+
platformKey: 'linux-arm64',
|
|
22
|
+
os: ['linux'],
|
|
23
|
+
cpu: ['arm64'],
|
|
24
|
+
binaryName: 'ai-desk-daemon',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
dirName: 'ai-desk-daemon-linux-x64',
|
|
28
|
+
packageName: '@agent-webui/ai-desk-daemon-linux-x64',
|
|
29
|
+
platformKey: 'linux-x64',
|
|
30
|
+
os: ['linux'],
|
|
31
|
+
cpu: ['x64'],
|
|
32
|
+
binaryName: 'ai-desk-daemon',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
dirName: 'ai-desk-daemon-win32-x64',
|
|
36
|
+
packageName: '@agent-webui/ai-desk-daemon-win32-x64',
|
|
37
|
+
platformKey: 'win32-x64',
|
|
38
|
+
os: ['win32'],
|
|
39
|
+
cpu: ['x64'],
|
|
40
|
+
binaryName: 'ai-desk-daemon.exe',
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const PYTHON_RUNTIME_RELEASE = '20260310';
|
|
45
|
+
const PYTHON_RUNTIME_VERSION = '3.13.12';
|
|
46
|
+
|
|
47
|
+
const PYTHON_RUNTIME_PACKAGES = [
|
|
48
|
+
{
|
|
49
|
+
dirName: 'ai-desk-python-darwin-arm64',
|
|
50
|
+
packageName: '@agent-webui/ai-desk-python-darwin-arm64',
|
|
51
|
+
platformKey: 'darwin-arm64',
|
|
52
|
+
os: ['darwin'],
|
|
53
|
+
cpu: ['arm64'],
|
|
54
|
+
archiveName: `cpython-${PYTHON_RUNTIME_VERSION}+${PYTHON_RUNTIME_RELEASE}-aarch64-apple-darwin-install_only.tar.gz`,
|
|
55
|
+
sha256: '8b49181b776a9ebc8323a645dc55126b389d62c50a0b9f072e37811a9391244d',
|
|
56
|
+
pythonRelativePath: 'python/bin/python3',
|
|
57
|
+
binDirRelativePath: 'python/bin',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
dirName: 'ai-desk-python-darwin-x64',
|
|
61
|
+
packageName: '@agent-webui/ai-desk-python-darwin-x64',
|
|
62
|
+
platformKey: 'darwin-x64',
|
|
63
|
+
os: ['darwin'],
|
|
64
|
+
cpu: ['x64'],
|
|
65
|
+
archiveName: `cpython-${PYTHON_RUNTIME_VERSION}+${PYTHON_RUNTIME_RELEASE}-x86_64-apple-darwin-install_only.tar.gz`,
|
|
66
|
+
sha256: 'd778d46b49c640a54a13dc2bd356561b4d4f85466a2d21bc0ab1483a209bb05c',
|
|
67
|
+
pythonRelativePath: 'python/bin/python3',
|
|
68
|
+
binDirRelativePath: 'python/bin',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
dirName: 'ai-desk-python-linux-arm64',
|
|
72
|
+
packageName: '@agent-webui/ai-desk-python-linux-arm64',
|
|
73
|
+
platformKey: 'linux-arm64',
|
|
74
|
+
os: ['linux'],
|
|
75
|
+
cpu: ['arm64'],
|
|
76
|
+
archiveName: `cpython-${PYTHON_RUNTIME_VERSION}+${PYTHON_RUNTIME_RELEASE}-aarch64-unknown-linux-gnu-install_only.tar.gz`,
|
|
77
|
+
sha256: '563bf262875fc0c6a22dbbb35ab7df3082184f5a587c16c534b8712e4e05c7c2',
|
|
78
|
+
pythonRelativePath: 'python/bin/python3',
|
|
79
|
+
binDirRelativePath: 'python/bin',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
dirName: 'ai-desk-python-linux-x64',
|
|
83
|
+
packageName: '@agent-webui/ai-desk-python-linux-x64',
|
|
84
|
+
platformKey: 'linux-x64',
|
|
85
|
+
os: ['linux'],
|
|
86
|
+
cpu: ['x64'],
|
|
87
|
+
archiveName: `cpython-${PYTHON_RUNTIME_VERSION}+${PYTHON_RUNTIME_RELEASE}-x86_64-unknown-linux-gnu-install_only.tar.gz`,
|
|
88
|
+
sha256: 'a1d58266fede23e795b1b7d1dee3cc77470538fd14292a46cc96e735af030fec',
|
|
89
|
+
pythonRelativePath: 'python/bin/python3',
|
|
90
|
+
binDirRelativePath: 'python/bin',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
dirName: 'ai-desk-python-win32-x64',
|
|
94
|
+
packageName: '@agent-webui/ai-desk-python-win32-x64',
|
|
95
|
+
platformKey: 'win32-x64',
|
|
96
|
+
os: ['win32'],
|
|
97
|
+
cpu: ['x64'],
|
|
98
|
+
archiveName: `cpython-${PYTHON_RUNTIME_VERSION}+${PYTHON_RUNTIME_RELEASE}-x86_64-pc-windows-msvc-install_only.tar.gz`,
|
|
99
|
+
sha256: '6204052c096536f9fa926f8312a1dcd5ac0846dc182a0c05ee0011d580546af0',
|
|
100
|
+
pythonRelativePath: 'python/python.exe',
|
|
101
|
+
binDirRelativePath: 'python',
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const DEFAULT_HARNESS_PACKAGES = ['@agent-webui/ai-desk-harness-gimp'];
|
|
106
|
+
|
|
107
|
+
function getBinaryPackageByPlatformKey(platformKey) {
|
|
108
|
+
return DAEMON_BINARY_PACKAGES.find((pkg) => pkg.platformKey === platformKey) || null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getPythonRuntimePackageByPlatformKey(platformKey) {
|
|
112
|
+
return PYTHON_RUNTIME_PACKAGES.find((pkg) => pkg.platformKey === platformKey) || null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getWorkspacePackagesRoot() {
|
|
116
|
+
return require('path').join(__dirname, '..', 'packages');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function findWorkspaceSiblingPackageDir(packageName) {
|
|
120
|
+
const fs = require('fs');
|
|
121
|
+
const path = require('path');
|
|
122
|
+
const packagesRoot = getWorkspacePackagesRoot();
|
|
123
|
+
if (!fs.existsSync(packagesRoot)) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const child of fs.readdirSync(packagesRoot, { withFileTypes: true })) {
|
|
128
|
+
if (!child.isDirectory()) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const packageJsonPath = path.join(packagesRoot, child.name, 'package.json');
|
|
133
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
139
|
+
if (pkg.name === packageName) {
|
|
140
|
+
return path.dirname(packageJsonPath);
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
// Ignore malformed workspace packages and keep searching.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function resolveInstalledPackageDir(packageName, searchPaths = []) {
|
|
151
|
+
const path = require('path');
|
|
152
|
+
const defaultPaths = [path.join(__dirname, '..'), process.cwd(), ...searchPaths];
|
|
153
|
+
try {
|
|
154
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
|
155
|
+
paths: defaultPaths,
|
|
156
|
+
});
|
|
157
|
+
return path.dirname(packageJsonPath);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
return findWorkspaceSiblingPackageDir(packageName);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports = {
|
|
164
|
+
DAEMON_BINARY_PACKAGES,
|
|
165
|
+
PYTHON_RUNTIME_RELEASE,
|
|
166
|
+
PYTHON_RUNTIME_VERSION,
|
|
167
|
+
PYTHON_RUNTIME_PACKAGES,
|
|
168
|
+
DEFAULT_HARNESS_PACKAGES,
|
|
169
|
+
getBinaryPackageByPlatformKey,
|
|
170
|
+
getPythonRuntimePackageByPlatformKey,
|
|
171
|
+
resolveInstalledPackageDir,
|
|
172
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-webui/ai-desk-daemon",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29-beta1",
|
|
4
4
|
"description": "AI Desk Daemon - CLI tool for managing the AI Desk daemon service",
|
|
5
|
+
"workspaces": [
|
|
6
|
+
"packages/*"
|
|
7
|
+
],
|
|
5
8
|
"main": "lib/daemon-manager.js",
|
|
6
9
|
"bin": {
|
|
7
10
|
"aidesk": "bin/cli.js"
|
|
8
11
|
},
|
|
9
12
|
"scripts": {
|
|
10
13
|
"postinstall": "node scripts/postinstall.js",
|
|
14
|
+
"prepare:packages": "node scripts/prepare-npm-packages.js",
|
|
15
|
+
"publish:npm:workspaces": "node scripts/publish-npm-packages.js",
|
|
11
16
|
"test": "node bin/cli.js --help"
|
|
12
17
|
},
|
|
13
18
|
"keywords": [
|
|
@@ -24,11 +29,6 @@
|
|
|
24
29
|
"files": [
|
|
25
30
|
"bin/",
|
|
26
31
|
"lib/",
|
|
27
|
-
"dist/darwin-arm64/",
|
|
28
|
-
"dist/darwin-x64/",
|
|
29
|
-
"dist/linux-arm64/",
|
|
30
|
-
"dist/linux-x64/",
|
|
31
|
-
"dist/win32-x64/",
|
|
32
32
|
"scripts/postinstall.js",
|
|
33
33
|
"README.md"
|
|
34
34
|
],
|
|
@@ -36,6 +36,18 @@
|
|
|
36
36
|
"commander": "^11.0.0",
|
|
37
37
|
"chalk": "^4.1.2"
|
|
38
38
|
},
|
|
39
|
+
"optionalDependencies": {
|
|
40
|
+
"@agent-webui/ai-desk-daemon-darwin-arm64": "1.0.29-beta1",
|
|
41
|
+
"@agent-webui/ai-desk-daemon-darwin-x64": "1.0.29-beta1",
|
|
42
|
+
"@agent-webui/ai-desk-daemon-linux-arm64": "1.0.29-beta1",
|
|
43
|
+
"@agent-webui/ai-desk-daemon-linux-x64": "1.0.29-beta1",
|
|
44
|
+
"@agent-webui/ai-desk-daemon-win32-x64": "1.0.29-beta1",
|
|
45
|
+
"@agent-webui/ai-desk-python-darwin-arm64": "1.0.29-beta1",
|
|
46
|
+
"@agent-webui/ai-desk-python-darwin-x64": "1.0.29-beta1",
|
|
47
|
+
"@agent-webui/ai-desk-python-linux-arm64": "1.0.29-beta1",
|
|
48
|
+
"@agent-webui/ai-desk-python-linux-x64": "1.0.29-beta1",
|
|
49
|
+
"@agent-webui/ai-desk-python-win32-x64": "1.0.29-beta1"
|
|
50
|
+
},
|
|
39
51
|
"repository": {
|
|
40
52
|
"type": "git",
|
|
41
53
|
"url": "git+https://github.com/agent-webui/ai-desk-daemon.git"
|
package/scripts/postinstall.js
CHANGED
|
@@ -7,10 +7,24 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const chalk = require('chalk');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { ensureRuntime } = require('../lib/runtime-manager');
|
|
12
|
+
const { installHarnessesForPackageRoot } = require('../lib/harness-manager');
|
|
10
13
|
|
|
11
14
|
console.log('');
|
|
12
|
-
console.log(chalk.green('✓ @agent-webui/ai-desk-daemon installed successfully'));
|
|
13
|
-
console.log('');
|
|
14
|
-
console.log('Run ' + chalk.cyan('aidesk --help') + ' to get started');
|
|
15
|
-
console.log('');
|
|
16
15
|
|
|
16
|
+
try {
|
|
17
|
+
const runtime = ensureRuntime();
|
|
18
|
+
const installResult = installHarnessesForPackageRoot(path.join(__dirname, '..'));
|
|
19
|
+
|
|
20
|
+
console.log(chalk.green('✓ @agent-webui/ai-desk-daemon installed successfully'));
|
|
21
|
+
console.log(chalk.cyan(`Runtime: ${runtime.pythonPath}`));
|
|
22
|
+
console.log(chalk.cyan(`Harnesses installed: ${installResult.harnessCount}`));
|
|
23
|
+
console.log('');
|
|
24
|
+
console.log('Run ' + chalk.cyan('aidesk --help') + ' to get started');
|
|
25
|
+
console.log('');
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.log(chalk.yellow('! AI Desk daemon installed with runtime warnings'));
|
|
28
|
+
console.log(chalk.yellow(error.message));
|
|
29
|
+
console.log('');
|
|
30
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|