@hivemagnus/magnus-agent 1.0.1 → 1.0.3
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/.env.example +3 -0
- package/README.md +12 -1
- package/dist/env-catalog.js +1 -0
- package/dist/env.js +7 -0
- package/dist/executors/ardent-manager.d.ts +3 -2
- package/dist/executors/ardent-manager.js +49 -20
- package/dist/executors/ardent-packages.d.ts +8 -0
- package/dist/executors/ardent-packages.js +16 -0
- package/dist/executors/managed-scheduler.d.ts +5 -5
- package/package.json +8 -8
package/.env.example
CHANGED
|
@@ -95,6 +95,9 @@ LOG_LEVEL=info
|
|
|
95
95
|
# ── Ardent (optional) ────────────────────────────────────────────────
|
|
96
96
|
# ARDENT_OWNER_USER=operator
|
|
97
97
|
# ARDENT_STAGED_PACKAGE=/opt/magnus-agent/ardent-package.tgz
|
|
98
|
+
# Scoped npm names accepted as the Ardent runtime, in preference order. Add an
|
|
99
|
+
# older build's package name to keep managing it (interoperating with older components).
|
|
100
|
+
# MAGNUS_AGENT_ARDENT_PACKAGES=@hivemagnus/ardent
|
|
98
101
|
|
|
99
102
|
# ── HiveMem credential renewal (optional, all lists empty by default) ─
|
|
100
103
|
# Entries live in a root-owned 0600 JSON file; the lists below bound what the
|
package/README.md
CHANGED
|
@@ -150,7 +150,7 @@ and `magnus-agent env-schema` prints them as JSON.
|
|
|
150
150
|
| `SKILLS_DIR` / `SKILLS_EXTRA_DIRS` | Skill directories |
|
|
151
151
|
| `HERMES_USER`, `HERMES_REGISTRY_TOKEN`, `MAGNUS_HERMES_SYNC_PULL` | Hermes Agent management and registry sync |
|
|
152
152
|
| `CODEX_USER`, `CODEX_BIN`, `CODEX_HOME` | Codex CLI management |
|
|
153
|
-
| `ARDENT_OWNER_USER`, `ARDENT_STAGED_PACKAGE` | Ardent management |
|
|
153
|
+
| `ARDENT_OWNER_USER`, `ARDENT_STAGED_PACKAGE`, `MAGNUS_AGENT_ARDENT_PACKAGES` | Ardent management |
|
|
154
154
|
| `MAGNUS_AGENT_RENEWAL_*` | HiveMem credential renewal allowlists (empty by default) |
|
|
155
155
|
| `MAGNUS_AGENT_TLS_RENEWAL=tailscale` | Renew a Tailscale listener certificate |
|
|
156
156
|
| `MAGNUS_AGENT_PRIVILEGED` | Privileged (root, default `true`) or unprivileged mode |
|
|
@@ -175,6 +175,17 @@ With `--submit-only` it only reports the local Hermes inventory. Applying the
|
|
|
175
175
|
server's desired skills, plugins and MCP releases also needs
|
|
176
176
|
`MAGNUS_HERMES_SYNC_PULL=true`.
|
|
177
177
|
|
|
178
|
+
## Interoperating with older components
|
|
179
|
+
|
|
180
|
+
`MAGNUS_AGENT_ARDENT_PACKAGES` (default `@hivemagnus/ardent`) lists the scoped
|
|
181
|
+
npm package names the agent accepts as the Ardent runtime, in preference order.
|
|
182
|
+
It applies to the staged `ardent-package.json` sidecar, the install path
|
|
183
|
+
`node_modules/<name>`, the install receipt and the managed `ardent@<profile>`
|
|
184
|
+
user unit. To keep managing an Ardent build published under another scope, add
|
|
185
|
+
its name, for example `MAGNUS_AGENT_ARDENT_PACKAGES=@hivemagnus/ardent,@legacy-scope/ardent`.
|
|
186
|
+
Older sidecars with the `{name, version, sha256}` shape are accepted unchanged.
|
|
187
|
+
Profile channel maps accept any channel key that matches `[a-z][a-z0-9_-]{0,31}`.
|
|
188
|
+
|
|
178
189
|
## Development
|
|
179
190
|
|
|
180
191
|
```bash
|
package/dist/env-catalog.js
CHANGED
|
@@ -36,6 +36,7 @@ export const agentEnvCatalog = [
|
|
|
36
36
|
{ name: 'CODEX_HOME', required: false, secret: false, default: '~/.codex', group: 'codex', description: 'Codex state directory override.' },
|
|
37
37
|
{ name: 'ARDENT_OWNER_USER', required: false, secret: false, group: 'ardent', description: 'Local account that owns the Ardent runtime and profiles.' },
|
|
38
38
|
{ name: 'ARDENT_STAGED_PACKAGE', required: false, secret: false, default: '/opt/magnus-agent/ardent-package.tgz', group: 'ardent', description: 'Verified Ardent package tarball staged for installation.' },
|
|
39
|
+
{ name: 'MAGNUS_AGENT_ARDENT_PACKAGES', required: false, secret: false, default: '@hivemagnus/ardent', group: 'ardent', description: 'Comma-separated scoped npm package names accepted as the Ardent runtime (staged sidecar, install path, receipt), in preference order. Add a legacy name to keep managing an older Ardent build.' },
|
|
39
40
|
{ name: 'MAGNUS_AGENT_RENEWAL_CONFIG', required: false, secret: false, default: '$AGENT_INSTALL_DIR/credential-renewal.json', group: 'renewal', description: 'HiveMem credential renewal entries (root-owned, mode 0600). Absent means renewal is off.' },
|
|
40
41
|
{ name: 'MAGNUS_AGENT_RENEWAL_ENDPOINTS', required: false, secret: false, group: 'renewal', description: 'Comma-separated HTTPS HiveMem base URLs renewal may call.' },
|
|
41
42
|
{ name: 'MAGNUS_AGENT_RENEWAL_UNITS', required: false, secret: false, group: 'renewal', description: 'Comma-separated systemd units renewal may try-restart after replacing a credential.' },
|
package/dist/env.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { getFqdn } from './fqdn.js';
|
|
11
11
|
import { isIPv4 } from 'node:net';
|
|
12
12
|
import { agentPrivileged, isRoot } from './privileged.js';
|
|
13
|
+
import { ardentPackageNames } from './executors/ardent-packages.js';
|
|
13
14
|
function envFlag(name, fallback = false) {
|
|
14
15
|
return (process.env[name] ?? String(fallback)).toLowerCase() === 'true';
|
|
15
16
|
}
|
|
@@ -113,6 +114,12 @@ export function configurationErrors() {
|
|
|
113
114
|
if (!agentPrivileged() && MAGNUS_EXECUTION_SUPERVISOR_ENABLED) {
|
|
114
115
|
errors.push('MAGNUS_EXECUTION_SUPERVISOR_ENABLED=true requires MAGNUS_AGENT_PRIVILEGED=true');
|
|
115
116
|
}
|
|
117
|
+
try {
|
|
118
|
+
ardentPackageNames();
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
errors.push(error instanceof Error ? error.message : 'MAGNUS_AGENT_ARDENT_PACKAGES is invalid');
|
|
122
|
+
}
|
|
116
123
|
return errors;
|
|
117
124
|
}
|
|
118
125
|
//# sourceMappingURL=env.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Hono } from 'hono';
|
|
2
|
+
export { ardentPackageNames, DEFAULT_ARDENT_PACKAGE } from './ardent-packages.js';
|
|
2
3
|
type ArdentRoot = {
|
|
3
4
|
owner: string;
|
|
4
5
|
home: string;
|
|
@@ -6,13 +7,13 @@ type ArdentRoot = {
|
|
|
6
7
|
install: string;
|
|
7
8
|
};
|
|
8
9
|
export declare function verifiedInstalledArdentPackage(install: string, staged: {
|
|
10
|
+
name?: string;
|
|
9
11
|
version: string;
|
|
10
12
|
sha256: string;
|
|
11
13
|
}): Promise<boolean>;
|
|
12
14
|
export declare function readArdentState(target?: ArdentRoot): Promise<object>;
|
|
13
15
|
export declare function hermesTrafficConsumersDisabled(home: string): Promise<boolean>;
|
|
14
|
-
export declare function ardentUserUnit(root: ArdentRoot, profile: string): string;
|
|
16
|
+
export declare function ardentUserUnit(root: ArdentRoot, profile: string, packageName?: string): string;
|
|
15
17
|
export declare function createArdentRoutes(resolveRoot?: () => Promise<ArdentRoot>): Hono;
|
|
16
18
|
export declare const ardentRoutes: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
17
|
-
export {};
|
|
18
19
|
//# sourceMappingURL=ardent-manager.d.ts.map
|
|
@@ -7,6 +7,8 @@ import { Hono } from 'hono';
|
|
|
7
7
|
import { parse as parseEnv } from 'dotenv';
|
|
8
8
|
import YAML from 'yaml';
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
import { ardentPackageNames } from './ardent-packages.js';
|
|
11
|
+
export { ardentPackageNames, DEFAULT_ARDENT_PACKAGE } from './ardent-packages.js';
|
|
10
12
|
const profileName = z.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
|
|
11
13
|
const configSummary = z.object({
|
|
12
14
|
schema_version: z.literal(1), profile: profileName, name: z.string().min(1),
|
|
@@ -15,12 +17,34 @@ const configSummary = z.object({
|
|
|
15
17
|
a2a: z.object({ enabled: z.boolean() }).passthrough(),
|
|
16
18
|
channels: z.record(z.string().regex(/^[a-z][a-z0-9_-]{0,31}$/), z.object({ enabled: z.boolean() }).passthrough()).default({}),
|
|
17
19
|
}).passthrough();
|
|
18
|
-
const
|
|
20
|
+
const acceptedPackageName = z.string().refine(name => ardentPackageNames().includes(name), 'Ardent package name is not accepted by MAGNUS_AGENT_ARDENT_PACKAGES');
|
|
21
|
+
const packageVersion = z.object({ name: acceptedPackageName, version: z.string() });
|
|
19
22
|
const installedPackageReceipt = z.object({
|
|
20
|
-
schemaVersion: z.literal(1), name:
|
|
23
|
+
schemaVersion: z.literal(1), name: acceptedPackageName,
|
|
21
24
|
version: z.string(), sha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
22
25
|
packageTreeSha256: z.string().regex(/^[a-f0-9]{64}$/),
|
|
23
26
|
}).strict();
|
|
27
|
+
/** Package directory of an accepted Ardent package name inside an install prefix. */
|
|
28
|
+
function packageDir(install, name) {
|
|
29
|
+
if (!ardentPackageNames().includes(name))
|
|
30
|
+
throw new Error('Ardent package name is not accepted by MAGNUS_AGENT_ARDENT_PACKAGES');
|
|
31
|
+
return join(install, 'node_modules', ...name.split('/'));
|
|
32
|
+
}
|
|
33
|
+
/** The accepted Ardent package installed under `install`, in preference order. */
|
|
34
|
+
async function installedPackageName(install) {
|
|
35
|
+
for (const name of ardentPackageNames()) {
|
|
36
|
+
try {
|
|
37
|
+
const installed = packageVersion.parse(JSON.parse(await readFile(join(packageDir(install, name), 'package.json'), 'utf8')));
|
|
38
|
+
if (installed.name === name)
|
|
39
|
+
return name;
|
|
40
|
+
}
|
|
41
|
+
catch { /* Try the next accepted name. */ }
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
async function installedCli(install) {
|
|
46
|
+
return join(packageDir(install, await installedPackageName(install) ?? ardentPackageNames()[0]), 'dist/cli.js');
|
|
47
|
+
}
|
|
24
48
|
/** Channel name -> enabled, for every channel the profile config declares. */
|
|
25
49
|
function channelStates(config) {
|
|
26
50
|
return Object.fromEntries(Object.entries(config.channels).map(([name, channel]) => [name, channel.enabled]));
|
|
@@ -112,11 +136,11 @@ async function stagedPackage() {
|
|
|
112
136
|
const sidecarBytes = await readFile(sidecar);
|
|
113
137
|
if (createHash('sha256').update(sidecarBytes).digest('hex') !== entry('ardent-package.json'))
|
|
114
138
|
throw new Error('Staged Ardent package sidecar differs from release manifest');
|
|
115
|
-
const details = z.object({ name:
|
|
139
|
+
const details = z.object({ name: acceptedPackageName, version: z.string(), sha256: z.string().regex(/^[a-f0-9]{64}$/) }).parse(JSON.parse(sidecarBytes.toString('utf8')));
|
|
116
140
|
const digest = createHash('sha256').update(await readFile(archive)).digest('hex');
|
|
117
141
|
if (digest !== details.sha256 || digest !== entry('ardent-package.tgz'))
|
|
118
142
|
throw new Error('Staged Ardent package differs from release manifest');
|
|
119
|
-
return { version: details.version, sha256: digest };
|
|
143
|
+
return { name: details.name, version: details.version, sha256: digest };
|
|
120
144
|
}
|
|
121
145
|
async function packageTreeDigest(packageRoot) {
|
|
122
146
|
const entries = [];
|
|
@@ -160,15 +184,20 @@ export async function verifiedInstalledArdentPackage(install, staged) {
|
|
|
160
184
|
const receipt = installedPackageReceipt.safeParse(JSON.parse(await readFile(receiptPath, 'utf8')));
|
|
161
185
|
if (!receipt.success || receipt.data.version !== staged.version || receipt.data.sha256 !== staged.sha256)
|
|
162
186
|
return false;
|
|
163
|
-
|
|
187
|
+
if (staged.name !== undefined && receipt.data.name !== staged.name)
|
|
188
|
+
return false;
|
|
189
|
+
return await packageTreeDigest(packageDir(install, receipt.data.name)) === receipt.data.packageTreeSha256;
|
|
164
190
|
}
|
|
165
191
|
export async function readArdentState(target) {
|
|
166
192
|
const root = target ?? await ardentRoot();
|
|
167
193
|
let version = null;
|
|
194
|
+
let packageName = null;
|
|
168
195
|
try {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
196
|
+
packageName = await installedPackageName(root.install);
|
|
197
|
+
if (packageName) {
|
|
198
|
+
const installed = JSON.parse(await readFile(join(packageDir(root.install, packageName), 'package.json'), 'utf8'));
|
|
199
|
+
version = packageVersion.parse(installed).version;
|
|
200
|
+
}
|
|
172
201
|
}
|
|
173
202
|
catch { /* An uninstalled package is a normal inventory state. */ }
|
|
174
203
|
const profiles = await Promise.all((await safeProfiles(root.root)).map(async (name) => {
|
|
@@ -191,7 +220,7 @@ export async function readArdentState(target) {
|
|
|
191
220
|
catch (error) {
|
|
192
221
|
stagedPackageError = error instanceof Error ? error.message.slice(0, 200) : 'Staged package unavailable';
|
|
193
222
|
}
|
|
194
|
-
return { installed: version !== null, version, owner: root.owner, profiles, stagedPackage: staged, stagedPackageError, checkedAt: new Date().toISOString() };
|
|
223
|
+
return { installed: version !== null, version, packageName, owner: root.owner, profiles, stagedPackage: staged, stagedPackageError, checkedAt: new Date().toISOString() };
|
|
195
224
|
}
|
|
196
225
|
async function managementToken(dir, envName) {
|
|
197
226
|
const processToken = process.env[envName];
|
|
@@ -264,12 +293,12 @@ export async function hermesTrafficConsumersDisabled(home) {
|
|
|
264
293
|
return false;
|
|
265
294
|
}
|
|
266
295
|
}
|
|
267
|
-
export function ardentUserUnit(root, profile) {
|
|
296
|
+
export function ardentUserUnit(root, profile, packageName = ardentPackageNames()[0]) {
|
|
268
297
|
profileName.parse(profile);
|
|
269
298
|
const safe = /^[A-Za-z0-9_./-]+$/;
|
|
270
299
|
if (![root.home, root.root, root.install].every(path => safe.test(path)))
|
|
271
300
|
throw new Error('Ardent service paths contain unsupported characters');
|
|
272
|
-
return `[Unit]\nDescription=Magnus Ardent ${profile}\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nWorkingDirectory=${join(root.root, 'profiles', profile)}\nEnvironment=ARDENT_HOME=${root.root}\nExecStart=/usr/bin/node ${join(root.install, '
|
|
301
|
+
return `[Unit]\nDescription=Magnus Ardent ${profile}\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nWorkingDirectory=${join(root.root, 'profiles', profile)}\nEnvironment=ARDENT_HOME=${root.root}\nExecStart=/usr/bin/node ${join(packageDir(root.install, packageName), 'dist/cli.js')} --profile ${profile} gateway run\nRestart=on-failure\nRestartSec=5\nTimeoutStopSec=75\nNoNewPrivileges=true\n\n[Install]\nWantedBy=default.target\n`;
|
|
273
302
|
}
|
|
274
303
|
async function serviceAction(root, profile, action) {
|
|
275
304
|
if (process.getuid?.() !== 0)
|
|
@@ -289,7 +318,7 @@ async function serviceAction(root, profile, action) {
|
|
|
289
318
|
}
|
|
290
319
|
const unit = `ardent@${profile}.service`;
|
|
291
320
|
const path = join(root.home, '.config/systemd/user', unit);
|
|
292
|
-
const expected = ardentUserUnit(root, profile);
|
|
321
|
+
const expected = ardentUserUnit(root, profile, await installedPackageName(root.install) ?? undefined);
|
|
293
322
|
const metadata = await lstat(path).catch((error) => {
|
|
294
323
|
if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')
|
|
295
324
|
return undefined;
|
|
@@ -307,7 +336,7 @@ async function serviceAction(root, profile, action) {
|
|
|
307
336
|
if (action !== 'service-start' && existing === undefined)
|
|
308
337
|
throw new Error('Managed Ardent user service is not installed');
|
|
309
338
|
if (action === 'service-start' && existing === undefined) {
|
|
310
|
-
const script =
|
|
339
|
+
const script = await installedCli(root.install);
|
|
311
340
|
const scriptInfo = await lstat(script);
|
|
312
341
|
if (!scriptInfo.isFile() || scriptInfo.isSymbolicLink())
|
|
313
342
|
throw new Error('Ardent package executable is unavailable');
|
|
@@ -377,14 +406,14 @@ async function installPackage(root) {
|
|
|
377
406
|
let installed = false;
|
|
378
407
|
try {
|
|
379
408
|
await runAsOwner(root, ['/usr/bin/npm', 'install', '--prefix', stage, '--omit=dev', '--no-audit', '--no-fund', '--no-save', archive], 9 * 60_000);
|
|
380
|
-
const packageFile = join(stage, '
|
|
409
|
+
const packageFile = join(packageDir(stage, staged.name), 'package.json');
|
|
381
410
|
const candidate = packageVersion.parse(JSON.parse(await readFile(packageFile, 'utf8')));
|
|
382
|
-
if (candidate.version !== staged.version)
|
|
383
|
-
throw new Error('Staged Ardent package version differs');
|
|
411
|
+
if (candidate.name !== staged.name || candidate.version !== staged.version)
|
|
412
|
+
throw new Error('Staged Ardent package name or version differs');
|
|
384
413
|
await runAsOwner(root, ['/usr/bin/node', '-e', "const Database=require(process.argv[1]);new Database(':memory:').close()", join(stage, 'node_modules/better-sqlite3')], 10_000);
|
|
385
|
-
const packageTreeSha256 = await packageTreeDigest(
|
|
414
|
+
const packageTreeSha256 = await packageTreeDigest(packageDir(stage, staged.name));
|
|
386
415
|
await writeFile(join(stage, 'package-receipt.json'), `${JSON.stringify({
|
|
387
|
-
schemaVersion: 1, name:
|
|
416
|
+
schemaVersion: 1, name: staged.name, version: staged.version, sha256: staged.sha256, packageTreeSha256,
|
|
388
417
|
})}\n`, { mode: 0o644 });
|
|
389
418
|
if (priorInfo) {
|
|
390
419
|
await rename(root.install, previous);
|
|
@@ -426,7 +455,7 @@ async function createProfile(root, profile, body) {
|
|
|
426
455
|
if (current.config.api.port === input.api_port)
|
|
427
456
|
throw new Error(`API port is already assigned to profile ${name}`);
|
|
428
457
|
}
|
|
429
|
-
const script =
|
|
458
|
+
const script = await installedCli(root.install);
|
|
430
459
|
const metadata = await lstat(script);
|
|
431
460
|
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
432
461
|
throw new Error('Installed Ardent CLI is unsafe');
|
|
@@ -453,7 +482,7 @@ async function importHermesProfile(root, profile, body) {
|
|
|
453
482
|
const sourceInfo = await lstat(source);
|
|
454
483
|
if (!sourceInfo.isDirectory() || sourceInfo.isSymbolicLink())
|
|
455
484
|
throw new Error('Hermes source home is unsafe');
|
|
456
|
-
const script =
|
|
485
|
+
const script = await installedCli(root.install);
|
|
457
486
|
const scriptInfo = await lstat(script);
|
|
458
487
|
if (!scriptInfo.isFile() || scriptInfo.isSymbolicLink())
|
|
459
488
|
throw new Error('Installed Ardent CLI is unsafe');
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const DEFAULT_ARDENT_PACKAGE = "@hivemagnus/ardent";
|
|
2
|
+
/**
|
|
3
|
+
* npm package names the agent accepts as the Ardent runtime, in preference
|
|
4
|
+
* order. `MAGNUS_AGENT_ARDENT_PACKAGES` (comma-separated scoped names) lets a
|
|
5
|
+
* node keep managing an Ardent build published under another scope.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ardentPackageNames(value?: string | undefined): string[];
|
|
8
|
+
//# sourceMappingURL=ardent-packages.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const DEFAULT_ARDENT_PACKAGE = '@hivemagnus/ardent';
|
|
2
|
+
const scopedPackageName = /^@[a-z0-9][a-z0-9._-]{0,99}\/[a-z0-9][a-z0-9._-]{0,99}$/;
|
|
3
|
+
/**
|
|
4
|
+
* npm package names the agent accepts as the Ardent runtime, in preference
|
|
5
|
+
* order. `MAGNUS_AGENT_ARDENT_PACKAGES` (comma-separated scoped names) lets a
|
|
6
|
+
* node keep managing an Ardent build published under another scope.
|
|
7
|
+
*/
|
|
8
|
+
export function ardentPackageNames(value = process.env['MAGNUS_AGENT_ARDENT_PACKAGES']) {
|
|
9
|
+
if (value === undefined || value.trim() === '')
|
|
10
|
+
return [DEFAULT_ARDENT_PACKAGE];
|
|
11
|
+
const names = value.split(',').map(item => item.trim()).filter(Boolean);
|
|
12
|
+
if (!names.length || names.some(name => !scopedPackageName.test(name)))
|
|
13
|
+
throw new Error('MAGNUS_AGENT_ARDENT_PACKAGES must list scoped npm package names such as @scope/ardent');
|
|
14
|
+
return [...new Set(names)];
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=ardent-packages.js.map
|
|
@@ -110,11 +110,11 @@ export declare const schedulerSourceSettlementSchema: z.ZodObject<{
|
|
|
110
110
|
}, z.core.$strict>;
|
|
111
111
|
export type SchedulerSourceSettlement = z.infer<typeof schedulerSourceSettlementSchema>;
|
|
112
112
|
export declare const schedulerSourceSettlementReceiptSchema: z.ZodObject<{
|
|
113
|
+
version: z.ZodLiteral<1>;
|
|
113
114
|
expiresAt: z.ZodNumber;
|
|
114
115
|
nodeId: z.ZodString;
|
|
115
116
|
count: z.ZodNumber;
|
|
116
117
|
kind: z.ZodString;
|
|
117
|
-
version: z.ZodLiteral<1>;
|
|
118
118
|
nodeFqdn: z.ZodString;
|
|
119
119
|
disposition: z.ZodEnum<{
|
|
120
120
|
effects_verified: "effects_verified";
|
|
@@ -138,11 +138,11 @@ export declare function schedulerSourceSettlementReceiptPayload(value: Omit<Sche
|
|
|
138
138
|
replayed: boolean;
|
|
139
139
|
}): string;
|
|
140
140
|
declare const legacySettlementReceiptSchema: z.ZodObject<{
|
|
141
|
+
version: z.ZodLiteral<1>;
|
|
141
142
|
expiresAt: z.ZodNumber;
|
|
142
143
|
nodeId: z.ZodString;
|
|
143
144
|
count: z.ZodNumber;
|
|
144
145
|
kind: z.ZodString;
|
|
145
|
-
version: z.ZodLiteral<1>;
|
|
146
146
|
nodeFqdn: z.ZodString;
|
|
147
147
|
disposition: z.ZodEnum<{
|
|
148
148
|
effects_verified: "effects_verified";
|
|
@@ -194,11 +194,11 @@ export declare class ManagedScheduler {
|
|
|
194
194
|
count: number;
|
|
195
195
|
}[];
|
|
196
196
|
settlements: {
|
|
197
|
+
version: 1;
|
|
197
198
|
expiresAt: number;
|
|
198
199
|
nodeId: string;
|
|
199
200
|
count: number;
|
|
200
201
|
kind: string;
|
|
201
|
-
version: 1;
|
|
202
202
|
nodeFqdn: string;
|
|
203
203
|
disposition: "effects_verified" | "no_effect_verified";
|
|
204
204
|
evidenceSha256: string;
|
|
@@ -213,11 +213,11 @@ export declare class ManagedScheduler {
|
|
|
213
213
|
receiptSignature: string;
|
|
214
214
|
}[];
|
|
215
215
|
legacySettlements: {
|
|
216
|
+
version: 1;
|
|
216
217
|
expiresAt: number;
|
|
217
218
|
nodeId: string;
|
|
218
219
|
count: number;
|
|
219
220
|
kind: string;
|
|
220
|
-
version: 1;
|
|
221
221
|
nodeFqdn: string;
|
|
222
222
|
disposition: "effects_verified" | "no_effect_verified";
|
|
223
223
|
evidenceSha256: string;
|
|
@@ -240,11 +240,11 @@ export declare class ManagedScheduler {
|
|
|
240
240
|
settlementReceipt(decisionId: string): Promise<SchedulerSourceSettlementReceipt | z.infer<typeof legacySettlementReceiptSchema> | undefined>;
|
|
241
241
|
settleForeignSource(raw: SchedulerSourceSettlement, signReceipt: (payload: Omit<SchedulerSourceSettlementReceipt, 'receiptSignature'>) => string): Promise<{
|
|
242
242
|
receipt: {
|
|
243
|
+
version: 1;
|
|
243
244
|
expiresAt: number;
|
|
244
245
|
nodeId: string;
|
|
245
246
|
count: number;
|
|
246
247
|
kind: string;
|
|
247
|
-
version: 1;
|
|
248
248
|
nodeFqdn: string;
|
|
249
249
|
disposition: "effects_verified" | "no_effect_verified";
|
|
250
250
|
evidenceSha256: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hivemagnus/magnus-agent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Magnus node agent: a small daemon that enrolls a Linux host with a magnus-server and runs authenticated health, command, cron, file and skill management, with optional Hermes Agent, Codex and Ardent management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"magnus",
|
|
@@ -55,19 +55,19 @@
|
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"@hono/node-server": "^2.1.5",
|
|
58
|
-
"dotenv": "^
|
|
59
|
-
"hono": "^4.13.
|
|
60
|
-
"ky": "^
|
|
58
|
+
"dotenv": "^18.0.9",
|
|
59
|
+
"hono": "^4.13.14",
|
|
60
|
+
"ky": "^2.2.0",
|
|
61
61
|
"nanoid": "^5.1.16",
|
|
62
|
-
"tar-stream": "3.2.
|
|
62
|
+
"tar-stream": "3.2.2",
|
|
63
63
|
"undici": "^7.30.1",
|
|
64
64
|
"yaml": "^2.9.1",
|
|
65
65
|
"zod": "^4.6.7"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@types/node": "^22.
|
|
69
|
-
"@types/tar-stream": "^3.1.
|
|
70
|
-
"tsx": "^4.
|
|
68
|
+
"@types/node": "^22.20.5",
|
|
69
|
+
"@types/tar-stream": "^3.1.5",
|
|
70
|
+
"tsx": "^4.23.15",
|
|
71
71
|
"typescript": "^5.8.3",
|
|
72
72
|
"vitest": "^4.1.12"
|
|
73
73
|
}
|