newmark-agent 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conversation-utility-host.bundle.cjs +287 -18
- package/dist/conversation-utility-host.js +3 -0
- package/dist/core/agent.d.ts +2 -0
- package/dist/core/agent.js +20 -0
- package/dist/core/agentKernelRunner.js +27 -10
- package/dist/core/conversationKernel.d.ts +40 -0
- package/dist/core/conversationKernel.js +219 -8
- package/dist/core/electronUtilityAgentClient.d.ts +8 -0
- package/dist/core/electronUtilityAgentClient.js +5 -1
- package/dist/core/electronUtilityRuntimePool.d.ts +15 -0
- package/dist/core/electronUtilityRuntimePool.js +11 -0
- package/dist/core/toolPolicy.js +3 -0
- package/dist/core/utilityAgentProtocol.d.ts +29 -1
- package/dist/core/utilityHostToolRouter.js +18 -0
- package/dist/core/wslAgentClient.d.ts +8 -0
- package/dist/core/wslAgentClient.js +5 -1
- package/dist/core/wslAgentProtocol.d.ts +18 -1
- package/dist/core/wslAgentRuntimePool.d.ts +15 -0
- package/dist/core/wslAgentRuntimePool.js +11 -0
- package/dist/main.js +193 -7
- package/dist/server.d.ts +32 -1
- package/dist/server.js +157 -35
- package/dist/tools/index.js +46 -1
- package/dist/tools/nativeTools.js +1 -0
- package/dist/wsl-agent-host.bundle.cjs +287 -18
- package/dist/wsl-agent-host.js +3 -0
- package/package.json +2 -2
|
@@ -327556,6 +327556,7 @@ var NATIVE_TOOL_CATALOG = [
|
|
|
327556
327556
|
{ name: "browser_reload", label: "Browser reload", description: "Reload the built-in browser.", category: "browser", defaultEnabled: true },
|
|
327557
327557
|
{ name: "browser_cdp", label: "Browser CDP", description: "Run an advanced Chrome DevTools Protocol command.", category: "browser", defaultEnabled: true },
|
|
327558
327558
|
{ name: "browser_use", label: "Browser Use", description: "Observe and control the built-in browser through scoped opaque element refs and structured receipts.", category: "browser", defaultEnabled: true },
|
|
327559
|
+
{ name: "screen_capture", label: "Active screenshot", description: "Capture the Windows desktop or one visible application without starting the full Computer Use control surface.", category: "desktop", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327559
327560
|
{ name: "computer_use", label: "Computer Use", description: "Observe and control Windows desktop UI with screenshots and semantic objects.", category: "desktop", defaultEnabled: true },
|
|
327560
327561
|
{ name: "image_inspect", label: "Image inspect", description: "Crop and magnify images submitted in the current conversation for closer visual inspection.", category: "core", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327561
327562
|
{ name: "image_display", label: "Image display", description: "Present a workspace PNG/JPEG inside the current Build Block.", category: "core", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
@@ -335746,6 +335747,7 @@ var import_crypto6 = require("crypto");
|
|
|
335746
335747
|
// src/core/toolPolicy.ts
|
|
335747
335748
|
var REQUIRED_TOOLS = /* @__PURE__ */ new Set(["pwd", "read", "glob", "grep"]);
|
|
335748
335749
|
var MODE_SCOPED_TOOLS = /* @__PURE__ */ new Set([
|
|
335750
|
+
"screen_capture",
|
|
335749
335751
|
"image_inspect",
|
|
335750
335752
|
"image_display",
|
|
335751
335753
|
"ocr_read",
|
|
@@ -335778,6 +335780,7 @@ var MODE_SCOPED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335778
335780
|
"branch_create"
|
|
335779
335781
|
]);
|
|
335780
335782
|
var PLAN_READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
335783
|
+
"screen_capture",
|
|
335781
335784
|
"task_read",
|
|
335782
335785
|
"pwd",
|
|
335783
335786
|
"read",
|
|
@@ -335825,6 +335828,7 @@ var CONCURRENCY_SAFE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335825
335828
|
"git_status",
|
|
335826
335829
|
"file_audit",
|
|
335827
335830
|
"repo_security_audit",
|
|
335831
|
+
"screen_capture",
|
|
335828
335832
|
"SubAgent"
|
|
335829
335833
|
]);
|
|
335830
335834
|
function isConcurrencySafeTool(name50, riskLevel) {
|
|
@@ -336908,6 +336912,13 @@ var ToolExecutor = class {
|
|
|
336908
336912
|
max_refs: { type: "number" },
|
|
336909
336913
|
attribute: { type: "string" }
|
|
336910
336914
|
}, ["action"]),
|
|
336915
|
+
t3("screen_capture", "Read-only active Windows screenshot available without provisioning or starting full Computer Use. Capture the whole desktop or one visible application. The image is a one-use model input and is deleted immediately; semantic Windows UI objects are returned alongside it.", {
|
|
336916
|
+
target: { type: "string", enum: ["desktop", "application"], description: "Capture the whole desktop or one visible application. Defaults to desktop." },
|
|
336917
|
+
app_target: { type: "string", description: "For target=application: application title, process name, process id, or window handle." },
|
|
336918
|
+
capture_max_width: { type: "number", minimum: 320, maximum: 2048, description: "Maximum ephemeral screenshot width; defaults to 1280. Aspect ratio is preserved and the source is never enlarged." },
|
|
336919
|
+
capture_max_height: { type: "number", minimum: 240, maximum: 2048, description: "Maximum ephemeral screenshot height; defaults to 960. Aspect ratio is preserved and the source is never enlarged." },
|
|
336920
|
+
max_chars: { type: "number", minimum: 1e3, maximum: 1e5, description: "Maximum returned semantic UI text characters." }
|
|
336921
|
+
}, []),
|
|
336911
336922
|
t3("computer_use", "Native Windows desktop control with persistent observation/action helpers. Use observe/app_observe before acting. sequence may perform up to three stable low-risk move/click/scroll/wait/app_activate steps and stops when focus, window, menu, dialog, scene, or risk changes. Vision screenshots remain one-time inputs and are deleted immediately.", {
|
|
336912
336923
|
action: { type: "string", enum: ["observe", "app_list", "app_observe", "sequence", "takeover_start", "takeover_stop", "move", "click", "scroll", "type", "key", "wait", "app_activate", "app_click", "app_scroll", "app_type", "app_key"] },
|
|
336913
336924
|
capture_max_width: { type: "number", minimum: 320, maximum: 2048, description: "For observe/app_observe only. Maximum ephemeral screenshot width; defaults to 1280. Aspect ratio is preserved and the source is never enlarged." },
|
|
@@ -337398,6 +337409,44 @@ var ToolExecutor = class {
|
|
|
337398
337409
|
result: parsed
|
|
337399
337410
|
}, null, 2);
|
|
337400
337411
|
}
|
|
337412
|
+
case "screen_capture": {
|
|
337413
|
+
const target = g2("target").toLowerCase() === "application" ? "application" : "desktop";
|
|
337414
|
+
if (process.env.NEWMARK_WSL_DISTRO) {
|
|
337415
|
+
const result = await requestWindowsHostTool("screen_capture", args, {
|
|
337416
|
+
conversationId: context.conversationId || "default",
|
|
337417
|
+
workspaceId: context.workspaceId || terminalTakeoverWorkspaceId(context.workspacePath || wsPath),
|
|
337418
|
+
actorId: context.actorId || ROOT_TERMINAL_ACTOR_ID,
|
|
337419
|
+
runtimeKey: browserUseScope(context, wsPath).runtimeKey,
|
|
337420
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
337421
|
+
mode: context.mode || "build"
|
|
337422
|
+
}, 12e4, context.signal);
|
|
337423
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
337424
|
+
}
|
|
337425
|
+
if (process.env.NEWMARK_ISOLATED_RUNTIME === "1") {
|
|
337426
|
+
const result = await requestUtilityHostTool("screen_capture", args, {
|
|
337427
|
+
conversationId: context.conversationId || "default",
|
|
337428
|
+
workspaceId: context.workspaceId || terminalTakeoverWorkspaceId(context.workspacePath || wsPath),
|
|
337429
|
+
actorId: context.actorId || ROOT_TERMINAL_ACTOR_ID,
|
|
337430
|
+
workspacePath: context.workspacePath || wsPath,
|
|
337431
|
+
backend: "utility",
|
|
337432
|
+
mode: context.mode || "build",
|
|
337433
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true
|
|
337434
|
+
}, 12e4, context.signal);
|
|
337435
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
337436
|
+
}
|
|
337437
|
+
return await runComputerUse({
|
|
337438
|
+
action: target === "application" ? "app_observe" : "observe",
|
|
337439
|
+
appTarget: g2("app_target"),
|
|
337440
|
+
windowHandle: target === "application" ? g2("app_target") : "",
|
|
337441
|
+
maxChars: Number(args.max_chars || 3e4),
|
|
337442
|
+
workspacePath: wsPath,
|
|
337443
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
337444
|
+
captureMaxWidth: Number(args.capture_max_width),
|
|
337445
|
+
captureMaxHeight: Number(args.capture_max_height),
|
|
337446
|
+
invocation: context.invocation,
|
|
337447
|
+
ownerId: `screen-capture:${computerUseOwner(context, wsPath)}:${String(context.actorId || "root")}`
|
|
337448
|
+
});
|
|
337449
|
+
}
|
|
337401
337450
|
case "computer_use": {
|
|
337402
337451
|
const action = normalizeComputerUseAction(g2("action"));
|
|
337403
337452
|
const owner = `${computerUseOwner(context, wsPath)}:${String(context.actorId || "root")}`;
|
|
@@ -337604,7 +337653,7 @@ var ToolExecutor = class {
|
|
|
337604
337653
|
}
|
|
337605
337654
|
hostSupportsTool(name50) {
|
|
337606
337655
|
if (name50.startsWith("browser_") && !this.hostProfile.electronBrowser) return false;
|
|
337607
|
-
if (name50 === "computer_use" && !this.hostProfile.windowsComputerUse) return false;
|
|
337656
|
+
if ((name50 === "computer_use" || name50 === "screen_capture") && !this.hostProfile.windowsComputerUse) return false;
|
|
337608
337657
|
return true;
|
|
337609
337658
|
}
|
|
337610
337659
|
async decorateBrowserUseReceipt(input, context, runtimeKey) {
|
|
@@ -341504,10 +341553,12 @@ function toKernelTools(agent, definitions, provisioning) {
|
|
|
341504
341553
|
throw new Error(rawText);
|
|
341505
341554
|
}
|
|
341506
341555
|
const visionImage = visualFallbackImageInput(agent, name50, rawText);
|
|
341556
|
+
const capturedInput = name50 === "screen_capture" ? agent.registerCapturedImageInput(visionImage.image || "", "active-screenshot.jpg") : null;
|
|
341507
341557
|
const directImage = imageInspectDataUrl(name50, rawText);
|
|
341508
|
-
const text = spillOversizedToolResult(agent, name50, sanitizeVisualToolText(name50, rawText));
|
|
341558
|
+
const text = spillOversizedToolResult(agent, name50, capturedImageToolText(name50, sanitizeVisualToolText(name50, rawText), capturedInput?.id));
|
|
341509
341559
|
const content = [{ type: "text", text }];
|
|
341510
|
-
if (
|
|
341560
|
+
if (name50 === "screen_capture" && capturedInput?.dataUrl) content.push({ type: "image", image: capturedInput.dataUrl, mimeType: capturedInput.mimeType });
|
|
341561
|
+
else if (visionImage.imagePath) content.push({ type: "image", imagePath: visionImage.imagePath, mimeType: imageMimeForPath(visionImage.imagePath) });
|
|
341511
341562
|
else if (visionImage.image) content.push({ type: "image", image: visionImage.image, mimeType: visionImage.mimeType });
|
|
341512
341563
|
if (directImage) content.push({ type: "image", image: directImage, mimeType: "image/png" });
|
|
341513
341564
|
const terminate = shouldTerminateAfterToolResult(name50) && (name50 !== "question" || agent.pendingOptions.length > 0);
|
|
@@ -341520,7 +341571,7 @@ function toKernelTools(agent, definitions, provisioning) {
|
|
|
341520
341571
|
} catch {
|
|
341521
341572
|
}
|
|
341522
341573
|
}
|
|
341523
|
-
return { content, details: { tool: name50, ok: true, terminate, ...launchReceipt ? { launchReceipt } : {}, visionImagePath: visionImage.imagePath || void 0, ephemeralVisionImage: !!visionImage.image, displayImage }, terminate };
|
|
341574
|
+
return { content, details: { tool: name50, ok: true, terminate, ...launchReceipt ? { launchReceipt } : {}, visionImagePath: visionImage.imagePath || void 0, ephemeralVisionImage: !!visionImage.image, capturedAttachmentId: capturedInput?.id, displayImage }, terminate };
|
|
341524
341575
|
}
|
|
341525
341576
|
};
|
|
341526
341577
|
}).filter((tool) => !!tool.name);
|
|
@@ -341544,7 +341595,7 @@ var INLINE_TOOL_RESULT_MAX_CHARS = 24e3;
|
|
|
341544
341595
|
function spillOversizedToolResult(agent, name50, text) {
|
|
341545
341596
|
const value = String(text || "");
|
|
341546
341597
|
if (value.length <= INLINE_TOOL_RESULT_MAX_CHARS) return value;
|
|
341547
|
-
if (["computer_use", "browser_use", "pdf_read", "image_inspect", "image_display", "task", "subagent_create", "SubAgent", "subagent_send", "subagent_result", "subagent_read", "linked_plan", "question"].includes(name50)) {
|
|
341598
|
+
if (["screen_capture", "computer_use", "browser_use", "pdf_read", "image_inspect", "image_display", "task", "subagent_create", "SubAgent", "subagent_send", "subagent_result", "subagent_read", "linked_plan", "question"].includes(name50)) {
|
|
341548
341599
|
return value;
|
|
341549
341600
|
}
|
|
341550
341601
|
const artifactId = agent.storeToolResultArtifact(name50, value);
|
|
@@ -341559,10 +341610,10 @@ function spillOversizedToolResult(agent, name50, text) {
|
|
|
341559
341610
|
].join("\n");
|
|
341560
341611
|
}
|
|
341561
341612
|
function sanitizeVisualToolText(name50, text) {
|
|
341562
|
-
if (name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read" && name50 !== "image_inspect") return text;
|
|
341613
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read" && name50 !== "image_inspect") return text;
|
|
341563
341614
|
try {
|
|
341564
341615
|
const parsed = JSON.parse(text);
|
|
341565
|
-
if (name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read") {
|
|
341616
|
+
if (name50 === "screen_capture" || name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read") {
|
|
341566
341617
|
delete parsed.vision_image_path;
|
|
341567
341618
|
delete parsed.vision_image_data_url;
|
|
341568
341619
|
if (name50 === "pdf_read" && parsed.result && typeof parsed.result === "object") {
|
|
@@ -341578,7 +341629,7 @@ function sanitizeVisualToolText(name50, text) {
|
|
|
341578
341629
|
}
|
|
341579
341630
|
}
|
|
341580
341631
|
function discardComputerUseVisionImage(name50, text) {
|
|
341581
|
-
if (name50 !== "computer_use") return;
|
|
341632
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use") return;
|
|
341582
341633
|
try {
|
|
341583
341634
|
const parsed = JSON.parse(text);
|
|
341584
341635
|
const screenshotPath = String(parsed.vision_image_path || "");
|
|
@@ -341596,8 +341647,20 @@ function imageInspectDataUrl(name50, text) {
|
|
|
341596
341647
|
return "";
|
|
341597
341648
|
}
|
|
341598
341649
|
}
|
|
341650
|
+
function capturedImageToolText(name50, text, attachmentId) {
|
|
341651
|
+
if (name50 !== "screen_capture" || !attachmentId) return text;
|
|
341652
|
+
try {
|
|
341653
|
+
const parsed = JSON.parse(text);
|
|
341654
|
+
parsed.attachment_id = attachmentId;
|
|
341655
|
+
parsed.image_input_channel = "user-image";
|
|
341656
|
+
parsed.inspect_next = { tool: "image_inspect", actions: ["source_info", "crop"], max_scale: 4 };
|
|
341657
|
+
return JSON.stringify(parsed, null, 2);
|
|
341658
|
+
} catch {
|
|
341659
|
+
return text;
|
|
341660
|
+
}
|
|
341661
|
+
}
|
|
341599
341662
|
function visualFallbackImageInput(agent, name50, text) {
|
|
341600
|
-
if (name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read") return {};
|
|
341663
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read") return {};
|
|
341601
341664
|
const model = agent.activeModelConfig();
|
|
341602
341665
|
if (!model?.vision) return {};
|
|
341603
341666
|
try {
|
|
@@ -341723,7 +341786,7 @@ async function executeNewmarkTool(agent, name50, args, inputSchema, signal) {
|
|
|
341723
341786
|
actorId: agent.runtimeActorId,
|
|
341724
341787
|
workspaceId: terminalTakeoverWorkspaceId(wsDir),
|
|
341725
341788
|
backend: process.env.NEWMARK_WSL_DISTRO ? "wsl" : process.platform === "win32" ? "windows" : process.platform,
|
|
341726
|
-
allowEphemeralVisionImage: (name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read" || name50 === "ocr_read") && !!agent.activeModelConfig()?.vision,
|
|
341789
|
+
allowEphemeralVisionImage: (name50 === "screen_capture" || name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read" || name50 === "ocr_read") && !!agent.activeModelConfig()?.vision,
|
|
341727
341790
|
signal
|
|
341728
341791
|
});
|
|
341729
341792
|
if (signal?.aborted) throw abortError4();
|
|
@@ -344866,6 +344929,7 @@ var Agent4 = class _Agent {
|
|
|
344866
344929
|
memoryLabRebuildState = "idle";
|
|
344867
344930
|
memoryLabRebuildError = "";
|
|
344868
344931
|
displayImageDescriptionCache = /* @__PURE__ */ new Map();
|
|
344932
|
+
latestCapturedImageInputs = [];
|
|
344869
344933
|
activeProcessAbortController = null;
|
|
344870
344934
|
automationManager = null;
|
|
344871
344935
|
activeAgentKernelRuntime = null;
|
|
@@ -347063,6 +347127,13 @@ ${String(event.toolArgs || "")}`;
|
|
|
347063
347127
|
listConversationStates() {
|
|
347064
347128
|
return this.listWorkspaceConversationStates(this.workspace.current);
|
|
347065
347129
|
}
|
|
347130
|
+
registerCapturedImageInput(dataUrl, name50 = "active-screenshot.jpg") {
|
|
347131
|
+
if (!String(dataUrl || "").startsWith("data:image/")) return null;
|
|
347132
|
+
const prepared = this.prepareSubmittedConversationImages([{ dataUrl, name: name50, type: dataUrl.slice(5, dataUrl.indexOf(";")) }]);
|
|
347133
|
+
const attachment = prepared.attachments[0] || null;
|
|
347134
|
+
this.latestCapturedImageInputs = attachment ? [attachment] : [];
|
|
347135
|
+
return attachment;
|
|
347136
|
+
}
|
|
347066
347137
|
subagentConcurrencyLimit() {
|
|
347067
347138
|
return this.intelligence === "ultra" ? 16 : 4;
|
|
347068
347139
|
}
|
|
@@ -351980,6 +352051,13 @@ ${items.map((item) => this.formatAutomation(item)).join("\n")}`;
|
|
|
351980
352051
|
}
|
|
351981
352052
|
latestSubmittedImages(attachmentId = "") {
|
|
351982
352053
|
const normalizedId = String(attachmentId || "").trim();
|
|
352054
|
+
const captured = hydrateConversationImageAttachments(this.rootPath, this.latestCapturedImageInputs).flatMap((attachment) => attachment.dataUrl ? [{ id: attachment.id, dataUrl: attachment.dataUrl }] : []);
|
|
352055
|
+
if (normalizedId) {
|
|
352056
|
+
const capturedMatch = captured.find((item) => item.id === normalizedId);
|
|
352057
|
+
if (capturedMatch) return [capturedMatch];
|
|
352058
|
+
} else if (captured.length) {
|
|
352059
|
+
return captured;
|
|
352060
|
+
}
|
|
351983
352061
|
for (let index = this.chatMessages.length - 1; index >= 0; index -= 1) {
|
|
351984
352062
|
const message = this.chatMessages[index];
|
|
351985
352063
|
if (message?.role !== "user") continue;
|
|
@@ -353164,6 +353242,155 @@ var ConversationKernel = class {
|
|
|
353164
353242
|
followUp: queued?.followUp.slice() || []
|
|
353165
353243
|
};
|
|
353166
353244
|
}
|
|
353245
|
+
queueItems(target) {
|
|
353246
|
+
const runtime = this.findRuntime(target);
|
|
353247
|
+
if (!runtime) return [];
|
|
353248
|
+
return runtime.pendingNextTurn.flatMap((item) => {
|
|
353249
|
+
if (item.queueMode !== "followUp") return [];
|
|
353250
|
+
if (typeof item.message === "string") return [];
|
|
353251
|
+
const id = String(item.message.clientMessageId || "");
|
|
353252
|
+
if (!id) return [];
|
|
353253
|
+
return [{
|
|
353254
|
+
id,
|
|
353255
|
+
text: String(item.message.visibleUserInput || item.message.text || "").replace(/^\[Next queued while current turn is running\]\n/, ""),
|
|
353256
|
+
queueMode: item.queueMode,
|
|
353257
|
+
requestedMode: item.message.visibleMode,
|
|
353258
|
+
goalObjective: item.message.goalObjective,
|
|
353259
|
+
runId: item.message.runId,
|
|
353260
|
+
createdAt: String(item.message.createdAt || "")
|
|
353261
|
+
}];
|
|
353262
|
+
});
|
|
353263
|
+
}
|
|
353264
|
+
enqueueNext(target, input) {
|
|
353265
|
+
const runtime = this.findRuntime(target);
|
|
353266
|
+
if (!runtime?.activePromise || !runtime.runId) throw new Error("Target conversation is not running");
|
|
353267
|
+
const id = String(input.id || "").trim().slice(0, 200);
|
|
353268
|
+
const text = String(input.text || "").trim();
|
|
353269
|
+
if (!id || !text) throw new Error("Queue item id and text are required");
|
|
353270
|
+
const existing = this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353271
|
+
if (existing) return existing;
|
|
353272
|
+
const prompt = `[Next queued while current turn is running]
|
|
353273
|
+
${text}`;
|
|
353274
|
+
const createdAt = String(input.createdAt || (/* @__PURE__ */ new Date()).toISOString());
|
|
353275
|
+
runtime.pendingNextTurn.push({
|
|
353276
|
+
message: {
|
|
353277
|
+
text: prompt,
|
|
353278
|
+
visibleUserInput: text,
|
|
353279
|
+
visibleMode: String(input.requestedMode || "build"),
|
|
353280
|
+
goalObjective: String(input.goalObjective || "") || void 0,
|
|
353281
|
+
clientMessageId: id,
|
|
353282
|
+
runId: runtime.runId,
|
|
353283
|
+
createdAt
|
|
353284
|
+
},
|
|
353285
|
+
queueMode: "followUp"
|
|
353286
|
+
});
|
|
353287
|
+
runtime.runner.retainConversationContinuations([{
|
|
353288
|
+
content: prompt,
|
|
353289
|
+
queueMode: "followUp",
|
|
353290
|
+
clientMessageId: id,
|
|
353291
|
+
runId: runtime.runId,
|
|
353292
|
+
createdAt
|
|
353293
|
+
}]);
|
|
353294
|
+
this.trackQueuedMessage(runtime, prompt, "followUp");
|
|
353295
|
+
this.emitQueueUpdate(runtime);
|
|
353296
|
+
return this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353297
|
+
}
|
|
353298
|
+
updateQueueItem(target, idInput, textInput) {
|
|
353299
|
+
const runtime = this.findRuntime(target);
|
|
353300
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353301
|
+
const id = String(idInput || "").trim();
|
|
353302
|
+
const text = String(textInput || "").trim();
|
|
353303
|
+
if (!id || !text) throw new Error("Queue item id and text are required");
|
|
353304
|
+
const pending3 = runtime.pendingNextTurn.find((item) => typeof item.message !== "string" && item.message.clientMessageId === id);
|
|
353305
|
+
if (!pending3 || typeof pending3.message === "string") throw new Error("Queue item is no longer editable");
|
|
353306
|
+
const oldPrompt = pending3.message.text;
|
|
353307
|
+
pending3.message.text = `[Next queued while current turn is running]
|
|
353308
|
+
${text}`;
|
|
353309
|
+
pending3.message.visibleUserInput = text;
|
|
353310
|
+
runtime.runner.consumeConversationContinuation({ content: oldPrompt, queueMode: pending3.queueMode, clientMessageId: id });
|
|
353311
|
+
runtime.runner.retainConversationContinuations([{
|
|
353312
|
+
content: pending3.message.text,
|
|
353313
|
+
queueMode: pending3.queueMode,
|
|
353314
|
+
clientMessageId: id,
|
|
353315
|
+
runId: pending3.message.runId
|
|
353316
|
+
}]);
|
|
353317
|
+
this.replaceTrackedQueuedMessage(runtime, oldPrompt, pending3.message.text, pending3.queueMode);
|
|
353318
|
+
this.emitQueueUpdate(runtime);
|
|
353319
|
+
return this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353320
|
+
}
|
|
353321
|
+
deleteQueueItem(target, idInput) {
|
|
353322
|
+
const runtime = this.findRuntime(target);
|
|
353323
|
+
if (!runtime) return false;
|
|
353324
|
+
const id = String(idInput || "").trim();
|
|
353325
|
+
const index = runtime.pendingNextTurn.findIndex((item) => typeof item.message !== "string" && item.message.clientMessageId === id);
|
|
353326
|
+
if (index < 0) return false;
|
|
353327
|
+
const [removed] = runtime.pendingNextTurn.splice(index, 1);
|
|
353328
|
+
if (typeof removed.message !== "string") {
|
|
353329
|
+
runtime.runner.consumeConversationContinuation({ content: removed.message.text, queueMode: removed.queueMode, clientMessageId: id });
|
|
353330
|
+
this.consumeQueuedMessage(runtime, removed.message.text);
|
|
353331
|
+
}
|
|
353332
|
+
this.emitQueueUpdate(runtime);
|
|
353333
|
+
return true;
|
|
353334
|
+
}
|
|
353335
|
+
setQueuePaused(target, paused) {
|
|
353336
|
+
const runtime = this.findRuntime(target);
|
|
353337
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353338
|
+
runtime.queuePaused = paused;
|
|
353339
|
+
this.emitQueueUpdate(runtime);
|
|
353340
|
+
if (!paused && !runtime.activePromise && runtime.pendingNextTurn.length) {
|
|
353341
|
+
this.schedulePendingRuntimeContinuation(runtime, runtime.runId);
|
|
353342
|
+
}
|
|
353343
|
+
return runtime.queuePaused;
|
|
353344
|
+
}
|
|
353345
|
+
queueAction(target, action, input = {}) {
|
|
353346
|
+
const runtime = this.findRuntime(target);
|
|
353347
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353348
|
+
let receipt;
|
|
353349
|
+
if (action === "enqueue") {
|
|
353350
|
+
this.enqueueNext(runtime.target, {
|
|
353351
|
+
id: String(input.id || ""),
|
|
353352
|
+
text: String(input.text || ""),
|
|
353353
|
+
requestedMode: input.requestedMode,
|
|
353354
|
+
goalObjective: input.goalObjective,
|
|
353355
|
+
createdAt: input.createdAt
|
|
353356
|
+
});
|
|
353357
|
+
} else if (action === "update") {
|
|
353358
|
+
this.updateQueueItem(runtime.target, String(input.id || ""), String(input.text || ""));
|
|
353359
|
+
} else if (action === "delete") {
|
|
353360
|
+
if (!this.deleteQueueItem(runtime.target, String(input.id || ""))) throw new Error("Queue item was not found");
|
|
353361
|
+
} else if (action === "toggle_pause") {
|
|
353362
|
+
this.setQueuePaused(runtime.target, !runtime.queuePaused);
|
|
353363
|
+
} else if (action === "guide") {
|
|
353364
|
+
const item = this.queueItems(runtime.target).find((entry) => entry.id === String(input.id || ""));
|
|
353365
|
+
if (!item) throw new Error("Queue item was not found");
|
|
353366
|
+
receipt = this.enqueueGuide({
|
|
353367
|
+
clientMessageId: item.id,
|
|
353368
|
+
guideId: (0, import_crypto16.randomUUID)(),
|
|
353369
|
+
target: runtime.target,
|
|
353370
|
+
runId: runtime.runId,
|
|
353371
|
+
deliveryMode: "steer",
|
|
353372
|
+
text: item.goalObjective ? `Goal for the current Build:
|
|
353373
|
+
${item.goalObjective}` : item.text,
|
|
353374
|
+
goalObjective: item.goalObjective,
|
|
353375
|
+
createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
353376
|
+
});
|
|
353377
|
+
if (receipt.status === "rejected") return {
|
|
353378
|
+
ok: false,
|
|
353379
|
+
queueItems: this.queueItems(runtime.target),
|
|
353380
|
+
queuePaused: runtime.queuePaused,
|
|
353381
|
+
queued: this.queued(runtime.target),
|
|
353382
|
+
receipt
|
|
353383
|
+
};
|
|
353384
|
+
this.deleteQueueItem(runtime.target, item.id);
|
|
353385
|
+
}
|
|
353386
|
+
return {
|
|
353387
|
+
ok: true,
|
|
353388
|
+
queueItems: this.queueItems(runtime.target),
|
|
353389
|
+
queuePaused: runtime.queuePaused,
|
|
353390
|
+
queued: this.queued(runtime.target),
|
|
353391
|
+
receipt
|
|
353392
|
+
};
|
|
353393
|
+
}
|
|
353167
353394
|
events(target) {
|
|
353168
353395
|
return this.findRuntime(target)?.events.slice() || [];
|
|
353169
353396
|
}
|
|
@@ -353192,6 +353419,8 @@ var ConversationKernel = class {
|
|
|
353192
353419
|
workRuns: this.bindWorkRunsToRuntimeTarget(conversationSnapshot.workRuns, normalized),
|
|
353193
353420
|
target: normalized,
|
|
353194
353421
|
queued: this.queued(normalized),
|
|
353422
|
+
queueItems: this.queueItems(normalized),
|
|
353423
|
+
queuePaused: runtime?.queuePaused === true,
|
|
353195
353424
|
workEvents: this.events(normalized),
|
|
353196
353425
|
runtime: this.runtimeState(normalized),
|
|
353197
353426
|
mode: runner.mode,
|
|
@@ -353627,7 +353856,7 @@ var ConversationKernel = class {
|
|
|
353627
353856
|
if (runtime.stopRequestedRunId === runId) {
|
|
353628
353857
|
stopped = true;
|
|
353629
353858
|
this.settleCooperativeStop(runtime, runId);
|
|
353630
|
-
} else if (runtime.pendingNextTurn.length > 0) {
|
|
353859
|
+
} else if (!runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353631
353860
|
this.schedulePendingRuntimeContinuation(runtime, runId);
|
|
353632
353861
|
}
|
|
353633
353862
|
}
|
|
@@ -353662,7 +353891,7 @@ var ConversationKernel = class {
|
|
|
353662
353891
|
return this.result(runtime, lastTokens);
|
|
353663
353892
|
}
|
|
353664
353893
|
for (; ; ) {
|
|
353665
|
-
while (runtime.pendingNextTurn.length > 0) {
|
|
353894
|
+
while (!runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353666
353895
|
if (runtime.stopRequestedRunId === runtime.runId) return this.result(runtime, lastTokens);
|
|
353667
353896
|
const next = runtime.pendingNextTurn.shift();
|
|
353668
353897
|
if (next.queueMode === "steer" && typeof next.message !== "string" && !!next.message.clientMessageId) {
|
|
@@ -353704,11 +353933,11 @@ ${batchText}`,
|
|
|
353704
353933
|
this.mirrorHostIfTargetActive(runtime);
|
|
353705
353934
|
return this.result(runtime, lastTokens);
|
|
353706
353935
|
}
|
|
353707
|
-
this.clearQueued(runtime);
|
|
353936
|
+
if (!runtime.pendingNextTurn.length) this.clearQueued(runtime);
|
|
353708
353937
|
const completedRunId = runtime.runId;
|
|
353709
353938
|
runtime.runner.finishConversationWorkRun(completedRunId, "completed");
|
|
353710
353939
|
await new Promise((resolve16) => setImmediate(resolve16));
|
|
353711
|
-
if (runtime.runId === completedRunId && runtime.stopRequestedRunId !== completedRunId && runtime.pendingNextTurn.length > 0) {
|
|
353940
|
+
if (runtime.runId === completedRunId && runtime.stopRequestedRunId !== completedRunId && !runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353712
353941
|
runtime.guideAcceptanceClosedRunId = "";
|
|
353713
353942
|
if (!runtime.runner.resumeConversationWorkRun(completedRunId)) {
|
|
353714
353943
|
throw new Error(`Unable to resume deferred Guide work run ${completedRunId}`);
|
|
@@ -353799,6 +354028,7 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
353799
354028
|
events: [],
|
|
353800
354029
|
pendingNextTurn: [],
|
|
353801
354030
|
queued: { steering: [], followUp: [] },
|
|
354031
|
+
queuePaused: false,
|
|
353802
354032
|
runId: "",
|
|
353803
354033
|
generation: this.generations.get(target.runtimeKey) || 0,
|
|
353804
354034
|
stopRequestedRunId: "",
|
|
@@ -353894,7 +354124,7 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
353894
354124
|
}
|
|
353895
354125
|
setImmediate(() => {
|
|
353896
354126
|
runtime.pendingContinuationRunId = void 0;
|
|
353897
|
-
if (runtime.runId !== runId || runtime.activePromise || runtime.stopRequestedRunId === runId) return;
|
|
354127
|
+
if (runtime.runId !== runId || runtime.activePromise || runtime.stopRequestedRunId === runId || runtime.queuePaused) return;
|
|
353898
354128
|
const next = runtime.pendingNextTurn.shift();
|
|
353899
354129
|
if (!next) return;
|
|
353900
354130
|
const message = typeof next.message === "string" ? { text: next.message, runId } : { ...next.message, runId: next.message.runId || runId };
|
|
@@ -354045,7 +354275,36 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
354045
354275
|
const text = typeof message === "string" ? message : message.text;
|
|
354046
354276
|
const prompt = isSteer ? text : `[Next queued while current turn is running]
|
|
354047
354277
|
${text}`;
|
|
354048
|
-
if (!isSteer)
|
|
354278
|
+
if (!isSteer) {
|
|
354279
|
+
const structured = typeof message === "string" ? null : message;
|
|
354280
|
+
const clientMessageId = String(structured?.clientMessageId || (0, import_crypto16.randomUUID)());
|
|
354281
|
+
const queuedMessage = {
|
|
354282
|
+
...structured || {},
|
|
354283
|
+
text: prompt,
|
|
354284
|
+
visibleUserInput: structured?.visibleUserInput || text,
|
|
354285
|
+
visibleMode: structured?.visibleMode || runtime.options.mode,
|
|
354286
|
+
clientMessageId,
|
|
354287
|
+
runId: structured?.runId || runtime.runId,
|
|
354288
|
+
createdAt: String(structured?.createdAt || (/* @__PURE__ */ new Date()).toISOString())
|
|
354289
|
+
};
|
|
354290
|
+
if (!runtime.pendingNextTurn.some((item) => typeof item.message !== "string" && item.message.clientMessageId === clientMessageId)) {
|
|
354291
|
+
runtime.pendingNextTurn.push({ message: queuedMessage, queueMode: "followUp" });
|
|
354292
|
+
}
|
|
354293
|
+
runtime.runner.retainConversationContinuations([{
|
|
354294
|
+
content: prompt,
|
|
354295
|
+
queueMode: "followUp",
|
|
354296
|
+
clientMessageId,
|
|
354297
|
+
runId: queuedMessage.runId,
|
|
354298
|
+
images: queuedMessage.images?.map((image) => ({ ...image })),
|
|
354299
|
+
attachments: queuedMessage.attachments?.map((attachment) => ({ ...attachment })),
|
|
354300
|
+
createdAt: queuedMessage.createdAt
|
|
354301
|
+
}]);
|
|
354302
|
+
this.trackQueuedMessage(runtime, prompt, "followUp");
|
|
354303
|
+
runtime.runner.recordWorkStatus(runtime.stopRequestedRunId === runtime.runId ? "Next message retained while stopping." : "Next message queued.");
|
|
354304
|
+
if (runtime.stopRequestedRunId === runtime.runId) runtime.forceStopArmedRunId = "";
|
|
354305
|
+
this.emitQueueUpdate(runtime);
|
|
354306
|
+
return;
|
|
354307
|
+
}
|
|
354049
354308
|
if (runtime.stopRequestedRunId === runtime.runId) {
|
|
354050
354309
|
runtime.forceStopArmedRunId = "";
|
|
354051
354310
|
const structured = typeof message === "string" ? void 0 : message;
|
|
@@ -354091,6 +354350,12 @@ ${text}`;
|
|
|
354091
354350
|
}
|
|
354092
354351
|
if (changed) this.emitQueueUpdate(runtime);
|
|
354093
354352
|
}
|
|
354353
|
+
replaceTrackedQueuedMessage(runtime, oldMessage, nextMessage, queueMode) {
|
|
354354
|
+
this.queueState(runtime);
|
|
354355
|
+
const list = queueMode === "steer" ? runtime.queued.steering : runtime.queued.followUp;
|
|
354356
|
+
const index = list.indexOf(oldMessage);
|
|
354357
|
+
if (index >= 0) list[index] = nextMessage;
|
|
354358
|
+
}
|
|
354094
354359
|
emitQueueUpdate(runtime) {
|
|
354095
354360
|
this.queueState(runtime);
|
|
354096
354361
|
runtime.runner.emitWorkEvent({
|
|
@@ -354212,9 +354477,10 @@ ${text}`;
|
|
|
354212
354477
|
const runId = runtime.runId;
|
|
354213
354478
|
await Promise.resolve();
|
|
354214
354479
|
if (runtime.runId !== runId || runtime.stopRequestedRunId === runId) return true;
|
|
354215
|
-
|
|
354480
|
+
const hasSteering = runtime.pendingNextTurn.some((item) => item.queueMode === "steer");
|
|
354481
|
+
if (hasSteering || runtime.runner.subagents.readRootInbox().length > 0) return false;
|
|
354216
354482
|
runtime.guideAcceptanceClosedRunId = runId;
|
|
354217
|
-
if (runtime.pendingNextTurn.
|
|
354483
|
+
if (runtime.pendingNextTurn.some((item) => item.queueMode === "steer") || runtime.runner.subagents.readRootInbox().length > 0) {
|
|
354218
354484
|
runtime.guideAcceptanceClosedRunId = "";
|
|
354219
354485
|
return false;
|
|
354220
354486
|
}
|
|
@@ -354367,6 +354633,9 @@ async function handle(request) {
|
|
|
354367
354633
|
target
|
|
354368
354634
|
});
|
|
354369
354635
|
}
|
|
354636
|
+
if (request.method === "queue_action") {
|
|
354637
|
+
return kernel.queueAction(checkedTarget(request.params.target), request.params.action, request.params.input);
|
|
354638
|
+
}
|
|
354370
354639
|
if (request.method === "checkpoint") return kernel.checkpoint(checkedTarget(request.params.target));
|
|
354371
354640
|
if (request.method === "context_compress") {
|
|
354372
354641
|
return kernel.compressContext(checkedTarget(request.params.target), request.params.options);
|
|
@@ -79,6 +79,9 @@ async function handle(request) {
|
|
|
79
79
|
target,
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
+
if (request.method === 'queue_action') {
|
|
83
|
+
return kernel.queueAction(checkedTarget(request.params.target), request.params.action, request.params.input);
|
|
84
|
+
}
|
|
82
85
|
if (request.method === 'checkpoint')
|
|
83
86
|
return kernel.checkpoint(checkedTarget(request.params.target));
|
|
84
87
|
if (request.method === 'context_compress') {
|
package/dist/core/agent.d.ts
CHANGED
|
@@ -346,6 +346,7 @@ export declare class Agent {
|
|
|
346
346
|
private memoryLabRebuildState;
|
|
347
347
|
private memoryLabRebuildError;
|
|
348
348
|
private displayImageDescriptionCache;
|
|
349
|
+
private latestCapturedImageInputs;
|
|
349
350
|
private activeProcessAbortController;
|
|
350
351
|
private automationManager;
|
|
351
352
|
private activeAgentKernelRuntime;
|
|
@@ -622,6 +623,7 @@ export declare class Agent {
|
|
|
622
623
|
order: number;
|
|
623
624
|
branchCommunication: boolean;
|
|
624
625
|
}>;
|
|
626
|
+
registerCapturedImageInput(dataUrl: string, name?: string): ConversationImageAttachment | null;
|
|
625
627
|
private subagentConcurrencyLimit;
|
|
626
628
|
/** 当前工作区使用内存中的前台选择;后台工作区从各自持久化状态读取 active id。 */
|
|
627
629
|
activeConversationIdForWorkspace(ws: WorkspaceInfo | null): string;
|
package/dist/core/agent.js
CHANGED
|
@@ -241,6 +241,7 @@ class Agent {
|
|
|
241
241
|
memoryLabRebuildState = 'idle';
|
|
242
242
|
memoryLabRebuildError = '';
|
|
243
243
|
displayImageDescriptionCache = new Map();
|
|
244
|
+
latestCapturedImageInputs = [];
|
|
244
245
|
activeProcessAbortController = null;
|
|
245
246
|
automationManager = null;
|
|
246
247
|
activeAgentKernelRuntime = null;
|
|
@@ -2859,6 +2860,14 @@ class Agent {
|
|
|
2859
2860
|
listConversationStates() {
|
|
2860
2861
|
return this.listWorkspaceConversationStates(this.workspace.current);
|
|
2861
2862
|
}
|
|
2863
|
+
registerCapturedImageInput(dataUrl, name = 'active-screenshot.jpg') {
|
|
2864
|
+
if (!String(dataUrl || '').startsWith('data:image/'))
|
|
2865
|
+
return null;
|
|
2866
|
+
const prepared = this.prepareSubmittedConversationImages([{ dataUrl, name, type: dataUrl.slice(5, dataUrl.indexOf(';')) }]);
|
|
2867
|
+
const attachment = prepared.attachments[0] || null;
|
|
2868
|
+
this.latestCapturedImageInputs = attachment ? [attachment] : [];
|
|
2869
|
+
return attachment;
|
|
2870
|
+
}
|
|
2862
2871
|
subagentConcurrencyLimit() {
|
|
2863
2872
|
return this.intelligence === 'ultra' ? 16 : 4;
|
|
2864
2873
|
}
|
|
@@ -8382,6 +8391,17 @@ class Agent {
|
|
|
8382
8391
|
}
|
|
8383
8392
|
latestSubmittedImages(attachmentId = '') {
|
|
8384
8393
|
const normalizedId = String(attachmentId || '').trim();
|
|
8394
|
+
const captured = (0, conversationAttachments_1.hydrateConversationImageAttachments)(this.rootPath, this.latestCapturedImageInputs).flatMap(attachment => attachment.dataUrl
|
|
8395
|
+
? [{ id: attachment.id, dataUrl: attachment.dataUrl }]
|
|
8396
|
+
: []);
|
|
8397
|
+
if (normalizedId) {
|
|
8398
|
+
const capturedMatch = captured.find(item => item.id === normalizedId);
|
|
8399
|
+
if (capturedMatch)
|
|
8400
|
+
return [capturedMatch];
|
|
8401
|
+
}
|
|
8402
|
+
else if (captured.length) {
|
|
8403
|
+
return captured;
|
|
8404
|
+
}
|
|
8385
8405
|
for (let index = this.chatMessages.length - 1; index >= 0; index -= 1) {
|
|
8386
8406
|
const message = this.chatMessages[index];
|
|
8387
8407
|
if (message?.role !== 'user')
|