newmark-agent 0.4.6 → 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/assets/app-icon-dark.svg +6 -0
- package/dist/assets/app-icon-dark.svg +6 -0
- package/dist/cli-commands.js +2 -1
- package/dist/cli-discovery.js +2 -0
- package/dist/conversation-utility-host.bundle.cjs +577 -166
- package/dist/conversation-utility-host.js +3 -0
- package/dist/core/agent.d.ts +40 -4
- package/dist/core/agent.js +251 -49
- package/dist/core/agentKernelRunner.d.ts +3 -0
- package/dist/core/agentKernelRunner.js +74 -91
- package/dist/core/config.js +1 -1
- 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/installUpdate.js +11 -8
- package/dist/core/mobilePairing.d.ts +1 -0
- package/dist/core/mobilePairing.js +15 -1
- package/dist/core/subagent.d.ts +10 -3
- package/dist/core/subagent.js +23 -8
- package/dist/core/toolPolicy.js +14 -3
- 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/launcher.js +14 -11
- package/dist/main.js +207 -9
- package/dist/providers/chat-completions.adapter.js +6 -2
- package/dist/providers/responses.adapter.js +1 -0
- package/dist/server.d.ts +33 -1
- package/dist/server.js +696 -48
- package/dist/toolchain/registry-seeder.js +3 -1
- package/dist/tools/index.js +57 -6
- package/dist/tools/nativeTools.js +2 -1
- package/dist/ui/index.html +88 -101
- package/dist/wsl-agent-host.bundle.cjs +577 -166
- package/dist/wsl-agent-host.js +3 -0
- package/package.json +4 -2
|
@@ -327560,6 +327560,7 @@ var NATIVE_TOOL_CATALOG = [
|
|
|
327560
327560
|
{ name: "browser_reload", label: "Browser reload", description: "Reload the built-in browser.", category: "browser", defaultEnabled: true },
|
|
327561
327561
|
{ name: "browser_cdp", label: "Browser CDP", description: "Run an advanced Chrome DevTools Protocol command.", category: "browser", defaultEnabled: true },
|
|
327562
327562
|
{ 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 },
|
|
327563
|
+
{ 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" },
|
|
327563
327564
|
{ name: "computer_use", label: "Computer Use", description: "Observe and control Windows desktop UI with screenshots and semantic objects.", category: "desktop", defaultEnabled: true },
|
|
327564
327565
|
{ 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" },
|
|
327565
327566
|
{ 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" },
|
|
@@ -327567,7 +327568,7 @@ var NATIVE_TOOL_CATALOG = [
|
|
|
327567
327568
|
{ name: "pdf_read", label: "PDF read", description: "Read PDF text and render scanned pages through vision before local OCR fallback.", category: "core", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327568
327569
|
{ name: "terminal_takeover", label: "Terminal takeover", description: "Maintain a persistent Agent-controlled shell session.", category: "desktop", defaultEnabled: true },
|
|
327569
327570
|
{ name: "ssh_workspace", label: "OpenSSH workspace", description: "Manage native OpenSSH connections and link remote workspaces by PC_Hash.", category: "ssh", defaultEnabled: true },
|
|
327570
|
-
{ name: "
|
|
327571
|
+
{ name: "SubAgent", label: "SubAgent", description: "Create one real same-conversation peer SubAgent.", category: "agent", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327571
327572
|
{ name: "subagent_list", label: "Subagent list", description: "List same-conversation peer agents.", category: "agent", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327572
327573
|
{ name: "subagent_read", label: "Subagent read", description: "Read bounded status, feedback, result, queue, and mailbox summaries for a same-conversation peer.", category: "agent", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
327573
327574
|
{ name: "subagent_send", label: "Subagent send", description: "Persist a message to a peer mailbox.", category: "agent", defaultEnabled: true, protected: true, availability: "mode-scoped" },
|
|
@@ -328319,7 +328320,7 @@ function defaultConfig() {
|
|
|
328319
328320
|
auto_archive_on_close: { _description: "Auto archive on close", _type: "boolean", value: true }
|
|
328320
328321
|
},
|
|
328321
328322
|
remote: {
|
|
328322
|
-
touch_enabled: { _description: "Allow mobile devices to reach this Newmark instance
|
|
328323
|
+
touch_enabled: { _description: "Allow mobile devices to reach this Newmark instance on the same LAN / Tailscale network", _type: "boolean", value: true }
|
|
328323
328324
|
},
|
|
328324
328325
|
models: {
|
|
328325
328326
|
providers: { _description: "LLM providers", _type: "array", value: [] },
|
|
@@ -328867,14 +328868,18 @@ var ChatCompletionsAdapter = class {
|
|
|
328867
328868
|
...request.systemPrompt ? [{ role: CHAT_SYSTEM_ROLE, content: request.systemPrompt }] : [],
|
|
328868
328869
|
...openAIChatMessages(request.messages)
|
|
328869
328870
|
];
|
|
328871
|
+
const tools = this.serializeTools(request.tools);
|
|
328870
328872
|
const body = {
|
|
328871
328873
|
model: request.model,
|
|
328872
328874
|
messages,
|
|
328873
328875
|
temperature: request.temperature,
|
|
328874
|
-
max_tokens: request.maxOutputTokens
|
|
328875
|
-
tools: this.serializeTools(request.tools),
|
|
328876
|
-
tool_choice: "auto"
|
|
328876
|
+
max_tokens: request.maxOutputTokens
|
|
328877
328877
|
};
|
|
328878
|
+
if (tools.length) {
|
|
328879
|
+
body.tools = tools;
|
|
328880
|
+
body.tool_choice = "auto";
|
|
328881
|
+
body.parallel_tool_calls = true;
|
|
328882
|
+
}
|
|
328878
328883
|
if (request.reasoningEffort) body.reasoning_effort = request.reasoningEffort;
|
|
328879
328884
|
if (request.sessionId) body.session_id = request.sessionId;
|
|
328880
328885
|
const base2 = request.baseUrl.replace(/\/+$/, "");
|
|
@@ -329128,6 +329133,7 @@ var ResponsesAdapter = class {
|
|
|
329128
329133
|
if (tools.length) {
|
|
329129
329134
|
body.tools = tools;
|
|
329130
329135
|
body.tool_choice = "auto";
|
|
329136
|
+
body.parallel_tool_calls = true;
|
|
329131
329137
|
}
|
|
329132
329138
|
const base2 = request.baseUrl.replace(/\/+$/, "");
|
|
329133
329139
|
return {
|
|
@@ -335749,6 +335755,7 @@ var import_crypto6 = require("crypto");
|
|
|
335749
335755
|
// src/core/toolPolicy.ts
|
|
335750
335756
|
var REQUIRED_TOOLS = /* @__PURE__ */ new Set(["pwd", "read", "glob", "grep"]);
|
|
335751
335757
|
var MODE_SCOPED_TOOLS = /* @__PURE__ */ new Set([
|
|
335758
|
+
"screen_capture",
|
|
335752
335759
|
"image_inspect",
|
|
335753
335760
|
"image_display",
|
|
335754
335761
|
"ocr_read",
|
|
@@ -335765,6 +335772,10 @@ var MODE_SCOPED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335765
335772
|
"task_read",
|
|
335766
335773
|
"task_create",
|
|
335767
335774
|
"question",
|
|
335775
|
+
"SubAgent",
|
|
335776
|
+
"subagent_create",
|
|
335777
|
+
// Legacy runtime alias. It is no longer published to models because its
|
|
335778
|
+
// generic name collides with the persistent task checklist.
|
|
335768
335779
|
"task",
|
|
335769
335780
|
"subagent_list",
|
|
335770
335781
|
"subagent_read",
|
|
@@ -335777,6 +335788,7 @@ var MODE_SCOPED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335777
335788
|
"branch_create"
|
|
335778
335789
|
]);
|
|
335779
335790
|
var PLAN_READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
335791
|
+
"screen_capture",
|
|
335780
335792
|
"task_read",
|
|
335781
335793
|
"pwd",
|
|
335782
335794
|
"read",
|
|
@@ -335798,6 +335810,8 @@ var PLAN_READ_ONLY_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335798
335810
|
"skill",
|
|
335799
335811
|
"linked_plan",
|
|
335800
335812
|
"build_history_query",
|
|
335813
|
+
"SubAgent",
|
|
335814
|
+
"subagent_create",
|
|
335801
335815
|
"task",
|
|
335802
335816
|
"subagent_list",
|
|
335803
335817
|
"subagent_read",
|
|
@@ -335821,7 +335835,9 @@ var CONCURRENCY_SAFE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
335821
335835
|
"web_fetch",
|
|
335822
335836
|
"git_status",
|
|
335823
335837
|
"file_audit",
|
|
335824
|
-
"repo_security_audit"
|
|
335838
|
+
"repo_security_audit",
|
|
335839
|
+
"screen_capture",
|
|
335840
|
+
"SubAgent"
|
|
335825
335841
|
]);
|
|
335826
335842
|
function isConcurrencySafeTool(name50, riskLevel) {
|
|
335827
335843
|
const toolName = String(name50 || "").trim();
|
|
@@ -336900,6 +336916,13 @@ var ToolExecutor = class {
|
|
|
336900
336916
|
max_refs: { type: "number" },
|
|
336901
336917
|
attribute: { type: "string" }
|
|
336902
336918
|
}, ["action"]),
|
|
336919
|
+
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.", {
|
|
336920
|
+
target: { type: "string", enum: ["desktop", "application"], description: "Capture the whole desktop or one visible application. Defaults to desktop." },
|
|
336921
|
+
app_target: { type: "string", description: "For target=application: application title, process name, process id, or window handle." },
|
|
336922
|
+
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." },
|
|
336923
|
+
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." },
|
|
336924
|
+
max_chars: { type: "number", minimum: 1e3, maximum: 1e5, description: "Maximum returned semantic UI text characters." }
|
|
336925
|
+
}, []),
|
|
336903
336926
|
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.", {
|
|
336904
336927
|
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"] },
|
|
336905
336928
|
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." },
|
|
@@ -336985,7 +337008,7 @@ var ToolExecutor = class {
|
|
|
336985
337008
|
remote_root: { type: "string" },
|
|
336986
337009
|
remote_path: { type: "string" }
|
|
336987
337010
|
}, ["action"]),
|
|
336988
|
-
t3("
|
|
337011
|
+
t3("SubAgent", "Create one real same-conversation peer SubAgent and return immediately. This tool is only for delegation; never use it to create or update the conversation task checklist (use task_create for that). Creation is bound to the currently running Build Block: non-Ultra intelligence has a hard ceiling of 4 active peers for that Build, Ultra has 16, and excess calls terminate without creating or queueing a record. The peer has a stable human-readable name plus a separate exact id. Pass model to select an exact configured model deployment (deployment:providerId:modelId or an unambiguous provider/model name). When model is omitted, the peer inherits the parent Agent's currently resolved model deployment. Plan mode peers are forced to Plan.", { name: { type: "string", description: "Human-readable SubAgent name shown in the monitoring sidebar. Omit only when a named preset supplies it." }, nature: { type: "string", description: "Legacy alias for name." }, prompt: { type: "string", description: "Work delegated to this SubAgent; this is not a checklist item." }, preset: { type: "string" }, agent: { type: "string" }, model: { type: "string", description: "Optional exact model deployment. Omit to inherit the parent Agent resolved model." }, mode: { type: "string" }, input_mode: { type: "string" }, flow: { type: "string" } }, ["prompt"]),
|
|
336989
337012
|
t3("subagent_list", "List flat same-conversation peer agents, optionally filtered by status. Each entry exposes both the stable name and the exact id; use the id for any subsequent targeting.", { status: { type: "string", enum: ["idle", "queued", "working", "completed", "error", "closed"] } }, []),
|
|
336990
337013
|
t3("subagent_read", "Read one same-conversation peer status, queue/mailbox summary, latest bounded feedback, and result. Available for running, queued, completed, error, and closed peers. Pass the exact id returned by subagent_list, or a name for convenience lookup.", { id: { type: "string", description: "Exact peer id from subagent_list." }, name: { type: "string", description: "Convenience peer name; ambiguous names resolve to the first match." }, max_chars: { type: "number", description: "Bounded result size from 2000 to 32000 characters." } }, []),
|
|
336991
337014
|
t3("subagent_send", "Persist a mailbox message to a same-conversation peer agent. Target by exact id (preferred) or name.", { id: { type: "string", description: "Exact peer id from subagent_list." }, name: { type: "string", description: "Convenience peer name." }, message: { type: "string" }, prompt: { type: "string", description: "Legacy alias for message." }, kind: { type: "string", enum: ["directive", "question", "result", "handoff"] }, reply_to: { type: "string" }, correlation_id: { type: "string" } }, []),
|
|
@@ -337162,7 +337185,8 @@ var ToolExecutor = class {
|
|
|
337162
337185
|
return normalizeToolResult(output, { tool, workspacePath: wsPath, mode: context.mode || "" });
|
|
337163
337186
|
}
|
|
337164
337187
|
validateInvocation(tool, argsStr, _mode = "", inputSchema) {
|
|
337165
|
-
|
|
337188
|
+
const schemaTool = tool === "task" || tool === "subagent_create" ? "SubAgent" : tool;
|
|
337189
|
+
if (inputSchema === void 0 && !isNativeToolEnabled(schemaTool, this.config.nativeToolEnabled())) {
|
|
337166
337190
|
return { ok: false, error: `[tool disabled] ${tool} is disabled in Settings > Tools.` };
|
|
337167
337191
|
}
|
|
337168
337192
|
let parsed;
|
|
@@ -337184,11 +337208,11 @@ var ToolExecutor = class {
|
|
|
337184
337208
|
}, args);
|
|
337185
337209
|
return validation2.ok ? { ok: false, error: "[permission] Question is disabled by fully_autonomous option feedback." } : { ok: false, error: `[tool schema error] ${validation2.error}` };
|
|
337186
337210
|
}
|
|
337187
|
-
const definition = inputSchema === void 0 ? this.definitions().find((candidate) => candidate.function?.name ===
|
|
337211
|
+
const definition = inputSchema === void 0 ? this.definitions().find((candidate) => candidate.function?.name === schemaTool) : { function: { name: tool, parameters: inputSchema } };
|
|
337188
337212
|
if (!definition) {
|
|
337189
337213
|
return { ok: false, error: `[tool unsupported] ${tool || "(missing tool)"} is not available for the ${this.hostProfile.kind} host on ${this.hostProfile.platform}.` };
|
|
337190
337214
|
}
|
|
337191
|
-
const validation = this.argumentValidators.validate(
|
|
337215
|
+
const validation = this.argumentValidators.validate(schemaTool, definition.function.parameters, args);
|
|
337192
337216
|
return validation.ok ? { ok: true, args } : { ok: false, error: `[tool schema error] ${validation.error}` };
|
|
337193
337217
|
}
|
|
337194
337218
|
async execute(tool, argsStr, wsPath, context = {}) {
|
|
@@ -337389,6 +337413,44 @@ var ToolExecutor = class {
|
|
|
337389
337413
|
result: parsed
|
|
337390
337414
|
}, null, 2);
|
|
337391
337415
|
}
|
|
337416
|
+
case "screen_capture": {
|
|
337417
|
+
const target = g2("target").toLowerCase() === "application" ? "application" : "desktop";
|
|
337418
|
+
if (process.env.NEWMARK_WSL_DISTRO) {
|
|
337419
|
+
const result = await requestWindowsHostTool("screen_capture", args, {
|
|
337420
|
+
conversationId: context.conversationId || "default",
|
|
337421
|
+
workspaceId: context.workspaceId || terminalTakeoverWorkspaceId(context.workspacePath || wsPath),
|
|
337422
|
+
actorId: context.actorId || ROOT_TERMINAL_ACTOR_ID,
|
|
337423
|
+
runtimeKey: browserUseScope(context, wsPath).runtimeKey,
|
|
337424
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
337425
|
+
mode: context.mode || "build"
|
|
337426
|
+
}, 12e4, context.signal);
|
|
337427
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
337428
|
+
}
|
|
337429
|
+
if (process.env.NEWMARK_ISOLATED_RUNTIME === "1") {
|
|
337430
|
+
const result = await requestUtilityHostTool("screen_capture", args, {
|
|
337431
|
+
conversationId: context.conversationId || "default",
|
|
337432
|
+
workspaceId: context.workspaceId || terminalTakeoverWorkspaceId(context.workspacePath || wsPath),
|
|
337433
|
+
actorId: context.actorId || ROOT_TERMINAL_ACTOR_ID,
|
|
337434
|
+
workspacePath: context.workspacePath || wsPath,
|
|
337435
|
+
backend: "utility",
|
|
337436
|
+
mode: context.mode || "build",
|
|
337437
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true
|
|
337438
|
+
}, 12e4, context.signal);
|
|
337439
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
337440
|
+
}
|
|
337441
|
+
return await runComputerUse({
|
|
337442
|
+
action: target === "application" ? "app_observe" : "observe",
|
|
337443
|
+
appTarget: g2("app_target"),
|
|
337444
|
+
windowHandle: target === "application" ? g2("app_target") : "",
|
|
337445
|
+
maxChars: Number(args.max_chars || 3e4),
|
|
337446
|
+
workspacePath: wsPath,
|
|
337447
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
337448
|
+
captureMaxWidth: Number(args.capture_max_width),
|
|
337449
|
+
captureMaxHeight: Number(args.capture_max_height),
|
|
337450
|
+
invocation: context.invocation,
|
|
337451
|
+
ownerId: `screen-capture:${computerUseOwner(context, wsPath)}:${String(context.actorId || "root")}`
|
|
337452
|
+
});
|
|
337453
|
+
}
|
|
337392
337454
|
case "computer_use": {
|
|
337393
337455
|
const action = normalizeComputerUseAction(g2("action"));
|
|
337394
337456
|
const owner = `${computerUseOwner(context, wsPath)}:${String(context.actorId || "root")}`;
|
|
@@ -337510,7 +337572,9 @@ var ToolExecutor = class {
|
|
|
337510
337572
|
case "ssh_workspace":
|
|
337511
337573
|
return await this.sshWorkspace(args, wsPath, context.signal);
|
|
337512
337574
|
case "task":
|
|
337513
|
-
|
|
337575
|
+
case "subagent_create":
|
|
337576
|
+
case "SubAgent":
|
|
337577
|
+
return `[SubAgent] SubAgent request accepted: ${g2("name")}`;
|
|
337514
337578
|
case "subagent_send":
|
|
337515
337579
|
return `[subagent_send] Routed to Agent runtime: ${g2("name")}`;
|
|
337516
337580
|
case "subagent_read":
|
|
@@ -337593,7 +337657,7 @@ var ToolExecutor = class {
|
|
|
337593
337657
|
}
|
|
337594
337658
|
hostSupportsTool(name50) {
|
|
337595
337659
|
if (name50.startsWith("browser_") && !this.hostProfile.electronBrowser) return false;
|
|
337596
|
-
if (name50 === "computer_use" && !this.hostProfile.windowsComputerUse) return false;
|
|
337660
|
+
if ((name50 === "computer_use" || name50 === "screen_capture") && !this.hostProfile.windowsComputerUse) return false;
|
|
337597
337661
|
return true;
|
|
337598
337662
|
}
|
|
337599
337663
|
async decorateBrowserUseReceipt(input2, context, runtimeKey) {
|
|
@@ -338683,6 +338747,7 @@ var SubagentManager = class {
|
|
|
338683
338747
|
queueMicrotask(() => this.pump());
|
|
338684
338748
|
}
|
|
338685
338749
|
bind(options) {
|
|
338750
|
+
if (options.concurrency !== void 0) this.setConcurrencyLimit(options.concurrency);
|
|
338686
338751
|
if (options.executor) this.executor = options.executor;
|
|
338687
338752
|
if (options.onChange) this.onChange = options.onChange;
|
|
338688
338753
|
if (options.persist) this.persist = options.persist;
|
|
@@ -338699,12 +338764,13 @@ var SubagentManager = class {
|
|
|
338699
338764
|
removeRootInboxListener(listener) {
|
|
338700
338765
|
this.rootInboxListeners.delete(listener);
|
|
338701
338766
|
}
|
|
338702
|
-
create(name50, prompt, model, inputMode, agentMode = "build", createdByAgentId = this.rootAgentId, flowName = "", goalObjective = "", flowPc = 0) {
|
|
338767
|
+
create(name50, prompt, model, inputMode, agentMode = "build", createdByAgentId = this.rootAgentId, flowName = "", goalObjective = "", flowPc = 0, buildRunId = "", intelligenceTier = "") {
|
|
338703
338768
|
const id = (0, import_crypto8.randomUUID)();
|
|
338704
338769
|
const shortId = id.replace(/-/g, "").slice(0, 8);
|
|
338705
338770
|
const slug = natureSlug(name50);
|
|
338706
|
-
const
|
|
338707
|
-
const
|
|
338771
|
+
const createdName = String(name50 || "SubAgent").replace(/\s+/g, " ").trim().slice(0, 160) || "SubAgent";
|
|
338772
|
+
const displayName = createdName;
|
|
338773
|
+
const qualifiedName = `${slug}--${id}`;
|
|
338708
338774
|
const stamp = now();
|
|
338709
338775
|
const record = {
|
|
338710
338776
|
id,
|
|
@@ -338712,9 +338778,11 @@ var SubagentManager = class {
|
|
|
338712
338778
|
natureSlug: slug,
|
|
338713
338779
|
displayName,
|
|
338714
338780
|
qualifiedName,
|
|
338715
|
-
name:
|
|
338781
|
+
name: createdName,
|
|
338716
338782
|
conversationId: this.conversationId,
|
|
338717
338783
|
createdByAgentId,
|
|
338784
|
+
buildRunId: String(buildRunId || "").trim() || void 0,
|
|
338785
|
+
intelligenceTier: String(intelligenceTier || "").trim() || void 0,
|
|
338718
338786
|
prompt,
|
|
338719
338787
|
model: model || "default",
|
|
338720
338788
|
inputMode: inputMode || "guide",
|
|
@@ -339037,6 +339105,20 @@ var SubagentManager = class {
|
|
|
339037
339105
|
listAll() {
|
|
339038
339106
|
return [...this.subs.values()].map(cloneRecord);
|
|
339039
339107
|
}
|
|
339108
|
+
activeCountForBuild(buildRunId) {
|
|
339109
|
+
const target = String(buildRunId || "").trim();
|
|
339110
|
+
if (!target) return 0;
|
|
339111
|
+
return [...this.subs.values()].filter(
|
|
339112
|
+
(record) => record.buildRunId === target && (record.status === "queued" || record.status === "working")
|
|
339113
|
+
).length;
|
|
339114
|
+
}
|
|
339115
|
+
setConcurrencyLimit(value) {
|
|
339116
|
+
this.concurrency = Math.max(1, Math.min(16, Math.floor(Number(value) || 4)));
|
|
339117
|
+
this.pump();
|
|
339118
|
+
}
|
|
339119
|
+
concurrencyLimit() {
|
|
339120
|
+
return this.concurrency;
|
|
339121
|
+
}
|
|
339040
339122
|
pauseScheduling() {
|
|
339041
339123
|
if (this.schedulingPaused) return;
|
|
339042
339124
|
this.schedulingPaused = true;
|
|
@@ -340202,7 +340284,8 @@ function inferDomain(name50) {
|
|
|
340202
340284
|
}
|
|
340203
340285
|
if (name50 === "question") return "interaction";
|
|
340204
340286
|
if (name50 === "skill") return "skills";
|
|
340205
|
-
if (name50 === "task") return "subagent";
|
|
340287
|
+
if (name50 === "task" || name50 === "subagent_create" || name50 === "SubAgent") return "subagent";
|
|
340288
|
+
if (/^task_(read|create)$/.test(name50)) return "plan";
|
|
340206
340289
|
if (/^(linked_plan|build_history_query)$/.test(name50)) return "plan";
|
|
340207
340290
|
return "general";
|
|
340208
340291
|
}
|
|
@@ -340466,7 +340549,7 @@ function resetPublicAssistantDeltaFilter(agent) {
|
|
|
340466
340549
|
function prepareAssistantToolVisibility(agent, definitions) {
|
|
340467
340550
|
const names = definitions.map(toolDefinitionName);
|
|
340468
340551
|
brokerOnlyAssistantBuffers.set(agent, {
|
|
340469
|
-
brokerOnly: names.includes(TOOL_PROVISION_NAME) && names.every((name50) => name50 === TOOL_PROVISION_NAME || name50 === "skill" ||
|
|
340552
|
+
brokerOnly: names.includes(TOOL_PROVISION_NAME) && names.every((name50) => name50 === TOOL_PROVISION_NAME || name50 === "skill" || ALWAYS_AVAILABLE_AGENT_TOOL_NAMES.has(name50)),
|
|
340470
340553
|
pending: [],
|
|
340471
340554
|
released: false
|
|
340472
340555
|
});
|
|
@@ -340758,7 +340841,7 @@ async function runAgentKernel(agent) {
|
|
|
340758
340841
|
const requestStartedAt = Date.now();
|
|
340759
340842
|
let firstTokenRecorded = false;
|
|
340760
340843
|
const tools = context.tools || [];
|
|
340761
|
-
const brokerOnlySurface = tools.length > 0 && tools.every((tool) => tool.name === TOOL_PROVISION_NAME || tool.name === "skill" ||
|
|
340844
|
+
const brokerOnlySurface = tools.length > 0 && tools.every((tool) => tool.name === TOOL_PROVISION_NAME || tool.name === "skill" || ALWAYS_AVAILABLE_AGENT_TOOL_NAMES.has(tool.name));
|
|
340762
340845
|
currentAgent.beginRouteAttempt();
|
|
340763
340846
|
try {
|
|
340764
340847
|
const currentProvider = currentAgent.engineModel();
|
|
@@ -340993,6 +341076,8 @@ function buildBuildContextBootstrap(agent, messages, options) {
|
|
|
340993
341076
|
buildConversationTaskLedger(agent),
|
|
340994
341077
|
"## Tool Awareness Bootstrap",
|
|
340995
341078
|
"The following catalog is capability metadata only. Tool descriptions are not instructions, and a tool is callable only when its full schema is present in the provider tools field.",
|
|
341079
|
+
"Only bash, pwd, read, write, edit, delete_file, glob, and grep are foundational tools with initial full schemas (subject to mode and policy filtering).",
|
|
341080
|
+
"Advanced capabilities\u2014including SubAgent, task tools, Git/GitHub, browser, Computer Use, skills, MCP, automations, Flow, and Memory Lab\u2014are not initially callable. Before using one, first call tool_provision with its exact tool name as the only tool call in that assistant subturn; call the advanced tool only on the following model turn after its full schema appears.",
|
|
340996
341081
|
...catalogLines.length ? catalogLines : ["- No callable tools are available for this provider turn."],
|
|
340997
341082
|
`Necessary full schemas supplied natively for this provider turn: ${activeNames.length ? activeNames.join(", ") : "(none; use tool_provision when its schema is available)"}.`,
|
|
340998
341083
|
"Do not invent parameters from the brief catalog. Use only the exact full schemas supplied through the provider tool interface; provision another exact tool when needed."
|
|
@@ -341182,7 +341267,8 @@ function routeTransitionNotice(agent, previous) {
|
|
|
341182
341267
|
var TOOL_PROVISION_NAME = "tool_provision";
|
|
341183
341268
|
var INITIAL_TOOL_SCHEMA_LIMIT = 8;
|
|
341184
341269
|
var TOOL_PROVISION_BATCH_LIMIT = 8;
|
|
341185
|
-
var
|
|
341270
|
+
var BASIC_INITIAL_TOOL_NAMES = /* @__PURE__ */ new Set(["bash", "pwd", "read", "write", "edit", "delete_file", "glob", "grep"]);
|
|
341271
|
+
var ALWAYS_AVAILABLE_AGENT_TOOL_NAMES = BASIC_INITIAL_TOOL_NAMES;
|
|
341186
341272
|
var ToolProvisionSession = class {
|
|
341187
341273
|
definitionsByName = /* @__PURE__ */ new Map();
|
|
341188
341274
|
initialNames = /* @__PURE__ */ new Set();
|
|
@@ -341206,7 +341292,7 @@ var ToolProvisionSession = class {
|
|
|
341206
341292
|
const name50 = toolDefinitionName(definition);
|
|
341207
341293
|
if (this.definitionsByName.has(name50)) this.initialNames.add(name50);
|
|
341208
341294
|
}
|
|
341209
|
-
for (const name50 of
|
|
341295
|
+
for (const name50 of ALWAYS_AVAILABLE_AGENT_TOOL_NAMES) {
|
|
341210
341296
|
if (this.definitionsByName.has(name50)) this.initialNames.add(name50);
|
|
341211
341297
|
}
|
|
341212
341298
|
for (const name50 of this.provisionedNames) {
|
|
@@ -341364,29 +341450,6 @@ function toolSurfaceIdentityForAgent(agent) {
|
|
|
341364
341450
|
optionFeedback: agent.config.getStr("agent", "option_feedback")
|
|
341365
341451
|
});
|
|
341366
341452
|
}
|
|
341367
|
-
var CAPABILITY_TO_DOMAIN = {
|
|
341368
|
-
"vcs.inspect": ["git"],
|
|
341369
|
-
"code.search": ["core"],
|
|
341370
|
-
"test.run": ["core"],
|
|
341371
|
-
"web.search": ["web"],
|
|
341372
|
-
"automation.manage": ["automation"],
|
|
341373
|
-
"flow.manage": ["flow"],
|
|
341374
|
-
"memory.manage": ["memory"],
|
|
341375
|
-
"computer.manage": ["computer"],
|
|
341376
|
-
"browser.manage": ["browser"],
|
|
341377
|
-
"terminal.manage": ["general", "core"],
|
|
341378
|
-
"github.manage": ["general"],
|
|
341379
|
-
"ssh.manage": ["general"],
|
|
341380
|
-
"skill.manage": ["skills", "general"],
|
|
341381
|
-
"plan.manage": ["plan"],
|
|
341382
|
-
"history.query": ["plan"],
|
|
341383
|
-
"media.display": ["media"],
|
|
341384
|
-
"interaction.manage": ["interaction"]
|
|
341385
|
-
};
|
|
341386
|
-
var CAPABILITY_TOOL_HINTS = {
|
|
341387
|
-
"skill.manage": ["skill", "skill_download"],
|
|
341388
|
-
"memory.manage": ["memory_lab_read", "memory_lab_query", "memory_lab_update", "memory_lab_reindex"]
|
|
341389
|
-
};
|
|
341390
341453
|
function routeToolSurfaceV2(agent, definitions, toolchain, task) {
|
|
341391
341454
|
if (!agent.shouldExposeToolInterface()) {
|
|
341392
341455
|
return {
|
|
@@ -341398,67 +341461,34 @@ function routeToolSurfaceV2(agent, definitions, toolchain, task) {
|
|
|
341398
341461
|
].join("\n")
|
|
341399
341462
|
};
|
|
341400
341463
|
}
|
|
341401
|
-
|
|
341402
|
-
const
|
|
341403
|
-
|
|
341404
|
-
|
|
341405
|
-
|
|
341406
|
-
|
|
341407
|
-
|
|
341408
|
-
|
|
341409
|
-
|
|
341410
|
-
|
|
341411
|
-
|
|
341412
|
-
|
|
341413
|
-
|
|
341414
|
-
|
|
341415
|
-
|
|
341416
|
-
|
|
341417
|
-
|
|
341418
|
-
for (const toolName of CAPABILITY_TOOL_HINTS[capabilityId] || []) toolHints.add(toolName);
|
|
341419
|
-
}
|
|
341420
|
-
const names = definitions.map(toolDefinitionName);
|
|
341421
|
-
for (const name50 of names) {
|
|
341422
|
-
if (name50 && new RegExp(`(?:^|[^A-Za-z0-9_])${name50.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:$|[^A-Za-z0-9_])`, "i").test(task)) {
|
|
341423
|
-
toolHints.add(name50);
|
|
341424
|
-
}
|
|
341425
|
-
}
|
|
341426
|
-
const selected = definitions.filter((definition) => {
|
|
341427
|
-
const name50 = toolDefinitionName(definition);
|
|
341428
|
-
const descriptor = toolchain.registry.get(name50);
|
|
341429
|
-
if (!descriptor || descriptor.riskLevel === "destructive") return false;
|
|
341430
|
-
if (toolHints.has(name50)) return true;
|
|
341431
|
-
if (!domains.has(descriptor.capabilityId.slice(4))) return false;
|
|
341432
|
-
return true;
|
|
341433
|
-
}).sort((a3, b2) => {
|
|
341434
|
-
const aHint = toolHints.has(toolDefinitionName(a3)) ? 0 : 1;
|
|
341435
|
-
const bHint = toolHints.has(toolDefinitionName(b2)) ? 0 : 1;
|
|
341436
|
-
return aHint - bHint || names.indexOf(toolDefinitionName(a3)) - names.indexOf(toolDefinitionName(b2));
|
|
341437
|
-
}).slice(0, INITIAL_TOOL_SCHEMA_LIMIT);
|
|
341438
|
-
const selectedNames = new Set(selected.map(toolDefinitionName));
|
|
341439
|
-
const core = definitions.filter((definition) => {
|
|
341440
|
-
const name50 = toolDefinitionName(definition);
|
|
341441
|
-
return SUBAGENT_CORE_TOOL_NAMES.has(name50) && !selectedNames.has(name50);
|
|
341442
|
-
});
|
|
341443
|
-
const surface = core.length ? selected.concat(core) : selected;
|
|
341444
|
-
if (surface.length === definitions.length) return { definitions, systemPromptNotice: "" };
|
|
341445
|
-
if (!selected.length) {
|
|
341446
|
-
return {
|
|
341447
|
-
definitions: surface,
|
|
341448
|
-
systemPromptNotice: [
|
|
341449
|
-
"## Tool Interface Availability",
|
|
341450
|
-
"This turn was classified as conversational, so no task-specific tool schema was preloaded.",
|
|
341451
|
-
`The ${TOOL_PROVISION_NAME} interface still exposes the complete compact capability catalog and can provision an original tool schema when the task requires it.`
|
|
341452
|
-
].join("\n")
|
|
341453
|
-
};
|
|
341464
|
+
const surface = definitions.filter((definition) => BASIC_INITIAL_TOOL_NAMES.has(toolDefinitionName(definition)));
|
|
341465
|
+
const advancedCount = Math.max(0, definitions.length - surface.length);
|
|
341466
|
+
let planFingerprint = "";
|
|
341467
|
+
if (toolchain) {
|
|
341468
|
+
const planner = new ToolExposurePlanner(toolchain.registry, toolchain.catalog);
|
|
341469
|
+
const plan = planner.plan({
|
|
341470
|
+
agentRunId: agent.runtimeActorId,
|
|
341471
|
+
buildBlockId: agent.activeConversationId || "build",
|
|
341472
|
+
userInput: task,
|
|
341473
|
+
objective: "",
|
|
341474
|
+
previousToolCalls: [],
|
|
341475
|
+
toolUsageFrequency: /* @__PURE__ */ new Map(),
|
|
341476
|
+
permissionScope: ["workspace"],
|
|
341477
|
+
tokenBudget: 2e4,
|
|
341478
|
+
providerToolLimit: 0
|
|
341479
|
+
});
|
|
341480
|
+
planFingerprint = plan.plan.stableToolsetHash.slice(0, 8);
|
|
341454
341481
|
}
|
|
341455
341482
|
return {
|
|
341456
341483
|
definitions: surface,
|
|
341457
341484
|
systemPromptNotice: [
|
|
341458
341485
|
"## Tool Interface Availability",
|
|
341459
|
-
`
|
|
341460
|
-
|
|
341461
|
-
|
|
341486
|
+
`The initial full-schema surface is restricted to foundational workspace tools: ${surface.map(toolDefinitionName).join(", ") || "(none allowed in this mode)"}.`,
|
|
341487
|
+
`${advancedCount} advanced tools are advertised by capability in the compact ${TOOL_PROVISION_NAME} catalog without loading their schemas.`,
|
|
341488
|
+
"Advanced tools include SubAgent, task tools, Git/GitHub, browser, Computer Use, skills, MCP, automations, Flow, and Memory Lab.",
|
|
341489
|
+
`Call ${TOOL_PROVISION_NAME} as the only tool in a subturn to load any advanced tool by exact name; its original schema becomes available on the next model turn.`,
|
|
341490
|
+
"Do not call an advanced tool directly from the initial catalog: capability presence is not callability until provisioning has completed.",
|
|
341491
|
+
planFingerprint ? `Capability routing fingerprint: ${planFingerprint}.` : "Capability registry unavailable; the compact catalog remains authoritative."
|
|
341462
341492
|
].join("\n")
|
|
341463
341493
|
};
|
|
341464
341494
|
}
|
|
@@ -341527,10 +341557,12 @@ function toKernelTools(agent, definitions, provisioning) {
|
|
|
341527
341557
|
throw new Error(rawText);
|
|
341528
341558
|
}
|
|
341529
341559
|
const visionImage = visualFallbackImageInput(agent, name50, rawText);
|
|
341560
|
+
const capturedInput = name50 === "screen_capture" ? agent.registerCapturedImageInput(visionImage.image || "", "active-screenshot.jpg") : null;
|
|
341530
341561
|
const directImage = imageInspectDataUrl(name50, rawText);
|
|
341531
|
-
const text = spillOversizedToolResult(agent, name50, sanitizeVisualToolText(name50, rawText));
|
|
341562
|
+
const text = spillOversizedToolResult(agent, name50, capturedImageToolText(name50, sanitizeVisualToolText(name50, rawText), capturedInput?.id));
|
|
341532
341563
|
const content = [{ type: "text", text }];
|
|
341533
|
-
if (
|
|
341564
|
+
if (name50 === "screen_capture" && capturedInput?.dataUrl) content.push({ type: "image", image: capturedInput.dataUrl, mimeType: capturedInput.mimeType });
|
|
341565
|
+
else if (visionImage.imagePath) content.push({ type: "image", imagePath: visionImage.imagePath, mimeType: imageMimeForPath(visionImage.imagePath) });
|
|
341534
341566
|
else if (visionImage.image) content.push({ type: "image", image: visionImage.image, mimeType: visionImage.mimeType });
|
|
341535
341567
|
if (directImage) content.push({ type: "image", image: directImage, mimeType: "image/png" });
|
|
341536
341568
|
const terminate = shouldTerminateAfterToolResult(name50) && (name50 !== "question" || agent.pendingOptions.length > 0);
|
|
@@ -341543,7 +341575,7 @@ function toKernelTools(agent, definitions, provisioning) {
|
|
|
341543
341575
|
} catch {
|
|
341544
341576
|
}
|
|
341545
341577
|
}
|
|
341546
|
-
return { content, details: { tool: name50, ok: true, terminate, ...launchReceipt ? { launchReceipt } : {}, visionImagePath: visionImage.imagePath || void 0, ephemeralVisionImage: !!visionImage.image, displayImage }, terminate };
|
|
341578
|
+
return { content, details: { tool: name50, ok: true, terminate, ...launchReceipt ? { launchReceipt } : {}, visionImagePath: visionImage.imagePath || void 0, ephemeralVisionImage: !!visionImage.image, capturedAttachmentId: capturedInput?.id, displayImage }, terminate };
|
|
341547
341579
|
}
|
|
341548
341580
|
};
|
|
341549
341581
|
}).filter((tool) => !!tool.name);
|
|
@@ -341567,7 +341599,7 @@ var INLINE_TOOL_RESULT_MAX_CHARS = 24e3;
|
|
|
341567
341599
|
function spillOversizedToolResult(agent, name50, text) {
|
|
341568
341600
|
const value = String(text || "");
|
|
341569
341601
|
if (value.length <= INLINE_TOOL_RESULT_MAX_CHARS) return value;
|
|
341570
|
-
if (["computer_use", "browser_use", "pdf_read", "image_inspect", "image_display", "task", "subagent_send", "subagent_result", "subagent_read", "linked_plan", "question"].includes(name50)) {
|
|
341602
|
+
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)) {
|
|
341571
341603
|
return value;
|
|
341572
341604
|
}
|
|
341573
341605
|
const artifactId = agent.storeToolResultArtifact(name50, value);
|
|
@@ -341582,10 +341614,10 @@ function spillOversizedToolResult(agent, name50, text) {
|
|
|
341582
341614
|
].join("\n");
|
|
341583
341615
|
}
|
|
341584
341616
|
function sanitizeVisualToolText(name50, text) {
|
|
341585
|
-
if (name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read" && name50 !== "image_inspect") return text;
|
|
341617
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read" && name50 !== "image_inspect") return text;
|
|
341586
341618
|
try {
|
|
341587
341619
|
const parsed = JSON.parse(text);
|
|
341588
|
-
if (name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read") {
|
|
341620
|
+
if (name50 === "screen_capture" || name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read") {
|
|
341589
341621
|
delete parsed.vision_image_path;
|
|
341590
341622
|
delete parsed.vision_image_data_url;
|
|
341591
341623
|
if (name50 === "pdf_read" && parsed.result && typeof parsed.result === "object") {
|
|
@@ -341601,7 +341633,7 @@ function sanitizeVisualToolText(name50, text) {
|
|
|
341601
341633
|
}
|
|
341602
341634
|
}
|
|
341603
341635
|
function discardComputerUseVisionImage(name50, text) {
|
|
341604
|
-
if (name50 !== "computer_use") return;
|
|
341636
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use") return;
|
|
341605
341637
|
try {
|
|
341606
341638
|
const parsed = JSON.parse(text);
|
|
341607
341639
|
const screenshotPath = String(parsed.vision_image_path || "");
|
|
@@ -341619,8 +341651,20 @@ function imageInspectDataUrl(name50, text) {
|
|
|
341619
341651
|
return "";
|
|
341620
341652
|
}
|
|
341621
341653
|
}
|
|
341654
|
+
function capturedImageToolText(name50, text, attachmentId) {
|
|
341655
|
+
if (name50 !== "screen_capture" || !attachmentId) return text;
|
|
341656
|
+
try {
|
|
341657
|
+
const parsed = JSON.parse(text);
|
|
341658
|
+
parsed.attachment_id = attachmentId;
|
|
341659
|
+
parsed.image_input_channel = "user-image";
|
|
341660
|
+
parsed.inspect_next = { tool: "image_inspect", actions: ["source_info", "crop"], max_scale: 4 };
|
|
341661
|
+
return JSON.stringify(parsed, null, 2);
|
|
341662
|
+
} catch {
|
|
341663
|
+
return text;
|
|
341664
|
+
}
|
|
341665
|
+
}
|
|
341622
341666
|
function visualFallbackImageInput(agent, name50, text) {
|
|
341623
|
-
if (name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read") return {};
|
|
341667
|
+
if (name50 !== "screen_capture" && name50 !== "computer_use" && name50 !== "browser_use" && name50 !== "pdf_read") return {};
|
|
341624
341668
|
const model = agent.activeModelConfig();
|
|
341625
341669
|
if (!model?.vision) return {};
|
|
341626
341670
|
try {
|
|
@@ -341668,7 +341712,7 @@ async function executeNewmarkTool(agent, name50, args, inputSchema, signal) {
|
|
|
341668
341712
|
if (signal?.aborted) throw abortError4();
|
|
341669
341713
|
return result2;
|
|
341670
341714
|
};
|
|
341671
|
-
if (name50 === "task") return (await agent.handleSubagentEnvelope(args)).output;
|
|
341715
|
+
if (name50 === "task" || name50 === "subagent_create" || name50 === "SubAgent") return (await agent.handleSubagentEnvelope(args, true)).output;
|
|
341672
341716
|
if (name50 === "subagent_send") return (await agent.handleSubagentContinueEnvelope(args)).output;
|
|
341673
341717
|
if (name50 === "subagent_list") return agent.handleSubagentListEnvelope(args).output;
|
|
341674
341718
|
if (name50 === "subagent_read") return agent.handleSubagentReadEnvelope(args).output;
|
|
@@ -341746,7 +341790,7 @@ async function executeNewmarkTool(agent, name50, args, inputSchema, signal) {
|
|
|
341746
341790
|
actorId: agent.runtimeActorId,
|
|
341747
341791
|
workspaceId: terminalTakeoverWorkspaceId(wsDir),
|
|
341748
341792
|
backend: process.env.NEWMARK_WSL_DISTRO ? "wsl" : process.platform === "win32" ? "windows" : process.platform,
|
|
341749
|
-
allowEphemeralVisionImage: (name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read" || name50 === "ocr_read") && !!agent.activeModelConfig()?.vision,
|
|
341793
|
+
allowEphemeralVisionImage: (name50 === "screen_capture" || name50 === "computer_use" || name50 === "browser_use" || name50 === "pdf_read" || name50 === "ocr_read") && !!agent.activeModelConfig()?.vision,
|
|
341750
341794
|
signal
|
|
341751
341795
|
});
|
|
341752
341796
|
if (signal?.aborted) throw abortError4();
|
|
@@ -344820,7 +344864,7 @@ var Agent4 = class _Agent {
|
|
|
344820
344864
|
this.tools = new ToolExecutor(rootPath, this.config, this.ssh, this.workspace);
|
|
344821
344865
|
this.skills = new SkillsManager(rootPath);
|
|
344822
344866
|
this.memoryLab = new MemoryLabManager(rootPath, this.config.getStr("general", "language"));
|
|
344823
|
-
this.subagents = new SubagentManager({ rootAgentId: this.runtimeActorId });
|
|
344867
|
+
this.subagents = new SubagentManager({ rootAgentId: this.runtimeActorId, concurrency: this.subagentConcurrencyLimit() });
|
|
344824
344868
|
if (this.mode === "goal" && !this.goal) {
|
|
344825
344869
|
this.goal = new GoalStateImpl("Set your objective");
|
|
344826
344870
|
}
|
|
@@ -344889,6 +344933,7 @@ var Agent4 = class _Agent {
|
|
|
344889
344933
|
memoryLabRebuildState = "idle";
|
|
344890
344934
|
memoryLabRebuildError = "";
|
|
344891
344935
|
displayImageDescriptionCache = /* @__PURE__ */ new Map();
|
|
344936
|
+
latestCapturedImageInputs = [];
|
|
344892
344937
|
activeProcessAbortController = null;
|
|
344893
344938
|
automationManager = null;
|
|
344894
344939
|
activeAgentKernelRuntime = null;
|
|
@@ -345419,6 +345464,7 @@ var Agent4 = class _Agent {
|
|
|
345419
345464
|
}
|
|
345420
345465
|
setIntelligence(tier, persist = false) {
|
|
345421
345466
|
this.intelligence = normalizeIntelligenceTier(tier);
|
|
345467
|
+
this.subagents?.setConcurrencyLimit(this.subagentConcurrencyLimit());
|
|
345422
345468
|
if (persist) {
|
|
345423
345469
|
this.config.set("models", "default_intelligence", this.intelligence);
|
|
345424
345470
|
this.config.save();
|
|
@@ -345623,12 +345669,17 @@ var Agent4 = class _Agent {
|
|
|
345623
345669
|
return path28.join(ws.path, "conversations", "state.json");
|
|
345624
345670
|
}
|
|
345625
345671
|
workspaceConversationStateKey(conversationId = this.activeConversationId) {
|
|
345626
|
-
|
|
345672
|
+
return this.workspaceConversationStateKeyFor(conversationId, this.workspace.current);
|
|
345673
|
+
}
|
|
345674
|
+
workspaceConversationStateKeyFor(conversationId, ws) {
|
|
345675
|
+
const prefix = this.workspaceConversationPrefixFor(ws);
|
|
345627
345676
|
if (!prefix) return null;
|
|
345628
345677
|
return `${prefix}-${this.safeConversationId(conversationId)}`;
|
|
345629
345678
|
}
|
|
345630
345679
|
workspaceConversationPrefix() {
|
|
345631
|
-
|
|
345680
|
+
return this.workspaceConversationPrefixFor(this.workspace.current);
|
|
345681
|
+
}
|
|
345682
|
+
workspaceConversationPrefixFor(ws) {
|
|
345632
345683
|
if (!ws) return null;
|
|
345633
345684
|
const supplied = String(ws.conversationStatePrefix || "").trim();
|
|
345634
345685
|
if (/^(?:internal|external)-[a-f0-9]{16}$/i.test(supplied)) return supplied.toLowerCase();
|
|
@@ -347078,8 +347129,56 @@ ${String(event.toolArgs || "")}`;
|
|
|
347078
347129
|
}
|
|
347079
347130
|
}
|
|
347080
347131
|
listConversationStates() {
|
|
347081
|
-
|
|
347082
|
-
|
|
347132
|
+
return this.listWorkspaceConversationStates(this.workspace.current);
|
|
347133
|
+
}
|
|
347134
|
+
registerCapturedImageInput(dataUrl, name50 = "active-screenshot.jpg") {
|
|
347135
|
+
if (!String(dataUrl || "").startsWith("data:image/")) return null;
|
|
347136
|
+
const prepared = this.prepareSubmittedConversationImages([{ dataUrl, name: name50, type: dataUrl.slice(5, dataUrl.indexOf(";")) }]);
|
|
347137
|
+
const attachment = prepared.attachments[0] || null;
|
|
347138
|
+
this.latestCapturedImageInputs = attachment ? [attachment] : [];
|
|
347139
|
+
return attachment;
|
|
347140
|
+
}
|
|
347141
|
+
subagentConcurrencyLimit() {
|
|
347142
|
+
return this.intelligence === "ultra" ? 16 : 4;
|
|
347143
|
+
}
|
|
347144
|
+
/** 当前工作区使用内存中的前台选择;后台工作区从各自持久化状态读取 active id。 */
|
|
347145
|
+
activeConversationIdForWorkspace(ws) {
|
|
347146
|
+
const targetWs = ws || this.workspace.current;
|
|
347147
|
+
if (!targetWs) return "default";
|
|
347148
|
+
const currentWs = this.workspace.current;
|
|
347149
|
+
const isCurrent = !!currentWs && path28.resolve(currentWs.path) === path28.resolve(targetWs.path);
|
|
347150
|
+
if (isCurrent) return this.safeConversationId(this.activeConversationId || "default");
|
|
347151
|
+
const stored = this.readStoredConversationState(targetWs);
|
|
347152
|
+
return this.safeConversationId(stored.activeConversationId || "default");
|
|
347153
|
+
}
|
|
347154
|
+
/**
|
|
347155
|
+
* 持久化的完整 work run 记录(含 interrupted/force_interrupted)。
|
|
347156
|
+
* 不依赖运行时内存(run 结束后内存清空,state 端点曾因此丢失被中断的构建记录),
|
|
347157
|
+
* 供 mobile 端点稳定透出完整对话信息;移动端按同一格式解析。
|
|
347158
|
+
*/
|
|
347159
|
+
getPersistedConversationWorkRuns(conversationId, ws = null) {
|
|
347160
|
+
const targetWs = ws || this.workspace.current;
|
|
347161
|
+
const clean = this.safeConversationId(conversationId || "default");
|
|
347162
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(clean, targetWs);
|
|
347163
|
+
const stored = this.readStoredConversationState(targetWs);
|
|
347164
|
+
const persisted = stateKey2 && stored.conversations ? stored.conversations[stateKey2] : void 0;
|
|
347165
|
+
const tree = persisted ? this.normalizeConversationTree(persisted) : null;
|
|
347166
|
+
const runtimeNodeId = String(tree?.activeNodeId || "");
|
|
347167
|
+
const viewedNodeId = tree ? this.resolveConversationTreePath(tree, this.storedConversationTreePath(tree, persisted?.viewedBranchNodePath, runtimeNodeId)) : "";
|
|
347168
|
+
const viewedNode = tree?.nodes[viewedNodeId];
|
|
347169
|
+
return this.normalizeWorkRuns(viewedNode?.workRuns || persisted?.workRuns);
|
|
347170
|
+
}
|
|
347171
|
+
/** Exact membership check against the raw persisted state key, before UI content deduplication. */
|
|
347172
|
+
hasConversationInWorkspace(conversationId, ws) {
|
|
347173
|
+
const targetWs = ws || this.workspace.current;
|
|
347174
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(this.safeConversationId(conversationId || "default"), targetWs);
|
|
347175
|
+
if (!stateKey2) return false;
|
|
347176
|
+
return Object.prototype.hasOwnProperty.call(this.readStoredConversationState(targetWs).conversations || {}, stateKey2);
|
|
347177
|
+
}
|
|
347178
|
+
/** 按工作区列对话(任意 ws,key 前缀 = kind-sha256(path).slice(0,16));供 mobile API 透出工作区从属对话 */
|
|
347179
|
+
listWorkspaceConversationStates(ws) {
|
|
347180
|
+
const stored = this.readStoredConversationState(ws);
|
|
347181
|
+
const prefix = this.workspaceConversationPrefixFor(ws) || "";
|
|
347083
347182
|
const scopedEntries = Object.entries(stored.conversations || {}).filter(([key3]) => !prefix || key3.startsWith(prefix));
|
|
347084
347183
|
if (scopedEntries.some(([, value]) => !Number.isFinite(value.order))) {
|
|
347085
347184
|
const legacyOrder = [...scopedEntries].sort(([, a3], [, b2]) => {
|
|
@@ -347090,7 +347189,7 @@ ${String(event.toolArgs || "")}`;
|
|
|
347090
347189
|
legacyOrder.forEach(([, value], index) => {
|
|
347091
347190
|
value.order = index;
|
|
347092
347191
|
});
|
|
347093
|
-
this.writeStoredConversationState(stored);
|
|
347192
|
+
this.writeStoredConversationState(stored, ws);
|
|
347094
347193
|
}
|
|
347095
347194
|
const rows = [];
|
|
347096
347195
|
for (const [key3, value] of Object.entries(stored.conversations || {})) {
|
|
@@ -347144,6 +347243,7 @@ ${String(event.toolArgs || "")}`;
|
|
|
347144
347243
|
this.subagents = sharedSubagentManager(this.subagentManagerKey(clean), {
|
|
347145
347244
|
conversationId: clean,
|
|
347146
347245
|
rootAgentId: state?.rootAgentId || this.runtimeActorId,
|
|
347246
|
+
concurrency: this.subagentConcurrencyLimit(),
|
|
347147
347247
|
state,
|
|
347148
347248
|
executor: (job) => this.runSubagentJob(job.record.id, job.prompt, job.flowName, job.reason),
|
|
347149
347249
|
persist: (subagentState) => this.persistSubagentState(clean, subagentState),
|
|
@@ -347213,15 +347313,14 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
347213
347313
|
}
|
|
347214
347314
|
getConversationSnapshot(conversationId = this.activeConversationId, options = {}) {
|
|
347215
347315
|
const clean = this.safeConversationId(conversationId || "default");
|
|
347216
|
-
const
|
|
347217
|
-
const
|
|
347218
|
-
const
|
|
347219
|
-
|
|
347220
|
-
|
|
347221
|
-
|
|
347222
|
-
})();
|
|
347316
|
+
const ws = options.workspace || this.workspace.current;
|
|
347317
|
+
const currentWs = this.workspace.current;
|
|
347318
|
+
const isActiveWorkspace = !ws && !currentWs || !!ws && !!currentWs && path28.resolve(ws.path) === path28.resolve(currentWs.path);
|
|
347319
|
+
const isActiveConversation = isActiveWorkspace && clean === this.safeConversationId(this.activeConversationId || "default");
|
|
347320
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(clean, ws);
|
|
347321
|
+
const memoryKey = ws ? `${ws.isInternal ? "internal" : "external"}:${path28.resolve(ws.path)}::conversation:${clean}` : null;
|
|
347223
347322
|
const memory = memoryKey ? this.workspaceConversations.get(memoryKey) : void 0;
|
|
347224
|
-
const stored = this.readStoredConversationState();
|
|
347323
|
+
const stored = this.readStoredConversationState(ws);
|
|
347225
347324
|
const persisted = stateKey2 && stored.conversations ? stored.conversations[stateKey2] : void 0;
|
|
347226
347325
|
const tree = persisted ? this.normalizeConversationTree(persisted) : null;
|
|
347227
347326
|
const runtimeNodeId = String(tree?.activeNodeId || "");
|
|
@@ -347241,7 +347340,7 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
347241
347340
|
const continuations = this.normalizeContinuations(isActiveConversation && viewingRuntimeNode ? this.continuations : viewedNode?.continuations || persisted?.continuations || memory?.continuations);
|
|
347242
347341
|
return {
|
|
347243
347342
|
conversationId: clean,
|
|
347244
|
-
conversations: this.
|
|
347343
|
+
conversations: this.listWorkspaceConversationStates(ws),
|
|
347245
347344
|
conversationPlan: this.normalizeConversationPlan(isActiveConversation ? this.conversationPlan : persisted?.plan || memory?.plan),
|
|
347246
347345
|
linkedPlan: this.normalizeLinkedPlan(isActiveConversation ? this.linkedPlan : persisted?.linkedPlan || memory?.linkedPlan),
|
|
347247
347346
|
subagents: this.recordsForState(isActiveConversation ? this.subagents.serialize() : persisted?.subagentState || memory?.subagentState),
|
|
@@ -347251,9 +347350,9 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
347251
347350
|
historyMessages: history.length,
|
|
347252
347351
|
workRuns,
|
|
347253
347352
|
continuations,
|
|
347254
|
-
modelSelection: isActiveConversation ? this.currentConversationModelSelection() : persisted?.modelSelection || memory?.modelSelection ||
|
|
347353
|
+
modelSelection: isActiveConversation ? this.currentConversationModelSelection() : persisted?.modelSelection || memory?.modelSelection || { kind: "auto" },
|
|
347255
347354
|
flowSelection: isActiveConversation ? this.currentConversationFlowSelection() : persisted?.flowSelection || memory?.flowSelection || null,
|
|
347256
|
-
inputMode: this.inputMode,
|
|
347355
|
+
inputMode: isActiveConversation ? this.inputMode : persisted?.inputMode || memory?.inputMode || "guide",
|
|
347257
347356
|
mode: isActiveConversation ? this.mode : persisted?.mode || memory?.mode || "build",
|
|
347258
347357
|
goal: isActiveConversation ? this.serializeGoal() : persisted?.goal || memory?.goal || null,
|
|
347259
347358
|
branches: this.branchGroupMetadata(tree),
|
|
@@ -347540,12 +347639,16 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
347540
347639
|
if (clean === this.safeConversationId(this.activeConversationId)) this.setConversationFromStorage(clean);
|
|
347541
347640
|
return this.getConversationSnapshot(clean);
|
|
347542
347641
|
}
|
|
347543
|
-
setConversationPinned(id, pinned) {
|
|
347642
|
+
setConversationPinned(id, pinned, ws = this.workspace.current) {
|
|
347643
|
+
const targetWs = ws || this.workspace.current;
|
|
347644
|
+
if (!targetWs) return false;
|
|
347544
347645
|
const clean = this.safeConversationId(id || "default");
|
|
347545
|
-
this.
|
|
347546
|
-
const
|
|
347646
|
+
const currentWs = this.workspace.current;
|
|
347647
|
+
const isCurrent = !!currentWs && path28.resolve(currentWs.path) === path28.resolve(targetWs.path);
|
|
347648
|
+
if (isCurrent) this.saveWorkspaceConversationState();
|
|
347649
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(clean, targetWs);
|
|
347547
347650
|
if (!stateKey2) return false;
|
|
347548
|
-
const stored = this.readStoredConversationState();
|
|
347651
|
+
const stored = this.readStoredConversationState(targetWs);
|
|
347549
347652
|
stored.conversations = stored.conversations || {};
|
|
347550
347653
|
const existing = stored.conversations[stateKey2];
|
|
347551
347654
|
if (!existing) return false;
|
|
@@ -347554,23 +347657,65 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
347554
347657
|
const siblingOrders = Object.entries(stored.conversations).filter(([key3, value]) => key3 !== stateKey2 && !!value.pinned === existing.pinned && Number.isFinite(value.order)).map(([, value]) => Number(value.order));
|
|
347555
347658
|
existing.order = siblingOrders.length ? Math.min(...siblingOrders) - 1 : 0;
|
|
347556
347659
|
existing.updatedAt = existing.updatedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
347557
|
-
this.writeStoredConversationState(stored);
|
|
347660
|
+
this.writeStoredConversationState(stored, targetWs);
|
|
347558
347661
|
return true;
|
|
347559
347662
|
}
|
|
347560
|
-
renameConversation(id, title) {
|
|
347663
|
+
renameConversation(id, title, ws = this.workspace.current) {
|
|
347664
|
+
const targetWs = ws || this.workspace.current;
|
|
347665
|
+
if (!targetWs) return false;
|
|
347561
347666
|
const clean = this.safeConversationId(id || "default");
|
|
347562
347667
|
const nextTitle = String(title || "").replace(/\s+/g, " ").trim().slice(0, 80);
|
|
347563
347668
|
if (!nextTitle) return false;
|
|
347564
|
-
this.
|
|
347565
|
-
const
|
|
347669
|
+
const currentWs = this.workspace.current;
|
|
347670
|
+
const isCurrent = !!currentWs && path28.resolve(currentWs.path) === path28.resolve(targetWs.path);
|
|
347671
|
+
if (isCurrent) this.saveWorkspaceConversationState();
|
|
347672
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(clean, targetWs);
|
|
347566
347673
|
if (!stateKey2) return false;
|
|
347567
|
-
const stored = this.readStoredConversationState();
|
|
347674
|
+
const stored = this.readStoredConversationState(targetWs);
|
|
347568
347675
|
const existing = stored.conversations?.[stateKey2];
|
|
347569
347676
|
if (!existing) return false;
|
|
347570
347677
|
existing.title = nextTitle;
|
|
347571
|
-
this.writeStoredConversationState(stored);
|
|
347678
|
+
this.writeStoredConversationState(stored, targetWs);
|
|
347572
347679
|
return true;
|
|
347573
347680
|
}
|
|
347681
|
+
/** 为指定工作区创建空白对话,不临时切换全局前台工作区。 */
|
|
347682
|
+
createConversationInWorkspace(ws, title = "") {
|
|
347683
|
+
const existing = this.listWorkspaceConversationStates(ws);
|
|
347684
|
+
const id = this.safeConversationId(`conv-${Date.now()}-${crypto14.randomUUID().slice(0, 8)}`);
|
|
347685
|
+
const resolvedTitle = String(title || "").replace(/\s+/g, " ").trim().slice(0, 80) || `New chat ${existing.length + 1}`;
|
|
347686
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(id, ws);
|
|
347687
|
+
if (!stateKey2) throw new Error("Conversation workspace is unavailable.");
|
|
347688
|
+
const unpinnedOrders = existing.filter((item) => !item.pinned).map((item) => Number(item.order || 0));
|
|
347689
|
+
const order = unpinnedOrders.length ? Math.min(...unpinnedOrders) - 1 : 0;
|
|
347690
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
347691
|
+
this.mutateStoredConversationState(ws, (latest) => {
|
|
347692
|
+
latest.version = 3;
|
|
347693
|
+
latest.activeConversationId = id;
|
|
347694
|
+
latest.conversations = latest.conversations || {};
|
|
347695
|
+
latest.conversations[stateKey2] = {
|
|
347696
|
+
title: resolvedTitle,
|
|
347697
|
+
chatMessages: [],
|
|
347698
|
+
history: [],
|
|
347699
|
+
plan: { items: [] },
|
|
347700
|
+
linkedPlan: { markdown: "", revision: 0 },
|
|
347701
|
+
workRuns: [],
|
|
347702
|
+
continuations: [],
|
|
347703
|
+
inputMode: this.defaultInputMode(),
|
|
347704
|
+
mode: "build",
|
|
347705
|
+
updatedAt: now2,
|
|
347706
|
+
pinned: false,
|
|
347707
|
+
pinnedAt: "",
|
|
347708
|
+
order,
|
|
347709
|
+
branchCommunication: false
|
|
347710
|
+
};
|
|
347711
|
+
return latest;
|
|
347712
|
+
});
|
|
347713
|
+
const currentWs = this.workspace.current;
|
|
347714
|
+
if (currentWs && path28.resolve(currentWs.path) === path28.resolve(ws.path)) {
|
|
347715
|
+
this.setConversationFromStorage(id);
|
|
347716
|
+
}
|
|
347717
|
+
return { id, title: resolvedTitle };
|
|
347718
|
+
}
|
|
347574
347719
|
/**
|
|
347575
347720
|
* 首 Build 命名判定:仅当 (1) 当前对话尚无历史 Build(排除当前 run)且
|
|
347576
347721
|
* (2) 其持久化 title 仍是自动生成(含为空)时返回 true。dev-0.4.3 起不再
|
|
@@ -347681,6 +347826,34 @@ Conversation title (a few words):`;
|
|
|
347681
347826
|
this.writeStoredConversationState(stored);
|
|
347682
347827
|
return true;
|
|
347683
347828
|
}
|
|
347829
|
+
/** Reorder one pinned group inside an explicit workspace without changing membership. */
|
|
347830
|
+
reorderWorkspaceConversationGroup(ids, ws) {
|
|
347831
|
+
const targetWs = ws || this.workspace.current;
|
|
347832
|
+
if (!targetWs || !Array.isArray(ids) || ids.length < 2) return false;
|
|
347833
|
+
const normalized = ids.map((id) => this.safeConversationId(String(id || "")));
|
|
347834
|
+
if (normalized.some((id) => !id) || new Set(normalized).size !== normalized.length) return false;
|
|
347835
|
+
const currentWs = this.workspace.current;
|
|
347836
|
+
const isCurrent = !!currentWs && path28.resolve(currentWs.path) === path28.resolve(targetWs.path);
|
|
347837
|
+
if (isCurrent) this.saveWorkspaceConversationState();
|
|
347838
|
+
let accepted = false;
|
|
347839
|
+
this.mutateStoredConversationState(targetWs, (latest) => {
|
|
347840
|
+
const prefix = this.workspaceConversationPrefixFor(targetWs) || "";
|
|
347841
|
+
const entries = Object.entries(latest.conversations || {}).filter(([key3]) => !prefix || key3.startsWith(prefix));
|
|
347842
|
+
const entryById = new Map(entries.map(([key3, value]) => [key3.slice(prefix.length + 1) || key3, value]));
|
|
347843
|
+
const requested = normalized.map((id) => entryById.get(id));
|
|
347844
|
+
if (requested.some((entry) => !entry)) return latest;
|
|
347845
|
+
if (new Set(requested.map((entry) => !!entry.pinned)).size !== 1) return latest;
|
|
347846
|
+
const orderSlots = requested.map((entry) => Number(entry.order));
|
|
347847
|
+
if (orderSlots.some((order) => !Number.isFinite(order))) return latest;
|
|
347848
|
+
orderSlots.sort((a3, b2) => a3 - b2);
|
|
347849
|
+
normalized.forEach((id, index) => {
|
|
347850
|
+
entryById.get(id).order = orderSlots[index];
|
|
347851
|
+
});
|
|
347852
|
+
accepted = true;
|
|
347853
|
+
return latest;
|
|
347854
|
+
});
|
|
347855
|
+
return accepted;
|
|
347856
|
+
}
|
|
347684
347857
|
flushConversationState() {
|
|
347685
347858
|
this.saveWorkspaceConversationState();
|
|
347686
347859
|
}
|
|
@@ -349629,21 +349802,21 @@ ${summary}`, segment, "local-summarize", true);
|
|
|
349629
349802
|
this.saveWorkspaceConversationState(true);
|
|
349630
349803
|
return { text, hiddenUserInput: true, goalContinuation: true };
|
|
349631
349804
|
}
|
|
349632
|
-
buildSessionArchive(messages,
|
|
349805
|
+
buildSessionArchive(messages, context, archiveDir) {
|
|
349633
349806
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "").replace("T", "_").replace("Z", "");
|
|
349634
349807
|
const filename = `session_${stamp}_${crypto14.randomUUID().slice(0, 8)}.md`;
|
|
349635
349808
|
let markdown = `# Newmark Session \u2014 ${stamp}
|
|
349636
349809
|
|
|
349637
349810
|
`;
|
|
349638
|
-
markdown += `**Mode**: ${mode}
|
|
349639
|
-
**Model**: ${model}
|
|
349811
|
+
markdown += `**Mode**: ${context.mode}
|
|
349812
|
+
**Model**: ${context.model}
|
|
349640
349813
|
`;
|
|
349641
349814
|
markdown += `**Messages**: ${messages.length}
|
|
349642
349815
|
|
|
349643
349816
|
---
|
|
349644
349817
|
|
|
349645
349818
|
`;
|
|
349646
|
-
if (
|
|
349819
|
+
if (context.goal?.objective) markdown += `**Goal**: ${context.goal.objective}
|
|
349647
349820
|
|
|
349648
349821
|
`;
|
|
349649
349822
|
for (const msg of messages) {
|
|
@@ -349666,12 +349839,12 @@ ${msg.content}
|
|
|
349666
349839
|
writeSessionArchive(messages, mode, model) {
|
|
349667
349840
|
const archiveDir = this.archiveDir();
|
|
349668
349841
|
fs25.mkdirSync(archiveDir, { recursive: true });
|
|
349669
|
-
const archive = this.buildSessionArchive(messages, mode, model, archiveDir);
|
|
349842
|
+
const archive = this.buildSessionArchive(messages, { mode, model, goal: this.serializeGoal() }, archiveDir);
|
|
349670
349843
|
fs25.writeFileSync(path28.join(archiveDir, archive.filename), archive.markdown, "utf-8");
|
|
349671
349844
|
return archive.filename;
|
|
349672
349845
|
}
|
|
349673
|
-
async writeSessionArchiveAsync(messages,
|
|
349674
|
-
const archive = this.buildSessionArchive(messages,
|
|
349846
|
+
async writeSessionArchiveAsync(messages, context, archiveDir = this.archiveDir()) {
|
|
349847
|
+
const archive = this.buildSessionArchive(messages, context, archiveDir);
|
|
349675
349848
|
await fs25.promises.mkdir(archiveDir, { recursive: true });
|
|
349676
349849
|
const outPath = path28.join(archiveDir, archive.filename);
|
|
349677
349850
|
const tempPath = `${outPath}.${process.pid}.${crypto14.randomUUID()}.tmp`;
|
|
@@ -349758,30 +349931,36 @@ ${msg.content}
|
|
|
349758
349931
|
* large markdown payload and manifest use promise-based filesystem I/O so
|
|
349759
349932
|
* independent workspaces can archive in parallel without freezing Electron.
|
|
349760
349933
|
*/
|
|
349761
|
-
async archiveConversationAsync(conversationId) {
|
|
349762
|
-
return await this.archiveConversationAsyncUnlocked(conversationId);
|
|
349934
|
+
async archiveConversationAsync(conversationId, ws = this.workspace.current) {
|
|
349935
|
+
return await this.archiveConversationAsyncUnlocked(conversationId, ws);
|
|
349763
349936
|
}
|
|
349764
|
-
async archiveConversationAsyncUnlocked(conversationId) {
|
|
349765
|
-
const ws = this.workspace.current;
|
|
349937
|
+
async archiveConversationAsyncUnlocked(conversationId, targetWorkspace = this.workspace.current) {
|
|
349938
|
+
const ws = targetWorkspace || this.workspace.current;
|
|
349766
349939
|
if (!ws) return null;
|
|
349767
349940
|
const clean = this.safeConversationId(conversationId || "default");
|
|
349768
|
-
const stateKey2 = this.
|
|
349941
|
+
const stateKey2 = this.workspaceConversationStateKeyFor(clean, ws);
|
|
349769
349942
|
if (!stateKey2) return null;
|
|
349770
349943
|
const memoryKey = `${ws.isInternal ? "internal" : "external"}:${path28.resolve(ws.path)}::conversation:${clean}`;
|
|
349771
349944
|
const archiveDir = path28.join(ws.path, "archive");
|
|
349772
|
-
const workspacePrefix = this.
|
|
349773
|
-
const archiveMode = this.modeName();
|
|
349774
|
-
const archiveModel = this.model;
|
|
349945
|
+
const workspacePrefix = this.workspaceConversationPrefixFor(ws) || "";
|
|
349775
349946
|
const cachedStored = this.readStoredConversationState(ws);
|
|
349776
349947
|
const stored = JSON.parse(JSON.stringify(cachedStored || {}));
|
|
349777
349948
|
const persisted = stored.conversations?.[stateKey2];
|
|
349778
349949
|
if (persisted) this.normalizeConversationTree(persisted);
|
|
349779
349950
|
const memory = this.workspaceConversations.get(memoryKey);
|
|
349951
|
+
const archiveMode = persisted?.mode || memory?.mode || "build";
|
|
349952
|
+
const archiveSelection = persisted?.modelSelection || memory?.modelSelection;
|
|
349953
|
+
const archiveModel = archiveSelection?.kind === "deployment" ? archiveSelection.modelId : archiveSelection?.kind === "auto" ? "auto" : "auto";
|
|
349954
|
+
const archiveGoal = persisted?.goal || memory?.goal || null;
|
|
349780
349955
|
const persistedMessagesAvailable = persisted?.chatMessages !== void 0;
|
|
349781
349956
|
const sourceMessages = persisted?.chatMessages ?? memory?.chatMessages ?? [];
|
|
349782
349957
|
const sourceHistory = persistedMessagesAvailable ? persisted?.history ?? [] : memory?.history ?? persisted?.history ?? [];
|
|
349783
349958
|
const messages = this.normalizeConversationChatMessages(sourceMessages, sourceHistory);
|
|
349784
|
-
const filename = await this.writeSessionArchiveAsync(messages,
|
|
349959
|
+
const filename = await this.writeSessionArchiveAsync(messages, {
|
|
349960
|
+
mode: archiveMode,
|
|
349961
|
+
model: archiveModel,
|
|
349962
|
+
goal: archiveGoal
|
|
349963
|
+
}, archiveDir);
|
|
349785
349964
|
const archiveEntry = persisted ? JSON.parse(JSON.stringify(persisted)) : {
|
|
349786
349965
|
title: this.titleFromMessages(messages, clean),
|
|
349787
349966
|
chatMessages: messages,
|
|
@@ -349834,7 +350013,9 @@ ${msg.content}
|
|
|
349834
350013
|
this.workspaceConversations.delete(memoryKey);
|
|
349835
350014
|
const duplicateMemoryKey = `${ws.isInternal ? "internal" : "external"}:${path28.resolve(ws.path)}::conversation:${clean}`;
|
|
349836
350015
|
this.workspaceConversations.delete(duplicateMemoryKey);
|
|
349837
|
-
|
|
350016
|
+
const currentWs = this.workspace.current;
|
|
350017
|
+
const isCurrentWorkspace = !!currentWs && path28.resolve(currentWs.path) === path28.resolve(ws.path);
|
|
350018
|
+
if (isCurrentWorkspace && clean === this.safeConversationId(this.activeConversationId || "default")) {
|
|
349838
350019
|
this.activeConversationId = nextActiveId || "default";
|
|
349839
350020
|
this.loadWorkspaceConversationState();
|
|
349840
350021
|
}
|
|
@@ -351079,7 +351260,7 @@ ${persisted.map((guide, index) => `Guide ${index + 1}: ${guide.text}`).join("\n"
|
|
|
351079
351260
|
return `${accepted.output}
|
|
351080
351261
|
${settled?.result || settled?.error || ""}`.trim();
|
|
351081
351262
|
}
|
|
351082
|
-
async handleSubagentEnvelope(args) {
|
|
351263
|
+
async handleSubagentEnvelope(args, requireRunningBuild = false) {
|
|
351083
351264
|
try {
|
|
351084
351265
|
const params = JSON.parse(args);
|
|
351085
351266
|
const preset = this.resolveSubagentPreset(params);
|
|
@@ -351094,6 +351275,36 @@ ${settled?.result || settled?.error || ""}`.trim();
|
|
|
351094
351275
|
const requestedModel = this.normalizeSubagentModelSelection(params.model || preset?.model || inheritedModel);
|
|
351095
351276
|
const activeDeployment = this.activeDeployment();
|
|
351096
351277
|
const peerModel = requestedModel !== "auto" && !parseDeploymentSelectionValue2(requestedModel) && activeDeployment && requestedModel === activeDeployment.modelId ? `deployment:${encodeURIComponent(activeDeployment.providerId)}:${encodeURIComponent(activeDeployment.modelId)}` : requestedModel;
|
|
351278
|
+
const buildRunId = this.currentWorkRunId();
|
|
351279
|
+
const runningBuild = buildRunId ? this.workRuns.find((run) => run.runId === buildRunId && run.status === "running") : void 0;
|
|
351280
|
+
const limit = this.subagentConcurrencyLimit();
|
|
351281
|
+
if (requireRunningBuild && !runningBuild) {
|
|
351282
|
+
return {
|
|
351283
|
+
ok: false,
|
|
351284
|
+
output: "[SubAgent terminated] No running Build Block owns this call; no SubAgent was created.",
|
|
351285
|
+
error: "SubAgent tool calls require a running Build Block.",
|
|
351286
|
+
metadata: { kind: "subagent", buildRunId: buildRunId || "", limit, terminated: true }
|
|
351287
|
+
};
|
|
351288
|
+
}
|
|
351289
|
+
if (buildRunId && !runningBuild) {
|
|
351290
|
+
return {
|
|
351291
|
+
ok: false,
|
|
351292
|
+
output: `[SubAgent terminated] Build Block ${buildRunId} is not running; no SubAgent was created.`,
|
|
351293
|
+
error: "SubAgent creation requires a running Build Block.",
|
|
351294
|
+
metadata: { kind: "subagent", buildRunId, limit, terminated: true }
|
|
351295
|
+
};
|
|
351296
|
+
}
|
|
351297
|
+
if (runningBuild) {
|
|
351298
|
+
const activeForBuild = this.subagents.activeCountForBuild(buildRunId);
|
|
351299
|
+
if (activeForBuild >= limit) {
|
|
351300
|
+
return {
|
|
351301
|
+
ok: false,
|
|
351302
|
+
output: `[SubAgent terminated] Build Block ${buildRunId} reached the ${this.intelligence === "ultra" ? "Ultra" : "non-Ultra"} hard limit (${limit}); no SubAgent was created or queued.`,
|
|
351303
|
+
error: `SubAgent hard limit reached for Build Block ${buildRunId}: ${activeForBuild}/${limit}.`,
|
|
351304
|
+
metadata: { kind: "subagent", buildRunId, intelligence: this.intelligence, activeForBuild, limit, terminated: true }
|
|
351305
|
+
};
|
|
351306
|
+
}
|
|
351307
|
+
}
|
|
351097
351308
|
const id = this.subagents.create(
|
|
351098
351309
|
name50,
|
|
351099
351310
|
prompt,
|
|
@@ -351103,7 +351314,9 @@ ${settled?.result || settled?.error || ""}`.trim();
|
|
|
351103
351314
|
this.runtimeActorId,
|
|
351104
351315
|
peerFlow,
|
|
351105
351316
|
peerGoal,
|
|
351106
|
-
Number(params.flow_pc ?? params.flowPc ?? (peerMode === "flow" ? this.flowPc : 0))
|
|
351317
|
+
Number(params.flow_pc ?? params.flowPc ?? (peerMode === "flow" ? this.flowPc : 0)),
|
|
351318
|
+
runningBuild?.runId || "",
|
|
351319
|
+
this.intelligence
|
|
351107
351320
|
);
|
|
351108
351321
|
const sa = this.subagents.get(id);
|
|
351109
351322
|
if (sa && preset) {
|
|
@@ -351842,6 +352055,13 @@ ${items.map((item) => this.formatAutomation(item)).join("\n")}`;
|
|
|
351842
352055
|
}
|
|
351843
352056
|
latestSubmittedImages(attachmentId = "") {
|
|
351844
352057
|
const normalizedId = String(attachmentId || "").trim();
|
|
352058
|
+
const captured = hydrateConversationImageAttachments(this.rootPath, this.latestCapturedImageInputs).flatMap((attachment) => attachment.dataUrl ? [{ id: attachment.id, dataUrl: attachment.dataUrl }] : []);
|
|
352059
|
+
if (normalizedId) {
|
|
352060
|
+
const capturedMatch = captured.find((item) => item.id === normalizedId);
|
|
352061
|
+
if (capturedMatch) return [capturedMatch];
|
|
352062
|
+
} else if (captured.length) {
|
|
352063
|
+
return captured;
|
|
352064
|
+
}
|
|
351845
352065
|
for (let index = this.chatMessages.length - 1; index >= 0; index -= 1) {
|
|
351846
352066
|
const message = this.chatMessages[index];
|
|
351847
352067
|
if (message?.role !== "user") continue;
|
|
@@ -352411,7 +352631,7 @@ ${custom}`);
|
|
|
352411
352631
|
if (this.intelligence === "ultra") {
|
|
352412
352632
|
parts.push([
|
|
352413
352633
|
"[Ultra Intelligence \u2013 Orchestrator Role]",
|
|
352414
|
-
"You are the lead orchestrator. Actively decompose complex tasks into parallel sub-tasks. Use the `
|
|
352634
|
+
"You are the lead orchestrator. Actively decompose complex tasks into parallel sub-tasks. Use the `SubAgent` tool to create specialized SubAgents for each distinct sub-task. Use `task_create` only for the conversation checklist; it never creates a SubAgent. Coordinate the SubAgent team: assign clear responsibilities, merge results, resolve conflicts, and produce a unified final output. SubAgents are your team; delegate aggressively and manage them as a manager, not just a tool caller.",
|
|
352415
352635
|
"Do not attempt to do all the work yourself. Use SubAgents for parallel investigation, verification, implementation, and review."
|
|
352416
352636
|
].join("\n"));
|
|
352417
352637
|
}
|
|
@@ -352517,7 +352737,7 @@ ${custom}`);
|
|
|
352517
352737
|
"- Build history disclosure is two-layered. The request prompt contains only each historical Build Block user input, final summary, and completion status. When the current task continues, fixes, verifies, or depends on earlier Build Blocks, proactively call build_history_query to read the concrete tool activity and results of the relevant block, and reuse that information instead of re-investigating (re-running commands or re-reading files) from scratch. Querying history is read-only and never authorizes resuming that work; do not query merely to answer completion status already shown in the prompt.",
|
|
352518
352738
|
"- Linked plan disclosure: a durable conversation-linked Markdown plan exists and can be inspected or updated with linked_plan when explicitly needed or required by Plan mode. Its full Markdown and revision are not injected into every model request.",
|
|
352519
352739
|
"- A memory_lab_update, memory_lab_delete, or memory_lab_reindex call is unfinished until its awaited tool result contains rebuildReceipt.completed=true. The completion receipt is represented by the tool activity inside the current Build block and should not be repeated as a separate completion message.",
|
|
352520
|
-
`- Skills and subagents: skill searches enabled metadata and loads one SKILL.md body on demand; skill_download installs offline skill folders;
|
|
352740
|
+
`- Skills and subagents: skill searches enabled metadata and loads one SKILL.md body on demand; skill_download installs offline skill folders; SubAgent creates constrained peer agents tracked in agent state. task_create is only for the conversation checklist and never creates a SubAgent.`,
|
|
352521
352741
|
`- Visible output contract: assistant replies are sanitized before display to remove hidden-reasoning markers. ${visibleOutputContract}`,
|
|
352522
352742
|
"- During Build work, before the first tool call and between materially different tool phases, emit a concise public progress explanation of what you are checking or changing and why. This is visible commentary, not hidden chain-of-thought. Do not wait until the final answer to explain the work."
|
|
352523
352743
|
].join("\n");
|
|
@@ -353026,6 +353246,155 @@ var ConversationKernel = class {
|
|
|
353026
353246
|
followUp: queued?.followUp.slice() || []
|
|
353027
353247
|
};
|
|
353028
353248
|
}
|
|
353249
|
+
queueItems(target) {
|
|
353250
|
+
const runtime = this.findRuntime(target);
|
|
353251
|
+
if (!runtime) return [];
|
|
353252
|
+
return runtime.pendingNextTurn.flatMap((item) => {
|
|
353253
|
+
if (item.queueMode !== "followUp") return [];
|
|
353254
|
+
if (typeof item.message === "string") return [];
|
|
353255
|
+
const id = String(item.message.clientMessageId || "");
|
|
353256
|
+
if (!id) return [];
|
|
353257
|
+
return [{
|
|
353258
|
+
id,
|
|
353259
|
+
text: String(item.message.visibleUserInput || item.message.text || "").replace(/^\[Next queued while current turn is running\]\n/, ""),
|
|
353260
|
+
queueMode: item.queueMode,
|
|
353261
|
+
requestedMode: item.message.visibleMode,
|
|
353262
|
+
goalObjective: item.message.goalObjective,
|
|
353263
|
+
runId: item.message.runId,
|
|
353264
|
+
createdAt: String(item.message.createdAt || "")
|
|
353265
|
+
}];
|
|
353266
|
+
});
|
|
353267
|
+
}
|
|
353268
|
+
enqueueNext(target, input2) {
|
|
353269
|
+
const runtime = this.findRuntime(target);
|
|
353270
|
+
if (!runtime?.activePromise || !runtime.runId) throw new Error("Target conversation is not running");
|
|
353271
|
+
const id = String(input2.id || "").trim().slice(0, 200);
|
|
353272
|
+
const text = String(input2.text || "").trim();
|
|
353273
|
+
if (!id || !text) throw new Error("Queue item id and text are required");
|
|
353274
|
+
const existing = this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353275
|
+
if (existing) return existing;
|
|
353276
|
+
const prompt = `[Next queued while current turn is running]
|
|
353277
|
+
${text}`;
|
|
353278
|
+
const createdAt = String(input2.createdAt || (/* @__PURE__ */ new Date()).toISOString());
|
|
353279
|
+
runtime.pendingNextTurn.push({
|
|
353280
|
+
message: {
|
|
353281
|
+
text: prompt,
|
|
353282
|
+
visibleUserInput: text,
|
|
353283
|
+
visibleMode: String(input2.requestedMode || "build"),
|
|
353284
|
+
goalObjective: String(input2.goalObjective || "") || void 0,
|
|
353285
|
+
clientMessageId: id,
|
|
353286
|
+
runId: runtime.runId,
|
|
353287
|
+
createdAt
|
|
353288
|
+
},
|
|
353289
|
+
queueMode: "followUp"
|
|
353290
|
+
});
|
|
353291
|
+
runtime.runner.retainConversationContinuations([{
|
|
353292
|
+
content: prompt,
|
|
353293
|
+
queueMode: "followUp",
|
|
353294
|
+
clientMessageId: id,
|
|
353295
|
+
runId: runtime.runId,
|
|
353296
|
+
createdAt
|
|
353297
|
+
}]);
|
|
353298
|
+
this.trackQueuedMessage(runtime, prompt, "followUp");
|
|
353299
|
+
this.emitQueueUpdate(runtime);
|
|
353300
|
+
return this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353301
|
+
}
|
|
353302
|
+
updateQueueItem(target, idInput, textInput) {
|
|
353303
|
+
const runtime = this.findRuntime(target);
|
|
353304
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353305
|
+
const id = String(idInput || "").trim();
|
|
353306
|
+
const text = String(textInput || "").trim();
|
|
353307
|
+
if (!id || !text) throw new Error("Queue item id and text are required");
|
|
353308
|
+
const pending3 = runtime.pendingNextTurn.find((item) => typeof item.message !== "string" && item.message.clientMessageId === id);
|
|
353309
|
+
if (!pending3 || typeof pending3.message === "string") throw new Error("Queue item is no longer editable");
|
|
353310
|
+
const oldPrompt = pending3.message.text;
|
|
353311
|
+
pending3.message.text = `[Next queued while current turn is running]
|
|
353312
|
+
${text}`;
|
|
353313
|
+
pending3.message.visibleUserInput = text;
|
|
353314
|
+
runtime.runner.consumeConversationContinuation({ content: oldPrompt, queueMode: pending3.queueMode, clientMessageId: id });
|
|
353315
|
+
runtime.runner.retainConversationContinuations([{
|
|
353316
|
+
content: pending3.message.text,
|
|
353317
|
+
queueMode: pending3.queueMode,
|
|
353318
|
+
clientMessageId: id,
|
|
353319
|
+
runId: pending3.message.runId
|
|
353320
|
+
}]);
|
|
353321
|
+
this.replaceTrackedQueuedMessage(runtime, oldPrompt, pending3.message.text, pending3.queueMode);
|
|
353322
|
+
this.emitQueueUpdate(runtime);
|
|
353323
|
+
return this.queueItems(runtime.target).find((item) => item.id === id);
|
|
353324
|
+
}
|
|
353325
|
+
deleteQueueItem(target, idInput) {
|
|
353326
|
+
const runtime = this.findRuntime(target);
|
|
353327
|
+
if (!runtime) return false;
|
|
353328
|
+
const id = String(idInput || "").trim();
|
|
353329
|
+
const index = runtime.pendingNextTurn.findIndex((item) => typeof item.message !== "string" && item.message.clientMessageId === id);
|
|
353330
|
+
if (index < 0) return false;
|
|
353331
|
+
const [removed] = runtime.pendingNextTurn.splice(index, 1);
|
|
353332
|
+
if (typeof removed.message !== "string") {
|
|
353333
|
+
runtime.runner.consumeConversationContinuation({ content: removed.message.text, queueMode: removed.queueMode, clientMessageId: id });
|
|
353334
|
+
this.consumeQueuedMessage(runtime, removed.message.text);
|
|
353335
|
+
}
|
|
353336
|
+
this.emitQueueUpdate(runtime);
|
|
353337
|
+
return true;
|
|
353338
|
+
}
|
|
353339
|
+
setQueuePaused(target, paused) {
|
|
353340
|
+
const runtime = this.findRuntime(target);
|
|
353341
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353342
|
+
runtime.queuePaused = paused;
|
|
353343
|
+
this.emitQueueUpdate(runtime);
|
|
353344
|
+
if (!paused && !runtime.activePromise && runtime.pendingNextTurn.length) {
|
|
353345
|
+
this.schedulePendingRuntimeContinuation(runtime, runtime.runId);
|
|
353346
|
+
}
|
|
353347
|
+
return runtime.queuePaused;
|
|
353348
|
+
}
|
|
353349
|
+
queueAction(target, action, input2 = {}) {
|
|
353350
|
+
const runtime = this.findRuntime(target);
|
|
353351
|
+
if (!runtime) throw new Error("Target conversation runtime is unavailable");
|
|
353352
|
+
let receipt;
|
|
353353
|
+
if (action === "enqueue") {
|
|
353354
|
+
this.enqueueNext(runtime.target, {
|
|
353355
|
+
id: String(input2.id || ""),
|
|
353356
|
+
text: String(input2.text || ""),
|
|
353357
|
+
requestedMode: input2.requestedMode,
|
|
353358
|
+
goalObjective: input2.goalObjective,
|
|
353359
|
+
createdAt: input2.createdAt
|
|
353360
|
+
});
|
|
353361
|
+
} else if (action === "update") {
|
|
353362
|
+
this.updateQueueItem(runtime.target, String(input2.id || ""), String(input2.text || ""));
|
|
353363
|
+
} else if (action === "delete") {
|
|
353364
|
+
if (!this.deleteQueueItem(runtime.target, String(input2.id || ""))) throw new Error("Queue item was not found");
|
|
353365
|
+
} else if (action === "toggle_pause") {
|
|
353366
|
+
this.setQueuePaused(runtime.target, !runtime.queuePaused);
|
|
353367
|
+
} else if (action === "guide") {
|
|
353368
|
+
const item = this.queueItems(runtime.target).find((entry) => entry.id === String(input2.id || ""));
|
|
353369
|
+
if (!item) throw new Error("Queue item was not found");
|
|
353370
|
+
receipt = this.enqueueGuide({
|
|
353371
|
+
clientMessageId: item.id,
|
|
353372
|
+
guideId: (0, import_crypto16.randomUUID)(),
|
|
353373
|
+
target: runtime.target,
|
|
353374
|
+
runId: runtime.runId,
|
|
353375
|
+
deliveryMode: "steer",
|
|
353376
|
+
text: item.goalObjective ? `Goal for the current Build:
|
|
353377
|
+
${item.goalObjective}` : item.text,
|
|
353378
|
+
goalObjective: item.goalObjective,
|
|
353379
|
+
createdAt: item.createdAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
353380
|
+
});
|
|
353381
|
+
if (receipt.status === "rejected") return {
|
|
353382
|
+
ok: false,
|
|
353383
|
+
queueItems: this.queueItems(runtime.target),
|
|
353384
|
+
queuePaused: runtime.queuePaused,
|
|
353385
|
+
queued: this.queued(runtime.target),
|
|
353386
|
+
receipt
|
|
353387
|
+
};
|
|
353388
|
+
this.deleteQueueItem(runtime.target, item.id);
|
|
353389
|
+
}
|
|
353390
|
+
return {
|
|
353391
|
+
ok: true,
|
|
353392
|
+
queueItems: this.queueItems(runtime.target),
|
|
353393
|
+
queuePaused: runtime.queuePaused,
|
|
353394
|
+
queued: this.queued(runtime.target),
|
|
353395
|
+
receipt
|
|
353396
|
+
};
|
|
353397
|
+
}
|
|
353029
353398
|
events(target) {
|
|
353030
353399
|
return this.findRuntime(target)?.events.slice() || [];
|
|
353031
353400
|
}
|
|
@@ -353054,6 +353423,8 @@ var ConversationKernel = class {
|
|
|
353054
353423
|
workRuns: this.bindWorkRunsToRuntimeTarget(conversationSnapshot.workRuns, normalized),
|
|
353055
353424
|
target: normalized,
|
|
353056
353425
|
queued: this.queued(normalized),
|
|
353426
|
+
queueItems: this.queueItems(normalized),
|
|
353427
|
+
queuePaused: runtime?.queuePaused === true,
|
|
353057
353428
|
workEvents: this.events(normalized),
|
|
353058
353429
|
runtime: this.runtimeState(normalized),
|
|
353059
353430
|
mode: runner.mode,
|
|
@@ -353489,7 +353860,7 @@ var ConversationKernel = class {
|
|
|
353489
353860
|
if (runtime.stopRequestedRunId === runId) {
|
|
353490
353861
|
stopped = true;
|
|
353491
353862
|
this.settleCooperativeStop(runtime, runId);
|
|
353492
|
-
} else if (runtime.pendingNextTurn.length > 0) {
|
|
353863
|
+
} else if (!runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353493
353864
|
this.schedulePendingRuntimeContinuation(runtime, runId);
|
|
353494
353865
|
}
|
|
353495
353866
|
}
|
|
@@ -353524,7 +353895,7 @@ var ConversationKernel = class {
|
|
|
353524
353895
|
return this.result(runtime, lastTokens);
|
|
353525
353896
|
}
|
|
353526
353897
|
for (; ; ) {
|
|
353527
|
-
while (runtime.pendingNextTurn.length > 0) {
|
|
353898
|
+
while (!runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353528
353899
|
if (runtime.stopRequestedRunId === runtime.runId) return this.result(runtime, lastTokens);
|
|
353529
353900
|
const next = runtime.pendingNextTurn.shift();
|
|
353530
353901
|
if (next.queueMode === "steer" && typeof next.message !== "string" && !!next.message.clientMessageId) {
|
|
@@ -353566,11 +353937,11 @@ ${batchText}`,
|
|
|
353566
353937
|
this.mirrorHostIfTargetActive(runtime);
|
|
353567
353938
|
return this.result(runtime, lastTokens);
|
|
353568
353939
|
}
|
|
353569
|
-
this.clearQueued(runtime);
|
|
353940
|
+
if (!runtime.pendingNextTurn.length) this.clearQueued(runtime);
|
|
353570
353941
|
const completedRunId = runtime.runId;
|
|
353571
353942
|
runtime.runner.finishConversationWorkRun(completedRunId, "completed");
|
|
353572
353943
|
await new Promise((resolve16) => setImmediate(resolve16));
|
|
353573
|
-
if (runtime.runId === completedRunId && runtime.stopRequestedRunId !== completedRunId && runtime.pendingNextTurn.length > 0) {
|
|
353944
|
+
if (runtime.runId === completedRunId && runtime.stopRequestedRunId !== completedRunId && !runtime.queuePaused && runtime.pendingNextTurn.length > 0) {
|
|
353574
353945
|
runtime.guideAcceptanceClosedRunId = "";
|
|
353575
353946
|
if (!runtime.runner.resumeConversationWorkRun(completedRunId)) {
|
|
353576
353947
|
throw new Error(`Unable to resume deferred Guide work run ${completedRunId}`);
|
|
@@ -353661,6 +354032,7 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
353661
354032
|
events: [],
|
|
353662
354033
|
pendingNextTurn: [],
|
|
353663
354034
|
queued: { steering: [], followUp: [] },
|
|
354035
|
+
queuePaused: false,
|
|
353664
354036
|
runId: "",
|
|
353665
354037
|
generation: this.generations.get(target.runtimeKey) || 0,
|
|
353666
354038
|
stopRequestedRunId: "",
|
|
@@ -353756,7 +354128,7 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
353756
354128
|
}
|
|
353757
354129
|
setImmediate(() => {
|
|
353758
354130
|
runtime.pendingContinuationRunId = void 0;
|
|
353759
|
-
if (runtime.runId !== runId || runtime.activePromise || runtime.stopRequestedRunId === runId) return;
|
|
354131
|
+
if (runtime.runId !== runId || runtime.activePromise || runtime.stopRequestedRunId === runId || runtime.queuePaused) return;
|
|
353760
354132
|
const next = runtime.pendingNextTurn.shift();
|
|
353761
354133
|
if (!next) return;
|
|
353762
354134
|
const message = typeof next.message === "string" ? { text: next.message, runId } : { ...next.message, runId: next.message.runId || runId };
|
|
@@ -353907,7 +354279,36 @@ Review this persisted peer result and summarize or continue the parent task as n
|
|
|
353907
354279
|
const text = typeof message === "string" ? message : message.text;
|
|
353908
354280
|
const prompt = isSteer ? text : `[Next queued while current turn is running]
|
|
353909
354281
|
${text}`;
|
|
353910
|
-
if (!isSteer)
|
|
354282
|
+
if (!isSteer) {
|
|
354283
|
+
const structured = typeof message === "string" ? null : message;
|
|
354284
|
+
const clientMessageId = String(structured?.clientMessageId || (0, import_crypto16.randomUUID)());
|
|
354285
|
+
const queuedMessage = {
|
|
354286
|
+
...structured || {},
|
|
354287
|
+
text: prompt,
|
|
354288
|
+
visibleUserInput: structured?.visibleUserInput || text,
|
|
354289
|
+
visibleMode: structured?.visibleMode || runtime.options.mode,
|
|
354290
|
+
clientMessageId,
|
|
354291
|
+
runId: structured?.runId || runtime.runId,
|
|
354292
|
+
createdAt: String(structured?.createdAt || (/* @__PURE__ */ new Date()).toISOString())
|
|
354293
|
+
};
|
|
354294
|
+
if (!runtime.pendingNextTurn.some((item) => typeof item.message !== "string" && item.message.clientMessageId === clientMessageId)) {
|
|
354295
|
+
runtime.pendingNextTurn.push({ message: queuedMessage, queueMode: "followUp" });
|
|
354296
|
+
}
|
|
354297
|
+
runtime.runner.retainConversationContinuations([{
|
|
354298
|
+
content: prompt,
|
|
354299
|
+
queueMode: "followUp",
|
|
354300
|
+
clientMessageId,
|
|
354301
|
+
runId: queuedMessage.runId,
|
|
354302
|
+
images: queuedMessage.images?.map((image) => ({ ...image })),
|
|
354303
|
+
attachments: queuedMessage.attachments?.map((attachment) => ({ ...attachment })),
|
|
354304
|
+
createdAt: queuedMessage.createdAt
|
|
354305
|
+
}]);
|
|
354306
|
+
this.trackQueuedMessage(runtime, prompt, "followUp");
|
|
354307
|
+
runtime.runner.recordWorkStatus(runtime.stopRequestedRunId === runtime.runId ? "Next message retained while stopping." : "Next message queued.");
|
|
354308
|
+
if (runtime.stopRequestedRunId === runtime.runId) runtime.forceStopArmedRunId = "";
|
|
354309
|
+
this.emitQueueUpdate(runtime);
|
|
354310
|
+
return;
|
|
354311
|
+
}
|
|
353911
354312
|
if (runtime.stopRequestedRunId === runtime.runId) {
|
|
353912
354313
|
runtime.forceStopArmedRunId = "";
|
|
353913
354314
|
const structured = typeof message === "string" ? void 0 : message;
|
|
@@ -353953,6 +354354,12 @@ ${text}`;
|
|
|
353953
354354
|
}
|
|
353954
354355
|
if (changed) this.emitQueueUpdate(runtime);
|
|
353955
354356
|
}
|
|
354357
|
+
replaceTrackedQueuedMessage(runtime, oldMessage, nextMessage, queueMode) {
|
|
354358
|
+
this.queueState(runtime);
|
|
354359
|
+
const list = queueMode === "steer" ? runtime.queued.steering : runtime.queued.followUp;
|
|
354360
|
+
const index = list.indexOf(oldMessage);
|
|
354361
|
+
if (index >= 0) list[index] = nextMessage;
|
|
354362
|
+
}
|
|
353956
354363
|
emitQueueUpdate(runtime) {
|
|
353957
354364
|
this.queueState(runtime);
|
|
353958
354365
|
runtime.runner.emitWorkEvent({
|
|
@@ -354074,9 +354481,10 @@ ${text}`;
|
|
|
354074
354481
|
const runId = runtime.runId;
|
|
354075
354482
|
await Promise.resolve();
|
|
354076
354483
|
if (runtime.runId !== runId || runtime.stopRequestedRunId === runId) return true;
|
|
354077
|
-
|
|
354484
|
+
const hasSteering = runtime.pendingNextTurn.some((item) => item.queueMode === "steer");
|
|
354485
|
+
if (hasSteering || runtime.runner.subagents.readRootInbox().length > 0) return false;
|
|
354078
354486
|
runtime.guideAcceptanceClosedRunId = runId;
|
|
354079
|
-
if (runtime.pendingNextTurn.
|
|
354487
|
+
if (runtime.pendingNextTurn.some((item) => item.queueMode === "steer") || runtime.runner.subagents.readRootInbox().length > 0) {
|
|
354080
354488
|
runtime.guideAcceptanceClosedRunId = "";
|
|
354081
354489
|
return false;
|
|
354082
354490
|
}
|
|
@@ -354287,6 +354695,9 @@ async function handle(request) {
|
|
|
354287
354695
|
target
|
|
354288
354696
|
});
|
|
354289
354697
|
}
|
|
354698
|
+
if (request.method === "queue_action") {
|
|
354699
|
+
return kernel.queueAction(requestTarget(request.params), request.params.action, request.params.input);
|
|
354700
|
+
}
|
|
354290
354701
|
if (request.method === "checkpoint") return kernel.checkpoint(requestTarget(request.params));
|
|
354291
354702
|
if (request.method === "context_compress") {
|
|
354292
354703
|
return kernel.compressContext(requestTarget(request.params), request.params.options);
|