meshy-node 0.10.7 → 0.10.9
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-bZy6ZY6K.js +181 -0
- package/dashboard/assets/{DashboardShared-BUUqTMMG.js → DashboardShared-CrDF53oL.js} +18 -18
- package/dashboard/assets/{DiffTab-BJ-QDAVa.js → DiffTab-CNBS3yRm.js} +2 -2
- package/dashboard/assets/{FilesTab-CXyf-FqN.js → FilesTab-BHeht0ZL.js} +2 -2
- package/dashboard/assets/{MarkdownPreviewFrame-CFCsFLMN.js → MarkdownPreviewFrame-L2oxne--.js} +1 -1
- package/dashboard/assets/{PreviewTab-hYU-Sg4s.js → PreviewTab-UMpaLVaV.js} +2 -2
- package/dashboard/assets/SharedConversationPage-CTyYVCbw.js +2 -0
- package/dashboard/assets/{file-Ct6iLy28.js → file-BgR9-rpB.js} +1 -1
- package/dashboard/assets/index-By1kKB26.css +1 -0
- package/dashboard/assets/index-D260dUEm.js +346 -0
- package/dashboard/index.html +2 -2
- package/main.cjs +633 -160
- package/package.json +1 -1
- package/runtime-metadata.json +4 -4
- package/dashboard/assets/DashboardPage-B8aG_22p.js +0 -176
- package/dashboard/assets/SharedConversationPage-Bb7cY7t7.js +0 -2
- package/dashboard/assets/index-0SJFGvhq.js +0 -346
- package/dashboard/assets/index-Br15-PXW.css +0 -1
package/main.cjs
CHANGED
|
@@ -136339,6 +136339,8 @@ var fs3 = __toESM(require("fs"), 1);
|
|
|
136339
136339
|
var os3 = __toESM(require("os"), 1);
|
|
136340
136340
|
var path3 = __toESM(require("path"), 1);
|
|
136341
136341
|
var STARTUP_TRANSPORTS = /* @__PURE__ */ new Set(["direct", "devtunnel", "tailscale"]);
|
|
136342
|
+
var DEFAULT_TASK_AGENTS = /* @__PURE__ */ new Set(["codex", "claudecode", "copilot"]);
|
|
136343
|
+
var DEFAULT_NODE_TASK_AGENT = "codex";
|
|
136342
136344
|
function getDeviceNodeName() {
|
|
136343
136345
|
return os3.hostname();
|
|
136344
136346
|
}
|
|
@@ -136408,6 +136410,9 @@ function normalizeString(value) {
|
|
|
136408
136410
|
function normalizeStartupTransport(value) {
|
|
136409
136411
|
return typeof value === "string" && STARTUP_TRANSPORTS.has(value) ? value : void 0;
|
|
136410
136412
|
}
|
|
136413
|
+
function normalizeDefaultTaskAgent(value) {
|
|
136414
|
+
return typeof value === "string" && DEFAULT_TASK_AGENTS.has(value) ? value : void 0;
|
|
136415
|
+
}
|
|
136411
136416
|
function normalizeStartupMetadata(startup) {
|
|
136412
136417
|
return {
|
|
136413
136418
|
port: normalizePositiveInteger(startup?.port),
|
|
@@ -136445,6 +136450,9 @@ function resolveDefaultNodeName(storagePath, deviceName = getDeviceNodeName()) {
|
|
|
136445
136450
|
const preferredName = resolvePersistedDefaultNodeName(storagePath);
|
|
136446
136451
|
return preferredName && preferredName.length > 0 ? preferredName : deviceName;
|
|
136447
136452
|
}
|
|
136453
|
+
function resolveNodeDefaultTaskAgent(storagePath) {
|
|
136454
|
+
return normalizeDefaultTaskAgent(readNodeMetadata(storagePath).defaultTaskAgent) ?? DEFAULT_NODE_TASK_AGENT;
|
|
136455
|
+
}
|
|
136448
136456
|
function persistDefaultNodeName(storagePath, name2, deviceName = getDeviceNodeName()) {
|
|
136449
136457
|
const metadata = readNodeMetadata(storagePath);
|
|
136450
136458
|
const normalizedName = name2.trim();
|
|
@@ -136455,6 +136463,11 @@ function persistDefaultNodeName(storagePath, name2, deviceName = getDeviceNodeNa
|
|
|
136455
136463
|
}
|
|
136456
136464
|
writeNodeMetadata(storagePath, metadata);
|
|
136457
136465
|
}
|
|
136466
|
+
function persistNodeDefaultTaskAgent(storagePath, agent) {
|
|
136467
|
+
const metadata = readNodeMetadata(storagePath);
|
|
136468
|
+
metadata.defaultTaskAgent = agent;
|
|
136469
|
+
writeNodeMetadata(storagePath, metadata);
|
|
136470
|
+
}
|
|
136458
136471
|
function resolveNodeAuthMetadata(storagePath) {
|
|
136459
136472
|
return normalizeAuthMetadata(readNodeMetadata(storagePath).auth);
|
|
136460
136473
|
}
|
|
@@ -136958,6 +136971,7 @@ function parseTaskQueuedMessages(value) {
|
|
|
136958
136971
|
messages.push({
|
|
136959
136972
|
id: entry.id,
|
|
136960
136973
|
content: clone(entry.content),
|
|
136974
|
+
...typeof entry.targetAgent === "string" ? { targetAgent: entry.targetAgent } : {},
|
|
136961
136975
|
createdAt: entry.createdAt
|
|
136962
136976
|
});
|
|
136963
136977
|
}
|
|
@@ -138439,7 +138453,7 @@ var TaskEngine = class {
|
|
|
138439
138453
|
});
|
|
138440
138454
|
return true;
|
|
138441
138455
|
}
|
|
138442
|
-
enqueueTaskMessage(taskId, content3) {
|
|
138456
|
+
enqueueTaskMessage(taskId, content3, targetAgent) {
|
|
138443
138457
|
const task = this.store.getTask(taskId);
|
|
138444
138458
|
if (!task) {
|
|
138445
138459
|
throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
|
|
@@ -138454,7 +138468,12 @@ var TaskEngine = class {
|
|
|
138454
138468
|
const now = Date.now();
|
|
138455
138469
|
const queuedMessages = [
|
|
138456
138470
|
...task.queuedMessages ?? [],
|
|
138457
|
-
{
|
|
138471
|
+
{
|
|
138472
|
+
id: (0, import_node_crypto5.randomUUID)(),
|
|
138473
|
+
content: content3,
|
|
138474
|
+
...targetAgent ? { targetAgent } : {},
|
|
138475
|
+
createdAt: now
|
|
138476
|
+
}
|
|
138458
138477
|
];
|
|
138459
138478
|
const updated = this.store.updateTask(taskId, { queuedMessages, updatedAt: now });
|
|
138460
138479
|
this.eventBus.emit("task.updated", {
|
|
@@ -138742,11 +138761,12 @@ var DEFAULT_CONFIG = {
|
|
|
138742
138761
|
dispatchTimeout: 1e4
|
|
138743
138762
|
};
|
|
138744
138763
|
var TaskDispatcher = class {
|
|
138745
|
-
constructor(taskEngine, nodeRegistry, election, eventBus, config2, logger33, nodeMessageClient) {
|
|
138764
|
+
constructor(taskEngine, nodeRegistry, election, eventBus, config2, logger33, nodeMessageClient, localNodeMessageHandler) {
|
|
138746
138765
|
this.taskEngine = taskEngine;
|
|
138747
138766
|
this.nodeRegistry = nodeRegistry;
|
|
138748
138767
|
this.election = election;
|
|
138749
138768
|
this.eventBus = eventBus;
|
|
138769
|
+
this.localNodeMessageHandler = localNodeMessageHandler;
|
|
138750
138770
|
this.config = { ...DEFAULT_CONFIG, ...config2 };
|
|
138751
138771
|
this.log = logger33?.child("task-dispatcher") ?? { debug() {
|
|
138752
138772
|
}, info() {
|
|
@@ -138756,10 +138776,7 @@ var TaskDispatcher = class {
|
|
|
138756
138776
|
return this;
|
|
138757
138777
|
} };
|
|
138758
138778
|
this.messageClient = nodeMessageClient ?? new NodeMessageClient({ timeoutMs: this.config.dispatchTimeout, logger: logger33 });
|
|
138759
|
-
this.onTaskAssigned = (data) =>
|
|
138760
|
-
void this.dispatchTask(data.taskId, data.nodeId).catch(() => {
|
|
138761
|
-
});
|
|
138762
|
-
};
|
|
138779
|
+
this.onTaskAssigned = (data) => this.scheduleDispatch(data.taskId, data.nodeId);
|
|
138763
138780
|
this.onElectionComplete = (data) => {
|
|
138764
138781
|
const self2 = this.nodeRegistry.getSelf();
|
|
138765
138782
|
if (data.leaderId === self2.id) {
|
|
@@ -138773,10 +138790,12 @@ var TaskDispatcher = class {
|
|
|
138773
138790
|
nodeRegistry;
|
|
138774
138791
|
election;
|
|
138775
138792
|
eventBus;
|
|
138793
|
+
localNodeMessageHandler;
|
|
138776
138794
|
config;
|
|
138777
138795
|
log;
|
|
138778
138796
|
messageClient;
|
|
138779
138797
|
autoAssignTimer = null;
|
|
138798
|
+
pendingDispatchTimers = /* @__PURE__ */ new Set();
|
|
138780
138799
|
running = false;
|
|
138781
138800
|
onTaskAssigned;
|
|
138782
138801
|
onElectionComplete;
|
|
@@ -138794,6 +138813,7 @@ var TaskDispatcher = class {
|
|
|
138794
138813
|
this.eventBus.off("task.assigned", this.onTaskAssigned);
|
|
138795
138814
|
this.eventBus.off("election.complete", this.onElectionComplete);
|
|
138796
138815
|
this.stopAutoAssignLoop();
|
|
138816
|
+
this.clearPendingDispatchTimers();
|
|
138797
138817
|
}
|
|
138798
138818
|
// ── Dispatch ────────────────────────────────────────────────────────
|
|
138799
138819
|
async dispatchTask(taskId, nodeId) {
|
|
@@ -138817,7 +138837,13 @@ var TaskDispatcher = class {
|
|
|
138817
138837
|
endpoint: node2.endpoint,
|
|
138818
138838
|
devtunnelEndpoint: node2.devtunnelEndpoint
|
|
138819
138839
|
});
|
|
138820
|
-
|
|
138840
|
+
const message = createNodeMessage("task.execute", { task });
|
|
138841
|
+
if (node2.id === this.nodeRegistry.getSelf().id && this.localNodeMessageHandler) {
|
|
138842
|
+
await this.localNodeMessageHandler(message);
|
|
138843
|
+
this.log.info("task dispatch request accepted", { taskId, nodeId, local: true });
|
|
138844
|
+
return;
|
|
138845
|
+
}
|
|
138846
|
+
await this.messageClient.send(node2, message);
|
|
138821
138847
|
this.log.info("task dispatch request accepted", { taskId, nodeId });
|
|
138822
138848
|
} catch (err) {
|
|
138823
138849
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -138843,6 +138869,20 @@ var TaskDispatcher = class {
|
|
|
138843
138869
|
this.autoAssignTimer = null;
|
|
138844
138870
|
}
|
|
138845
138871
|
}
|
|
138872
|
+
scheduleDispatch(taskId, nodeId) {
|
|
138873
|
+
const timer = setTimeout(() => {
|
|
138874
|
+
this.pendingDispatchTimers.delete(timer);
|
|
138875
|
+
void this.dispatchTask(taskId, nodeId).catch(() => {
|
|
138876
|
+
});
|
|
138877
|
+
}, 0);
|
|
138878
|
+
this.pendingDispatchTimers.add(timer);
|
|
138879
|
+
}
|
|
138880
|
+
clearPendingDispatchTimers() {
|
|
138881
|
+
for (const timer of this.pendingDispatchTimers) {
|
|
138882
|
+
clearTimeout(timer);
|
|
138883
|
+
}
|
|
138884
|
+
this.pendingDispatchTimers.clear();
|
|
138885
|
+
}
|
|
138846
138886
|
};
|
|
138847
138887
|
|
|
138848
138888
|
// ../../packages/core/src/cluster/heartbeat.ts
|
|
@@ -140021,6 +140061,31 @@ var ExecutionEngine = class {
|
|
|
140021
140061
|
await Promise.all([...this.logWrites.values()]);
|
|
140022
140062
|
}
|
|
140023
140063
|
}
|
|
140064
|
+
async getLogLineCount(taskId) {
|
|
140065
|
+
const logPath = this.getLogPath(taskId);
|
|
140066
|
+
try {
|
|
140067
|
+
const content3 = await fs7.promises.readFile(logPath, "utf-8");
|
|
140068
|
+
const trimmed = content3.trim();
|
|
140069
|
+
return trimmed ? trimmed.split("\n").filter(Boolean).length : 0;
|
|
140070
|
+
} catch (error2) {
|
|
140071
|
+
if (error2.code === "ENOENT") return 0;
|
|
140072
|
+
throw error2;
|
|
140073
|
+
}
|
|
140074
|
+
}
|
|
140075
|
+
async flushLogsAndEmitReady(taskId) {
|
|
140076
|
+
try {
|
|
140077
|
+
await this.waitForLogWrites();
|
|
140078
|
+
const total = await this.getLogLineCount(taskId);
|
|
140079
|
+
this.eventBus.emit("task.logs.ready", { taskId, total });
|
|
140080
|
+
return total;
|
|
140081
|
+
} catch (error2) {
|
|
140082
|
+
this.logger.warn("failed to emit task log readiness checkpoint", {
|
|
140083
|
+
taskId,
|
|
140084
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
140085
|
+
});
|
|
140086
|
+
return 0;
|
|
140087
|
+
}
|
|
140088
|
+
}
|
|
140024
140089
|
getLogPath(taskId) {
|
|
140025
140090
|
return path7.join(this.logDir, `${taskId}.jsonl`);
|
|
140026
140091
|
}
|
|
@@ -140886,9 +140951,59 @@ function nonEmptyString(value) {
|
|
|
140886
140951
|
function getNativeHistorySessionId(payload) {
|
|
140887
140952
|
return nonEmptyString(payload?.nativeSessionId) || nonEmptyString(payload?.sessionId);
|
|
140888
140953
|
}
|
|
140889
|
-
function
|
|
140954
|
+
function isRecord5(value) {
|
|
140955
|
+
return typeof value === "object" && value !== null;
|
|
140956
|
+
}
|
|
140957
|
+
function getAgentSessions(payload) {
|
|
140958
|
+
const raw3 = payload.agentSessions;
|
|
140959
|
+
if (!isRecord5(raw3)) return {};
|
|
140960
|
+
const sessions = {};
|
|
140961
|
+
for (const [agent, value] of Object.entries(raw3)) {
|
|
140962
|
+
if (!isRecord5(value)) continue;
|
|
140963
|
+
const sessionId = nonEmptyString(value.sessionId);
|
|
140964
|
+
const cwd = nonEmptyString(value.cwd);
|
|
140965
|
+
if (!agent || !sessionId || !cwd) continue;
|
|
140966
|
+
sessions[agent] = { sessionId, cwd };
|
|
140967
|
+
}
|
|
140968
|
+
return sessions;
|
|
140969
|
+
}
|
|
140970
|
+
function getPersistedAgentSession(task, agent) {
|
|
140971
|
+
const payload = task?.payload ?? {};
|
|
140972
|
+
const sessions = getAgentSessions(payload);
|
|
140973
|
+
const session = sessions[agent];
|
|
140974
|
+
if (session) return session;
|
|
140975
|
+
if (Object.keys(sessions).length > 0 || task?.agent !== agent) {
|
|
140976
|
+
return null;
|
|
140977
|
+
}
|
|
140978
|
+
const legacySessionId = nonEmptyString(payload.sessionId);
|
|
140979
|
+
if (!legacySessionId) return null;
|
|
140980
|
+
return {
|
|
140981
|
+
sessionId: legacySessionId,
|
|
140982
|
+
cwd: nonEmptyString(payload.sessionCwd)
|
|
140983
|
+
};
|
|
140984
|
+
}
|
|
140985
|
+
function canUseSessionLogEventForAgent(task, agent, event) {
|
|
140986
|
+
const eventAgent = nonEmptyString(event.agent);
|
|
140987
|
+
if (eventAgent) return eventAgent === agent;
|
|
140988
|
+
const sessions = getAgentSessions(task?.payload ?? {});
|
|
140989
|
+
return Object.keys(sessions).length === 0 && task?.agent === agent;
|
|
140990
|
+
}
|
|
140991
|
+
function buildPersistedSessionPayload(task, sessionId, cwd, agent) {
|
|
140890
140992
|
const payload = task?.payload ?? {};
|
|
140993
|
+
const activeAgent = nonEmptyString(agent);
|
|
140891
140994
|
const nextPayload = { ...payload, sessionId, sessionCwd: cwd };
|
|
140995
|
+
if (activeAgent) {
|
|
140996
|
+
const agentSessions = getAgentSessions(payload);
|
|
140997
|
+
const taskAgent = nonEmptyString(task?.agent);
|
|
140998
|
+
const legacySessionId = nonEmptyString(payload.sessionId);
|
|
140999
|
+
const legacyCwd = nonEmptyString(payload.sessionCwd) || cwd;
|
|
141000
|
+
if (taskAgent && legacySessionId && !agentSessions[taskAgent]) {
|
|
141001
|
+
agentSessions[taskAgent] = { sessionId: legacySessionId, cwd: legacyCwd };
|
|
141002
|
+
}
|
|
141003
|
+
agentSessions[activeAgent] = { sessionId, cwd };
|
|
141004
|
+
nextPayload.activeAgent = activeAgent;
|
|
141005
|
+
nextPayload.agentSessions = agentSessions;
|
|
141006
|
+
}
|
|
140892
141007
|
if (task?.conversationKind !== "nativeSession") {
|
|
140893
141008
|
return nextPayload;
|
|
140894
141009
|
}
|
|
@@ -141001,10 +141116,44 @@ function forwardTaskOutputToLeader(log2, nodeRegistry, taskId, event) {
|
|
|
141001
141116
|
});
|
|
141002
141117
|
});
|
|
141003
141118
|
}
|
|
141119
|
+
function postLogsReadyToLeader(log2, leaderEndpoint, taskId, total) {
|
|
141120
|
+
fetch(`${leaderEndpoint}/api/worker/logs-ready`, applyRequestAuthHeaders({
|
|
141121
|
+
method: "POST",
|
|
141122
|
+
headers: { "Content-Type": "application/json" },
|
|
141123
|
+
body: JSON.stringify({ taskId, total })
|
|
141124
|
+
})).then((response) => {
|
|
141125
|
+
if (!response.ok) {
|
|
141126
|
+
log2.warn("leader rejected log readiness report", {
|
|
141127
|
+
taskId,
|
|
141128
|
+
total,
|
|
141129
|
+
leaderEndpoint,
|
|
141130
|
+
statusCode: response.status
|
|
141131
|
+
});
|
|
141132
|
+
return;
|
|
141133
|
+
}
|
|
141134
|
+
log2.debug("forwarded log readiness to leader", { taskId, total, leaderEndpoint, statusCode: response.status });
|
|
141135
|
+
}).catch((err) => {
|
|
141136
|
+
log2.warn("failed to forward log readiness", {
|
|
141137
|
+
taskId,
|
|
141138
|
+
total,
|
|
141139
|
+
leaderEndpoint,
|
|
141140
|
+
error: err instanceof Error ? err.message : String(err)
|
|
141141
|
+
});
|
|
141142
|
+
});
|
|
141143
|
+
}
|
|
141144
|
+
function forwardTaskLogsReadyToLeader(log2, nodeRegistry, taskId, total) {
|
|
141145
|
+
const leaderEndpoint = nodeRegistry.getLeaderEndpoint();
|
|
141146
|
+
if (!leaderEndpoint) {
|
|
141147
|
+
log2.warn("skipping log readiness forward because leader endpoint is missing", { taskId, total });
|
|
141148
|
+
return;
|
|
141149
|
+
}
|
|
141150
|
+
postLogsReadyToLeader(log2, leaderEndpoint, taskId, total);
|
|
141151
|
+
}
|
|
141004
141152
|
function registerLeaderForwarding(eventBus, nodeRegistry, log2, taskId, agent, reporter) {
|
|
141005
141153
|
const cleanup = () => {
|
|
141006
141154
|
eventBus.off("task.status", onTaskStatus);
|
|
141007
141155
|
eventBus.off("task.output", onTaskOutput);
|
|
141156
|
+
eventBus.off("task.logs.ready", onTaskLogsReady);
|
|
141008
141157
|
};
|
|
141009
141158
|
const onTaskOutput = (data) => {
|
|
141010
141159
|
if (data.taskId !== taskId) return;
|
|
@@ -141016,6 +141165,16 @@ function registerLeaderForwarding(eventBus, nodeRegistry, log2, taskId, agent, r
|
|
|
141016
141165
|
if (reporter) reporter.reportOutput(taskId, data.event);
|
|
141017
141166
|
else forwardTaskOutputToLeader(log2, nodeRegistry, taskId, data.event);
|
|
141018
141167
|
};
|
|
141168
|
+
const onTaskLogsReady = (data) => {
|
|
141169
|
+
if (data.taskId !== taskId) return;
|
|
141170
|
+
log2.debug("task.logs.ready event", {
|
|
141171
|
+
taskId,
|
|
141172
|
+
total: data.total,
|
|
141173
|
+
hasLeader: !!nodeRegistry.getLeaderEndpoint()
|
|
141174
|
+
});
|
|
141175
|
+
if (reporter) reporter.reportLogsReady(taskId, data.total);
|
|
141176
|
+
else forwardTaskLogsReadyToLeader(log2, nodeRegistry, taskId, data.total);
|
|
141177
|
+
};
|
|
141019
141178
|
const onTaskStatus = (data) => {
|
|
141020
141179
|
if (data.taskId !== taskId || data.status === "running") return;
|
|
141021
141180
|
cleanup();
|
|
@@ -141041,11 +141200,175 @@ function registerLeaderForwarding(eventBus, nodeRegistry, log2, taskId, agent, r
|
|
|
141041
141200
|
});
|
|
141042
141201
|
};
|
|
141043
141202
|
eventBus.on("task.output", onTaskOutput);
|
|
141203
|
+
eventBus.on("task.logs.ready", onTaskLogsReady);
|
|
141044
141204
|
eventBus.on("task.status", onTaskStatus);
|
|
141045
141205
|
log2.debug("registered leader forwarding listeners", { taskId, agent });
|
|
141046
141206
|
return cleanup;
|
|
141047
141207
|
}
|
|
141048
141208
|
|
|
141209
|
+
// ../../packages/core/src/tasks/agent-task-turn.ts
|
|
141210
|
+
init_cjs_shims();
|
|
141211
|
+
function startAgentTaskTurn(options) {
|
|
141212
|
+
const agent = resolveActiveAgent(options.task, options.targetAgent);
|
|
141213
|
+
if (!supportsFollowUpAgent(agent)) {
|
|
141214
|
+
throw new MeshyError("VALIDATION_ERROR", `Agent ${agent} does not support chat messages`, 400);
|
|
141215
|
+
}
|
|
141216
|
+
const engine = options.engineRegistry.get(agent);
|
|
141217
|
+
if (!engine) {
|
|
141218
|
+
throw new MeshyError("VALIDATION_ERROR", `Engine not registered for agent: ${agent}`, 400);
|
|
141219
|
+
}
|
|
141220
|
+
const updates = {
|
|
141221
|
+
status: "running",
|
|
141222
|
+
assignedTo: options.assignedTo
|
|
141223
|
+
};
|
|
141224
|
+
if (options.targetAgent || options.task.payload.activeAgent !== void 0) {
|
|
141225
|
+
updates.payload = {
|
|
141226
|
+
...options.task.payload,
|
|
141227
|
+
activeAgent: agent
|
|
141228
|
+
};
|
|
141229
|
+
}
|
|
141230
|
+
options.taskEngine.updateTask(options.task.id, updates);
|
|
141231
|
+
const handoffEvent = buildExplicitHandoffEvent(options.task, options.targetAgent, agent);
|
|
141232
|
+
if (handoffEvent) {
|
|
141233
|
+
recordAndEmit(options, engine, handoffEvent);
|
|
141234
|
+
}
|
|
141235
|
+
const handoffContent = handoffEvent ? buildAgentHandoffContent(options.task, engine, options.content, agent) : null;
|
|
141236
|
+
const sendContent = handoffContent ?? options.content;
|
|
141237
|
+
const sendOptions = handoffContent ? { logContent: options.content } : void 0;
|
|
141238
|
+
try {
|
|
141239
|
+
if (sendOptions) engine.sendMessage(options.task.id, sendContent, sendOptions);
|
|
141240
|
+
else engine.sendMessage(options.task.id, sendContent);
|
|
141241
|
+
return;
|
|
141242
|
+
} catch (err) {
|
|
141243
|
+
if (!shouldStartHandoff(options.targetAgent, err)) {
|
|
141244
|
+
throw err;
|
|
141245
|
+
}
|
|
141246
|
+
options.logger.info("starting cross-agent handoff turn", {
|
|
141247
|
+
taskId: options.task.id,
|
|
141248
|
+
fromAgent: resolveActiveAgent(options.task),
|
|
141249
|
+
toAgent: agent,
|
|
141250
|
+
...options.metadata
|
|
141251
|
+
});
|
|
141252
|
+
startHandoffRun(options, engine, agent, !handoffEvent, handoffContent);
|
|
141253
|
+
}
|
|
141254
|
+
}
|
|
141255
|
+
function resolveActiveAgent(task, targetAgent) {
|
|
141256
|
+
const explicit = targetAgent?.trim();
|
|
141257
|
+
if (explicit) return explicit;
|
|
141258
|
+
const active = typeof task.payload.activeAgent === "string" ? task.payload.activeAgent.trim() : "";
|
|
141259
|
+
return active || task.agent;
|
|
141260
|
+
}
|
|
141261
|
+
function shouldStartHandoff(targetAgent, err) {
|
|
141262
|
+
return Boolean(targetAgent) && err instanceof MeshyError && err.code === "TASK_NOT_FOUND";
|
|
141263
|
+
}
|
|
141264
|
+
function buildExplicitHandoffEvent(task, targetAgent, agent) {
|
|
141265
|
+
if (!targetAgent?.trim()) return null;
|
|
141266
|
+
const fromAgent = resolveActiveAgent(task);
|
|
141267
|
+
return fromAgent === agent ? null : buildAgentHandoffLogEvent(fromAgent, agent);
|
|
141268
|
+
}
|
|
141269
|
+
function startHandoffRun(options, engine, agent, recordBoundary, prebuiltContent) {
|
|
141270
|
+
const fromAgent = resolveActiveAgent(options.task);
|
|
141271
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
141272
|
+
const boundary = buildAgentHandoffLogEvent(fromAgent, agent, timestamp);
|
|
141273
|
+
const userEvent = {
|
|
141274
|
+
...buildTaskUserLogEvent(options.content, timestamp),
|
|
141275
|
+
agent
|
|
141276
|
+
};
|
|
141277
|
+
if (recordBoundary) {
|
|
141278
|
+
recordAndEmit(options, engine, boundary);
|
|
141279
|
+
}
|
|
141280
|
+
recordAndEmit(options, engine, userEvent);
|
|
141281
|
+
const handoffTask = {
|
|
141282
|
+
...options.task,
|
|
141283
|
+
agent,
|
|
141284
|
+
status: "running",
|
|
141285
|
+
assignedTo: options.assignedTo,
|
|
141286
|
+
payload: {
|
|
141287
|
+
...options.task.payload,
|
|
141288
|
+
activeAgent: agent,
|
|
141289
|
+
initialMessage: prebuiltContent ?? buildAgentHandoffContent(options.task, engine, options.content, agent)
|
|
141290
|
+
}
|
|
141291
|
+
};
|
|
141292
|
+
engine.run(handoffTask);
|
|
141293
|
+
}
|
|
141294
|
+
function recordAndEmit(options, engine, event) {
|
|
141295
|
+
engine.recordOutput(options.task.id, event);
|
|
141296
|
+
options.eventBus.emit("task.output", { taskId: options.task.id, event });
|
|
141297
|
+
}
|
|
141298
|
+
function buildAgentHandoffLogEvent(fromAgent, toAgent, timestamp = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
141299
|
+
return {
|
|
141300
|
+
type: "agent.handoff",
|
|
141301
|
+
fromAgent,
|
|
141302
|
+
toAgent,
|
|
141303
|
+
timestamp
|
|
141304
|
+
};
|
|
141305
|
+
}
|
|
141306
|
+
function buildAgentHandoffContent(task, engine, currentContent, targetAgent) {
|
|
141307
|
+
const logs4 = readTaskLogs(engine, task.id);
|
|
141308
|
+
const historyLines = extractVisibleTranscriptLines(logs4);
|
|
141309
|
+
if (historyLines.length === 0) {
|
|
141310
|
+
const initialLines = contentToVisibleLines("User", normalizeTaskUserMessageContent(task.payload.initialMessage));
|
|
141311
|
+
historyLines.push(...initialLines);
|
|
141312
|
+
}
|
|
141313
|
+
const currentText = contentToPlainText(currentContent) || "[non-text user content]";
|
|
141314
|
+
const text10 = [
|
|
141315
|
+
`You are taking over this Meshy task as ${targetAgent}.`,
|
|
141316
|
+
"",
|
|
141317
|
+
"Previous visible conversation:",
|
|
141318
|
+
historyLines.length > 0 ? historyLines.join("\n") : "[No visible previous transcript found.]",
|
|
141319
|
+
"",
|
|
141320
|
+
"Current user request:",
|
|
141321
|
+
currentText
|
|
141322
|
+
].join("\n");
|
|
141323
|
+
return [{ type: "text", text: text10 }, ...currentContent.filter((part) => part.type !== "text")];
|
|
141324
|
+
}
|
|
141325
|
+
function readTaskLogs(engine, taskId) {
|
|
141326
|
+
return readJsonLines(engine.getLogPath(taskId));
|
|
141327
|
+
}
|
|
141328
|
+
function extractVisibleTranscriptLines(events) {
|
|
141329
|
+
const lines = [];
|
|
141330
|
+
for (const event of events) {
|
|
141331
|
+
if (event.type === "user" && event.isMeta !== true && event.isSidechain !== true) {
|
|
141332
|
+
lines.push(...contentToVisibleLines("User", extractUserContent(event)));
|
|
141333
|
+
}
|
|
141334
|
+
if (event.type === "assistant") {
|
|
141335
|
+
const text10 = extractAssistantText(event);
|
|
141336
|
+
if (text10) lines.push(`Assistant: ${text10}`);
|
|
141337
|
+
}
|
|
141338
|
+
}
|
|
141339
|
+
return lines;
|
|
141340
|
+
}
|
|
141341
|
+
function extractUserContent(event) {
|
|
141342
|
+
const message = isRecord6(event.message) ? event.message : null;
|
|
141343
|
+
const messageContent = message?.content;
|
|
141344
|
+
const directContent = event.content;
|
|
141345
|
+
return normalizeTaskUserMessageContent(messageContent ?? directContent ?? event.message).filter((part) => part.type !== "tool_result");
|
|
141346
|
+
}
|
|
141347
|
+
function contentToVisibleLines(label, content3) {
|
|
141348
|
+
const text10 = contentToPlainText(content3);
|
|
141349
|
+
return text10 ? [`${label}: ${text10}`] : [];
|
|
141350
|
+
}
|
|
141351
|
+
function contentToPlainText(content3) {
|
|
141352
|
+
return content3.map((part) => {
|
|
141353
|
+
if (part.type === "text") return part.text;
|
|
141354
|
+
if (part.type === "image") return `[image: ${part.filename ?? part.mediaType}]`;
|
|
141355
|
+
return "";
|
|
141356
|
+
}).filter(Boolean).join("\n").trim();
|
|
141357
|
+
}
|
|
141358
|
+
function extractAssistantText(event) {
|
|
141359
|
+
if (typeof event.message === "string") return event.message.trim();
|
|
141360
|
+
const content3 = isRecord6(event.message) ? event.message.content : event.content;
|
|
141361
|
+
if (!Array.isArray(content3)) return "";
|
|
141362
|
+
return content3.flatMap((block) => {
|
|
141363
|
+
if (!isRecord6(block) || block.type !== "text" || typeof block.text !== "string") return [];
|
|
141364
|
+
const text10 = block.text.trim();
|
|
141365
|
+
return text10 ? [text10] : [];
|
|
141366
|
+
}).join("\n").trim();
|
|
141367
|
+
}
|
|
141368
|
+
function isRecord6(value) {
|
|
141369
|
+
return typeof value === "object" && value !== null;
|
|
141370
|
+
}
|
|
141371
|
+
|
|
141049
141372
|
// ../../packages/core/src/tasks/leader-task-reporter.ts
|
|
141050
141373
|
init_cjs_shims();
|
|
141051
141374
|
var RestLeaderTaskReporter = class {
|
|
@@ -141089,6 +141412,14 @@ var RestLeaderTaskReporter = class {
|
|
|
141089
141412
|
});
|
|
141090
141413
|
});
|
|
141091
141414
|
}
|
|
141415
|
+
reportLogsReady(taskId, total) {
|
|
141416
|
+
const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
|
|
141417
|
+
if (!leaderEndpoint) {
|
|
141418
|
+
this.logger.warn("skipping log readiness report because leader endpoint is missing", { taskId, total });
|
|
141419
|
+
return;
|
|
141420
|
+
}
|
|
141421
|
+
postLogsReadyToLeader(this.logger, leaderEndpoint, taskId, total);
|
|
141422
|
+
}
|
|
141092
141423
|
patchTask(taskId, data, label, successMessage) {
|
|
141093
141424
|
const leaderEndpoint = this.nodeRegistry.getLeaderEndpoint();
|
|
141094
141425
|
if (!leaderEndpoint) {
|
|
@@ -141540,14 +141871,14 @@ function getClaudeStreamError(event) {
|
|
|
141540
141871
|
}
|
|
141541
141872
|
return null;
|
|
141542
141873
|
}
|
|
141543
|
-
function
|
|
141874
|
+
function isRecord7(value) {
|
|
141544
141875
|
return typeof value === "object" && value !== null;
|
|
141545
141876
|
}
|
|
141546
141877
|
function getClaudeToolResultText(block) {
|
|
141547
141878
|
const content3 = block.content;
|
|
141548
141879
|
if (typeof content3 === "string") return content3;
|
|
141549
141880
|
if (Array.isArray(content3)) {
|
|
141550
|
-
return content3.filter(
|
|
141881
|
+
return content3.filter(isRecord7).map((entry) => String(entry.text ?? "")).join("\n");
|
|
141551
141882
|
}
|
|
141552
141883
|
return "";
|
|
141553
141884
|
}
|
|
@@ -141568,10 +141899,10 @@ function isEmptyClaudeMessageEvent(event) {
|
|
|
141568
141899
|
return false;
|
|
141569
141900
|
}
|
|
141570
141901
|
const message = event.message;
|
|
141571
|
-
if (!
|
|
141902
|
+
if (!isRecord7(message) || !Array.isArray(message.content)) {
|
|
141572
141903
|
return false;
|
|
141573
141904
|
}
|
|
141574
|
-
return !message.content.filter(
|
|
141905
|
+
return !message.content.filter(isRecord7).some(hasVisibleClaudeContentBlock);
|
|
141575
141906
|
}
|
|
141576
141907
|
function shouldSkipClaudeTranscriptEvent(event) {
|
|
141577
141908
|
return event.isMeta === true || event.isSidechain === true || event.type === "attachment" || event.type === "last-prompt" || isEmptyClaudeMessageEvent(event);
|
|
@@ -141585,13 +141916,13 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141585
141916
|
init() {
|
|
141586
141917
|
const { tasks } = this.taskEngine.listTasks();
|
|
141587
141918
|
for (const task of tasks) {
|
|
141588
|
-
|
|
141589
|
-
|
|
141590
|
-
|
|
141591
|
-
|
|
141592
|
-
|
|
141593
|
-
|
|
141594
|
-
|
|
141919
|
+
const session = getPersistedAgentSession(task, "claudecode");
|
|
141920
|
+
if (!session) continue;
|
|
141921
|
+
this.sessions.set(task.id, {
|
|
141922
|
+
sessionId: session.sessionId,
|
|
141923
|
+
cwd: path10.resolve(session.cwd || task.effectiveProjectPath || task.project || process.cwd()),
|
|
141924
|
+
title: task.title
|
|
141925
|
+
});
|
|
141595
141926
|
}
|
|
141596
141927
|
if (this.sessions.size > 0) {
|
|
141597
141928
|
this.logger.info("Recovered sessions from store", { count: this.sessions.size });
|
|
@@ -141647,7 +141978,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141647
141978
|
this.persistSession(task.id, event.session_id, cwd);
|
|
141648
141979
|
this.logger.info("Session established", { taskId: task.id, sessionId: event.session_id });
|
|
141649
141980
|
}
|
|
141650
|
-
const outputEvent = timestampClaudeTranscriptEvent(event);
|
|
141981
|
+
const outputEvent = event.type === "system" && event.subtype === "init" && typeof event.session_id === "string" ? { ...timestampClaudeTranscriptEvent(event), agent: "claudecode" } : timestampClaudeTranscriptEvent(event);
|
|
141651
141982
|
this.emitOutput(task.id, outputEvent);
|
|
141652
141983
|
this.appendLog(task.id, outputEvent);
|
|
141653
141984
|
} catch {
|
|
@@ -141664,7 +141995,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141664
141995
|
proc.stderr.on("data", (chunk) => {
|
|
141665
141996
|
stderrBuffer += chunk.toString();
|
|
141666
141997
|
});
|
|
141667
|
-
proc.on("close", (code4) => {
|
|
141998
|
+
proc.on("close", async (code4) => {
|
|
141668
141999
|
if (buffer.trim()) {
|
|
141669
142000
|
processLine(buffer);
|
|
141670
142001
|
}
|
|
@@ -141673,6 +142004,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141673
142004
|
return;
|
|
141674
142005
|
}
|
|
141675
142006
|
try {
|
|
142007
|
+
await this.flushLogsAndEmitReady(task.id);
|
|
141676
142008
|
if (code4 === 0 && !streamError) {
|
|
141677
142009
|
this.logger.info("Task completed successfully", { taskId: task.id, title: task.title });
|
|
141678
142010
|
this.taskEngine.reportResult(task.id, { message: `Task "${task.title}" completed` });
|
|
@@ -141710,7 +142042,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141710
142042
|
this.writeUserMessage(proc.stdin, initialContent);
|
|
141711
142043
|
proc.unref();
|
|
141712
142044
|
}
|
|
141713
|
-
sendMessage(taskId, content3) {
|
|
142045
|
+
sendMessage(taskId, content3, options) {
|
|
141714
142046
|
let session = this.sessions.get(taskId);
|
|
141715
142047
|
if (!session) {
|
|
141716
142048
|
const recovered = this.recoverSession(taskId);
|
|
@@ -141729,7 +142061,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141729
142061
|
if (!session) {
|
|
141730
142062
|
throw new MeshyError("TASK_NOT_FOUND", `No active session for task ${taskId}`, 404);
|
|
141731
142063
|
}
|
|
141732
|
-
const userEvent = buildTaskUserLogEvent(content3);
|
|
142064
|
+
const userEvent = buildTaskUserLogEvent(options?.logContent ?? content3);
|
|
141733
142065
|
this.appendLog(taskId, userEvent);
|
|
141734
142066
|
this.emitOutput(taskId, userEvent);
|
|
141735
142067
|
this.logger.info("Sending follow-up message", { taskId, sessionId: session.sessionId });
|
|
@@ -141776,7 +142108,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141776
142108
|
});
|
|
141777
142109
|
this.persistSession(taskId, event.session_id, session.cwd);
|
|
141778
142110
|
}
|
|
141779
|
-
const outputEvent = timestampClaudeTranscriptEvent(event);
|
|
142111
|
+
const outputEvent = event.type === "system" && event.subtype === "init" && typeof event.session_id === "string" ? { ...timestampClaudeTranscriptEvent(event), agent: "claudecode" } : timestampClaudeTranscriptEvent(event);
|
|
141780
142112
|
this.emitOutput(taskId, outputEvent);
|
|
141781
142113
|
this.appendLog(taskId, outputEvent);
|
|
141782
142114
|
} catch {
|
|
@@ -141793,7 +142125,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141793
142125
|
proc.stderr.on("data", (chunk) => {
|
|
141794
142126
|
stderrBuffer += chunk.toString();
|
|
141795
142127
|
});
|
|
141796
|
-
proc.on("close", (code4) => {
|
|
142128
|
+
proc.on("close", async (code4) => {
|
|
141797
142129
|
if (buffer.trim()) {
|
|
141798
142130
|
processLine(buffer);
|
|
141799
142131
|
}
|
|
@@ -141802,6 +142134,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141802
142134
|
return;
|
|
141803
142135
|
}
|
|
141804
142136
|
try {
|
|
142137
|
+
await this.flushLogsAndEmitReady(taskId);
|
|
141805
142138
|
if (code4 === 0 && !streamError) {
|
|
141806
142139
|
this.logger.info("Follow-up completed", { taskId, sessionId: session.sessionId });
|
|
141807
142140
|
this.taskEngine.reportResult(taskId, { message: `Task "${session.title}" completed` });
|
|
@@ -141854,7 +142187,7 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141854
142187
|
try {
|
|
141855
142188
|
const current = this.taskEngine.getTask(taskId);
|
|
141856
142189
|
this.taskEngine.updateTask(taskId, {
|
|
141857
|
-
payload: buildPersistedSessionPayload(current, sessionId, cwd)
|
|
142190
|
+
payload: buildPersistedSessionPayload(current, sessionId, cwd, "claudecode")
|
|
141858
142191
|
});
|
|
141859
142192
|
} catch {
|
|
141860
142193
|
}
|
|
@@ -141873,7 +142206,8 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141873
142206
|
const event = JSON.parse(line);
|
|
141874
142207
|
if (event.type === "system" && event.subtype === "init" && typeof event.session_id === "string") {
|
|
141875
142208
|
const task = this.taskEngine.getTask(taskId);
|
|
141876
|
-
|
|
142209
|
+
if (!canUseSessionLogEventForAgent(task, "claudecode", event)) continue;
|
|
142210
|
+
const persistedCwd = getPersistedAgentSession(task, "claudecode")?.cwd ?? (typeof task?.payload.sessionCwd === "string" ? task.payload.sessionCwd : void 0);
|
|
141877
142211
|
return {
|
|
141878
142212
|
sessionId: event.session_id,
|
|
141879
142213
|
cwd: path10.resolve(
|
|
@@ -141889,14 +142223,12 @@ var ClaudeCodeEngine = class extends ExecutionEngine {
|
|
|
141889
142223
|
}
|
|
141890
142224
|
recoverPersistedSession(taskId) {
|
|
141891
142225
|
const task = this.taskEngine.getTask(taskId);
|
|
141892
|
-
const
|
|
141893
|
-
if (!
|
|
141894
|
-
return null;
|
|
141895
|
-
}
|
|
142226
|
+
const persisted = getPersistedAgentSession(task, "claudecode");
|
|
142227
|
+
if (!persisted) return null;
|
|
141896
142228
|
return {
|
|
141897
|
-
sessionId,
|
|
142229
|
+
sessionId: persisted.sessionId,
|
|
141898
142230
|
cwd: path10.resolve(
|
|
141899
|
-
|
|
142231
|
+
persisted.cwd || task?.effectiveProjectPath || task?.project || process.cwd()
|
|
141900
142232
|
),
|
|
141901
142233
|
title: task?.title ?? taskId
|
|
141902
142234
|
};
|
|
@@ -141909,21 +142241,21 @@ var fs11 = __toESM(require("fs"), 1);
|
|
|
141909
142241
|
var path11 = __toESM(require("path"), 1);
|
|
141910
142242
|
var import_node_child_process5 = require("child_process");
|
|
141911
142243
|
var CODEX_SESSION_MIRROR_INTERVAL_MS = 500;
|
|
141912
|
-
function
|
|
142244
|
+
function isRecord8(value) {
|
|
141913
142245
|
return typeof value === "object" && value !== null;
|
|
141914
142246
|
}
|
|
141915
142247
|
function stableStringify(value) {
|
|
141916
142248
|
if (Array.isArray(value)) {
|
|
141917
142249
|
return `[${value.map((entry) => stableStringify(entry)).join(",")}]`;
|
|
141918
142250
|
}
|
|
141919
|
-
if (!
|
|
142251
|
+
if (!isRecord8(value)) {
|
|
141920
142252
|
return JSON.stringify(value);
|
|
141921
142253
|
}
|
|
141922
142254
|
return `{${Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)).map(([key2, entryValue]) => `${JSON.stringify(key2)}:${stableStringify(entryValue)}`).join(",")}}`;
|
|
141923
142255
|
}
|
|
141924
142256
|
function transcriptEventSignature(event) {
|
|
141925
142257
|
const message = event.message;
|
|
141926
|
-
if ((event.type === "assistant" || event.type === "user") &&
|
|
142258
|
+
if ((event.type === "assistant" || event.type === "user") && isRecord8(message) && Array.isArray(message.content)) {
|
|
141927
142259
|
return `${event.type}:${stableStringify(message.content)}`;
|
|
141928
142260
|
}
|
|
141929
142261
|
return stableStringify(event);
|
|
@@ -141962,9 +142294,6 @@ function splitPromptContent(content3) {
|
|
|
141962
142294
|
images
|
|
141963
142295
|
};
|
|
141964
142296
|
}
|
|
141965
|
-
function hasImageContent(content3) {
|
|
141966
|
-
return content3.some((part) => part.type === "image");
|
|
141967
|
-
}
|
|
141968
142297
|
function buildCodexModeArgs(mode) {
|
|
141969
142298
|
switch (mode) {
|
|
141970
142299
|
case "plan":
|
|
@@ -141987,13 +142316,13 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
141987
142316
|
init() {
|
|
141988
142317
|
const { tasks } = this.taskEngine.listTasks();
|
|
141989
142318
|
for (const task of tasks) {
|
|
141990
|
-
|
|
141991
|
-
|
|
141992
|
-
|
|
141993
|
-
|
|
141994
|
-
|
|
141995
|
-
|
|
141996
|
-
|
|
142319
|
+
const session = getPersistedAgentSession(task, "codex");
|
|
142320
|
+
if (!session) continue;
|
|
142321
|
+
this.sessions.set(task.id, {
|
|
142322
|
+
sessionId: session.sessionId,
|
|
142323
|
+
cwd: path11.resolve(session.cwd || task.effectiveProjectPath || task.project || process.cwd()),
|
|
142324
|
+
title: task.title
|
|
142325
|
+
});
|
|
141997
142326
|
}
|
|
141998
142327
|
if (this.sessions.size > 0) {
|
|
141999
142328
|
this.logger.info("Recovered Codex sessions from store", { count: this.sessions.size });
|
|
@@ -142004,7 +142333,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142004
142333
|
const cwd = task.effectiveProjectPath ?? task.project ?? process.cwd();
|
|
142005
142334
|
const initialContent = getTaskInitialMessageContent(task);
|
|
142006
142335
|
const { prompt, imagePaths, promptEcho } = this.prepareAssets(task.id, initialContent);
|
|
142007
|
-
this.markCodexPromptEchoEmitted(task.id, [promptEcho, prompt]
|
|
142336
|
+
this.markCodexPromptEchoEmitted(task.id, [promptEcho, prompt]);
|
|
142008
142337
|
const args = this.buildArgs(imagePaths, { model: config2.model, mode: config2.mode ?? "bypass" });
|
|
142009
142338
|
this.ensureLogDir();
|
|
142010
142339
|
this.logger.info("Spawning codex CLI", { taskId: task.id, title: task.title, cwd });
|
|
@@ -142017,7 +142346,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142017
142346
|
this.writePrompt(proc.stdin, prompt);
|
|
142018
142347
|
proc.unref();
|
|
142019
142348
|
}
|
|
142020
|
-
sendMessage(taskId, content3) {
|
|
142349
|
+
sendMessage(taskId, content3, options) {
|
|
142021
142350
|
let session = this.sessions.get(taskId);
|
|
142022
142351
|
if (!session) {
|
|
142023
142352
|
const recovered = this.recoverSession(taskId);
|
|
@@ -142039,12 +142368,12 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142039
142368
|
const current = this.taskEngine.getTask(taskId);
|
|
142040
142369
|
const model = typeof current?.payload.model === "string" ? current.payload.model : void 0;
|
|
142041
142370
|
const mode = current?.payload.mode;
|
|
142042
|
-
const userEvent = buildTaskUserLogEvent(content3);
|
|
142371
|
+
const userEvent = buildTaskUserLogEvent(options?.logContent ?? content3);
|
|
142043
142372
|
this.markTranscriptEventEmitted(taskId, userEvent);
|
|
142044
142373
|
this.appendLog(taskId, userEvent);
|
|
142045
142374
|
this.emitOutput(taskId, userEvent);
|
|
142046
142375
|
const { prompt, imagePaths, promptEcho } = this.prepareAssets(taskId, content3);
|
|
142047
|
-
this.markCodexPromptEchoEmitted(taskId, [promptEcho, prompt]
|
|
142376
|
+
this.markCodexPromptEchoEmitted(taskId, [promptEcho, prompt]);
|
|
142048
142377
|
const args = this.buildArgs(imagePaths, {
|
|
142049
142378
|
model,
|
|
142050
142379
|
sessionId: session.sessionId,
|
|
@@ -142103,7 +142432,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142103
142432
|
proc.stderr?.on("data", (chunk) => {
|
|
142104
142433
|
stderrBuffer += chunk.toString();
|
|
142105
142434
|
});
|
|
142106
|
-
proc.on("close", (code4) => {
|
|
142435
|
+
proc.on("close", async (code4) => {
|
|
142107
142436
|
if (buffer.trim()) {
|
|
142108
142437
|
processLine(buffer);
|
|
142109
142438
|
}
|
|
@@ -142116,6 +142445,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142116
142445
|
try {
|
|
142117
142446
|
this.flushNativeSessionMirror(taskId);
|
|
142118
142447
|
this.flushPendingAmbiguousAssistantTextEvents(taskId);
|
|
142448
|
+
await this.flushLogsAndEmitReady(taskId);
|
|
142119
142449
|
if (code4 === 0) {
|
|
142120
142450
|
this.logger.info(isFollowUp ? "Codex follow-up completed" : "Codex task completed successfully", {
|
|
142121
142451
|
taskId,
|
|
@@ -142262,8 +142592,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142262
142592
|
markTranscriptEventEmitted(taskId, event) {
|
|
142263
142593
|
this.getEmittedTranscriptSignatures(taskId).add(transcriptEventSignature(event));
|
|
142264
142594
|
}
|
|
142265
|
-
markCodexPromptEchoEmitted(taskId, prompts
|
|
142266
|
-
if (!hasImages) return;
|
|
142595
|
+
markCodexPromptEchoEmitted(taskId, prompts) {
|
|
142267
142596
|
for (const prompt of new Set(prompts.map((candidate) => candidate.trim()).filter(Boolean))) {
|
|
142268
142597
|
this.markTranscriptEventEmitted(taskId, buildTaskUserLogEvent([{ type: "text", text: prompt }]));
|
|
142269
142598
|
}
|
|
@@ -142302,8 +142631,9 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142302
142631
|
title
|
|
142303
142632
|
});
|
|
142304
142633
|
this.persistSession(taskId, event.thread_id, cwd);
|
|
142305
|
-
|
|
142306
|
-
this.
|
|
142634
|
+
const sessionEvent = { ...event, agent: "codex" };
|
|
142635
|
+
this.appendLog(taskId, sessionEvent);
|
|
142636
|
+
this.emitOutput(taskId, sessionEvent);
|
|
142307
142637
|
this.startNativeSessionMirror(taskId, event.thread_id);
|
|
142308
142638
|
this.logger.info("Codex session established", { taskId, sessionId: event.thread_id });
|
|
142309
142639
|
return [];
|
|
@@ -142348,7 +142678,7 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142348
142678
|
try {
|
|
142349
142679
|
const current = this.taskEngine.getTask(taskId);
|
|
142350
142680
|
this.taskEngine.updateTask(taskId, {
|
|
142351
|
-
payload: buildPersistedSessionPayload(current, sessionId, cwd)
|
|
142681
|
+
payload: buildPersistedSessionPayload(current, sessionId, cwd, "codex")
|
|
142352
142682
|
});
|
|
142353
142683
|
} catch {
|
|
142354
142684
|
}
|
|
@@ -142367,7 +142697,8 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142367
142697
|
const event = JSON.parse(line);
|
|
142368
142698
|
if (event.type === "thread.started" && typeof event.thread_id === "string") {
|
|
142369
142699
|
const task = this.taskEngine.getTask(taskId);
|
|
142370
|
-
|
|
142700
|
+
if (!canUseSessionLogEventForAgent(task, "codex", event)) continue;
|
|
142701
|
+
const persistedCwd = getPersistedAgentSession(task, "codex")?.cwd ?? (typeof task?.payload.sessionCwd === "string" ? task.payload.sessionCwd : void 0);
|
|
142371
142702
|
return {
|
|
142372
142703
|
sessionId: event.thread_id,
|
|
142373
142704
|
cwd: path11.resolve(persistedCwd ?? task?.effectiveProjectPath ?? task?.project ?? process.cwd()),
|
|
@@ -142381,14 +142712,12 @@ var CodexEngine = class extends ExecutionEngine {
|
|
|
142381
142712
|
}
|
|
142382
142713
|
recoverPersistedSession(taskId) {
|
|
142383
142714
|
const task = this.taskEngine.getTask(taskId);
|
|
142384
|
-
const
|
|
142385
|
-
if (!
|
|
142386
|
-
return null;
|
|
142387
|
-
}
|
|
142715
|
+
const persisted = getPersistedAgentSession(task, "codex");
|
|
142716
|
+
if (!persisted) return null;
|
|
142388
142717
|
return {
|
|
142389
|
-
sessionId,
|
|
142718
|
+
sessionId: persisted.sessionId,
|
|
142390
142719
|
cwd: path11.resolve(
|
|
142391
|
-
|
|
142720
|
+
persisted.cwd || task?.effectiveProjectPath || task?.project || process.cwd()
|
|
142392
142721
|
),
|
|
142393
142722
|
title: task?.title ?? taskId
|
|
142394
142723
|
};
|
|
@@ -142400,7 +142729,7 @@ init_cjs_shims();
|
|
|
142400
142729
|
var fs12 = __toESM(require("fs"), 1);
|
|
142401
142730
|
var path12 = __toESM(require("path"), 1);
|
|
142402
142731
|
var import_node_child_process6 = require("child_process");
|
|
142403
|
-
function
|
|
142732
|
+
function isRecord9(value) {
|
|
142404
142733
|
return typeof value === "object" && value !== null;
|
|
142405
142734
|
}
|
|
142406
142735
|
function contentToPrompt(content3) {
|
|
@@ -142438,7 +142767,7 @@ function inferExtension2(mediaType) {
|
|
|
142438
142767
|
return normalized.replace(/[^a-z0-9]/g, "") || "bin";
|
|
142439
142768
|
}
|
|
142440
142769
|
function extractSessionId(event) {
|
|
142441
|
-
const data =
|
|
142770
|
+
const data = isRecord9(event.data) ? event.data : void 0;
|
|
142442
142771
|
const direct = event.session_id ?? event.sessionId ?? event.conversation_id ?? event.conversationId ?? data?.sessionId ?? data?.session_id ?? data?.conversationId ?? data?.conversation_id;
|
|
142443
142772
|
if (typeof direct === "string" && direct.trim()) return direct.trim();
|
|
142444
142773
|
const type = typeof event.type === "string" ? event.type.toLowerCase() : "";
|
|
@@ -142452,13 +142781,13 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142452
142781
|
init() {
|
|
142453
142782
|
const { tasks } = this.taskEngine.listTasks();
|
|
142454
142783
|
for (const task of tasks) {
|
|
142455
|
-
|
|
142456
|
-
|
|
142457
|
-
|
|
142458
|
-
|
|
142459
|
-
|
|
142460
|
-
|
|
142461
|
-
|
|
142784
|
+
const session = getPersistedAgentSession(task, "copilot");
|
|
142785
|
+
if (!session) continue;
|
|
142786
|
+
this.sessions.set(task.id, {
|
|
142787
|
+
sessionId: session.sessionId,
|
|
142788
|
+
cwd: path12.resolve(session.cwd || task.effectiveProjectPath || task.project || process.cwd()),
|
|
142789
|
+
title: task.title
|
|
142790
|
+
});
|
|
142462
142791
|
}
|
|
142463
142792
|
if (this.sessions.size > 0) {
|
|
142464
142793
|
this.logger.info("Recovered Copilot CLI sessions from store", { count: this.sessions.size });
|
|
@@ -142487,7 +142816,7 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142487
142816
|
this.attachProcess(task.id, task.title, cwd, proc, false);
|
|
142488
142817
|
proc.unref();
|
|
142489
142818
|
}
|
|
142490
|
-
sendMessage(taskId, content3) {
|
|
142819
|
+
sendMessage(taskId, content3, options) {
|
|
142491
142820
|
let session = this.sessions.get(taskId);
|
|
142492
142821
|
if (!session) {
|
|
142493
142822
|
const recovered = this.recoverSession(taskId) ?? this.recoverPersistedSession(taskId);
|
|
@@ -142504,7 +142833,7 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142504
142833
|
const mode = current?.payload.mode;
|
|
142505
142834
|
const systemPrompt = typeof current?.payload.systemPrompt === "string" ? current.payload.systemPrompt : void 0;
|
|
142506
142835
|
const allowedTools = Array.isArray(current?.payload.allowedTools) && current.payload.allowedTools.every((tool) => typeof tool === "string") ? current.payload.allowedTools : void 0;
|
|
142507
|
-
const userEvent = buildTaskUserLogEvent(content3);
|
|
142836
|
+
const userEvent = buildTaskUserLogEvent(options?.logContent ?? content3);
|
|
142508
142837
|
this.appendLog(taskId, userEvent);
|
|
142509
142838
|
this.emitOutput(taskId, userEvent);
|
|
142510
142839
|
const prompt = buildPrompt(content3, systemPrompt);
|
|
@@ -142597,7 +142926,7 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142597
142926
|
proc.stderr?.on("data", (chunk) => {
|
|
142598
142927
|
stderrBuffer += chunk.toString();
|
|
142599
142928
|
});
|
|
142600
|
-
proc.on("close", (code4) => {
|
|
142929
|
+
proc.on("close", async (code4) => {
|
|
142601
142930
|
if (buffer.trim()) {
|
|
142602
142931
|
processLine(buffer);
|
|
142603
142932
|
}
|
|
@@ -142606,6 +142935,7 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142606
142935
|
return;
|
|
142607
142936
|
}
|
|
142608
142937
|
try {
|
|
142938
|
+
await this.flushLogsAndEmitReady(taskId);
|
|
142609
142939
|
if (code4 === 0) {
|
|
142610
142940
|
this.logger.info(isFollowUp ? "Copilot CLI follow-up completed" : "Copilot CLI task completed successfully", {
|
|
142611
142941
|
taskId,
|
|
@@ -142657,8 +142987,9 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142657
142987
|
if (sessionId) {
|
|
142658
142988
|
this.sessions.set(taskId, { sessionId, cwd, title });
|
|
142659
142989
|
this.persistSession(taskId, sessionId, cwd);
|
|
142660
|
-
|
|
142661
|
-
this.
|
|
142990
|
+
const sessionEvent = { ...event, agent: "copilot" };
|
|
142991
|
+
this.appendLog(taskId, sessionEvent);
|
|
142992
|
+
this.emitOutput(taskId, sessionEvent);
|
|
142662
142993
|
this.logger.info("Copilot CLI session established", { taskId, sessionId });
|
|
142663
142994
|
return [];
|
|
142664
142995
|
}
|
|
@@ -142668,7 +142999,7 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142668
142999
|
try {
|
|
142669
143000
|
const current = this.taskEngine.getTask(taskId);
|
|
142670
143001
|
this.taskEngine.updateTask(taskId, {
|
|
142671
|
-
payload: buildPersistedSessionPayload(current, sessionId, cwd)
|
|
143002
|
+
payload: buildPersistedSessionPayload(current, sessionId, cwd, "copilot")
|
|
142672
143003
|
});
|
|
142673
143004
|
} catch {
|
|
142674
143005
|
}
|
|
@@ -142687,7 +143018,8 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142687
143018
|
const sessionId = extractSessionId(event);
|
|
142688
143019
|
if (sessionId) {
|
|
142689
143020
|
const task = this.taskEngine.getTask(taskId);
|
|
142690
|
-
|
|
143021
|
+
if (!canUseSessionLogEventForAgent(task, "copilot", event)) continue;
|
|
143022
|
+
const persistedCwd = getPersistedAgentSession(task, "copilot")?.cwd ?? (typeof task?.payload.sessionCwd === "string" ? task.payload.sessionCwd : void 0);
|
|
142691
143023
|
return {
|
|
142692
143024
|
sessionId,
|
|
142693
143025
|
cwd: path12.resolve(persistedCwd ?? task?.effectiveProjectPath ?? task?.project ?? process.cwd()),
|
|
@@ -142701,12 +143033,12 @@ var CopilotCliEngine = class extends ExecutionEngine {
|
|
|
142701
143033
|
}
|
|
142702
143034
|
recoverPersistedSession(taskId) {
|
|
142703
143035
|
const task = this.taskEngine.getTask(taskId);
|
|
142704
|
-
const
|
|
142705
|
-
if (!
|
|
143036
|
+
const persisted = getPersistedAgentSession(task, "copilot");
|
|
143037
|
+
if (!persisted) return null;
|
|
142706
143038
|
return {
|
|
142707
|
-
sessionId,
|
|
143039
|
+
sessionId: persisted.sessionId,
|
|
142708
143040
|
cwd: path12.resolve(
|
|
142709
|
-
|
|
143041
|
+
persisted.cwd || task?.effectiveProjectPath || task?.project || process.cwd()
|
|
142710
143042
|
),
|
|
142711
143043
|
title: task?.title ?? taskId
|
|
142712
143044
|
};
|
|
@@ -144136,22 +144468,33 @@ async function handleLocalNodeMessage(deps, message) {
|
|
|
144136
144468
|
const payload = message.payload;
|
|
144137
144469
|
if (!payload.taskId || !payload.content) return;
|
|
144138
144470
|
const task = deps.taskEngine.getTask(payload.taskId);
|
|
144139
|
-
const
|
|
144140
|
-
|
|
144141
|
-
|
|
144471
|
+
const agent = task ? resolveActiveAgent(task, payload.targetAgent) : void 0;
|
|
144472
|
+
const engine = agent ? deps.engineRegistry.get(agent) : void 0;
|
|
144473
|
+
if (!task || !agent || !engine) return;
|
|
144142
144474
|
if (!deps.nodeRegistry.isLeader()) {
|
|
144143
144475
|
const reporter = new RestLeaderTaskReporter(deps.nodeRegistry, log2);
|
|
144144
144476
|
reporter.reportRunning(payload.taskId, { branch: task.branch });
|
|
144145
|
-
registerLeaderForwarding(deps.eventBus, deps.nodeRegistry, log2, payload.taskId,
|
|
144477
|
+
registerLeaderForwarding(deps.eventBus, deps.nodeRegistry, log2, payload.taskId, agent, reporter);
|
|
144146
144478
|
}
|
|
144147
144479
|
try {
|
|
144148
|
-
|
|
144149
|
-
|
|
144480
|
+
startAgentTaskTurn({
|
|
144481
|
+
task,
|
|
144482
|
+
content: payload.content,
|
|
144483
|
+
targetAgent: payload.targetAgent,
|
|
144484
|
+
assignedTo: task.assignedTo,
|
|
144485
|
+
taskEngine: deps.taskEngine,
|
|
144486
|
+
engineRegistry: deps.engineRegistry,
|
|
144487
|
+
eventBus: deps.eventBus,
|
|
144488
|
+
logger: log2
|
|
144489
|
+
});
|
|
144490
|
+
log2.info("started keepalive-delivered follow-up execution", { taskId: payload.taskId, agent });
|
|
144150
144491
|
} catch (error2) {
|
|
144151
|
-
|
|
144492
|
+
const messageText = error2 instanceof Error ? error2.message : String(error2);
|
|
144493
|
+
log2.error("failed to start keepalive-delivered follow-up execution", {
|
|
144152
144494
|
taskId: payload.taskId,
|
|
144153
|
-
error:
|
|
144495
|
+
error: messageText
|
|
144154
144496
|
});
|
|
144497
|
+
deps.taskEngine.reportFailure(payload.taskId, `Engine follow-up failed before execution started: ${messageText}`);
|
|
144155
144498
|
}
|
|
144156
144499
|
return;
|
|
144157
144500
|
}
|
|
@@ -144308,14 +144651,15 @@ var MeshyNode = class {
|
|
|
144308
144651
|
};
|
|
144309
144652
|
this.nodeRegistry.setSelf(this.selfInfo);
|
|
144310
144653
|
this.nodeRegistry.upsertNode(this.selfInfo);
|
|
144311
|
-
|
|
144654
|
+
const localNodeMessageHandler = (message) => handleLocalNodeMessage({
|
|
144312
144655
|
taskEngine: this.taskEngine,
|
|
144313
144656
|
engineRegistry: this.engineRegistry,
|
|
144314
144657
|
nodeRegistry: this.nodeRegistry,
|
|
144315
144658
|
eventBus: this.eventBus,
|
|
144316
144659
|
logger: this.logger,
|
|
144317
144660
|
getWorkDir: () => this.getWorkDir()
|
|
144318
|
-
}, message)
|
|
144661
|
+
}, message);
|
|
144662
|
+
this.heartbeat.setNodeMessageHandler(localNodeMessageHandler);
|
|
144319
144663
|
this.nodeMessageClient = new NodeMessageClient({ heartbeat: this.heartbeat, logger: this.logger });
|
|
144320
144664
|
this.taskDispatcher = new TaskDispatcher(
|
|
144321
144665
|
this.taskEngine,
|
|
@@ -144324,7 +144668,8 @@ var MeshyNode = class {
|
|
|
144324
144668
|
this.eventBus,
|
|
144325
144669
|
{ autoAssignInterval: 5e3, dispatchTimeout: 1e4 },
|
|
144326
144670
|
this.logger,
|
|
144327
|
-
this.nodeMessageClient
|
|
144671
|
+
this.nodeMessageClient,
|
|
144672
|
+
localNodeMessageHandler
|
|
144328
144673
|
);
|
|
144329
144674
|
this.dataRouter = new DataRouter(this.nodeRegistry, this.election);
|
|
144330
144675
|
const seeds = this.config.cluster.seeds;
|
|
@@ -145366,6 +145711,7 @@ var SystemAgentInfoSchema = external_exports.object({
|
|
|
145366
145711
|
detail: external_exports.string().nullable().optional()
|
|
145367
145712
|
}).optional()
|
|
145368
145713
|
});
|
|
145714
|
+
var DefaultTaskAgentSchema = external_exports.enum(["codex", "claudecode", "copilot"]);
|
|
145369
145715
|
var SystemRuntimeUpdateInfoSchema = external_exports.object({
|
|
145370
145716
|
packageName: external_exports.string(),
|
|
145371
145717
|
currentVersion: external_exports.string().nullable(),
|
|
@@ -145380,6 +145726,7 @@ var NodeSettingsSnapshotSchema = external_exports.object({
|
|
|
145380
145726
|
version: external_exports.string(),
|
|
145381
145727
|
packageName: external_exports.string().optional(),
|
|
145382
145728
|
uptime: external_exports.number(),
|
|
145729
|
+
defaultTaskAgent: DefaultTaskAgentSchema.optional(),
|
|
145383
145730
|
auth: SystemAuthInfoSchema.optional(),
|
|
145384
145731
|
os: SystemOsInfoSchema.optional(),
|
|
145385
145732
|
runtime: SystemRuntimeInfoSchema.optional(),
|
|
@@ -145721,6 +146068,10 @@ var QuickChatsResponse = external_exports.object({
|
|
|
145721
146068
|
var ReplaceQuickChatsBody = external_exports.object({
|
|
145722
146069
|
quickChats: external_exports.array(QuickChatItem).max(100)
|
|
145723
146070
|
});
|
|
146071
|
+
var DefaultTaskAgentResponse = external_exports.object({
|
|
146072
|
+
defaultTaskAgent: DefaultTaskAgentSchema
|
|
146073
|
+
});
|
|
146074
|
+
var UpdateDefaultTaskAgentBody = DefaultTaskAgentResponse;
|
|
145724
146075
|
|
|
145725
146076
|
// ../../packages/api/src/schemas/tasks.ts
|
|
145726
146077
|
init_cjs_shims();
|
|
@@ -145772,6 +146123,7 @@ var TaskListResponse = external_exports.object({
|
|
|
145772
146123
|
queuedMessages: external_exports.array(external_exports.object({
|
|
145773
146124
|
id: external_exports.string(),
|
|
145774
146125
|
content: external_exports.array(external_exports.record(external_exports.unknown())).min(1),
|
|
146126
|
+
targetAgent: external_exports.enum(NATIVE_SESSION_AGENT_OPTIONS).optional(),
|
|
145775
146127
|
createdAt: external_exports.number()
|
|
145776
146128
|
})).optional(),
|
|
145777
146129
|
status: external_exports.enum(["pending", "assigned", "running", "completed", "failed", "cancelled", "archived"]),
|
|
@@ -145838,12 +146190,15 @@ var TaskMessageContentPart = external_exports.union([
|
|
|
145838
146190
|
var TaskMessageContent = external_exports.array(TaskMessageContentPart).min(1);
|
|
145839
146191
|
var SendMessageBody = external_exports.union([
|
|
145840
146192
|
external_exports.object({
|
|
145841
|
-
content: TaskMessageContent
|
|
146193
|
+
content: TaskMessageContent,
|
|
146194
|
+
targetAgent: external_exports.enum(NATIVE_SESSION_AGENT_OPTIONS).optional()
|
|
145842
146195
|
}),
|
|
145843
146196
|
external_exports.object({
|
|
145844
|
-
message: external_exports.string().trim().min(1)
|
|
146197
|
+
message: external_exports.string().trim().min(1),
|
|
146198
|
+
targetAgent: external_exports.enum(NATIVE_SESSION_AGENT_OPTIONS).optional()
|
|
145845
146199
|
}).transform((value) => ({
|
|
145846
|
-
content: [{ type: "text", text: value.message }]
|
|
146200
|
+
content: [{ type: "text", text: value.message }],
|
|
146201
|
+
...value.targetAgent ? { targetAgent: value.targetAgent } : {}
|
|
145847
146202
|
}))
|
|
145848
146203
|
]);
|
|
145849
146204
|
var AttachNativeSessionBody = external_exports.object({
|
|
@@ -145860,7 +146215,8 @@ var WorkerImportTaskBody = external_exports.object({
|
|
|
145860
146215
|
logs: external_exports.array(TaskLogEvent).default([])
|
|
145861
146216
|
});
|
|
145862
146217
|
var TaskLogsQuery = external_exports.object({
|
|
145863
|
-
after: external_exports.coerce.number().int().min(0).optional()
|
|
146218
|
+
after: external_exports.coerce.number().int().min(0).optional(),
|
|
146219
|
+
minTotal: external_exports.coerce.number().int().min(0).optional()
|
|
145864
146220
|
});
|
|
145865
146221
|
var CreateTaskShareBody = external_exports.object({
|
|
145866
146222
|
tenant: external_exports.string().trim().min(1).max(128).default(DEFAULT_TASK_SHARE_TENANT),
|
|
@@ -146282,6 +146638,7 @@ function durationMs(startedAt) {
|
|
|
146282
146638
|
}
|
|
146283
146639
|
function createRequestLoggingMiddleware(rootLogger, options = {}) {
|
|
146284
146640
|
const log2 = rootLogger.child("api/request");
|
|
146641
|
+
const lastLoggedAt = /* @__PURE__ */ new Map();
|
|
146285
146642
|
return (req, res, next2) => {
|
|
146286
146643
|
if (options.shouldLog && !options.shouldLog(req)) {
|
|
146287
146644
|
next2();
|
|
@@ -146293,6 +146650,16 @@ function createRequestLoggingMiddleware(rootLogger, options = {}) {
|
|
|
146293
146650
|
const logCompletion = (closed) => {
|
|
146294
146651
|
if (logged) return;
|
|
146295
146652
|
logged = true;
|
|
146653
|
+
const throttle = options.throttle;
|
|
146654
|
+
if (throttle && throttle.intervalMs > 0 && throttle.shouldThrottle(req, res, closed, path47)) {
|
|
146655
|
+
const now = throttle.now?.() ?? Date.now();
|
|
146656
|
+
const key2 = throttle.key?.(req, path47) ?? `${req.method.toUpperCase()} ${path47}`;
|
|
146657
|
+
const previousLoggedAt = lastLoggedAt.get(key2);
|
|
146658
|
+
if (previousLoggedAt !== void 0 && now - previousLoggedAt < throttle.intervalMs) {
|
|
146659
|
+
return;
|
|
146660
|
+
}
|
|
146661
|
+
lastLoggedAt.set(key2, now);
|
|
146662
|
+
}
|
|
146296
146663
|
log2.info("request completed", {
|
|
146297
146664
|
method: req.method,
|
|
146298
146665
|
path: path47,
|
|
@@ -146413,8 +146780,21 @@ var sharedMcpControl;
|
|
|
146413
146780
|
var DEFAULT_START_POLL_INTERVAL_MS = 1e4;
|
|
146414
146781
|
var DEFAULT_START_TIMEOUT_MS = 15 * 6e4;
|
|
146415
146782
|
var ALWAYS_ONLINE_STARTABLE_DEVBOX_STATUSES = /* @__PURE__ */ new Set(["hibernated", "stopped"]);
|
|
146783
|
+
var DEVBOX_MCP_NODE_VERSION = "22";
|
|
146416
146784
|
var DEVBOX_MCP_COMMAND = "npx";
|
|
146417
|
-
var DEVBOX_MCP_ARGS = ["-y", "-p",
|
|
146785
|
+
var DEVBOX_MCP_ARGS = ["-y", "-p", `node@${DEVBOX_MCP_NODE_VERSION}`, "-p", "@microsoft/devbox-mcp@latest", "devbox-mcp-server"];
|
|
146786
|
+
var DEVBOX_MCP_DISPLAY_COMMAND = `${DEVBOX_MCP_COMMAND} ${DEVBOX_MCP_ARGS.join(" ")}`;
|
|
146787
|
+
function asDevBoxMcpError(err) {
|
|
146788
|
+
if (err instanceof MeshyError) return err;
|
|
146789
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
146790
|
+
if (!/connection closed/iu.test(cause)) return err;
|
|
146791
|
+
return new MeshyError(
|
|
146792
|
+
"DEVBOX_MCP_UNAVAILABLE",
|
|
146793
|
+
`Unable to reach the DevBox MCP server: it closed the connection. Meshy runs @microsoft/devbox-mcp with Node.js ${DEVBOX_MCP_NODE_VERSION} via npx; check that npx can install packages and Azure Dev Box authentication is available, then try again.`,
|
|
146794
|
+
502,
|
|
146795
|
+
{ cause, command: DEVBOX_MCP_DISPLAY_COMMAND }
|
|
146796
|
+
);
|
|
146797
|
+
}
|
|
146418
146798
|
function getDevBoxControl(deps) {
|
|
146419
146799
|
if (deps.devBoxControl) return deps.devBoxControl;
|
|
146420
146800
|
sharedMcpControl ??= new McpDevBoxControl(deps.logger);
|
|
@@ -146557,7 +146937,7 @@ var McpDevBoxControl = class {
|
|
|
146557
146937
|
return await client.callTool({ name: name2, arguments: args });
|
|
146558
146938
|
} catch (err) {
|
|
146559
146939
|
this.clientPromise = null;
|
|
146560
|
-
throw err;
|
|
146940
|
+
throw asDevBoxMcpError(err);
|
|
146561
146941
|
}
|
|
146562
146942
|
}
|
|
146563
146943
|
async getClient() {
|
|
@@ -146595,13 +146975,13 @@ function cleanDevBoxInfo(devbox) {
|
|
|
146595
146975
|
}
|
|
146596
146976
|
function normalizeMcpDevBoxList(value) {
|
|
146597
146977
|
const normalized = normalizeMcpValue(value);
|
|
146598
|
-
const record2 =
|
|
146978
|
+
const record2 = isRecord10(normalized) ? normalized : {};
|
|
146599
146979
|
const list4 = Array.isArray(normalized) ? normalized : Array.isArray(record2.devboxes) ? record2.devboxes : Array.isArray(record2.value) ? record2.value : [];
|
|
146600
146980
|
return list4.map((item) => normalizeDevBoxResource(item, void 0)).filter((item) => Boolean(item.name));
|
|
146601
146981
|
}
|
|
146602
146982
|
function normalizeDevBoxResource(value, fallback) {
|
|
146603
146983
|
const record2 = normalizeRecord(value);
|
|
146604
|
-
const additional =
|
|
146984
|
+
const additional = isRecord10(record2.additionalProperties) ? record2.additionalProperties : {};
|
|
146605
146985
|
const fromUri = parseDevBoxUri(readString(record2, "uri"));
|
|
146606
146986
|
const status = readString(record2, "status") ?? readString(record2, "powerState") ?? readString(record2, "lastStatus") ?? fallback?.lastStatus;
|
|
146607
146987
|
const name2 = readString(record2, "name") ?? fromUri?.name ?? fallback?.name ?? "";
|
|
@@ -146655,7 +147035,7 @@ function parseDevCenterEndpoint(hostname6) {
|
|
|
146655
147035
|
}
|
|
146656
147036
|
function normalizeRecord(value) {
|
|
146657
147037
|
const normalized = normalizeMcpValue(value);
|
|
146658
|
-
return
|
|
147038
|
+
return isRecord10(normalized) ? normalized : {};
|
|
146659
147039
|
}
|
|
146660
147040
|
function normalizeMcpValue(value) {
|
|
146661
147041
|
if (Array.isArray(value)) return value;
|
|
@@ -146690,7 +147070,7 @@ function tryParseJson(text10) {
|
|
|
146690
147070
|
return null;
|
|
146691
147071
|
}
|
|
146692
147072
|
}
|
|
146693
|
-
function
|
|
147073
|
+
function isRecord10(value) {
|
|
146694
147074
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
146695
147075
|
}
|
|
146696
147076
|
function readString(record2, key2) {
|
|
@@ -147982,6 +148362,7 @@ function buildNodeSettingsSnapshot(options) {
|
|
|
147982
148362
|
version: runtimeMetadata?.packageVersion ?? "0.1.0",
|
|
147983
148363
|
packageName: runtimeMetadata?.packageName ?? "meshy",
|
|
147984
148364
|
uptime,
|
|
148365
|
+
defaultTaskAgent: options.defaultTaskAgent,
|
|
147985
148366
|
auth: options.auth,
|
|
147986
148367
|
os: getOsSnapshot(),
|
|
147987
148368
|
runtime: {
|
|
@@ -148014,6 +148395,7 @@ function buildSystemInfo(deps) {
|
|
|
148014
148395
|
};
|
|
148015
148396
|
const settingsSnapshot = buildNodeSettingsSnapshot({
|
|
148016
148397
|
auth,
|
|
148398
|
+
defaultTaskAgent: deps.storagePath ? resolveNodeDefaultTaskAgent(deps.storagePath) : "codex",
|
|
148017
148399
|
inspectRuntimeTools: deps.inspectRuntimeTools,
|
|
148018
148400
|
localDashboardOrigin: deps.localDashboardOrigin,
|
|
148019
148401
|
runtimeMetadata: deps.runtimeMetadata,
|
|
@@ -148027,6 +148409,7 @@ function buildSystemInfo(deps) {
|
|
|
148027
148409
|
version: settingsSnapshot.version,
|
|
148028
148410
|
packageName: settingsSnapshot.packageName,
|
|
148029
148411
|
uptime: settingsSnapshot.uptime,
|
|
148412
|
+
defaultTaskAgent: settingsSnapshot.defaultTaskAgent,
|
|
148030
148413
|
transportType: deps.getTransportType?.() ?? "direct",
|
|
148031
148414
|
dashboardOrigin: deps.dashboardOrigin ?? self2.dashboardOrigin,
|
|
148032
148415
|
localDashboardOrigin: deps.localDashboardOrigin,
|
|
@@ -148117,7 +148500,7 @@ function upgradeRuntimeAgentForDeps(deps, agent) {
|
|
|
148117
148500
|
// ../../packages/api/src/node/runtime-restart-request.ts
|
|
148118
148501
|
init_cjs_shims();
|
|
148119
148502
|
function parseRuntimeRestartRequest(value) {
|
|
148120
|
-
const body3 =
|
|
148503
|
+
const body3 = isRecord11(value) ? value : {};
|
|
148121
148504
|
const startArgs = parseRuntimeRestartStartArgs(body3.startArgs);
|
|
148122
148505
|
return {
|
|
148123
148506
|
reason: body3.reason === "update" ? "update" : "restart",
|
|
@@ -148126,7 +148509,7 @@ function parseRuntimeRestartRequest(value) {
|
|
|
148126
148509
|
}
|
|
148127
148510
|
function parseRuntimeRestartStartArgs(value) {
|
|
148128
148511
|
if (value === void 0) return void 0;
|
|
148129
|
-
if (!
|
|
148512
|
+
if (!isRecord11(value)) {
|
|
148130
148513
|
throw new MeshyError("VALIDATION_ERROR", "Runtime restart startArgs must be an object", 400);
|
|
148131
148514
|
}
|
|
148132
148515
|
const startArgs = {};
|
|
@@ -148175,7 +148558,7 @@ function parseOptionalString(value, key2) {
|
|
|
148175
148558
|
const trimmed = value.trim();
|
|
148176
148559
|
return trimmed || void 0;
|
|
148177
148560
|
}
|
|
148178
|
-
function
|
|
148561
|
+
function isRecord11(value) {
|
|
148179
148562
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
148180
148563
|
}
|
|
148181
148564
|
|
|
@@ -149196,7 +149579,7 @@ function toLegacyWorkerControl2(message) {
|
|
|
149196
149579
|
}
|
|
149197
149580
|
|
|
149198
149581
|
// ../../packages/api/src/tasks/task-route-utils.ts
|
|
149199
|
-
function
|
|
149582
|
+
function isRecord12(value) {
|
|
149200
149583
|
return typeof value === "object" && value !== null;
|
|
149201
149584
|
}
|
|
149202
149585
|
function restoreTaskState(taskEngine, task) {
|
|
@@ -149263,7 +149646,7 @@ function normalizeStructuredValue(value) {
|
|
|
149263
149646
|
if (Array.isArray(value)) {
|
|
149264
149647
|
return value.map((entry) => normalizeStructuredValue(entry));
|
|
149265
149648
|
}
|
|
149266
|
-
if (!
|
|
149649
|
+
if (!isRecord12(value)) {
|
|
149267
149650
|
return value;
|
|
149268
149651
|
}
|
|
149269
149652
|
return Object.fromEntries(
|
|
@@ -149272,20 +149655,20 @@ function normalizeStructuredValue(value) {
|
|
|
149272
149655
|
}
|
|
149273
149656
|
function getTranscriptEventSignature(event) {
|
|
149274
149657
|
if (event.type === "user") {
|
|
149275
|
-
const signature = getTaskUserMessageSignature(
|
|
149658
|
+
const signature = getTaskUserMessageSignature(isRecord12(event.message) ? event.message.content : event.message) ?? getTaskUserMessageSignature(event.content);
|
|
149276
149659
|
return signature ? `user:${signature}` : null;
|
|
149277
149660
|
}
|
|
149278
149661
|
if (event.type === "assistant") {
|
|
149279
149662
|
if (typeof event.message === "string") {
|
|
149280
149663
|
return `assistant:${JSON.stringify(event.message)}`;
|
|
149281
149664
|
}
|
|
149282
|
-
if (
|
|
149665
|
+
if (isRecord12(event.message) && "content" in event.message) {
|
|
149283
149666
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.message.content))}`;
|
|
149284
149667
|
}
|
|
149285
149668
|
if (Array.isArray(event.content)) {
|
|
149286
149669
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.content))}`;
|
|
149287
149670
|
}
|
|
149288
|
-
if (
|
|
149671
|
+
if (isRecord12(event.message)) {
|
|
149289
149672
|
return `assistant:${JSON.stringify(normalizeStructuredValue(event.message))}`;
|
|
149290
149673
|
}
|
|
149291
149674
|
}
|
|
@@ -177128,22 +177511,32 @@ async function handleTaskMessage(deps, message) {
|
|
|
177128
177511
|
if (!task) {
|
|
177129
177512
|
throw new MeshyError("TASK_NOT_FOUND", `Task ${payload.taskId} not found`, 404);
|
|
177130
177513
|
}
|
|
177131
|
-
|
|
177132
|
-
|
|
177514
|
+
const targetAgent = typeof payload.targetAgent === "string" ? payload.targetAgent : void 0;
|
|
177515
|
+
const agent = resolveActiveAgent(task, targetAgent);
|
|
177516
|
+
if (!supportsFollowUpAgent(agent)) {
|
|
177517
|
+
throw new MeshyError("VALIDATION_ERROR", `Agent ${agent} does not support chat messages`, 400);
|
|
177133
177518
|
}
|
|
177134
|
-
const engine = deps.engineRegistry.get(
|
|
177519
|
+
const engine = deps.engineRegistry.get(agent);
|
|
177135
177520
|
if (!engine) {
|
|
177136
|
-
throw new MeshyError("VALIDATION_ERROR", `Engine not registered for agent: ${
|
|
177521
|
+
throw new MeshyError("VALIDATION_ERROR", `Engine not registered for agent: ${agent}`, 400);
|
|
177137
177522
|
}
|
|
177138
|
-
deps.taskEngine.updateTask(payload.taskId, { status: "running" });
|
|
177139
177523
|
if (!deps.nodeRegistry.isLeader()) {
|
|
177140
177524
|
const reporter = new RestLeaderTaskReporter(deps.nodeRegistry, log2);
|
|
177141
177525
|
reporter.reportRunning(payload.taskId, { branch: task.branch });
|
|
177142
|
-
registerLeaderForwarding(deps.eventBus, deps.nodeRegistry, log2, payload.taskId,
|
|
177526
|
+
registerLeaderForwarding(deps.eventBus, deps.nodeRegistry, log2, payload.taskId, agent, reporter);
|
|
177143
177527
|
}
|
|
177144
177528
|
try {
|
|
177145
|
-
|
|
177146
|
-
|
|
177529
|
+
startAgentTaskTurn({
|
|
177530
|
+
task,
|
|
177531
|
+
content: payload.content,
|
|
177532
|
+
targetAgent,
|
|
177533
|
+
assignedTo: task.assignedTo,
|
|
177534
|
+
taskEngine: deps.taskEngine,
|
|
177535
|
+
engineRegistry: deps.engineRegistry,
|
|
177536
|
+
eventBus: deps.eventBus,
|
|
177537
|
+
logger: log2
|
|
177538
|
+
});
|
|
177539
|
+
log2.info("started follow-up execution", { taskId: payload.taskId, agent });
|
|
177147
177540
|
} catch (error2) {
|
|
177148
177541
|
const messageText = error2 instanceof Error ? error2.message : String(error2);
|
|
177149
177542
|
log2.error("engine.sendMessage threw synchronously", { taskId: payload.taskId, error: messageText });
|
|
@@ -177394,6 +177787,7 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
177394
177787
|
const log2 = rootLogger.child("tasks/logs");
|
|
177395
177788
|
const query = TaskLogsQuery.parse(req.query);
|
|
177396
177789
|
const after = query.after ?? 0;
|
|
177790
|
+
const minTotal = query.minTotal ?? 0;
|
|
177397
177791
|
const proxyRequest = getTaskLogsProxyRequestMetadata(req);
|
|
177398
177792
|
let task = taskEngine.getTask(taskId);
|
|
177399
177793
|
if (!task && proxyRequest.task?.id === taskId) {
|
|
@@ -177439,7 +177833,8 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
177439
177833
|
if (isLeader) {
|
|
177440
177834
|
const local2 = readLocalTaskLogsWithNativeHistory(engineRegistry, task, taskId, after, task?.agent ?? "claudecode");
|
|
177441
177835
|
leaderLocal = local2;
|
|
177442
|
-
|
|
177836
|
+
const leaderLocalSatisfiesCheckpoint = minTotal === 0 || local2.total >= minTotal;
|
|
177837
|
+
if ((local2.total > 0 || !needsProxy) && leaderLocalSatisfiesCheckpoint && !shouldAskWorkerForNativeRepair) {
|
|
177443
177838
|
log2.debug("serving leader-local task logs", {
|
|
177444
177839
|
taskId,
|
|
177445
177840
|
assignedTo: task?.assignedTo,
|
|
@@ -177450,7 +177845,16 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
177450
177845
|
res.json(local2);
|
|
177451
177846
|
return;
|
|
177452
177847
|
}
|
|
177453
|
-
if (local2.total > 0 &&
|
|
177848
|
+
if (local2.total > 0 && !leaderLocalSatisfiesCheckpoint) {
|
|
177849
|
+
log2.debug("leader-local task logs behind requested checkpoint, falling back to worker proxy", {
|
|
177850
|
+
taskId,
|
|
177851
|
+
assignedTo: task?.assignedTo,
|
|
177852
|
+
selfId,
|
|
177853
|
+
total: local2.total,
|
|
177854
|
+
minTotal,
|
|
177855
|
+
after
|
|
177856
|
+
});
|
|
177857
|
+
} else if (local2.total > 0 && shouldAskWorkerForNativeRepair) {
|
|
177454
177858
|
log2.debug("leader-local native session logs may be partial, checking worker repair path", {
|
|
177455
177859
|
taskId,
|
|
177456
177860
|
assignedTo: task?.assignedTo,
|
|
@@ -177493,7 +177897,9 @@ async function sendTaskLogsResponse(req, res, taskId) {
|
|
|
177493
177897
|
return;
|
|
177494
177898
|
}
|
|
177495
177899
|
}
|
|
177496
|
-
const
|
|
177900
|
+
const proxyParams = new URLSearchParams({ after: String(after) });
|
|
177901
|
+
if (minTotal > 0) proxyParams.set("minTotal", String(minTotal));
|
|
177902
|
+
const proxyPath = `/api/tasks/${taskId}/logs?${proxyParams.toString()}`;
|
|
177497
177903
|
try {
|
|
177498
177904
|
const { endpoint, response: proxyRes } = await fetchNodeWithFallback(
|
|
177499
177905
|
node2,
|
|
@@ -177548,17 +177954,24 @@ init_cjs_shims();
|
|
|
177548
177954
|
|
|
177549
177955
|
// ../../packages/api/src/tasks/task-follow-up.ts
|
|
177550
177956
|
init_cjs_shims();
|
|
177551
|
-
function startLocalTaskFollowUp(deps, task, content3, assignedTo, metadata) {
|
|
177552
|
-
const
|
|
177957
|
+
function startLocalTaskFollowUp(deps, task, content3, assignedTo, targetAgent, metadata) {
|
|
177958
|
+
const agent = resolveActiveAgent(task, targetAgent);
|
|
177959
|
+
const engine = deps.engineRegistry.get(agent);
|
|
177553
177960
|
if (!engine) {
|
|
177554
|
-
throw new MeshyError("VALIDATION_ERROR", `Engine not registered for agent: ${
|
|
177961
|
+
throw new MeshyError("VALIDATION_ERROR", `Engine not registered for agent: ${agent}`, 400);
|
|
177555
177962
|
}
|
|
177556
|
-
deps.taskEngine.updateTask(task.id, {
|
|
177557
|
-
status: "running",
|
|
177558
|
-
assignedTo
|
|
177559
|
-
});
|
|
177560
177963
|
try {
|
|
177561
|
-
|
|
177964
|
+
startAgentTaskTurn({
|
|
177965
|
+
task,
|
|
177966
|
+
content: content3,
|
|
177967
|
+
targetAgent,
|
|
177968
|
+
assignedTo,
|
|
177969
|
+
taskEngine: deps.taskEngine,
|
|
177970
|
+
engineRegistry: deps.engineRegistry,
|
|
177971
|
+
eventBus: deps.eventBus,
|
|
177972
|
+
logger: deps.logger,
|
|
177973
|
+
metadata
|
|
177974
|
+
});
|
|
177562
177975
|
} catch (err) {
|
|
177563
177976
|
restoreTaskState(deps.taskEngine, task);
|
|
177564
177977
|
deps.logger.warn("failed to start local follow-up execution", {
|
|
@@ -177581,9 +177994,10 @@ function restoreQueuedMessage(taskEngine, taskId, message) {
|
|
|
177581
177994
|
queuedMessages: [message, ...current.queuedMessages ?? []]
|
|
177582
177995
|
});
|
|
177583
177996
|
}
|
|
177584
|
-
async function sendTaskFollowUpMessage(deps, task, content3, metadata) {
|
|
177585
|
-
|
|
177586
|
-
|
|
177997
|
+
async function sendTaskFollowUpMessage(deps, task, content3, targetAgent, metadata) {
|
|
177998
|
+
const agent = resolveActiveAgent(task, targetAgent);
|
|
177999
|
+
if (!supportsFollowUpAgent(agent)) {
|
|
178000
|
+
throw new MeshyError("VALIDATION_ERROR", `Agent ${agent} does not support chat messages`, 400);
|
|
177587
178001
|
}
|
|
177588
178002
|
if (task.assignedTo && task.assignedTo !== deps.nodeRegistry.getSelf()?.id) {
|
|
177589
178003
|
const node2 = deps.nodeRegistry.getNode(task.assignedTo);
|
|
@@ -177602,7 +178016,7 @@ async function sendTaskFollowUpMessage(deps, task, content3, metadata) {
|
|
|
177602
178016
|
409
|
|
177603
178017
|
);
|
|
177604
178018
|
}
|
|
177605
|
-
deps.taskEngine.updateTask(task.id, { status: "running" });
|
|
178019
|
+
deps.taskEngine.updateTask(task.id, targetAgent ? { status: "running", payload: { ...task.payload, activeAgent: agent } } : { status: "running" });
|
|
177606
178020
|
log2.info("proxying follow-up message to worker", {
|
|
177607
178021
|
taskId: task.id,
|
|
177608
178022
|
assignedTo: task.assignedTo,
|
|
@@ -177612,7 +178026,8 @@ async function sendTaskFollowUpMessage(deps, task, content3, metadata) {
|
|
|
177612
178026
|
const client = new NodeMessageClient({ heartbeat: deps.heartbeat, logger: deps.logger });
|
|
177613
178027
|
const delivery = await client.send(node2, createNodeMessage("task.message", {
|
|
177614
178028
|
taskId: task.id,
|
|
177615
|
-
content: content3
|
|
178029
|
+
content: content3,
|
|
178030
|
+
...targetAgent ? { targetAgent } : {}
|
|
177616
178031
|
}));
|
|
177617
178032
|
return delivery.queued ? { queued: true } : {};
|
|
177618
178033
|
} catch (err) {
|
|
@@ -177630,31 +178045,34 @@ async function sendTaskFollowUpMessage(deps, task, content3, metadata) {
|
|
|
177630
178045
|
startLocalTaskFollowUp({
|
|
177631
178046
|
taskEngine: deps.taskEngine,
|
|
177632
178047
|
engineRegistry: deps.engineRegistry,
|
|
178048
|
+
eventBus: deps.eventBus,
|
|
177633
178049
|
logger: deps.logger.child("tasks/message")
|
|
177634
|
-
}, task, content3, task.assignedTo, metadata);
|
|
178050
|
+
}, task, content3, task.assignedTo, targetAgent, metadata);
|
|
177635
178051
|
return {};
|
|
177636
178052
|
}
|
|
177637
|
-
function queueRunningTaskMessage(deps, task, content3) {
|
|
177638
|
-
|
|
177639
|
-
|
|
178053
|
+
function queueRunningTaskMessage(deps, task, content3, targetAgent) {
|
|
178054
|
+
const agent = resolveActiveAgent(task, targetAgent);
|
|
178055
|
+
if (!supportsFollowUpAgent(agent)) {
|
|
178056
|
+
throw new MeshyError("VALIDATION_ERROR", `Agent ${agent} does not support chat messages`, 400);
|
|
177640
178057
|
}
|
|
177641
|
-
const queued = deps.taskEngine.enqueueTaskMessage(task.id, content3);
|
|
178058
|
+
const queued = targetAgent ? deps.taskEngine.enqueueTaskMessage(task.id, content3, targetAgent) : deps.taskEngine.enqueueTaskMessage(task.id, content3);
|
|
177642
178059
|
deps.logger.child("tasks/message").info("queued follow-up message for running task", {
|
|
177643
178060
|
taskId: task.id,
|
|
178061
|
+
targetAgent,
|
|
177644
178062
|
queuedCount: queued.queuedMessages?.length ?? 0
|
|
177645
178063
|
});
|
|
177646
178064
|
return queued;
|
|
177647
178065
|
}
|
|
177648
178066
|
var MESSAGEABLE_STATUSES = /* @__PURE__ */ new Set(["running", "completed", "cancelled", "failed"]);
|
|
177649
|
-
async function applyTaskMessage(deps, task, content3) {
|
|
178067
|
+
async function applyTaskMessage(deps, task, content3, targetAgent) {
|
|
177650
178068
|
if (!MESSAGEABLE_STATUSES.has(task.status)) {
|
|
177651
178069
|
throw new MeshyError("VALIDATION_ERROR", `Cannot send message to task in ${task.status} status`, 400);
|
|
177652
178070
|
}
|
|
177653
178071
|
if (task.status === "running") {
|
|
177654
|
-
const queued = queueRunningTaskMessage(deps, task, content3);
|
|
178072
|
+
const queued = queueRunningTaskMessage(deps, task, content3, targetAgent);
|
|
177655
178073
|
return { ok: true, queued: true, queuedMessages: queued.queuedMessages ?? [] };
|
|
177656
178074
|
}
|
|
177657
|
-
const result = await sendTaskFollowUpMessage(deps, task, content3);
|
|
178075
|
+
const result = await sendTaskFollowUpMessage(deps, task, content3, targetAgent);
|
|
177658
178076
|
return result.queued ? { ok: true, queued: true } : { ok: true };
|
|
177659
178077
|
}
|
|
177660
178078
|
function cancelQueuedTaskMessage(deps, taskId, messageId) {
|
|
@@ -177687,7 +178105,7 @@ async function drainNextQueuedTaskMessage(deps, taskId) {
|
|
|
177687
178105
|
if (!dequeued) return false;
|
|
177688
178106
|
drainingTaskIds.add(taskId);
|
|
177689
178107
|
try {
|
|
177690
|
-
await sendTaskFollowUpMessage(deps, dequeued.task, dequeued.message.content, {
|
|
178108
|
+
await sendTaskFollowUpMessage(deps, dequeued.task, dequeued.message.content, dequeued.message.targetAgent, {
|
|
177691
178109
|
queuedMessageId: dequeued.message.id
|
|
177692
178110
|
});
|
|
177693
178111
|
deps.logger.child("tasks/message").info("started queued follow-up message", {
|
|
@@ -178671,7 +179089,7 @@ function createTaskRoutes() {
|
|
|
178671
179089
|
res.json({ ok: true, queuedMessages: task.queuedMessages ?? [] });
|
|
178672
179090
|
}));
|
|
178673
179091
|
router.post("/:id/message", asyncHandler8(async (req, res) => {
|
|
178674
|
-
const { taskEngine, engineRegistry, nodeRegistry, heartbeat, logger: rootLogger } = req.app.locals.deps;
|
|
179092
|
+
const { taskEngine, engineRegistry, nodeRegistry, heartbeat, eventBus, logger: rootLogger } = req.app.locals.deps;
|
|
178675
179093
|
const body3 = SendMessageBody.parse(req.body);
|
|
178676
179094
|
const taskId = req.params.id;
|
|
178677
179095
|
const task = taskEngine.getTask(taskId);
|
|
@@ -178679,9 +179097,10 @@ function createTaskRoutes() {
|
|
|
178679
179097
|
throw new MeshyError("TASK_NOT_FOUND", `Task ${taskId} not found`, 404);
|
|
178680
179098
|
}
|
|
178681
179099
|
res.json(await applyTaskMessage(
|
|
178682
|
-
{ taskEngine, engineRegistry, nodeRegistry, heartbeat, logger: rootLogger },
|
|
179100
|
+
{ taskEngine, engineRegistry, nodeRegistry, heartbeat, eventBus, logger: rootLogger },
|
|
178683
179101
|
task,
|
|
178684
|
-
body3.content
|
|
179102
|
+
body3.content,
|
|
179103
|
+
body3.targetAgent
|
|
178685
179104
|
));
|
|
178686
179105
|
}));
|
|
178687
179106
|
router.use(createTaskOutputRoutes());
|
|
@@ -178855,6 +179274,10 @@ var WorkerMessageBody = external_exports.object({
|
|
|
178855
179274
|
var WorkerTaskBody = external_exports.object({
|
|
178856
179275
|
taskId: external_exports.string().min(1)
|
|
178857
179276
|
});
|
|
179277
|
+
var WorkerLogsReadyBody = external_exports.object({
|
|
179278
|
+
taskId: external_exports.string().min(1),
|
|
179279
|
+
total: external_exports.number().int().min(0)
|
|
179280
|
+
});
|
|
178858
179281
|
function asyncHandler10(fn) {
|
|
178859
179282
|
return (req, res, next2) => fn(req, res, next2).catch(next2);
|
|
178860
179283
|
}
|
|
@@ -178909,15 +179332,15 @@ function createWorkerRoutes() {
|
|
|
178909
179332
|
if (!task) {
|
|
178910
179333
|
throw new MeshyError("TASK_NOT_FOUND", `Task ${body3.taskId} not found`, 404);
|
|
178911
179334
|
}
|
|
178912
|
-
|
|
178913
|
-
|
|
179335
|
+
const agent = resolveActiveAgent(task, body3.targetAgent);
|
|
179336
|
+
if (!supportsFollowUpAgent(agent)) {
|
|
179337
|
+
throw new MeshyError("VALIDATION_ERROR", `Agent ${agent} does not support chat messages`, 400);
|
|
178914
179338
|
}
|
|
178915
|
-
const engine = engineRegistry.get(
|
|
179339
|
+
const engine = engineRegistry.get(agent);
|
|
178916
179340
|
if (!engine) {
|
|
178917
|
-
res.status(400).json({ error: `Engine not registered for agent: ${
|
|
179341
|
+
res.status(400).json({ error: `Engine not registered for agent: ${agent}` });
|
|
178918
179342
|
return;
|
|
178919
179343
|
}
|
|
178920
|
-
taskEngine.updateTask(body3.taskId, { status: "running" });
|
|
178921
179344
|
if (!nodeRegistry.isLeader()) {
|
|
178922
179345
|
new RestLeaderTaskReporter(nodeRegistry, log2).reportRunning(body3.taskId, { branch: task.branch });
|
|
178923
179346
|
}
|
|
@@ -178928,13 +179351,22 @@ function createWorkerRoutes() {
|
|
|
178928
179351
|
nodeRegistry,
|
|
178929
179352
|
log2,
|
|
178930
179353
|
body3.taskId,
|
|
178931
|
-
|
|
179354
|
+
agent,
|
|
178932
179355
|
new RestLeaderTaskReporter(nodeRegistry, log2)
|
|
178933
179356
|
);
|
|
178934
179357
|
}
|
|
178935
179358
|
try {
|
|
178936
|
-
|
|
178937
|
-
|
|
179359
|
+
startAgentTaskTurn({
|
|
179360
|
+
task,
|
|
179361
|
+
content: body3.content,
|
|
179362
|
+
targetAgent: body3.targetAgent,
|
|
179363
|
+
assignedTo: task.assignedTo,
|
|
179364
|
+
taskEngine,
|
|
179365
|
+
engineRegistry,
|
|
179366
|
+
eventBus,
|
|
179367
|
+
logger: log2
|
|
179368
|
+
});
|
|
179369
|
+
log2.info("started follow-up execution", { taskId: body3.taskId, agent });
|
|
178938
179370
|
} catch (err) {
|
|
178939
179371
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
178940
179372
|
log2.error("engine.sendMessage threw synchronously", { taskId: body3.taskId, error: errorMessage });
|
|
@@ -178986,6 +179418,12 @@ function createWorkerRoutes() {
|
|
|
178986
179418
|
}
|
|
178987
179419
|
res.json({ ok: true });
|
|
178988
179420
|
}));
|
|
179421
|
+
router.post("/logs-ready", asyncHandler10(async (req, res) => {
|
|
179422
|
+
const { eventBus } = req.app.locals.deps;
|
|
179423
|
+
const body3 = WorkerLogsReadyBody.parse(req.body);
|
|
179424
|
+
eventBus.emit("task.logs.ready", { taskId: body3.taskId, total: body3.total });
|
|
179425
|
+
res.json({ ok: true });
|
|
179426
|
+
}));
|
|
178989
179427
|
router.post("/heartbeat", asyncHandler10(async (req, res) => {
|
|
178990
179428
|
const { heartbeat, logger: rootLogger } = req.app.locals.deps;
|
|
178991
179429
|
const log2 = rootLogger.child("worker/heartbeat");
|
|
@@ -179156,6 +179594,10 @@ function getQuickChatStore(deps) {
|
|
|
179156
179594
|
if (deps.storagePath) return createQuickChatStore(deps.storagePath);
|
|
179157
179595
|
throw new MeshyError("VALIDATION_ERROR", "Quick chats are not available for this node", 501);
|
|
179158
179596
|
}
|
|
179597
|
+
function getStoragePath2(deps) {
|
|
179598
|
+
if (deps.storagePath) return deps.storagePath;
|
|
179599
|
+
throw new MeshyError("VALIDATION_ERROR", "Node metadata is not available for this node", 501);
|
|
179600
|
+
}
|
|
179159
179601
|
function validateQuickChatAliases(quickChats) {
|
|
179160
179602
|
const seen = /* @__PURE__ */ new Set();
|
|
179161
179603
|
for (const quickChat of quickChats) {
|
|
@@ -179248,6 +179690,21 @@ function createSystemRoutes() {
|
|
|
179248
179690
|
const metrics2 = taskEngine.getMetrics();
|
|
179249
179691
|
res.json(metrics2);
|
|
179250
179692
|
}));
|
|
179693
|
+
router.get("/default-task-agent", asyncHandler11(async (req, res) => {
|
|
179694
|
+
const storagePath = getStoragePath2(req.app.locals.deps);
|
|
179695
|
+
res.json({ defaultTaskAgent: resolveNodeDefaultTaskAgent(storagePath) });
|
|
179696
|
+
}));
|
|
179697
|
+
router.put("/default-task-agent", asyncHandler11(async (req, res) => {
|
|
179698
|
+
const body3 = UpdateDefaultTaskAgentBody.parse(req.body);
|
|
179699
|
+
const deps = req.app.locals.deps;
|
|
179700
|
+
const storagePath = getStoragePath2(deps);
|
|
179701
|
+
persistNodeDefaultTaskAgent(storagePath, body3.defaultTaskAgent);
|
|
179702
|
+
const settingsSnapshot = deps.refreshSettingsSnapshot?.();
|
|
179703
|
+
if (settingsSnapshot) {
|
|
179704
|
+
deps.nodeRegistry.updateSettingsSnapshot(deps.nodeRegistry.getSelf().id, settingsSnapshot);
|
|
179705
|
+
}
|
|
179706
|
+
res.json({ defaultTaskAgent: resolveNodeDefaultTaskAgent(storagePath) });
|
|
179707
|
+
}));
|
|
179251
179708
|
router.get("/quick-chats", asyncHandler11(async (req, res) => {
|
|
179252
179709
|
const store = getQuickChatStore(req.app.locals.deps);
|
|
179253
179710
|
res.json({ quickChats: store.list() });
|
|
@@ -179284,6 +179741,7 @@ var ALL_EVENT_NAMES = [
|
|
|
179284
179741
|
"task.updated",
|
|
179285
179742
|
"task.deleted",
|
|
179286
179743
|
"task.output",
|
|
179744
|
+
"task.logs.ready",
|
|
179287
179745
|
"election.started",
|
|
179288
179746
|
"election.complete",
|
|
179289
179747
|
"cluster.state",
|
|
@@ -179590,12 +180048,22 @@ var REQUEST_TELEMETRY_SUPPRESSED_ROUTES = /* @__PURE__ */ new Set([
|
|
|
179590
180048
|
"POST /api/cluster-control/heartbeat",
|
|
179591
180049
|
"POST /api/cluster-control/keepalive"
|
|
179592
180050
|
]);
|
|
180051
|
+
var REQUEST_LOGGING_THROTTLED_ROUTES = /* @__PURE__ */ new Set([
|
|
180052
|
+
"POST /api/worker/keepalive",
|
|
180053
|
+
"POST /api/cluster-control/keepalive"
|
|
180054
|
+
]);
|
|
180055
|
+
var REQUEST_LOGGING_THROTTLE_MS = 6e4;
|
|
179593
180056
|
function normalizeRequestTelemetryPath(pathname) {
|
|
179594
180057
|
return pathname.length > 1 ? pathname.replace(/\/+$/, "") : pathname;
|
|
179595
180058
|
}
|
|
180059
|
+
function requestRouteKey(method, pathname) {
|
|
180060
|
+
return `${method.toUpperCase()} ${normalizeRequestTelemetryPath(pathname)}`;
|
|
180061
|
+
}
|
|
179596
180062
|
function isSuppressedRequestTelemetryRoute(req) {
|
|
179597
|
-
|
|
179598
|
-
|
|
180063
|
+
return REQUEST_TELEMETRY_SUPPRESSED_ROUTES.has(requestRouteKey(req.method, req.path));
|
|
180064
|
+
}
|
|
180065
|
+
function isThrottledRequestLoggingRoute(method, pathname) {
|
|
180066
|
+
return REQUEST_LOGGING_THROTTLED_ROUTES.has(requestRouteKey(method, pathname));
|
|
179599
180067
|
}
|
|
179600
180068
|
function usesLargeJsonBodyLimit(pathname) {
|
|
179601
180069
|
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/") || pathname.startsWith("/api/mobile/");
|
|
@@ -179767,7 +180235,11 @@ function createServer2(deps) {
|
|
|
179767
180235
|
const canServeDashboard = (req) => !deps.config.validateBearerToken || isTrustedDashboardRequest(req, authConfig);
|
|
179768
180236
|
const canServePreview = (req) => canServeDashboard(req) || hasAuthorizationHeader(req);
|
|
179769
180237
|
app.use(createRequestLoggingMiddleware(deps.logger, {
|
|
179770
|
-
shouldLog: (req) => isApiRequest(req) || isPreviewRequest(req)
|
|
180238
|
+
shouldLog: (req) => isApiRequest(req) || isPreviewRequest(req),
|
|
180239
|
+
throttle: {
|
|
180240
|
+
intervalMs: REQUEST_LOGGING_THROTTLE_MS,
|
|
180241
|
+
shouldThrottle: (req, res, closed, path47) => !closed && res.statusCode < 400 && isThrottledRequestLoggingRoute(req.method, path47)
|
|
180242
|
+
}
|
|
179771
180243
|
}));
|
|
179772
180244
|
app.use(createRequestTelemetryMiddleware(deps.telemetry ?? createNoopTelemetry(), {
|
|
179773
180245
|
shouldTrack: (req) => !isSuppressedRequestTelemetryRoute(req) && (isApiRequest(req) || isPreviewRequest(req))
|
|
@@ -181756,6 +182228,7 @@ function createSettingsSnapshotProvider(options) {
|
|
|
181756
182228
|
function buildSnapshot() {
|
|
181757
182229
|
cachedSnapshot = buildNodeSettingsSnapshot({
|
|
181758
182230
|
auth: options.authMetadata,
|
|
182231
|
+
defaultTaskAgent: resolveNodeDefaultTaskAgent(options.storagePath),
|
|
181759
182232
|
localDashboardOrigin: options.localDashboardOrigin,
|
|
181760
182233
|
runtimeMetadata: options.runtimeMetadata,
|
|
181761
182234
|
runtimeUpdate: createRuntimeUpdateSnapshot({
|