@naisys/hub 3.0.0-beta.37 → 3.0.0-beta.38
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/handlers/hubAgentService.js +96 -57
- package/dist/handlers/hubAttachmentService.js +12 -30
- package/dist/handlers/hubHeartbeatService.js +3 -1
- package/dist/handlers/hubUserService.js +0 -2
- package/dist/naisysHub.js +23 -6
- package/dist/services/agentRegistrar.js +1 -2
- package/npm-shrinkwrap.json +23 -23
- package/package.json +6 -6
|
@@ -1,6 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { hashToken } from "@naisys/common-node";
|
|
2
|
+
import { AgentPeekRequestSchema, AgentRunCommandRequestSchema, AgentRunPauseRequestSchema, AgentStartInboundSchema, AgentStopRequestSchema, HubEvents, } from "@naisys/hub-protocol";
|
|
3
|
+
import { randomBytes } from "crypto";
|
|
2
4
|
/** Handles agent_start requests by routing them to the least-loaded eligible host */
|
|
3
5
|
export function createHubAgentService(naisysServer, { hubDb }, logService, heartbeatService, sendMailService, hostRegistrar) {
|
|
6
|
+
/**
|
|
7
|
+
* Mint a fresh runtime API key for a user, rotating any prior key. Plaintext
|
|
8
|
+
* is returned only here and travels once over the AGENT_START message; the
|
|
9
|
+
* DB only stores the hash. Keys persist across hub restarts/crashes/updates;
|
|
10
|
+
* revocation lives on the user disable/archive/delete paths and on graceful
|
|
11
|
+
* AGENT_STOP.
|
|
12
|
+
*/
|
|
13
|
+
async function issueRuntimeApiKey(userId) {
|
|
14
|
+
const token = randomBytes(32).toString("hex");
|
|
15
|
+
await hubDb.users.update({
|
|
16
|
+
where: { id: userId },
|
|
17
|
+
data: { api_key_hash: hashToken(token) },
|
|
18
|
+
});
|
|
19
|
+
return token;
|
|
20
|
+
}
|
|
21
|
+
async function revokeRuntimeApiKey(userId) {
|
|
22
|
+
await hubDb.users.update({
|
|
23
|
+
where: { id: userId },
|
|
24
|
+
data: { api_key_hash: null },
|
|
25
|
+
});
|
|
26
|
+
}
|
|
4
27
|
/** Find the least-loaded eligible host for a given user */
|
|
5
28
|
async function findBestHost(startUserId) {
|
|
6
29
|
// Look up which hosts this user is assigned to
|
|
@@ -52,30 +75,61 @@ export function createHubAgentService(naisysServer, { hubDb }, logService, heart
|
|
|
52
75
|
});
|
|
53
76
|
return !!user?.enabled && !user?.archived;
|
|
54
77
|
}
|
|
78
|
+
/** Run the start preconditions and pick a host. */
|
|
79
|
+
async function decideStartAgent(userId) {
|
|
80
|
+
if (!(await isAgentEnabled(userId))) {
|
|
81
|
+
return { kind: "fail", error: `Agent ${userId} is disabled` };
|
|
82
|
+
}
|
|
83
|
+
if (heartbeatService.findHostsForAgent(userId).length > 0) {
|
|
84
|
+
return { kind: "fail", error: `Agent ${userId} is already running` };
|
|
85
|
+
}
|
|
86
|
+
const bestHostId = await findBestHost(userId);
|
|
87
|
+
if (bestHostId === null) {
|
|
88
|
+
return {
|
|
89
|
+
kind: "fail",
|
|
90
|
+
error: `No eligible hosts are online for user ${userId}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return { kind: "go", bestHostId };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Issue a runtime key and send AGENT_START. Stranded keys from a failed
|
|
97
|
+
* send or failed response stay in the DB until the next AGENT_START for
|
|
98
|
+
* that user rotates them, or the user is disabled/archived/deleted — the
|
|
99
|
+
* agent process that would have used the key never started, so there's
|
|
100
|
+
* nobody to authenticate with it in the meantime.
|
|
101
|
+
*/
|
|
102
|
+
async function dispatchAgentStart(args) {
|
|
103
|
+
const { bestHostId, payload, onResponse } = args;
|
|
104
|
+
const startUserId = payload.startUserId;
|
|
105
|
+
const runtimeApiKey = await issueRuntimeApiKey(startUserId);
|
|
106
|
+
const sent = naisysServer.sendMessage(bestHostId, HubEvents.AGENT_START, { ...payload, runtimeApiKey }, (response) => {
|
|
107
|
+
if (response.success) {
|
|
108
|
+
heartbeatService.addStartedAgent(bestHostId, startUserId);
|
|
109
|
+
}
|
|
110
|
+
onResponse(response);
|
|
111
|
+
});
|
|
112
|
+
return { sent };
|
|
113
|
+
}
|
|
55
114
|
/** Try to start an agent on the best available host (fire-and-forget) */
|
|
56
115
|
async function tryStartAgent(startUserId) {
|
|
57
116
|
try {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
const bestHostId = await findBestHost(startUserId);
|
|
63
|
-
if (bestHostId === null) {
|
|
64
|
-
logService.log(`[Hub:Agents] Auto-start: no eligible host for user ${startUserId}`);
|
|
117
|
+
const decision = await decideStartAgent(startUserId);
|
|
118
|
+
if (decision.kind === "fail") {
|
|
119
|
+
logService.log(`[Hub:Agents] Auto-start: ${decision.error}`);
|
|
65
120
|
return false;
|
|
66
121
|
}
|
|
67
|
-
const sent =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
122
|
+
const { sent } = await dispatchAgentStart({
|
|
123
|
+
bestHostId: decision.bestHostId,
|
|
124
|
+
payload: { startUserId },
|
|
125
|
+
onResponse: (response) => {
|
|
126
|
+
if (!response.success) {
|
|
127
|
+
logService.error(`[Hub:Agents] Auto-start failed for user ${startUserId}: ${response.error}`);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
76
130
|
});
|
|
77
131
|
if (sent) {
|
|
78
|
-
logService.log(`[Hub:Agents] Auto-start: sent start for user ${startUserId} to host ${bestHostId}`);
|
|
132
|
+
logService.log(`[Hub:Agents] Auto-start: sent start for user ${startUserId} to host ${decision.bestHostId}`);
|
|
79
133
|
}
|
|
80
134
|
return sent;
|
|
81
135
|
}
|
|
@@ -86,51 +140,33 @@ export function createHubAgentService(naisysServer, { hubDb }, logService, heart
|
|
|
86
140
|
}
|
|
87
141
|
naisysServer.registerEvent(HubEvents.AGENT_START, async (hostId, data, ack) => {
|
|
88
142
|
try {
|
|
89
|
-
const parsed =
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
92
|
-
ack({
|
|
93
|
-
success: false,
|
|
94
|
-
error: `Agent ${parsed.startUserId} is disabled`,
|
|
95
|
-
});
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const bestHostId = await findBestHost(parsed.startUserId);
|
|
99
|
-
if (bestHostId === null) {
|
|
100
|
-
ack({
|
|
101
|
-
success: false,
|
|
102
|
-
error: `No eligible hosts are online for user ${parsed.startUserId}`,
|
|
103
|
-
});
|
|
143
|
+
const parsed = AgentStartInboundSchema.parse(data);
|
|
144
|
+
const decision = await decideStartAgent(parsed.startUserId);
|
|
145
|
+
if (decision.kind === "fail") {
|
|
146
|
+
ack({ success: false, error: decision.error });
|
|
104
147
|
return;
|
|
105
148
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
// Reverse-ack with the response from the host (including success status and any error message) back to the original requester
|
|
123
|
-
ack(response);
|
|
124
|
-
// Send task description mail after successful start to avoid
|
|
125
|
-
// orphaned mails from failed start attempts
|
|
126
|
-
if (response.success && parsed.taskDescription) {
|
|
127
|
-
void sendTaskMail(parsed.startUserId, requesterUserId, parsed.taskDescription);
|
|
128
|
-
}
|
|
149
|
+
const { sent } = await dispatchAgentStart({
|
|
150
|
+
bestHostId: decision.bestHostId,
|
|
151
|
+
payload: {
|
|
152
|
+
startUserId: parsed.startUserId,
|
|
153
|
+
taskDescription: parsed.taskDescription,
|
|
154
|
+
sourceHostId: hostId,
|
|
155
|
+
},
|
|
156
|
+
onResponse: (response) => {
|
|
157
|
+
// Reverse-ack with the response from the host (including success status and any error message) back to the original requester
|
|
158
|
+
ack(response);
|
|
159
|
+
// Send task description mail after successful start to avoid
|
|
160
|
+
// orphaned mails from failed start attempts
|
|
161
|
+
if (response.success && parsed.taskDescription) {
|
|
162
|
+
void sendTaskMail(parsed.startUserId, parsed.requesterUserId, parsed.taskDescription);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
129
165
|
});
|
|
130
166
|
if (!sent) {
|
|
131
167
|
ack({
|
|
132
168
|
success: false,
|
|
133
|
-
error: `Failed to send to host ${bestHostId}`,
|
|
169
|
+
error: `Failed to send to host ${decision.bestHostId}`,
|
|
134
170
|
});
|
|
135
171
|
}
|
|
136
172
|
}
|
|
@@ -176,6 +212,9 @@ export function createHubAgentService(naisysServer, { hubDb }, logService, heart
|
|
|
176
212
|
}, (response) => {
|
|
177
213
|
if (response.success) {
|
|
178
214
|
heartbeatService.removeStoppedAgent(targetHostId, parsed.userId);
|
|
215
|
+
revokeRuntimeApiKey(parsed.userId).catch((err) => {
|
|
216
|
+
logService.error(`[Hub:Agents] Failed to revoke runtime key for user ${parsed.userId} on stop: ${err}`);
|
|
217
|
+
});
|
|
179
218
|
}
|
|
180
219
|
// Ack with the first response
|
|
181
220
|
if (!acked) {
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createReadStream, createWriteStream, existsSync, mkdirSync, renameSync, statSync, unlinkSync, } from "fs";
|
|
1
|
+
import { extractBearerToken, generateAttachmentPublicId, getHubAttachmentPath, hashToken, MAX_HUB_ATTACHMENT_SIZE, sendAttachmentResponse, } from "@naisys/common-node";
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import { createWriteStream, existsSync, mkdirSync, renameSync, unlinkSync, } from "fs";
|
|
5
4
|
import { join } from "path";
|
|
6
5
|
import { pipeline, Writable } from "stream";
|
|
7
|
-
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
8
6
|
/**
|
|
9
7
|
* HTTP attachment upload/download service.
|
|
10
8
|
* Registers Fastify routes for `/hub/attachments` paths.
|
|
@@ -12,7 +10,9 @@ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10 MB
|
|
|
12
10
|
export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
13
11
|
const naisysFolder = process.env.NAISYS_FOLDER || "";
|
|
14
12
|
async function resolveUserByApiKey(apiKey) {
|
|
15
|
-
const user = await hubDb.users.findUnique({
|
|
13
|
+
const user = await hubDb.users.findUnique({
|
|
14
|
+
where: { api_key_hash: hashToken(apiKey) },
|
|
15
|
+
});
|
|
16
16
|
return user?.id ?? null;
|
|
17
17
|
}
|
|
18
18
|
// Upload route — encapsulated so the raw content-type parser doesn't leak
|
|
@@ -49,9 +49,9 @@ export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
|
49
49
|
if (isNaN(fileSize) || fileSize <= 0) {
|
|
50
50
|
return reply.code(400).send({ error: "Invalid filesize" });
|
|
51
51
|
}
|
|
52
|
-
if (fileSize >
|
|
52
|
+
if (fileSize > MAX_HUB_ATTACHMENT_SIZE) {
|
|
53
53
|
return reply.code(413).send({
|
|
54
|
-
error: `File too large. Max size: ${
|
|
54
|
+
error: `File too large. Max size: ${MAX_HUB_ATTACHMENT_SIZE} bytes`,
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
const userId = await resolveUserByApiKey(apiKey);
|
|
@@ -71,7 +71,7 @@ export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
|
71
71
|
const sizeChecker = new Writable({
|
|
72
72
|
write(chunk, _encoding, callback) {
|
|
73
73
|
bytesWritten += chunk.length;
|
|
74
|
-
if (bytesWritten >
|
|
74
|
+
if (bytesWritten > MAX_HUB_ATTACHMENT_SIZE) {
|
|
75
75
|
callback(new Error("File exceeds size limit"));
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
@@ -116,10 +116,8 @@ export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
|
116
116
|
error: `Hash mismatch. Expected: ${fileHash}, got: ${computedHash}`,
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
const storageDir = join(naisysFolder, "attachments", "hub", computedHash.slice(0, 2), computedHash.slice(2, 4));
|
|
119
|
+
const { storageDir, storagePath } = getHubAttachmentPath(naisysFolder, computedHash);
|
|
121
120
|
mkdirSync(storageDir, { recursive: true });
|
|
122
|
-
const storagePath = join(storageDir, computedHash);
|
|
123
121
|
if (existsSync(storagePath)) {
|
|
124
122
|
// Dedup: identical file already on disk, discard temp
|
|
125
123
|
try {
|
|
@@ -132,10 +130,9 @@ export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
|
132
130
|
else {
|
|
133
131
|
renameSync(tmpPath, storagePath);
|
|
134
132
|
}
|
|
135
|
-
// Create DB record
|
|
136
133
|
const record = await hubDb.attachments.create({
|
|
137
134
|
data: {
|
|
138
|
-
public_id:
|
|
135
|
+
public_id: generateAttachmentPublicId(),
|
|
139
136
|
filepath: storagePath,
|
|
140
137
|
filename,
|
|
141
138
|
file_size: bytesWritten,
|
|
@@ -174,22 +171,7 @@ export function createHubAttachmentService(fastify, { hubDb }, logService) {
|
|
|
174
171
|
if (!attachment) {
|
|
175
172
|
return reply.code(404).send({ error: "Attachment not found" });
|
|
176
173
|
}
|
|
177
|
-
|
|
178
|
-
return reply
|
|
179
|
-
.code(404)
|
|
180
|
-
.send({ error: "Attachment file missing from disk" });
|
|
181
|
-
}
|
|
182
|
-
const stat = statSync(attachment.filepath);
|
|
183
|
-
const contentType = mimeFromFilename(attachment.filename);
|
|
184
|
-
const disposition = contentType.startsWith("image/")
|
|
185
|
-
? "inline"
|
|
186
|
-
: "attachment";
|
|
187
|
-
reply
|
|
188
|
-
.header("Content-Type", contentType)
|
|
189
|
-
.header("Content-Disposition", `${disposition}; filename="${attachment.filename.replace(/"/g, '\\"')}"`)
|
|
190
|
-
.header("Content-Length", stat.size);
|
|
191
|
-
const readStream = createReadStream(attachment.filepath);
|
|
192
|
-
return reply.send(readStream);
|
|
174
|
+
return sendAttachmentResponse(reply, attachment.filepath, attachment.filename);
|
|
193
175
|
}
|
|
194
176
|
fastify.get("/hub/attachments/:publicId/:filename", async (request, reply) => {
|
|
195
177
|
try {
|
|
@@ -64,7 +64,9 @@ export function createHubHeartbeatService(naisysServer, { hubDb }, logService) {
|
|
|
64
64
|
logService.error(`[Hub:Heartbeat] Error updating heartbeat for host ${hostId}: ${error}`);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
|
-
// Clean up tracking when a host disconnects
|
|
67
|
+
// Clean up tracking when a host disconnects. Runtime API keys are not
|
|
68
|
+
// touched here — they're rotated on the next AGENT_START and revoked
|
|
69
|
+
// explicitly on user disable/archive/delete.
|
|
68
70
|
naisysServer.registerEvent(HubEvents.CLIENT_DISCONNECTED, (hostId) => {
|
|
69
71
|
hostActiveAgents.delete(hostId);
|
|
70
72
|
hostActiveSessions.delete(hostId);
|
|
@@ -10,7 +10,6 @@ export function createHubUserService(naisysServer, { hubDb }, logService) {
|
|
|
10
10
|
enabled: true,
|
|
11
11
|
config: true,
|
|
12
12
|
lead_user_id: true,
|
|
13
|
-
api_key: true,
|
|
14
13
|
user_hosts: {
|
|
15
14
|
select: { host_id: true },
|
|
16
15
|
},
|
|
@@ -25,7 +24,6 @@ export function createHubUserService(naisysServer, { hubDb }, logService) {
|
|
|
25
24
|
assignedHostIds: u.user_hosts.length > 0
|
|
26
25
|
? u.user_hosts.map((uh) => uh.host_id)
|
|
27
26
|
: undefined,
|
|
28
|
-
apiKey: u.api_key || undefined,
|
|
29
27
|
}));
|
|
30
28
|
return { success: true, users };
|
|
31
29
|
}
|
package/dist/naisysHub.js
CHANGED
|
@@ -43,8 +43,9 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
43
43
|
await seedAgentConfigs(hubDatabaseService, logService, agentPath);
|
|
44
44
|
// Create host registrar for tracking NAISYS instance connections
|
|
45
45
|
const hostRegistrar = await createHostRegistrar(hubDatabaseService);
|
|
46
|
-
//
|
|
47
|
-
|
|
46
|
+
// trustProxy: TLS terminates at the reverse proxy, so honor X-Forwarded-*
|
|
47
|
+
// headers — otherwise request.protocol reads the internal http hop.
|
|
48
|
+
const fastify = Fastify({ pluginTimeout: 60_000, trustProxy: true });
|
|
48
49
|
// Register HTTP attachment upload/download routes
|
|
49
50
|
createHubAttachmentService(fastify, hubDatabaseService, logService);
|
|
50
51
|
// Attach Socket.IO to the underlying HTTP server.
|
|
@@ -89,7 +90,9 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
89
90
|
const supervisorModule = "@naisys/supervisor";
|
|
90
91
|
const { supervisorPlugin, bootstrapSupervisor } = (await import(supervisorModule));
|
|
91
92
|
const resetSuperAdminPasskey = wizardRan
|
|
92
|
-
? await promptResetSuperAdminPasskey("Supervisor Setup"
|
|
93
|
+
? await promptResetSuperAdminPasskey("Supervisor Setup", {
|
|
94
|
+
defaultReset: !process.argv.includes("--setup"),
|
|
95
|
+
})
|
|
93
96
|
: false;
|
|
94
97
|
// Bootstrap before plugin register so the operator prompt isn't bounded by pluginTimeout and doesn't interleave with hub connection logs.
|
|
95
98
|
await bootstrapSupervisor({ resetSuperAdminPasskey });
|
|
@@ -105,6 +108,21 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
105
108
|
if (startupType === "hosted") {
|
|
106
109
|
logService.disableConsole();
|
|
107
110
|
}
|
|
111
|
+
let shutdownPromise = null;
|
|
112
|
+
async function runShutdown() {
|
|
113
|
+
try {
|
|
114
|
+
heartbeatService.cleanup();
|
|
115
|
+
await io.close();
|
|
116
|
+
await fastify.close();
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
await hubDatabaseService.disconnect();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const shutdown = () => {
|
|
123
|
+
shutdownPromise ??= runShutdown();
|
|
124
|
+
return shutdownPromise;
|
|
125
|
+
};
|
|
108
126
|
// Hosted mode: parent process owns signal handling
|
|
109
127
|
if (startupType === "standalone") {
|
|
110
128
|
let shuttingDown = false;
|
|
@@ -116,8 +134,7 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
116
134
|
shuttingDown = true;
|
|
117
135
|
logService.log(`[Hub] Shutting down (${signal})...`);
|
|
118
136
|
try {
|
|
119
|
-
await
|
|
120
|
-
await fastify.close();
|
|
137
|
+
await shutdown();
|
|
121
138
|
}
|
|
122
139
|
catch (err) {
|
|
123
140
|
console.error("[Hub] Error during shutdown:", err);
|
|
@@ -127,7 +144,7 @@ export const startHub = async (startupType, startSupervisor, plugins, startupAge
|
|
|
127
144
|
process.on("SIGTERM", () => void handleShutdown("SIGTERM"));
|
|
128
145
|
process.on("SIGINT", () => void handleShutdown("SIGINT"));
|
|
129
146
|
}
|
|
130
|
-
return { serverPort };
|
|
147
|
+
return { serverPort, shutdown };
|
|
131
148
|
}
|
|
132
149
|
catch (err) {
|
|
133
150
|
console.error("[Hub] Failed to start hub server:", err);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { adminAgentConfig, toUrlSafeKey } from "@naisys/common";
|
|
2
2
|
import { loadAgentConfigs } from "@naisys/common-node";
|
|
3
|
-
import {
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
4
|
/** Seeds agent configs from YAML files into an empty database. Skips if users already exist. */
|
|
5
5
|
export async function seedAgentConfigs({ hubDb }, logService, startupAgentPath) {
|
|
6
6
|
// Check if users table already has rows (seed-once pattern)
|
|
@@ -38,7 +38,6 @@ async function seedUsersToDatabase(hubDb, logService, users) {
|
|
|
38
38
|
username: safeUsername,
|
|
39
39
|
title: user.config.title,
|
|
40
40
|
config: JSON.stringify({ ...user.config, username: safeUsername }),
|
|
41
|
-
api_key: randomBytes(32).toString("hex"),
|
|
42
41
|
},
|
|
43
42
|
});
|
|
44
43
|
loaderIdToDbId.set(user.userId, dbUser.id);
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/hub",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.38",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@naisys/hub",
|
|
9
|
-
"version": "3.0.0-beta.
|
|
9
|
+
"version": "3.0.0-beta.38",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@naisys/common": "3.0.0-beta.
|
|
12
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
13
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
14
|
-
"@naisys/hub-protocol": "3.0.0-beta.
|
|
11
|
+
"@naisys/common": "3.0.0-beta.38",
|
|
12
|
+
"@naisys/common-node": "3.0.0-beta.38",
|
|
13
|
+
"@naisys/hub-database": "3.0.0-beta.38",
|
|
14
|
+
"@naisys/hub-protocol": "3.0.0-beta.38",
|
|
15
15
|
"commander": "^14.0.3",
|
|
16
16
|
"dotenv": "^17.3.1",
|
|
17
17
|
"fastify": "^5.8.2",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node": ">=22.0.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@naisys/supervisor": "3.0.0-beta.
|
|
27
|
+
"@naisys/supervisor": "3.0.0-beta.38"
|
|
28
28
|
},
|
|
29
29
|
"peerDependenciesMeta": {
|
|
30
30
|
"@naisys/supervisor": {
|
|
@@ -189,32 +189,32 @@
|
|
|
189
189
|
"license": "MIT"
|
|
190
190
|
},
|
|
191
191
|
"node_modules/@naisys/common": {
|
|
192
|
-
"version": "3.0.0-beta.
|
|
193
|
-
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.
|
|
194
|
-
"integrity": "sha512-
|
|
192
|
+
"version": "3.0.0-beta.38",
|
|
193
|
+
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.38.tgz",
|
|
194
|
+
"integrity": "sha512-YJIawcV12XNgzQz/QcM2oAYhu4O4V55tHm0JZrEdmBt2GS33VsGIVJqhDtg3sVWvtsDfh8QkK7EjwPEvgj7fzA==",
|
|
195
195
|
"dependencies": {
|
|
196
196
|
"semver": "^7.7.4",
|
|
197
197
|
"zod": "^4.3.6"
|
|
198
198
|
}
|
|
199
199
|
},
|
|
200
200
|
"node_modules/@naisys/common-node": {
|
|
201
|
-
"version": "3.0.0-beta.
|
|
202
|
-
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.
|
|
203
|
-
"integrity": "sha512-
|
|
201
|
+
"version": "3.0.0-beta.38",
|
|
202
|
+
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.38.tgz",
|
|
203
|
+
"integrity": "sha512-dNVvY+gWzBx4I+3chvNl74MgrcxVBFpPB+0acYSl7bcINvhqmbqLMYryR4AwOvU+dc09GDbpgugE6EWIQnn/zA==",
|
|
204
204
|
"dependencies": {
|
|
205
|
-
"@naisys/common": "3.0.0-beta.
|
|
205
|
+
"@naisys/common": "3.0.0-beta.38",
|
|
206
206
|
"better-sqlite3": "^12.6.2",
|
|
207
207
|
"js-yaml": "^4.1.1",
|
|
208
208
|
"pino": "^10.3.1"
|
|
209
209
|
}
|
|
210
210
|
},
|
|
211
211
|
"node_modules/@naisys/hub-database": {
|
|
212
|
-
"version": "3.0.0-beta.
|
|
213
|
-
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.
|
|
214
|
-
"integrity": "sha512-
|
|
212
|
+
"version": "3.0.0-beta.38",
|
|
213
|
+
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.38.tgz",
|
|
214
|
+
"integrity": "sha512-h+e50Qjg389ewSKU2jAisexlmajEAK34lMz6FKWd8Hog/PI6v3BYKB/8wgL2HmI78apmHIjh1FRW3NQNF+D8rw==",
|
|
215
215
|
"dependencies": {
|
|
216
|
-
"@naisys/common": "3.0.0-beta.
|
|
217
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
216
|
+
"@naisys/common": "3.0.0-beta.38",
|
|
217
|
+
"@naisys/common-node": "3.0.0-beta.38",
|
|
218
218
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
219
219
|
"@prisma/client": "^7.5.0",
|
|
220
220
|
"better-sqlite3": "^12.6.2",
|
|
@@ -222,11 +222,11 @@
|
|
|
222
222
|
}
|
|
223
223
|
},
|
|
224
224
|
"node_modules/@naisys/hub-protocol": {
|
|
225
|
-
"version": "3.0.0-beta.
|
|
226
|
-
"resolved": "https://registry.npmjs.org/@naisys/hub-protocol/-/hub-protocol-3.0.0-beta.
|
|
227
|
-
"integrity": "sha512-
|
|
225
|
+
"version": "3.0.0-beta.38",
|
|
226
|
+
"resolved": "https://registry.npmjs.org/@naisys/hub-protocol/-/hub-protocol-3.0.0-beta.38.tgz",
|
|
227
|
+
"integrity": "sha512-HLNcDmbdQVDeOxQlohoSrQdz/EXvNKx16BZVEovlwixuGCfINgweOkjtr4qypHO0peHPD0p1ayBa2QAjRrSY5Q==",
|
|
228
228
|
"dependencies": {
|
|
229
|
-
"@naisys/common": "3.0.0-beta.
|
|
229
|
+
"@naisys/common": "3.0.0-beta.38",
|
|
230
230
|
"zod": "^4.3.6"
|
|
231
231
|
}
|
|
232
232
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/hub",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.38",
|
|
4
4
|
"description": "NAISYS Hub - Adds persistence and multi-instance coordination to NAISYS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/naisysHub.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"!dist/**/*.d.ts.map"
|
|
32
32
|
],
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@naisys/supervisor": "3.0.0-beta.
|
|
34
|
+
"@naisys/supervisor": "3.0.0-beta.38"
|
|
35
35
|
},
|
|
36
36
|
"peerDependenciesMeta": {
|
|
37
37
|
"@naisys/supervisor": {
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@naisys/common": "3.0.0-beta.
|
|
43
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
44
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
45
|
-
"@naisys/hub-protocol": "3.0.0-beta.
|
|
42
|
+
"@naisys/common": "3.0.0-beta.38",
|
|
43
|
+
"@naisys/common-node": "3.0.0-beta.38",
|
|
44
|
+
"@naisys/hub-database": "3.0.0-beta.38",
|
|
45
|
+
"@naisys/hub-protocol": "3.0.0-beta.38",
|
|
46
46
|
"commander": "^14.0.3",
|
|
47
47
|
"dotenv": "^17.3.1",
|
|
48
48
|
"fastify": "^5.8.2",
|