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.
@@ -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};
@@ -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'>&#x1F578;</text></svg>" />
8
- <script type="module" crossorigin src="/assets/index-BgSOSh2K.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-BzzXPy7Y.css">
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 tasks = this.store.getAllTasks(filter);
33948
- return { tasks, total: tasks.length };
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 capableNodes = availableNodes.filter((node) => nodeSupportsAgent(node, task.agent));
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 task = { ...options.task };
36164
- const existing = taskEngine.getTask(task.id);
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: task.id,
36227
+ taskId: incomingTask.id,
36168
36228
  status: existing.status,
36169
- agent: task.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
- return deps.restartRuntime({ reason, deferShutdown: true }).then(
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 isRecord4(value) {
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 (!isRecord4(value)) {
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(isRecord4(event.message) ? event.message.content : event.message) ?? getTaskUserMessageSignature(event.content);
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 (isRecord4(event.message) && "content" in event.message) {
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 (isRecord4(event.message)) {
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 reason = parseRestartReason(req.body?.reason);
47317
+ const restartRequest = parseRuntimeRestartRequest(req.body);
47180
47318
  const operations = getNodeOperationService(deps);
47181
- const operation = operations.create("runtime.restart", nodeId, { reason });
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 && !!(task?.assignedTo && task.assignedTo !== selfId);
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
- const assignedTo = task.assignedTo;
48145
- if (needsProxy && assignedTo) {
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
- const seededLogs = await seedTaskSnapshotOnWorker(task, [], node, log2).catch((err) => {
48150
- log2.warn("failed to seed task snapshot before task logs proxy", {
48151
- taskId,
48152
- assignedTo,
48153
- ...describeProxyError3(err)
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
- return [];
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, assignedTo, task, after);
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
- res.json(toTaskResponse(task, nodeRegistry, taskEngine, shareOrigin));
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 body = req.body;
49495
- const reason = body.reason === "update" ? "update" : "restart";
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
- app.use(import_express14.default.json({ limit: JSON_BODY_LIMIT }));
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", largeBodyParser, createNodeMessageRoutes());
50037
+ app.use("/api/node", createNodeMessageRoutes());
49831
50038
  app.use("/api/nodes", createNodeRoutes());
49832
- app.use("/api/tasks", largeBodyParser, createTaskRoutes());
50039
+ app.use("/api/tasks", createTaskRoutes());
49833
50040
  app.use("/api/shared", createSharedRoutes());
49834
- app.use("/api/worker", largeBodyParser, createWorkerRoutes());
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meshy-node",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "private": false,
5
5
  "description": "Standalone Meshy node package with bundled runtime and dashboard assets.",
6
6
  "type": "commonjs",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "packageName": "meshy-node",
3
- "packageVersion": "0.4.5",
3
+ "packageVersion": "0.4.7",
4
4
  "packages": {
5
5
  "workspace": {
6
6
  "name": "meshy",
7
- "version": "0.4.5"
7
+ "version": "0.4.7"
8
8
  },
9
9
  "node": {
10
10
  "name": "meshy-node",
11
- "version": "0.4.5"
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": "NodeRelaunch",
29
- "commit": "9e6493f"
28
+ "branch": "fixTaskCount",
29
+ "commit": "ba555ae"
30
30
  }
31
31
  }