jishushell 0.4.10 → 0.4.17
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/INSTALL-NOTICE +10 -12
- package/dist/cli/app.d.ts +3 -0
- package/dist/cli/app.js +156 -0
- package/dist/cli/app.js.map +1 -0
- package/dist/{doctor.d.ts → cli/doctor.d.ts} +6 -1
- package/dist/{doctor.js → cli/doctor.js} +343 -14
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/helpers.d.ts +4 -0
- package/dist/cli/helpers.js +32 -0
- package/dist/cli/helpers.js.map +1 -0
- package/dist/cli/job.d.ts +3 -0
- package/dist/cli/job.js +260 -0
- package/dist/cli/job.js.map +1 -0
- package/dist/cli/llm.d.ts +24 -0
- package/dist/cli/llm.js +593 -0
- package/dist/cli/llm.js.map +1 -0
- package/dist/cli/openclaw.d.ts +12 -0
- package/dist/cli/openclaw.js +156 -0
- package/dist/cli/openclaw.js.map +1 -0
- package/dist/cli/panel.d.ts +25 -0
- package/dist/cli/panel.js +734 -0
- package/dist/cli/panel.js.map +1 -0
- package/dist/cli.js +67 -326
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +11 -4
- package/dist/config.js.map +1 -1
- package/dist/control.d.ts +13 -41
- package/dist/control.js +12 -1355
- package/dist/control.js.map +1 -1
- package/dist/routes/apps.d.ts +3 -0
- package/dist/routes/apps.js +99 -0
- package/dist/routes/apps.js.map +1 -0
- package/dist/routes/instances.js +12 -6
- package/dist/routes/instances.js.map +1 -1
- package/dist/routes/llm.d.ts +15 -0
- package/dist/routes/llm.js +246 -0
- package/dist/routes/llm.js.map +1 -0
- package/dist/routes/setup.js +29 -2
- package/dist/routes/setup.js.map +1 -1
- package/dist/routes/system.js +31 -6
- package/dist/routes/system.js.map +1 -1
- package/dist/server.js +40 -4
- package/dist/server.js.map +1 -1
- package/dist/services/app-compiler.d.ts +15 -0
- package/dist/services/app-compiler.js +169 -0
- package/dist/services/app-compiler.js.map +1 -0
- package/dist/services/app-manager.d.ts +17 -0
- package/dist/services/app-manager.js +168 -0
- package/dist/services/app-manager.js.map +1 -0
- package/dist/services/instance-manager.d.ts +51 -3
- package/dist/services/instance-manager.js +233 -30
- package/dist/services/instance-manager.js.map +1 -1
- package/dist/services/job-manager.d.ts +22 -0
- package/dist/services/job-manager.js +102 -0
- package/dist/services/job-manager.js.map +1 -0
- package/dist/services/llm-proxy/adapters.js +5 -1
- package/dist/services/llm-proxy/adapters.js.map +1 -1
- package/dist/services/llm-proxy/index.d.ts +30 -0
- package/dist/services/llm-proxy/index.js +71 -1
- package/dist/services/llm-proxy/index.js.map +1 -1
- package/dist/services/llm-proxy/ssrf.js +1 -1
- package/dist/services/llm-proxy/ssrf.js.map +1 -1
- package/dist/services/nomad-manager.js +192 -29
- package/dist/services/nomad-manager.js.map +1 -1
- package/dist/services/panel-manager.d.ts +40 -0
- package/dist/services/panel-manager.js +346 -0
- package/dist/services/panel-manager.js.map +1 -0
- package/dist/services/process-manager.js +20 -7
- package/dist/services/process-manager.js.map +1 -1
- package/dist/services/setup-manager.js +316 -31
- package/dist/services/setup-manager.js.map +1 -1
- package/dist/services/update-manager.d.ts +47 -0
- package/dist/services/update-manager.js +305 -0
- package/dist/services/update-manager.js.map +1 -0
- package/dist/types.d.ts +62 -0
- package/install/jishu-install.sh +279 -37
- package/install/post-install.sh +64 -5
- package/package.json +6 -2
- package/public/assets/Dashboard-CQsp1Mr9.js +1 -0
- package/public/assets/InitPassword-BEC8SE4A.js +1 -0
- package/public/assets/InstanceDetail-B5wTgNEg.js +17 -0
- package/public/assets/{Login-CUoEZOWR.js → Login-D1Bt-Lyk.js} +1 -1
- package/public/assets/NewInstance-GQzm3K9D.js +1 -0
- package/public/assets/Settings-ByjGlqhP.js +1 -0
- package/public/assets/Setup-cMF21Y-8.js +1 -0
- package/public/assets/index-B6qQP4mH.css +1 -0
- package/public/assets/index-BuTQtuNy.js +16 -0
- package/public/assets/{providers-lBSOjUWy.js → providers-V-vwrExZ.js} +1 -1
- package/public/index.html +2 -2
- package/dist/doctor.js.map +0 -1
- package/install/jishu-install-china.sh +0 -3092
- package/public/assets/Dashboard-DhsrzJ4F.js +0 -1
- package/public/assets/InitPassword-BjubiVdd.js +0 -1
- package/public/assets/InstanceDetail-DMcywsof.js +0 -17
- package/public/assets/NewInstance-Bk0G4EiJ.js +0 -1
- package/public/assets/Settings-D5tHL_h5.js +0 -1
- package/public/assets/Setup-4t6E3Rut.js +0 -1
- package/public/assets/index-BJ47MWpF.css +0 -1
- package/public/assets/index-DbX85irc.js +0 -16
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
export function parseCpuToMHz(cpu) {
|
|
2
|
+
if (!cpu)
|
|
3
|
+
return 500;
|
|
4
|
+
if (cpu.endsWith("m")) {
|
|
5
|
+
const n = parseInt(cpu.slice(0, -1), 10);
|
|
6
|
+
if (isNaN(n))
|
|
7
|
+
throw new Error(`Invalid CPU format: ${cpu}`);
|
|
8
|
+
return n;
|
|
9
|
+
}
|
|
10
|
+
const n = parseFloat(cpu);
|
|
11
|
+
if (isNaN(n))
|
|
12
|
+
throw new Error(`Invalid CPU format: ${cpu}`);
|
|
13
|
+
return Math.round(n * 1000);
|
|
14
|
+
}
|
|
15
|
+
export function parseMemoryToMB(memory) {
|
|
16
|
+
if (!memory)
|
|
17
|
+
return 512;
|
|
18
|
+
if (memory.endsWith("Gi")) {
|
|
19
|
+
const n = parseInt(memory.slice(0, -2), 10);
|
|
20
|
+
if (isNaN(n))
|
|
21
|
+
throw new Error(`Invalid memory format: ${memory}`);
|
|
22
|
+
return n * 1024;
|
|
23
|
+
}
|
|
24
|
+
if (memory.endsWith("Mi")) {
|
|
25
|
+
const n = parseInt(memory.slice(0, -2), 10);
|
|
26
|
+
if (isNaN(n))
|
|
27
|
+
throw new Error(`Invalid memory format: ${memory}`);
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
if (memory.endsWith("G")) {
|
|
31
|
+
const n = parseInt(memory.slice(0, -1), 10);
|
|
32
|
+
if (isNaN(n))
|
|
33
|
+
throw new Error(`Invalid memory format: ${memory}`);
|
|
34
|
+
return n * 1024;
|
|
35
|
+
}
|
|
36
|
+
if (memory.endsWith("M")) {
|
|
37
|
+
const n = parseInt(memory.slice(0, -1), 10);
|
|
38
|
+
if (isNaN(n))
|
|
39
|
+
throw new Error(`Invalid memory format: ${memory}`);
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
const n = parseInt(memory, 10);
|
|
43
|
+
if (isNaN(n))
|
|
44
|
+
throw new Error(`Invalid memory format: ${memory}`);
|
|
45
|
+
return n;
|
|
46
|
+
}
|
|
47
|
+
/** Parse interval strings like "10s", "1m" into nanoseconds (Nomad unit) */
|
|
48
|
+
function parseIntervalNs(s) {
|
|
49
|
+
if (!s)
|
|
50
|
+
return 10_000_000_000; // 10s default
|
|
51
|
+
if (s.endsWith("ms"))
|
|
52
|
+
return parseInt(s) * 1_000_000;
|
|
53
|
+
if (s.endsWith("s"))
|
|
54
|
+
return parseInt(s) * 1_000_000_000;
|
|
55
|
+
if (s.endsWith("m"))
|
|
56
|
+
return parseInt(s) * 60_000_000_000;
|
|
57
|
+
return parseInt(s) * 1_000_000_000;
|
|
58
|
+
}
|
|
59
|
+
/** Compile AppTask ports → Nomad network port mappings */
|
|
60
|
+
export function compilePorts(ports) {
|
|
61
|
+
if (!ports || ports.length === 0)
|
|
62
|
+
return [];
|
|
63
|
+
return ports.map((p) => ({
|
|
64
|
+
Label: p.name,
|
|
65
|
+
Value: p.port,
|
|
66
|
+
To: p.port,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
/** Compile AppTask health → Nomad service check */
|
|
70
|
+
export function compileHealthCheck(health, taskName) {
|
|
71
|
+
if (!health)
|
|
72
|
+
return null;
|
|
73
|
+
if (health.http) {
|
|
74
|
+
return {
|
|
75
|
+
Name: `${taskName || "service"}-health`,
|
|
76
|
+
Type: "http",
|
|
77
|
+
Path: health.http.path,
|
|
78
|
+
PortLabel: String(health.http.port),
|
|
79
|
+
Interval: parseIntervalNs(health.interval || "10s"),
|
|
80
|
+
Timeout: parseIntervalNs(health.timeout || "2s"),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/** Map AppTask role → Nomad lifecycle hook */
|
|
86
|
+
export function compileLifecycle(role) {
|
|
87
|
+
switch (role) {
|
|
88
|
+
case "init":
|
|
89
|
+
return { Hook: "prestart", Sidecar: false };
|
|
90
|
+
case "sidecar":
|
|
91
|
+
return { Hook: "prestart", Sidecar: true };
|
|
92
|
+
case "cleanup":
|
|
93
|
+
return { Hook: "poststop", Sidecar: false };
|
|
94
|
+
default: // "service" — main task, no lifecycle hook
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function compileTaskRuntime(task, instanceId) {
|
|
99
|
+
return {
|
|
100
|
+
command: task.command || "/usr/bin/openclaw",
|
|
101
|
+
args: task.args || [],
|
|
102
|
+
cwd: "/",
|
|
103
|
+
user: "root",
|
|
104
|
+
env_files: [],
|
|
105
|
+
env: task.env || {},
|
|
106
|
+
image: task.image || null,
|
|
107
|
+
resources: {
|
|
108
|
+
CPU: parseCpuToMHz(task.resources?.cpu),
|
|
109
|
+
MemoryMB: parseMemoryToMB(task.resources?.memory),
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Compile a full AppSpec into a Nomad-compatible task group structure.
|
|
115
|
+
* Returns an array of Nomad task objects (to be placed inside TaskGroups[0].Tasks).
|
|
116
|
+
*/
|
|
117
|
+
export function compileAppToNomadTasks(spec, instanceId) {
|
|
118
|
+
const tasks = [];
|
|
119
|
+
// Sort tasks by role precedence: init → sidecar → service → cleanup
|
|
120
|
+
const roleOrder = { init: 0, sidecar: 1, service: 2, cleanup: 3 };
|
|
121
|
+
const sorted = [...spec.tasks].sort((a, b) => (roleOrder[a.role] ?? 2) - (roleOrder[b.role] ?? 2));
|
|
122
|
+
for (const task of sorted) {
|
|
123
|
+
const compiled = {
|
|
124
|
+
Name: task.name,
|
|
125
|
+
Driver: task.runtime === "container" ? "docker" : "raw_exec",
|
|
126
|
+
Config: {},
|
|
127
|
+
Env: { ...task.env },
|
|
128
|
+
Resources: {
|
|
129
|
+
CPU: parseCpuToMHz(task.resources?.cpu),
|
|
130
|
+
MemoryMB: parseMemoryToMB(task.resources?.memory),
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
// Driver-specific config
|
|
134
|
+
if (task.runtime === "container") {
|
|
135
|
+
compiled.Config.image = task.image;
|
|
136
|
+
if (task.command)
|
|
137
|
+
compiled.Config.command = task.command;
|
|
138
|
+
if (task.args?.length)
|
|
139
|
+
compiled.Config.args = task.args;
|
|
140
|
+
// Port mappings for Docker
|
|
141
|
+
const ports = compilePorts(task.ports);
|
|
142
|
+
if (ports.length > 0) {
|
|
143
|
+
compiled.Config.ports = ports.map((p) => p.Label);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// raw_exec (process runtime)
|
|
148
|
+
compiled.Config.command = task.command || "/usr/bin/openclaw";
|
|
149
|
+
if (task.args?.length)
|
|
150
|
+
compiled.Config.args = task.args;
|
|
151
|
+
}
|
|
152
|
+
// Lifecycle for non-service tasks
|
|
153
|
+
const lifecycle = compileLifecycle(task.role);
|
|
154
|
+
if (lifecycle)
|
|
155
|
+
compiled.Lifecycle = lifecycle;
|
|
156
|
+
// Health check → Nomad service block
|
|
157
|
+
const check = compileHealthCheck(task.health, task.name);
|
|
158
|
+
if (check) {
|
|
159
|
+
compiled.Services = [{
|
|
160
|
+
Name: `${instanceId}-${task.name}`,
|
|
161
|
+
PortLabel: check.PortLabel,
|
|
162
|
+
Checks: [check],
|
|
163
|
+
}];
|
|
164
|
+
}
|
|
165
|
+
tasks.push(compiled);
|
|
166
|
+
}
|
|
167
|
+
return tasks;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=app-compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-compiler.js","sourceRoot":"","sources":["../../src/services/app-compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AppManifest, AppSpec } from "../types.js";
|
|
2
|
+
export declare function installApp(specYaml: string): Promise<{
|
|
3
|
+
spec: AppSpec;
|
|
4
|
+
manifest: AppManifest;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function listApps(): Array<{
|
|
7
|
+
spec: AppSpec;
|
|
8
|
+
manifest: AppManifest;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function getApp(id: string): {
|
|
11
|
+
spec: AppSpec;
|
|
12
|
+
manifest: AppManifest;
|
|
13
|
+
} | null;
|
|
14
|
+
export declare function uninstallApp(id: string): void;
|
|
15
|
+
export declare function registerCapabilities(instanceId: string, spec: AppSpec, port: number): void;
|
|
16
|
+
export declare function unregisterCapabilities(instanceId: string): void;
|
|
17
|
+
export declare function resolveRequires(spec: AppSpec): Record<string, string>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { parse } from "yaml";
|
|
5
|
+
import { APPS_DIR } from "../config.js";
|
|
6
|
+
import { ensureDirHost } from "../utils/fs.js";
|
|
7
|
+
import { safeReadJson, safeWriteJson } from "../utils/safe-json.js";
|
|
8
|
+
const DOCKER_IMAGE_RE = /^[a-zA-Z0-9][a-zA-Z0-9\-_.:/@]*$/;
|
|
9
|
+
const APP_ID_RE = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
10
|
+
const REGISTRY_PATH = join(APPS_DIR, "capability-registry.json");
|
|
11
|
+
function readRegistry() {
|
|
12
|
+
const reg = safeReadJson(REGISTRY_PATH, "capability-registry");
|
|
13
|
+
return reg ?? { capabilities: {} };
|
|
14
|
+
}
|
|
15
|
+
function writeRegistry(reg) {
|
|
16
|
+
ensureDirHost(APPS_DIR);
|
|
17
|
+
safeWriteJson(REGISTRY_PATH, reg, true);
|
|
18
|
+
}
|
|
19
|
+
export async function installApp(specYaml) {
|
|
20
|
+
let spec;
|
|
21
|
+
try {
|
|
22
|
+
spec = parse(specYaml);
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
throw new Error(`YAML 解析失败: ${e.message}`);
|
|
26
|
+
}
|
|
27
|
+
if (!spec || !spec.id || !APP_ID_RE.test(spec.id)) {
|
|
28
|
+
throw new Error(`App id '${spec?.id}' 格式无效,必须符合 /^[a-z0-9][a-z0-9-]{0,62}$/`);
|
|
29
|
+
}
|
|
30
|
+
if (!Array.isArray(spec.tasks) || spec.tasks.length === 0) {
|
|
31
|
+
throw new Error("tasks 不能为空");
|
|
32
|
+
}
|
|
33
|
+
const hasService = spec.tasks.some((t) => t.role === "service");
|
|
34
|
+
if (!hasService) {
|
|
35
|
+
throw new Error("tasks 中至少需要一个 role 为 'service' 的任务");
|
|
36
|
+
}
|
|
37
|
+
for (const task of spec.tasks) {
|
|
38
|
+
if (task.runtime === "vm") {
|
|
39
|
+
throw new Error(`runtime 'vm' 暂不支持,请使用 runtime: container 或 process`);
|
|
40
|
+
}
|
|
41
|
+
if (task.runtime === "container" && !task.image) {
|
|
42
|
+
throw new Error(`container task '${task.name}' 需要指定 image 字段`);
|
|
43
|
+
}
|
|
44
|
+
if (task.runtime === "process" && !task.command) {
|
|
45
|
+
throw new Error(`process task '${task.name}' 需要指定 command 字段`);
|
|
46
|
+
}
|
|
47
|
+
if (task.image && !DOCKER_IMAGE_RE.test(task.image)) {
|
|
48
|
+
throw new Error(`task '${task.name}' 的 image '${task.image}' 格式无效`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const appDir = join(APPS_DIR, spec.id);
|
|
52
|
+
const manifestPath = join(appDir, "manifest.json");
|
|
53
|
+
if (existsSync(manifestPath)) {
|
|
54
|
+
const err = new Error(`App '${spec.id}' 已安装,如需更新请先卸载`);
|
|
55
|
+
err.code = 409;
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
ensureDirHost(appDir);
|
|
59
|
+
const yamlPath = join(appDir, "app-spec.yaml");
|
|
60
|
+
const yamlTmp = yamlPath + ".tmp";
|
|
61
|
+
writeFileSync(yamlTmp, specYaml, { mode: 0o644 });
|
|
62
|
+
renameSync(yamlTmp, yamlPath);
|
|
63
|
+
const manifest = {
|
|
64
|
+
id: spec.id,
|
|
65
|
+
installed_at: new Date().toISOString(),
|
|
66
|
+
spec_hash: createHash("sha256").update(specYaml).digest("hex"),
|
|
67
|
+
};
|
|
68
|
+
safeWriteJson(manifestPath, manifest, true);
|
|
69
|
+
return { spec, manifest };
|
|
70
|
+
}
|
|
71
|
+
export function listApps() {
|
|
72
|
+
if (!existsSync(APPS_DIR))
|
|
73
|
+
return [];
|
|
74
|
+
let entries;
|
|
75
|
+
try {
|
|
76
|
+
entries = readdirSync(APPS_DIR, { withFileTypes: true });
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
const results = [];
|
|
82
|
+
for (const entry of entries) {
|
|
83
|
+
if (!entry.isDirectory())
|
|
84
|
+
continue;
|
|
85
|
+
const appId = entry.name;
|
|
86
|
+
const appDir = join(APPS_DIR, appId);
|
|
87
|
+
try {
|
|
88
|
+
const yamlPath = join(appDir, "app-spec.yaml");
|
|
89
|
+
const manifestPath = join(appDir, "manifest.json");
|
|
90
|
+
if (!existsSync(yamlPath) || !existsSync(manifestPath))
|
|
91
|
+
continue;
|
|
92
|
+
const spec = parse(readFileSync(yamlPath, "utf-8"));
|
|
93
|
+
const manifest = safeReadJson(manifestPath, `app:${appId}`);
|
|
94
|
+
if (!manifest)
|
|
95
|
+
continue;
|
|
96
|
+
results.push({ spec, manifest });
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.warn(`[app-manager] Skipping app '${appId}': ${e.message}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return results;
|
|
103
|
+
}
|
|
104
|
+
export function getApp(id) {
|
|
105
|
+
if (!APP_ID_RE.test(id))
|
|
106
|
+
return null;
|
|
107
|
+
const appDir = join(APPS_DIR, id);
|
|
108
|
+
const yamlPath = join(appDir, "app-spec.yaml");
|
|
109
|
+
const manifestPath = join(appDir, "manifest.json");
|
|
110
|
+
if (!existsSync(yamlPath) || !existsSync(manifestPath))
|
|
111
|
+
return null;
|
|
112
|
+
try {
|
|
113
|
+
const spec = parse(readFileSync(yamlPath, "utf-8"));
|
|
114
|
+
const manifest = safeReadJson(manifestPath, `app:${id}`);
|
|
115
|
+
if (!manifest)
|
|
116
|
+
return null;
|
|
117
|
+
return { spec, manifest };
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function uninstallApp(id) {
|
|
124
|
+
if (!APP_ID_RE.test(id))
|
|
125
|
+
return;
|
|
126
|
+
rmSync(join(APPS_DIR, id), { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
export function registerCapabilities(instanceId, spec, port) {
|
|
129
|
+
if (!spec.provides || spec.provides.length === 0)
|
|
130
|
+
return;
|
|
131
|
+
const reg = readRegistry();
|
|
132
|
+
const now = new Date().toISOString();
|
|
133
|
+
for (const provide of spec.provides) {
|
|
134
|
+
reg.capabilities[provide.capability] = {
|
|
135
|
+
instanceId,
|
|
136
|
+
hostPort: port,
|
|
137
|
+
address: `127.0.0.1:${port}`,
|
|
138
|
+
registered_at: now,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
writeRegistry(reg);
|
|
142
|
+
}
|
|
143
|
+
export function unregisterCapabilities(instanceId) {
|
|
144
|
+
const reg = readRegistry();
|
|
145
|
+
for (const key of Object.keys(reg.capabilities)) {
|
|
146
|
+
if (reg.capabilities[key].instanceId === instanceId) {
|
|
147
|
+
delete reg.capabilities[key];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
writeRegistry(reg);
|
|
151
|
+
}
|
|
152
|
+
export function resolveRequires(spec) {
|
|
153
|
+
if (!spec.requires || spec.requires.length === 0)
|
|
154
|
+
return {};
|
|
155
|
+
const reg = readRegistry();
|
|
156
|
+
const result = {};
|
|
157
|
+
for (const req of spec.requires) {
|
|
158
|
+
const entry = reg.capabilities[req.capability];
|
|
159
|
+
if (entry) {
|
|
160
|
+
result[req.inject_as] = entry.address;
|
|
161
|
+
}
|
|
162
|
+
else if (req.required !== false) {
|
|
163
|
+
throw new Error(`Required capability '${req.capability}' is not registered`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=app-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-manager.js","sourceRoot":"","sources":["../../src/services/app-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,30 @@
|
|
|
1
|
+
import type { AppSpec } from "../types.js";
|
|
1
2
|
type ConfigChangeListener = (instanceId: string) => void;
|
|
2
3
|
export declare function onConfigChange(listener: ConfigChangeListener): () => void;
|
|
3
4
|
declare function instanceDir(instanceId: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Probes whether a port is currently held by any process on the host.
|
|
7
|
+
*
|
|
8
|
+
* Binds `0.0.0.0:port` — under the Linux default socket semantics, this fails
|
|
9
|
+
* with EADDRINUSE whenever another listener holds the port on `0.0.0.0`, on
|
|
10
|
+
* any specific interface (e.g. `127.0.0.1`), or via Docker's published port
|
|
11
|
+
* map. An IPv6-only listener on `::1` is not detected, but that edge case
|
|
12
|
+
* never comes up in the Nomad+Docker path this project uses.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isPortInUse(port: number): Promise<boolean>;
|
|
15
|
+
/**
|
|
16
|
+
* Result of {@link allocateGatewayPort}.
|
|
17
|
+
*
|
|
18
|
+
* `skipped` is the ordered list of ports we walked past because they were
|
|
19
|
+
* already configured on another instance, already pending for a concurrent
|
|
20
|
+
* allocation, or held by a real listener on the host. When non-empty it
|
|
21
|
+
* means the default port was taken and the caller can surface a toast to
|
|
22
|
+
* the user explaining the shift.
|
|
23
|
+
*/
|
|
24
|
+
export type GatewayPortAllocation = {
|
|
25
|
+
port: number;
|
|
26
|
+
skipped: number[];
|
|
27
|
+
};
|
|
4
28
|
export declare function getResolvedOpenclawBin(): string;
|
|
5
29
|
/**
|
|
6
30
|
* When jishushell runs as root (e.g. systemd service), returns the actual
|
|
@@ -40,17 +64,17 @@ export declare function isChannelPluginInstalled(instanceId: string, channelId:
|
|
|
40
64
|
export declare function installChannelPlugin(instanceId: string, channelId: string): Promise<void>;
|
|
41
65
|
export declare function listInstances(): Record<string, any>[];
|
|
42
66
|
export declare function getInstance(instanceId: string): Record<string, any> | null;
|
|
43
|
-
export declare function createInstance(instanceId: string, name: string, description?: string, cloneFrom?: string, openclawHome?: string, cloneOptions?: {
|
|
67
|
+
export declare function createInstance(instanceId: string, name: string, description?: string, cloneFrom?: string, openclawHome?: string, appSpec?: AppSpec, cloneOptions?: {
|
|
44
68
|
include_sessions?: boolean;
|
|
45
69
|
include_memory?: boolean;
|
|
46
70
|
}): Promise<Record<string, any>>;
|
|
47
71
|
export declare function updateInstance(instanceId: string, name?: string, description?: string): Record<string, any> | null;
|
|
48
72
|
/** Update instance.json metadata fields (shallow merge at top level). */
|
|
49
73
|
export declare function updateInstanceMeta(instanceId: string, patch: Record<string, any>): void;
|
|
50
|
-
export declare function deleteInstance(instanceId: string, purgeBackups?: boolean): {
|
|
74
|
+
export declare function deleteInstance(instanceId: string, purgeBackups?: boolean): Promise<{
|
|
51
75
|
ok: boolean;
|
|
52
76
|
warnings?: string[];
|
|
53
|
-
}
|
|
77
|
+
}>;
|
|
54
78
|
export declare function getConfig(instanceId: string): Record<string, any> | null;
|
|
55
79
|
export declare function getStoredConfig(instanceId: string): Record<string, any> | null;
|
|
56
80
|
export declare function saveConfig(instanceId: string, config: Record<string, any>): boolean;
|
|
@@ -81,7 +105,31 @@ export declare function getInstanceRuntime(instanceId: string): Record<string, a
|
|
|
81
105
|
export declare function getRuntimeEnvFiles(instanceId: string): string[];
|
|
82
106
|
export declare function getGatewayPort(instanceId: string): number;
|
|
83
107
|
export declare function getGatewayHost(instanceId: string): Promise<string>;
|
|
108
|
+
/**
|
|
109
|
+
* Wrap an IPv6 literal in brackets for safe URL host-component / Host-header
|
|
110
|
+
* use. Bare names ("gateway.local") and IPv4 ("127.0.0.1") contain no colon
|
|
111
|
+
* and pass through unchanged; anything with a colon is an IPv6 literal and
|
|
112
|
+
* MUST be bracketed before being concatenated with a port, otherwise
|
|
113
|
+
* `http://::1:18789/` is unparseable.
|
|
114
|
+
*/
|
|
115
|
+
export declare function urlHost(host: string): string;
|
|
84
116
|
export declare function findInstancesSharingOpenclawHome(instanceId: string): string[];
|
|
117
|
+
/**
|
|
118
|
+
* Re-pick a gateway port for an existing instance and rewrite its persisted
|
|
119
|
+
* runtime metadata (`runtime.args` and `runtime.env.OPENCLAW_GATEWAY_PORT`).
|
|
120
|
+
*
|
|
121
|
+
* Used when {@link isPortInUse} reports that the previously-assigned port has
|
|
122
|
+
* been taken by something else between create-time and start-time (e.g. a
|
|
123
|
+
* host-side openclaw started by the user, an unrelated service that grabbed
|
|
124
|
+
* the port at boot, or a Docker race on the next allocation). The Nomad job
|
|
125
|
+
* spec is rebuilt from instance metadata on every submit, so updating
|
|
126
|
+
* `instance.json` here is sufficient — no other files need patching.
|
|
127
|
+
*/
|
|
128
|
+
export declare function reallocateGatewayPort(instanceId: string): Promise<{
|
|
129
|
+
from: number;
|
|
130
|
+
to: number;
|
|
131
|
+
skipped: number[];
|
|
132
|
+
}>;
|
|
85
133
|
export declare function findInstancesSharingGatewayPort(instanceId: string): string[];
|
|
86
134
|
export declare function getRuntimeEnv(instanceId: string): Record<string, string>;
|
|
87
135
|
export { instanceDir as getInstanceDir };
|