@ours.network/fleet 1.2.0-nightly.29 → 1.2.0-nightly.30
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/build-info.json +4 -4
- package/dist/cli.js +1 -1
- package/dist/web/service.d.ts +6 -2
- package/dist/web/service.js +22 -4
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.0-nightly.
|
|
3
|
-
"buildId": "
|
|
4
|
-
"commit": "
|
|
2
|
+
"version": "1.2.0-nightly.30",
|
|
3
|
+
"buildId": "a2babf441212",
|
|
4
|
+
"commit": "3cd486a81e62d5bd2c345c0d73cb443aee02dee1",
|
|
5
5
|
"dirty": true,
|
|
6
|
-
"builtAt": "2026-10-
|
|
6
|
+
"builtAt": "2026-10-01T21:40:11.246Z",
|
|
7
7
|
"capabilities": [
|
|
8
8
|
"workspace.enroll.preserve-profile-v1",
|
|
9
9
|
"cowork.http-management-v1",
|
package/dist/cli.js
CHANGED
|
@@ -1544,7 +1544,7 @@ cOpt(program.command('workspace-enroll').description('enroll this host using a p
|
|
|
1544
1544
|
const controlDeadline = Date.now() + 20000;
|
|
1545
1545
|
while (!existsSync(webControlPath())) {
|
|
1546
1546
|
if (Date.now() >= controlDeadline)
|
|
1547
|
-
throw Error('
|
|
1547
|
+
throw Error('Fleet backend did not become ready within 20 seconds. Run ours-fleet web status; on Linux inspect journalctl --user -u ours-fleet-web.service -n 25 --no-pager. Resolve the startup error before running ours-fleet link-device');
|
|
1548
1548
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
1549
1549
|
}
|
|
1550
1550
|
const link = await requestWebControl('link-device');
|
package/dist/web/service.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Exec } from '../exec.js';
|
|
2
2
|
export declare const WEB_SYSTEMD_UNIT = "ours-fleet-web.service";
|
|
3
3
|
export declare const WEB_LAUNCHD_LABEL = "network.ours.fleet.web";
|
|
4
|
+
type ServiceEnvironment = Partial<Record<'OURS_CONFIG' | 'OURS_FLEET_HOME' | 'PATH', string>>;
|
|
4
5
|
interface ServiceMetadata {
|
|
5
6
|
version: 3;
|
|
6
7
|
platform: 'linux' | 'darwin';
|
|
@@ -10,6 +11,7 @@ interface ServiceMetadata {
|
|
|
10
11
|
configuration?: string;
|
|
11
12
|
bind?: string;
|
|
12
13
|
publicOrigin?: string;
|
|
14
|
+
environment?: ServiceEnvironment;
|
|
13
15
|
}
|
|
14
16
|
export interface WebServiceOptions {
|
|
15
17
|
platform?: NodeJS.Platform;
|
|
@@ -18,6 +20,7 @@ export interface WebServiceOptions {
|
|
|
18
20
|
stateDir?: string;
|
|
19
21
|
uid?: number;
|
|
20
22
|
runtimeExecutable?: string;
|
|
23
|
+
environment?: NodeJS.ProcessEnv;
|
|
21
24
|
}
|
|
22
25
|
export declare class WebServiceManager {
|
|
23
26
|
private readonly platform;
|
|
@@ -26,6 +29,7 @@ export declare class WebServiceManager {
|
|
|
26
29
|
private readonly stateDir;
|
|
27
30
|
private readonly uid;
|
|
28
31
|
private readonly runtimeExecutable;
|
|
32
|
+
private readonly environment;
|
|
29
33
|
constructor(options?: WebServiceOptions);
|
|
30
34
|
get metadataPath(): string;
|
|
31
35
|
get definitionPath(): string;
|
|
@@ -45,9 +49,9 @@ export declare class WebServiceManager {
|
|
|
45
49
|
export declare function systemdUnit(runtime: string, script: string, port: number, configuration?: string, web?: {
|
|
46
50
|
bind?: string;
|
|
47
51
|
publicOrigin?: string;
|
|
48
|
-
}): string;
|
|
52
|
+
}, environment?: ServiceEnvironment): string;
|
|
49
53
|
export declare function launchdPlist(runtime: string, script: string, port: number, configuration?: string, web?: {
|
|
50
54
|
bind?: string;
|
|
51
55
|
publicOrigin?: string;
|
|
52
|
-
}): string;
|
|
56
|
+
}, environment?: ServiceEnvironment): string;
|
|
53
57
|
export {};
|
package/dist/web/service.js
CHANGED
|
@@ -15,6 +15,7 @@ export class WebServiceManager {
|
|
|
15
15
|
stateDir;
|
|
16
16
|
uid;
|
|
17
17
|
runtimeExecutable;
|
|
18
|
+
environment;
|
|
18
19
|
constructor(options = {}) {
|
|
19
20
|
const platform = options.platform ?? process.platform;
|
|
20
21
|
if (platform !== 'linux' && platform !== 'darwin')
|
|
@@ -25,6 +26,7 @@ export class WebServiceManager {
|
|
|
25
26
|
this.stateDir = options.stateDir ?? join(stateRoot(), 'web');
|
|
26
27
|
this.uid = options.uid ?? process.getuid?.() ?? 501;
|
|
27
28
|
this.runtimeExecutable = options.runtimeExecutable ?? process.execPath;
|
|
29
|
+
this.environment = serviceEnvironment(options.environment ?? process.env);
|
|
28
30
|
}
|
|
29
31
|
get metadataPath() { return join(this.stateDir, 'service.json'); }
|
|
30
32
|
get definitionPath() {
|
|
@@ -42,13 +44,14 @@ export class WebServiceManager {
|
|
|
42
44
|
const config = configuration ? resolve(configuration) : undefined;
|
|
43
45
|
const metadata = {
|
|
44
46
|
version: VERSION, platform: this.platform, runtime, script: resolvedScript, port,
|
|
47
|
+
environment: this.environment,
|
|
45
48
|
...(config ? { configuration: config } : {}),
|
|
46
49
|
...(web.bind ? { bind: web.bind } : {}),
|
|
47
50
|
...(web.publicOrigin ? { publicOrigin: web.publicOrigin } : {}),
|
|
48
51
|
};
|
|
49
52
|
replaceFileAtomically(this.definitionPath, this.platform === 'linux'
|
|
50
|
-
? systemdUnit(runtime, resolvedScript, port, config, web)
|
|
51
|
-
: launchdPlist(runtime, resolvedScript, port, config, web), 0o600);
|
|
53
|
+
? systemdUnit(runtime, resolvedScript, port, config, web, this.environment)
|
|
54
|
+
: launchdPlist(runtime, resolvedScript, port, config, web, this.environment), 0o600);
|
|
52
55
|
replaceFileAtomically(this.metadataPath, JSON.stringify(metadata, null, 2) + '\n', 0o600);
|
|
53
56
|
if (this.platform === 'linux') {
|
|
54
57
|
await this.must('systemctl', ['--user', 'daemon-reload']);
|
|
@@ -159,19 +162,20 @@ function validatePort(port) {
|
|
|
159
162
|
function systemdQuote(value) {
|
|
160
163
|
return `"${value.replace(/[%\\"]/g, char => char === '%' ? '%%' : `\\${char}`)}"`;
|
|
161
164
|
}
|
|
162
|
-
export function systemdUnit(runtime, script, port, configuration, web = {}) {
|
|
165
|
+
export function systemdUnit(runtime, script, port, configuration, web = {}, environment = {}) {
|
|
163
166
|
const config = configuration ? ` --configuration ${systemdQuote(configuration)}` : '';
|
|
164
167
|
const access = `${web.bind ? ` --bind ${systemdQuote(web.bind)}` : ''}`
|
|
165
168
|
+ `${web.publicOrigin ? ` --public-origin ${systemdQuote(web.publicOrigin)}` : ''}`;
|
|
166
169
|
return `[Unit]\nDescription=ours-fleet localhost web console\nAfter=default.target\n\n`
|
|
167
170
|
+ `[Service]\nType=simple\nExecStart=${systemdQuote(runtime)} ${systemdQuote(script)} web serve --port ${port} --no-open${config}${access}\n`
|
|
171
|
+
+ Object.entries(serviceEnvironment(environment)).map(([key, value]) => `Environment=${systemdQuote(`${key}=${value}`)}\n`).join('')
|
|
168
172
|
+ `Restart=on-failure\nRestartSec=5\nTimeoutStopSec=15\n\n`
|
|
169
173
|
+ `[Install]\nWantedBy=default.target\n`;
|
|
170
174
|
}
|
|
171
175
|
const xml = (value) => value.replace(/[&<>"']/g, char => ({
|
|
172
176
|
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
|
173
177
|
}[char]));
|
|
174
|
-
export function launchdPlist(runtime, script, port, configuration, web = {}) {
|
|
178
|
+
export function launchdPlist(runtime, script, port, configuration, web = {}, environment = {}) {
|
|
175
179
|
const config = configuration
|
|
176
180
|
? `<string>--configuration</string><string>${xml(configuration)}</string>` : '';
|
|
177
181
|
const access = `${web.bind ? `<string>--bind</string><string>${xml(web.bind)}</string>` : ''}`
|
|
@@ -181,6 +185,20 @@ export function launchdPlist(runtime, script, port, configuration, web = {}) {
|
|
|
181
185
|
+ `<plist version="1.0"><dict>\n<key>Label</key><string>${WEB_LAUNCHD_LABEL}</string>\n`
|
|
182
186
|
+ `<key>ProgramArguments</key><array><string>${xml(runtime)}</string><string>${xml(script)}</string><string>web</string>`
|
|
183
187
|
+ `<string>serve</string><string>--port</string><string>${port}</string><string>--no-open</string>${config}${access}</array>\n`
|
|
188
|
+
+ `<key>EnvironmentVariables</key><dict>${Object.entries(serviceEnvironment(environment)).map(([key, value]) => `<key>${key}</key><string>${xml(value)}</string>`).join('')}</dict>\n`
|
|
184
189
|
+ `<key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>\n`
|
|
185
190
|
+ `<key>ProcessType</key><string>Background</string>\n</dict></plist>\n`;
|
|
186
191
|
}
|
|
192
|
+
// Retain only profile/tool paths, never inherited credentials or arbitrary environment.
|
|
193
|
+
function serviceEnvironment(source) {
|
|
194
|
+
const result = {};
|
|
195
|
+
for (const key of ['OURS_CONFIG', 'OURS_FLEET_HOME', 'PATH']) {
|
|
196
|
+
const value = source[key];
|
|
197
|
+
if (!value)
|
|
198
|
+
continue;
|
|
199
|
+
if (/[\r\n\0]/.test(value))
|
|
200
|
+
throw new FleetError('invalid_request', `invalid service path setting: ${key}`);
|
|
201
|
+
result[key] = key === 'PATH' ? value : resolve(value);
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/fleet",
|
|
3
|
-
"version": "1.2.0-nightly.
|
|
3
|
+
"version": "1.2.0-nightly.30",
|
|
4
4
|
"description": "Harness-agnostic fleet of persistent, identity-bound AI agents. Declarative fleet.yaml, managed native/ACP sessions, supervision, and ours.network messaging.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|