meshy-node 0.4.5 → 0.4.7
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/README.md +1 -1
- package/dashboard/assets/DashboardPage-D9Y-YlT8.js +124 -0
- package/dashboard/assets/{DashboardShared-BdpxWcCV.js → DashboardShared-C7i9cRdE.js} +2 -2
- package/dashboard/assets/{DiffTab-CMaYxRh2.js → DiffTab-CNxzfPY1.js} +2 -2
- package/dashboard/assets/{FilesTab-8EoW1a5F.js → FilesTab-Dvib04o-.js} +1 -1
- package/dashboard/assets/{PreviewTab-DJEeyGWo.js → PreviewTab-D35bIOEK.js} +2 -2
- package/dashboard/assets/{SharedConversationPage-hyt9OBkY.js → SharedConversationPage-DaFHobVu.js} +3 -3
- package/dashboard/assets/{file-BBYxpzot.js → file-BxG0OwCA.js} +1 -1
- package/dashboard/assets/{folder-BCnKXNII.js → folder-6mjPM2Gc.js} +1 -1
- package/dashboard/assets/index-BOC8nP24.css +1 -0
- package/dashboard/assets/index-BTOpELYB.js +301 -0
- package/dashboard/assets/play-CSZ3EHkb.js +6 -0
- package/dashboard/index.html +2 -2
- package/main.cjs +256 -46
- package/package.json +1 -1
- package/runtime-metadata.json +5 -5
- package/dashboard/assets/DashboardPage-ByMFp2Hx.js +0 -124
- package/dashboard/assets/index-BgSOSh2K.js +0 -301
- package/dashboard/assets/index-BzzXPy7Y.css +0 -1
- package/dashboard/assets/input-BcMrrsRJ.js +0 -6
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{c as a}from"./index-BTOpELYB.js";/**
|
|
2
|
+
* @license lucide-react v1.7.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const o=[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]],e=a("play",o);export{e as P};
|
package/dashboard/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Meshy Dashboard</title>
|
|
7
7
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🕸</text></svg>" />
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BTOpELYB.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BOC8nP24.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/main.cjs
CHANGED
|
@@ -33863,9 +33863,56 @@ var LeaderElection = class {
|
|
|
33863
33863
|
var import_node_crypto5 = require("crypto");
|
|
33864
33864
|
var fs4 = __toESM(require("fs"), 1);
|
|
33865
33865
|
var path4 = __toESM(require("path"), 1);
|
|
33866
|
+
|
|
33867
|
+
// ../../packages/core/src/tasks/task-join-snapshot.ts
|
|
33868
|
+
var JOIN_TASK_SNAPSHOT_PAYLOAD_KEY = "__meshyJoinSnapshot";
|
|
33869
|
+
var MAX_JOIN_TASK_ERROR_LENGTH = 2e3;
|
|
33870
|
+
function truncate(value, maxLength) {
|
|
33871
|
+
if (value === null || value.length <= maxLength) {
|
|
33872
|
+
return value;
|
|
33873
|
+
}
|
|
33874
|
+
return `${value.slice(0, maxLength)}...`;
|
|
33875
|
+
}
|
|
33876
|
+
function shouldIncludeTaskInJoinSnapshot(task, selfId) {
|
|
33877
|
+
return task.assignedTo === null || task.assignedTo === selfId;
|
|
33878
|
+
}
|
|
33879
|
+
function createJoinTaskSnapshot(task, ownerNodeId) {
|
|
33880
|
+
return {
|
|
33881
|
+
...task,
|
|
33882
|
+
description: "",
|
|
33883
|
+
payload: {
|
|
33884
|
+
[JOIN_TASK_SNAPSHOT_PAYLOAD_KEY]: {
|
|
33885
|
+
ownerNodeId,
|
|
33886
|
+
version: 1
|
|
33887
|
+
}
|
|
33888
|
+
},
|
|
33889
|
+
result: null,
|
|
33890
|
+
error: truncate(task.error, MAX_JOIN_TASK_ERROR_LENGTH)
|
|
33891
|
+
};
|
|
33892
|
+
}
|
|
33893
|
+
function buildJoinTaskSnapshots(tasks, ownerNodeId) {
|
|
33894
|
+
return tasks.filter((task) => shouldIncludeTaskInJoinSnapshot(task, ownerNodeId)).map((task) => createJoinTaskSnapshot(task, ownerNodeId));
|
|
33895
|
+
}
|
|
33896
|
+
function getJoinTaskSnapshotOwnerId(task) {
|
|
33897
|
+
const metadata = task.payload[JOIN_TASK_SNAPSHOT_PAYLOAD_KEY];
|
|
33898
|
+
if (typeof metadata !== "object" || metadata === null) {
|
|
33899
|
+
return null;
|
|
33900
|
+
}
|
|
33901
|
+
const ownerNodeId = metadata.ownerNodeId;
|
|
33902
|
+
return typeof ownerNodeId === "string" && ownerNodeId.length > 0 ? ownerNodeId : null;
|
|
33903
|
+
}
|
|
33904
|
+
function isJoinTaskSnapshot(task) {
|
|
33905
|
+
return getJoinTaskSnapshotOwnerId(task) !== null;
|
|
33906
|
+
}
|
|
33907
|
+
|
|
33908
|
+
// ../../packages/core/src/tasks/task-engine.ts
|
|
33866
33909
|
function nodeSupportsAgent(node, agent) {
|
|
33867
33910
|
return !node.supportedAgents || node.supportedAgents.length === 0 || node.supportedAgents.includes(agent);
|
|
33868
33911
|
}
|
|
33912
|
+
function normalizePaginationBound(value) {
|
|
33913
|
+
if (value === void 0 || !Number.isFinite(value)) return void 0;
|
|
33914
|
+
return Math.max(0, Math.trunc(value));
|
|
33915
|
+
}
|
|
33869
33916
|
function getPublicTaskUpdates(updates, updatedAt) {
|
|
33870
33917
|
const publicUpdates = { updatedAt };
|
|
33871
33918
|
if (updates.title !== void 0) publicUpdates.title = updates.title;
|
|
@@ -33944,8 +33991,19 @@ var TaskEngine = class {
|
|
|
33944
33991
|
return this.store.getTask(id);
|
|
33945
33992
|
}
|
|
33946
33993
|
listTasks(filter) {
|
|
33947
|
-
const
|
|
33948
|
-
|
|
33994
|
+
const { limit, offset, ...storeFilter } = filter ?? {};
|
|
33995
|
+
const tasks = this.store.getAllTasks(storeFilter);
|
|
33996
|
+
const ordered = [...tasks].sort((left, right) => {
|
|
33997
|
+
const updatedDelta = right.updatedAt - left.updatedAt;
|
|
33998
|
+
if (updatedDelta !== 0) return updatedDelta;
|
|
33999
|
+
const createdDelta = right.createdAt - left.createdAt;
|
|
34000
|
+
if (createdDelta !== 0) return createdDelta;
|
|
34001
|
+
return left.id.localeCompare(right.id);
|
|
34002
|
+
});
|
|
34003
|
+
const normalizedOffset = normalizePaginationBound(offset) ?? 0;
|
|
34004
|
+
const normalizedLimit = normalizePaginationBound(limit);
|
|
34005
|
+
const paged = normalizedLimit === void 0 ? ordered.slice(normalizedOffset) : ordered.slice(normalizedOffset, normalizedOffset + normalizedLimit);
|
|
34006
|
+
return { tasks: paged, total: paged.length };
|
|
33949
34007
|
}
|
|
33950
34008
|
importTasks(tasks) {
|
|
33951
34009
|
let created = 0;
|
|
@@ -34148,7 +34206,9 @@ var TaskEngine = class {
|
|
|
34148
34206
|
if (now - task.updatedAt < backoff) continue;
|
|
34149
34207
|
}
|
|
34150
34208
|
const previousNodeId = this.previousAssignments.get(task.id);
|
|
34151
|
-
const
|
|
34209
|
+
const snapshotOwnerId = getJoinTaskSnapshotOwnerId(task);
|
|
34210
|
+
const candidateNodes = snapshotOwnerId ? availableNodes.filter((node) => node.id === snapshotOwnerId) : availableNodes;
|
|
34211
|
+
const capableNodes = candidateNodes.filter((node) => nodeSupportsAgent(node, task.agent));
|
|
34152
34212
|
if (capableNodes.length === 0) continue;
|
|
34153
34213
|
const targetNode = this.pickLeastBusyNode(capableNodes, nodeLoad, previousNodeId);
|
|
34154
34214
|
if (!targetNode) continue;
|
|
@@ -36160,16 +36220,17 @@ var RestLeaderTaskReporter = class {
|
|
|
36160
36220
|
var import_node_child_process2 = require("child_process");
|
|
36161
36221
|
async function startWorkerTaskExecution(options) {
|
|
36162
36222
|
const { taskEngine, engineRegistry, nodeRegistry, eventBus, logger: logger27, workDir, leaderReporter } = options;
|
|
36163
|
-
const
|
|
36164
|
-
const existing = taskEngine.getTask(
|
|
36223
|
+
const incomingTask = { ...options.task };
|
|
36224
|
+
const existing = taskEngine.getTask(incomingTask.id);
|
|
36165
36225
|
if (existing && hasExecutionAlreadyStarted(existing.status)) {
|
|
36166
36226
|
logger27.warn("skipping duplicate task.execute for already-started task", {
|
|
36167
|
-
taskId:
|
|
36227
|
+
taskId: incomingTask.id,
|
|
36168
36228
|
status: existing.status,
|
|
36169
|
-
agent:
|
|
36229
|
+
agent: incomingTask.agent
|
|
36170
36230
|
});
|
|
36171
36231
|
return existing;
|
|
36172
36232
|
}
|
|
36233
|
+
const task = getExecutionTask(incomingTask, existing);
|
|
36173
36234
|
task.effectiveProjectPath = resolveTaskWorkDir(task.project, workDir);
|
|
36174
36235
|
task.branch = getCurrentGitBranch(task.effectiveProjectPath) ?? task.branch ?? null;
|
|
36175
36236
|
await taskEngine.executeTask(task);
|
|
@@ -36219,6 +36280,17 @@ async function startWorkerTaskExecution(options) {
|
|
|
36219
36280
|
}
|
|
36220
36281
|
return task;
|
|
36221
36282
|
}
|
|
36283
|
+
function getExecutionTask(incomingTask, existing) {
|
|
36284
|
+
if (!existing || !isJoinTaskSnapshot(incomingTask) || isJoinTaskSnapshot(existing)) {
|
|
36285
|
+
return incomingTask;
|
|
36286
|
+
}
|
|
36287
|
+
return {
|
|
36288
|
+
...existing,
|
|
36289
|
+
status: incomingTask.status,
|
|
36290
|
+
assignedTo: incomingTask.assignedTo,
|
|
36291
|
+
assignedNodeName: incomingTask.assignedNodeName
|
|
36292
|
+
};
|
|
36293
|
+
}
|
|
36222
36294
|
function hasExecutionAlreadyStarted(status) {
|
|
36223
36295
|
return status === "running" || status === "completed" || status === "failed" || status === "cancelled" || status === "archived";
|
|
36224
36296
|
}
|
|
@@ -37780,8 +37852,8 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
37780
37852
|
devtunnelEndpoint
|
|
37781
37853
|
});
|
|
37782
37854
|
}
|
|
37783
|
-
const tasks = this.taskEngine.listTasks().tasks;
|
|
37784
37855
|
const self2 = this.nodeRegistry.getSelf();
|
|
37856
|
+
const tasks = buildJoinTaskSnapshots(this.taskEngine.listTasks().tasks, self2.id);
|
|
37785
37857
|
const joinBody = {
|
|
37786
37858
|
id: self2.id,
|
|
37787
37859
|
endpoint: self2.endpoint,
|
|
@@ -37872,6 +37944,7 @@ ${joinErrors.map((e) => ` - ${e}`).join("\n")}`
|
|
|
37872
37944
|
leaderEndpoint,
|
|
37873
37945
|
selfId: self2.id
|
|
37874
37946
|
});
|
|
37947
|
+
persistNodeStartupJoin(this.config.storage.path, void 0);
|
|
37875
37948
|
return;
|
|
37876
37949
|
}
|
|
37877
37950
|
if (leader && leaderEndpoint) {
|
|
@@ -43030,6 +43103,7 @@ var JoinTaskSchema = external_exports.object({
|
|
|
43030
43103
|
agent: external_exports.string(),
|
|
43031
43104
|
project: external_exports.string().nullable(),
|
|
43032
43105
|
effectiveProjectPath: external_exports.string().nullable(),
|
|
43106
|
+
branch: external_exports.string().nullable().optional(),
|
|
43033
43107
|
conversationKind: external_exports.enum(["meshyChat", "nativeSession"]).optional(),
|
|
43034
43108
|
payload: external_exports.record(external_exports.unknown()),
|
|
43035
43109
|
status: external_exports.enum(["pending", "assigned", "running", "completed", "failed", "cancelled", "archived"]),
|
|
@@ -43816,10 +43890,19 @@ function createClusterRoutes() {
|
|
|
43816
43890
|
});
|
|
43817
43891
|
}));
|
|
43818
43892
|
router.post("/leave", asyncHandler(async (req, res) => {
|
|
43819
|
-
const { nodeRegistry, logger: rootLogger } = req.app.locals.deps;
|
|
43893
|
+
const { nodeRegistry, election, leaveCurrentCluster, logger: rootLogger } = req.app.locals.deps;
|
|
43820
43894
|
const log2 = rootLogger.child("cluster/leave");
|
|
43821
43895
|
const { nodeId } = req.body;
|
|
43822
43896
|
log2.info("received cluster leave request", { nodeId });
|
|
43897
|
+
if (!election.isLeader()) {
|
|
43898
|
+
if (!leaveCurrentCluster) {
|
|
43899
|
+
throw new MeshyError("VALIDATION_ERROR", "Leave flow is not available on this node", 501);
|
|
43900
|
+
}
|
|
43901
|
+
log2.info("handling cluster leave request as local follower detach", { requestedNodeId: nodeId });
|
|
43902
|
+
await leaveCurrentCluster();
|
|
43903
|
+
res.json({ ok: true });
|
|
43904
|
+
return;
|
|
43905
|
+
}
|
|
43823
43906
|
nodeRegistry.removeNode(nodeId);
|
|
43824
43907
|
res.json({ ok: true });
|
|
43825
43908
|
}));
|
|
@@ -44849,6 +44932,58 @@ function upgradeRuntimeAgentForDeps(deps, agent) {
|
|
|
44849
44932
|
return result;
|
|
44850
44933
|
}
|
|
44851
44934
|
|
|
44935
|
+
// ../../packages/api/src/node/runtime-restart-request.ts
|
|
44936
|
+
function parseRuntimeRestartRequest(value) {
|
|
44937
|
+
const body = isRecord4(value) ? value : {};
|
|
44938
|
+
const startArgs = parseRuntimeRestartStartArgs(body.startArgs);
|
|
44939
|
+
return {
|
|
44940
|
+
reason: body.reason === "update" ? "update" : "restart",
|
|
44941
|
+
...startArgs && { startArgs }
|
|
44942
|
+
};
|
|
44943
|
+
}
|
|
44944
|
+
function parseRuntimeRestartStartArgs(value) {
|
|
44945
|
+
if (value === void 0) return void 0;
|
|
44946
|
+
if (!isRecord4(value)) {
|
|
44947
|
+
throw new MeshyError("VALIDATION_ERROR", "Runtime restart startArgs must be an object", 400);
|
|
44948
|
+
}
|
|
44949
|
+
const startArgs = {};
|
|
44950
|
+
if (value.port !== void 0) {
|
|
44951
|
+
const port = value.port;
|
|
44952
|
+
if (typeof port !== "number" || !Number.isInteger(port) || port <= 0) {
|
|
44953
|
+
throw new MeshyError("VALIDATION_ERROR", "Runtime restart port must be a positive integer", 400);
|
|
44954
|
+
}
|
|
44955
|
+
startArgs.port = port;
|
|
44956
|
+
}
|
|
44957
|
+
for (const key of ["name", "join", "workDir", "config"]) {
|
|
44958
|
+
const parsed = parseOptionalString(value[key], key);
|
|
44959
|
+
if (parsed !== void 0) startArgs[key] = parsed;
|
|
44960
|
+
}
|
|
44961
|
+
if (value.transport !== void 0) {
|
|
44962
|
+
if (value.transport !== "direct" && value.transport !== "devtunnel" && value.transport !== "tailscale") {
|
|
44963
|
+
throw new MeshyError("VALIDATION_ERROR", "Runtime restart transport must be direct, devtunnel, or tailscale", 400);
|
|
44964
|
+
}
|
|
44965
|
+
startArgs.transport = value.transport;
|
|
44966
|
+
}
|
|
44967
|
+
if (value.disableAuth !== void 0) {
|
|
44968
|
+
if (typeof value.disableAuth !== "boolean") {
|
|
44969
|
+
throw new MeshyError("VALIDATION_ERROR", "Runtime restart disableAuth must be a boolean", 400);
|
|
44970
|
+
}
|
|
44971
|
+
startArgs.disableAuth = value.disableAuth;
|
|
44972
|
+
}
|
|
44973
|
+
return Object.keys(startArgs).length > 0 ? startArgs : void 0;
|
|
44974
|
+
}
|
|
44975
|
+
function parseOptionalString(value, key) {
|
|
44976
|
+
if (value === void 0) return void 0;
|
|
44977
|
+
if (typeof value !== "string") {
|
|
44978
|
+
throw new MeshyError("VALIDATION_ERROR", `Runtime restart ${key} must be a string`, 400);
|
|
44979
|
+
}
|
|
44980
|
+
const trimmed = value.trim();
|
|
44981
|
+
return trimmed || void 0;
|
|
44982
|
+
}
|
|
44983
|
+
function isRecord4(value) {
|
|
44984
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
44985
|
+
}
|
|
44986
|
+
|
|
44852
44987
|
// ../../packages/api/src/node/node-operation-service.ts
|
|
44853
44988
|
var LEADER_REPORT_RETRY_MS = 5e3;
|
|
44854
44989
|
var OPERATION_COMMIT_EFFECT = /* @__PURE__ */ Symbol("operationCommitEffect");
|
|
@@ -45062,7 +45197,8 @@ function runAgentUpgradeOperation(operation, deps) {
|
|
|
45062
45197
|
function runRuntimeRestartOperation(operation, deps) {
|
|
45063
45198
|
if (!deps.restartRuntime) throw new Error("Runtime restart is not available for this node");
|
|
45064
45199
|
const reason = readPayloadString(operation, "reason") === "update" ? "update" : "restart";
|
|
45065
|
-
|
|
45200
|
+
const startArgs = readPayloadStartArgs(operation);
|
|
45201
|
+
return deps.restartRuntime({ reason, ...startArgs && { startArgs }, deferShutdown: true }).then(
|
|
45066
45202
|
({ completeShutdown, ...result }) => operationCommitEffect(result, completeShutdown)
|
|
45067
45203
|
);
|
|
45068
45204
|
}
|
|
@@ -45109,6 +45245,11 @@ function readPayloadBoolean(operation, key, fallback) {
|
|
|
45109
45245
|
const value = payload[key];
|
|
45110
45246
|
return typeof value === "boolean" ? value : fallback;
|
|
45111
45247
|
}
|
|
45248
|
+
function readPayloadStartArgs(operation) {
|
|
45249
|
+
const payload = operation.payload;
|
|
45250
|
+
if (!payload || typeof payload !== "object") return void 0;
|
|
45251
|
+
return parseRuntimeRestartStartArgs(payload.startArgs);
|
|
45252
|
+
}
|
|
45112
45253
|
function readSettingsSnapshot(value) {
|
|
45113
45254
|
if (!value || typeof value !== "object") return void 0;
|
|
45114
45255
|
const snapshot = value.settingsSnapshot;
|
|
@@ -45276,7 +45417,7 @@ function toLegacyWorkerControl2(message) {
|
|
|
45276
45417
|
}
|
|
45277
45418
|
|
|
45278
45419
|
// ../../packages/api/src/tasks/task-route-utils.ts
|
|
45279
|
-
function
|
|
45420
|
+
function isRecord5(value) {
|
|
45280
45421
|
return typeof value === "object" && value !== null;
|
|
45281
45422
|
}
|
|
45282
45423
|
function restoreTaskState(taskEngine, task) {
|
|
@@ -45343,7 +45484,7 @@ function normalizeStructuredValue(value) {
|
|
|
45343
45484
|
if (Array.isArray(value)) {
|
|
45344
45485
|
return value.map((entry) => normalizeStructuredValue(entry));
|
|
45345
45486
|
}
|
|
45346
|
-
if (!
|
|
45487
|
+
if (!isRecord5(value)) {
|
|
45347
45488
|
return value;
|
|
45348
45489
|
}
|
|
45349
45490
|
return Object.fromEntries(
|
|
@@ -45352,20 +45493,20 @@ function normalizeStructuredValue(value) {
|
|
|
45352
45493
|
}
|
|
45353
45494
|
function getTranscriptEventSignature(event) {
|
|
45354
45495
|
if (event.type === "user") {
|
|
45355
|
-
const signature = getTaskUserMessageSignature(
|
|
45496
|
+
const signature = getTaskUserMessageSignature(isRecord5(event.message) ? event.message.content : event.message) ?? getTaskUserMessageSignature(event.content);
|
|
45356
45497
|
return signature ? `user:${signature}` : null;
|
|
45357
45498
|
}
|
|
45358
45499
|
if (event.type === "assistant") {
|
|
45359
45500
|
if (typeof event.message === "string") {
|
|
45360
45501
|
return `assistant:${JSON.stringify(event.message)}`;
|
|
45361
45502
|
}
|
|
45362
|
-
if (
|
|
45503
|
+
if (isRecord5(event.message) && "content" in event.message) {
|
|
45363
45504
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.message.content))}`;
|
|
45364
45505
|
}
|
|
45365
45506
|
if (Array.isArray(event.content)) {
|
|
45366
45507
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.content))}`;
|
|
45367
45508
|
}
|
|
45368
|
-
if (
|
|
45509
|
+
if (isRecord5(event.message)) {
|
|
45369
45510
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.message))}`;
|
|
45370
45511
|
}
|
|
45371
45512
|
}
|
|
@@ -47162,9 +47303,6 @@ async function sendNodeAgentUpgrade(req, res, nodeId, agentParam) {
|
|
|
47162
47303
|
}
|
|
47163
47304
|
|
|
47164
47305
|
// ../../packages/api/src/routes/node-runtime.ts
|
|
47165
|
-
function parseRestartReason(value) {
|
|
47166
|
-
return value === "update" ? "update" : "restart";
|
|
47167
|
-
}
|
|
47168
47306
|
async function sendNodeRuntimeRestart(req, res, nodeId) {
|
|
47169
47307
|
const deps = req.app.locals.deps;
|
|
47170
47308
|
const self2 = deps.nodeRegistry.getSelf();
|
|
@@ -47176,9 +47314,9 @@ async function sendNodeRuntimeRestart(req, res, nodeId) {
|
|
|
47176
47314
|
if (!node) {
|
|
47177
47315
|
throw new MeshyError("NODE_NOT_FOUND", `Node ${nodeId} not found`, 404);
|
|
47178
47316
|
}
|
|
47179
|
-
const
|
|
47317
|
+
const restartRequest = parseRuntimeRestartRequest(req.body);
|
|
47180
47318
|
const operations = getNodeOperationService(deps);
|
|
47181
|
-
const operation = operations.create("runtime.restart", nodeId, {
|
|
47319
|
+
const operation = operations.create("runtime.restart", nodeId, { ...restartRequest });
|
|
47182
47320
|
if (isSelf) {
|
|
47183
47321
|
operations.runLocal(operation.id);
|
|
47184
47322
|
} else {
|
|
@@ -48099,8 +48237,10 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
48099
48237
|
if (!task && !proxyRequest.isProxy && await maybeProxyReadToLeader(req, res)) return;
|
|
48100
48238
|
const selfId = nodeRegistry.getSelf()?.id;
|
|
48101
48239
|
const isLeader = nodeRegistry.isLeader();
|
|
48240
|
+
const snapshotOwnerId = task ? getJoinTaskSnapshotOwnerId(task) : null;
|
|
48241
|
+
const proxyNodeId = task?.assignedTo ?? snapshotOwnerId;
|
|
48102
48242
|
const isFollowerRemoteTask = !isLeader && !!(task?.assignedTo && task.assignedTo !== selfId);
|
|
48103
|
-
const needsProxy = isLeader && !!(
|
|
48243
|
+
const needsProxy = isLeader && !!(proxyNodeId && proxyNodeId !== selfId);
|
|
48104
48244
|
if (proxyRequest.isProxy) {
|
|
48105
48245
|
log2.info("received proxied task logs request", {
|
|
48106
48246
|
taskId,
|
|
@@ -48118,6 +48258,7 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
48118
48258
|
log2.debug("log request", {
|
|
48119
48259
|
taskId,
|
|
48120
48260
|
assignedTo: task?.assignedTo,
|
|
48261
|
+
snapshotOwnerId,
|
|
48121
48262
|
selfId,
|
|
48122
48263
|
isLeader,
|
|
48123
48264
|
needsProxy
|
|
@@ -48141,20 +48282,21 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
48141
48282
|
selfId
|
|
48142
48283
|
});
|
|
48143
48284
|
}
|
|
48144
|
-
|
|
48145
|
-
|
|
48146
|
-
const node = nodeRegistry.getNode(assignedTo);
|
|
48285
|
+
if (needsProxy && proxyNodeId) {
|
|
48286
|
+
const node = nodeRegistry.getNode(proxyNodeId);
|
|
48147
48287
|
log2.debug("proxy target", { nodeId: node?.id, endpoint: node?.endpoint, devtunnel: node?.devtunnelEndpoint, status: node?.status });
|
|
48148
48288
|
if (node) {
|
|
48149
|
-
|
|
48150
|
-
|
|
48151
|
-
|
|
48152
|
-
|
|
48153
|
-
|
|
48289
|
+
if (task.assignedTo === proxyNodeId && !snapshotOwnerId) {
|
|
48290
|
+
const seededLogs = await seedTaskSnapshotOnWorker(task, [], node, log2).catch((err) => {
|
|
48291
|
+
log2.warn("failed to seed task snapshot before task logs proxy", {
|
|
48292
|
+
taskId,
|
|
48293
|
+
assignedTo: proxyNodeId,
|
|
48294
|
+
...describeProxyError3(err)
|
|
48295
|
+
});
|
|
48296
|
+
return [];
|
|
48154
48297
|
});
|
|
48155
|
-
|
|
48156
|
-
}
|
|
48157
|
-
if (seededLogs.length > 0) recordLocalTaskLogs(engineRegistry, task, seededLogs);
|
|
48298
|
+
if (seededLogs.length > 0) recordLocalTaskLogs(engineRegistry, task, seededLogs);
|
|
48299
|
+
}
|
|
48158
48300
|
const proxyPath = `/api/tasks/${taskId}/logs?after=${after}`;
|
|
48159
48301
|
try {
|
|
48160
48302
|
const { endpoint, response: proxyRes } = await fetchNodeWithFallback(
|
|
@@ -48168,7 +48310,7 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
48168
48310
|
const proxyUrl = `${endpoint}${proxyPath}`;
|
|
48169
48311
|
log2.info("proxying task logs request", {
|
|
48170
48312
|
taskId,
|
|
48171
|
-
assignedTo,
|
|
48313
|
+
assignedTo: proxyNodeId,
|
|
48172
48314
|
endpoint,
|
|
48173
48315
|
proxyPath,
|
|
48174
48316
|
url: proxyUrl
|
|
@@ -48181,11 +48323,11 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
48181
48323
|
} catch (err) {
|
|
48182
48324
|
log2.warn("task logs proxy failed; falling back to keepalive control", {
|
|
48183
48325
|
taskId,
|
|
48184
|
-
assignedTo,
|
|
48326
|
+
assignedTo: proxyNodeId,
|
|
48185
48327
|
timeoutMs: TASK_LOG_PROXY_TIMEOUT_MS,
|
|
48186
48328
|
...describeProxyError3(err)
|
|
48187
48329
|
});
|
|
48188
|
-
const fallback = await requestTaskLogsOverKeepalive(heartbeat,
|
|
48330
|
+
const fallback = await requestTaskLogsOverKeepalive(heartbeat, proxyNodeId, task, after);
|
|
48189
48331
|
if (fallback) {
|
|
48190
48332
|
sendWorkerControlResponse(res, fallback);
|
|
48191
48333
|
return;
|
|
@@ -48576,6 +48718,8 @@ var TERMINAL_STATUSES3 = /* @__PURE__ */ new Set(["completed", "failed", "cancel
|
|
|
48576
48718
|
var ARCHIVABLE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "archived"]);
|
|
48577
48719
|
var ACTIVE_STATUSES = /* @__PURE__ */ new Set(["pending", "assigned", "running"]);
|
|
48578
48720
|
var TASK_DELETE_NOTIFY_TIMEOUT_MS = 1500;
|
|
48721
|
+
var TASK_DETAIL_PROXY_TIMEOUT_MS = 1e4;
|
|
48722
|
+
var TASK_DETAIL_PROXY_HEADER = "x-meshy-task-detail-proxy";
|
|
48579
48723
|
function shouldGenerateTitle(task) {
|
|
48580
48724
|
return task.payload.titleSource === "derived";
|
|
48581
48725
|
}
|
|
@@ -48686,6 +48830,62 @@ function withShareMetadata(task, taskEngine, shareOrigin) {
|
|
|
48686
48830
|
function toTaskResponse(task, nodeRegistry, taskEngine, shareOrigin) {
|
|
48687
48831
|
return withShareMetadata(withAssignedNodeMetadata(task, nodeRegistry), taskEngine, shareOrigin);
|
|
48688
48832
|
}
|
|
48833
|
+
async function proxyJoinSnapshotTaskDetail(deps) {
|
|
48834
|
+
if (deps.req.get(TASK_DETAIL_PROXY_HEADER) === "1") {
|
|
48835
|
+
return null;
|
|
48836
|
+
}
|
|
48837
|
+
const ownerNodeId = getJoinTaskSnapshotOwnerId(deps.task);
|
|
48838
|
+
const selfId = deps.nodeRegistry.getSelf()?.id;
|
|
48839
|
+
if (!ownerNodeId || ownerNodeId === selfId) {
|
|
48840
|
+
return null;
|
|
48841
|
+
}
|
|
48842
|
+
const owner = deps.nodeRegistry.getNode(ownerNodeId);
|
|
48843
|
+
const log2 = deps.logger.child("tasks/detail");
|
|
48844
|
+
if (!owner) {
|
|
48845
|
+
log2.warn("join snapshot owner is unavailable for task detail proxy", {
|
|
48846
|
+
taskId: deps.task.id,
|
|
48847
|
+
ownerNodeId
|
|
48848
|
+
});
|
|
48849
|
+
return null;
|
|
48850
|
+
}
|
|
48851
|
+
const proxyPath = `/api/tasks/${encodeURIComponent(deps.task.id)}`;
|
|
48852
|
+
try {
|
|
48853
|
+
const { endpoint, response } = await fetchNodeWithFallback(
|
|
48854
|
+
owner,
|
|
48855
|
+
proxyPath,
|
|
48856
|
+
{ method: "GET", headers: { [TASK_DETAIL_PROXY_HEADER]: "1" } },
|
|
48857
|
+
TASK_DETAIL_PROXY_TIMEOUT_MS,
|
|
48858
|
+
void 0,
|
|
48859
|
+
{ preferPublicEndpoint: true }
|
|
48860
|
+
);
|
|
48861
|
+
if (!response.ok) {
|
|
48862
|
+
log2.warn("join snapshot task detail proxy returned non-ok response", {
|
|
48863
|
+
taskId: deps.task.id,
|
|
48864
|
+
ownerNodeId,
|
|
48865
|
+
endpoint,
|
|
48866
|
+
statusCode: response.status
|
|
48867
|
+
});
|
|
48868
|
+
return null;
|
|
48869
|
+
}
|
|
48870
|
+
const fullTask = await response.json();
|
|
48871
|
+
if (fullTask.id !== deps.task.id) {
|
|
48872
|
+
log2.warn("join snapshot task detail proxy returned a different task id", {
|
|
48873
|
+
taskId: deps.task.id,
|
|
48874
|
+
ownerNodeId,
|
|
48875
|
+
returnedTaskId: fullTask.id
|
|
48876
|
+
});
|
|
48877
|
+
return null;
|
|
48878
|
+
}
|
|
48879
|
+
return fullTask;
|
|
48880
|
+
} catch (err) {
|
|
48881
|
+
log2.warn("join snapshot task detail proxy failed", {
|
|
48882
|
+
taskId: deps.task.id,
|
|
48883
|
+
ownerNodeId,
|
|
48884
|
+
error: err instanceof Error ? err.message : String(err)
|
|
48885
|
+
});
|
|
48886
|
+
return null;
|
|
48887
|
+
}
|
|
48888
|
+
}
|
|
48689
48889
|
function buildShareUrl(origin, shareId) {
|
|
48690
48890
|
return `${origin.replace(/\/+$/, "")}/shared/tasks/${encodeURIComponent(shareId)}`;
|
|
48691
48891
|
}
|
|
@@ -48809,14 +49009,15 @@ function createTaskRoutes() {
|
|
|
48809
49009
|
res.json({ results });
|
|
48810
49010
|
}));
|
|
48811
49011
|
router.get("/:id", asyncHandler6(async (req, res) => {
|
|
48812
|
-
const { taskEngine, nodeRegistry, shareOrigin } = req.app.locals.deps;
|
|
49012
|
+
const { taskEngine, nodeRegistry, shareOrigin, logger: logger27 } = req.app.locals.deps;
|
|
48813
49013
|
const taskId = req.params.id;
|
|
48814
49014
|
const task = taskEngine.getTask(taskId);
|
|
48815
49015
|
if (!task) {
|
|
48816
49016
|
if (await maybeProxyReadToLeader(req, res)) return;
|
|
48817
49017
|
throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
|
|
48818
49018
|
}
|
|
48819
|
-
|
|
49019
|
+
const fullTask = await proxyJoinSnapshotTaskDetail({ task, req, logger: logger27, nodeRegistry });
|
|
49020
|
+
res.json(toTaskResponse(fullTask ?? task, nodeRegistry, taskEngine, shareOrigin));
|
|
48820
49021
|
}));
|
|
48821
49022
|
router.post("/:id/share", asyncHandler6(async (req, res) => {
|
|
48822
49023
|
const { taskEngine, ensureShareTunnel } = req.app.locals.deps;
|
|
@@ -49491,9 +49692,8 @@ function createSystemRoutes() {
|
|
|
49491
49692
|
if (!restartRuntime) {
|
|
49492
49693
|
throw new MeshyError("VALIDATION_ERROR", "Runtime restart is not available for this node", 501);
|
|
49493
49694
|
}
|
|
49494
|
-
const
|
|
49495
|
-
const
|
|
49496
|
-
const result = await restartRuntime({ reason });
|
|
49695
|
+
const restartRequest = parseRuntimeRestartRequest(req.body);
|
|
49696
|
+
const result = await restartRuntime(restartRequest);
|
|
49497
49697
|
res.status(202).json(result);
|
|
49498
49698
|
}));
|
|
49499
49699
|
router.post("/runtime/stop", asyncHandler9(async (req, res) => {
|
|
@@ -49672,6 +49872,9 @@ function createNodeOperationRoutes() {
|
|
|
49672
49872
|
var JSON_BODY_LIMIT = "1mb";
|
|
49673
49873
|
var JSON_BODY_LIMIT_LARGE = "25mb";
|
|
49674
49874
|
var TRUSTED_LOCAL_HOSTS2 = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
|
|
49875
|
+
function usesLargeJsonBodyLimit(pathname) {
|
|
49876
|
+
return pathname === "/api/cluster/join" || pathname === "/api/node" || pathname.startsWith("/api/node/") || pathname === "/api/tasks" || pathname.startsWith("/api/tasks/") || pathname === "/api/worker" || pathname.startsWith("/api/worker/");
|
|
49877
|
+
}
|
|
49675
49878
|
function normalizeHost2(value) {
|
|
49676
49879
|
const trimmed = value?.trim().toLowerCase();
|
|
49677
49880
|
return trimmed ? trimmed.replace(/:\d+$/, "") : void 0;
|
|
@@ -49798,7 +50001,12 @@ function createServer2(deps) {
|
|
|
49798
50001
|
staticMiddleware(req, res, next);
|
|
49799
50002
|
});
|
|
49800
50003
|
}
|
|
49801
|
-
|
|
50004
|
+
const defaultJsonParser = import_express14.default.json({ limit: JSON_BODY_LIMIT });
|
|
50005
|
+
const largeJsonParser = import_express14.default.json({ limit: JSON_BODY_LIMIT_LARGE });
|
|
50006
|
+
app.use((req, res, next) => {
|
|
50007
|
+
const parser = usesLargeJsonBodyLimit(req.path) ? largeJsonParser : defaultJsonParser;
|
|
50008
|
+
parser(req, res, next);
|
|
50009
|
+
});
|
|
49802
50010
|
app.use(createAuthMiddleware(authConfig));
|
|
49803
50011
|
app.use((req, res, next) => {
|
|
49804
50012
|
void (async () => {
|
|
@@ -49824,14 +50032,13 @@ function createServer2(deps) {
|
|
|
49824
50032
|
taskEngine: deps.taskEngine,
|
|
49825
50033
|
logger: deps.logger
|
|
49826
50034
|
}));
|
|
49827
|
-
const largeBodyParser = import_express14.default.json({ limit: JSON_BODY_LIMIT_LARGE });
|
|
49828
50035
|
app.use("/api/cluster", createClusterRoutes());
|
|
49829
50036
|
app.use("/api/cluster-control", createClusterControlRoutes());
|
|
49830
|
-
app.use("/api/node",
|
|
50037
|
+
app.use("/api/node", createNodeMessageRoutes());
|
|
49831
50038
|
app.use("/api/nodes", createNodeRoutes());
|
|
49832
|
-
app.use("/api/tasks",
|
|
50039
|
+
app.use("/api/tasks", createTaskRoutes());
|
|
49833
50040
|
app.use("/api/shared", createSharedRoutes());
|
|
49834
|
-
app.use("/api/worker",
|
|
50041
|
+
app.use("/api/worker", createWorkerRoutes());
|
|
49835
50042
|
app.use("/api/system", createSystemRoutes());
|
|
49836
50043
|
app.use("/api/node-operations", createNodeOperationRoutes());
|
|
49837
50044
|
app.use("/api/events", createEventRoutes());
|
|
@@ -50875,6 +51082,9 @@ function buildRuntimeMetadata(storagePath) {
|
|
|
50875
51082
|
var fs22 = __toESM(require("fs"), 1);
|
|
50876
51083
|
var nodePath2 = __toESM(require("path"), 1);
|
|
50877
51084
|
var import_node_child_process14 = require("child_process");
|
|
51085
|
+
function resolveRuntimeRestartStartArgs(hydratedArgs, restartArgs) {
|
|
51086
|
+
return restartArgs ? { ...restartArgs } : hydratedArgs;
|
|
51087
|
+
}
|
|
50878
51088
|
var runtimeUpdateCache = /* @__PURE__ */ new Map();
|
|
50879
51089
|
var RESTARTER_SOURCE = String.raw`
|
|
50880
51090
|
const { spawn } = require('node:child_process');
|
|
@@ -51842,7 +52052,7 @@ async function startNode(args) {
|
|
|
51842
52052
|
cwd: process.cwd(),
|
|
51843
52053
|
env: process.env,
|
|
51844
52054
|
localDashboardOrigin,
|
|
51845
|
-
startArgs: hydratedArgs.args,
|
|
52055
|
+
startArgs: resolveRuntimeRestartStartArgs(hydratedArgs.args, request.startArgs),
|
|
51846
52056
|
storagePath: config.storage.path
|
|
51847
52057
|
});
|
|
51848
52058
|
scheduleRuntimeRestart(plan, { parentPid: process.pid });
|
package/package.json
CHANGED
package/runtime-metadata.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "meshy-node",
|
|
3
|
-
"packageVersion": "0.4.
|
|
3
|
+
"packageVersion": "0.4.7",
|
|
4
4
|
"packages": {
|
|
5
5
|
"workspace": {
|
|
6
6
|
"name": "meshy",
|
|
7
|
-
"version": "0.4.
|
|
7
|
+
"version": "0.4.7"
|
|
8
8
|
},
|
|
9
9
|
"node": {
|
|
10
10
|
"name": "meshy-node",
|
|
11
|
-
"version": "0.4.
|
|
11
|
+
"version": "0.4.7"
|
|
12
12
|
},
|
|
13
13
|
"core": {
|
|
14
14
|
"name": "@meshy/core",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"repository": {
|
|
27
27
|
"url": "https://github.com/ai-microsoft/meshy",
|
|
28
|
-
"branch": "
|
|
29
|
-
"commit": "
|
|
28
|
+
"branch": "fixTaskCount",
|
|
29
|
+
"commit": "ba555ae"
|
|
30
30
|
}
|
|
31
31
|
}
|