@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 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
@@ -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 packageVersion = z.object({ name: z.literal('@hivemagnus/ardent'), version: z.string() });
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: z.literal('@hivemagnus/ardent'),
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: z.literal('@hivemagnus/ardent'), version: z.string(), sha256: z.string().regex(/^[a-f0-9]{64}$/) }).parse(JSON.parse(sidecarBytes.toString('utf8')));
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
- return await packageTreeDigest(join(install, 'node_modules/@hivemagnus/ardent')) === receipt.data.packageTreeSha256;
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
- const packageFile = join(root.install, 'node_modules/@hivemagnus/ardent/package.json');
170
- const installed = JSON.parse(await readFile(packageFile, 'utf8'));
171
- version = packageVersion.parse(installed).version;
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, 'node_modules/@hivemagnus/ardent/dist/cli.js')} --profile ${profile} gateway run\nRestart=on-failure\nRestartSec=5\nTimeoutStopSec=75\nNoNewPrivileges=true\n\n[Install]\nWantedBy=default.target\n`;
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 = join(root.install, 'node_modules/@hivemagnus/ardent/dist/cli.js');
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, 'node_modules/@hivemagnus/ardent/package.json');
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(join(stage, 'node_modules/@hivemagnus/ardent'));
414
+ const packageTreeSha256 = await packageTreeDigest(packageDir(stage, staged.name));
386
415
  await writeFile(join(stage, 'package-receipt.json'), `${JSON.stringify({
387
- schemaVersion: 1, name: '@hivemagnus/ardent', version: staged.version, sha256: staged.sha256, packageTreeSha256,
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 = join(root.install, 'node_modules/@hivemagnus/ardent/dist/cli.js');
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 = join(root.install, 'node_modules/@hivemagnus/ardent/dist/cli.js');
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.1",
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": "^17.3.1",
59
- "hono": "^4.13.7",
60
- "ky": "^1.7.5",
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.1",
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.10.0",
69
- "@types/tar-stream": "^3.1.4",
70
- "tsx": "^4.19.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
  }