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
|
@@ -35,8 +35,10 @@ function inferDomain(name) {
|
|
|
35
35
|
return 'interaction';
|
|
36
36
|
if (name === 'skill')
|
|
37
37
|
return 'skills';
|
|
38
|
-
if (name === 'task')
|
|
38
|
+
if (name === 'task' || name === 'subagent_create' || name === 'SubAgent')
|
|
39
39
|
return 'subagent';
|
|
40
|
+
if (/^task_(read|create)$/.test(name))
|
|
41
|
+
return 'plan';
|
|
40
42
|
if (/^(linked_plan|build_history_query)$/.test(name))
|
|
41
43
|
return 'plan';
|
|
42
44
|
return 'general';
|
package/dist/tools/index.js
CHANGED
|
@@ -294,6 +294,13 @@ class ToolExecutor {
|
|
|
294
294
|
max_refs: { type: 'number' },
|
|
295
295
|
attribute: { type: 'string' },
|
|
296
296
|
}, ['action']),
|
|
297
|
+
t('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.', {
|
|
298
|
+
target: { type: 'string', enum: ['desktop', 'application'], description: 'Capture the whole desktop or one visible application. Defaults to desktop.' },
|
|
299
|
+
app_target: { type: 'string', description: 'For target=application: application title, process name, process id, or window handle.' },
|
|
300
|
+
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.' },
|
|
301
|
+
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.' },
|
|
302
|
+
max_chars: { type: 'number', minimum: 1000, maximum: 100000, description: 'Maximum returned semantic UI text characters.' },
|
|
303
|
+
}, []),
|
|
297
304
|
t('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.', {
|
|
298
305
|
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'] },
|
|
299
306
|
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.' },
|
|
@@ -379,7 +386,7 @@ class ToolExecutor {
|
|
|
379
386
|
remote_root: { type: 'string' },
|
|
380
387
|
remote_path: { type: 'string' },
|
|
381
388
|
}, ['action']),
|
|
382
|
-
t('
|
|
389
|
+
t('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']),
|
|
383
390
|
t('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'] } }, []),
|
|
384
391
|
t('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.' } }, []),
|
|
385
392
|
t('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' } }, []),
|
|
@@ -559,7 +566,11 @@ class ToolExecutor {
|
|
|
559
566
|
return (0, compat_1.normalizeToolResult)(output, { tool, workspacePath: wsPath, mode: context.mode || '' });
|
|
560
567
|
}
|
|
561
568
|
validateInvocation(tool, argsStr, _mode = '', inputSchema) {
|
|
562
|
-
|
|
569
|
+
// Persisted work history may replay the old create aliases. They share the
|
|
570
|
+
// public SubAgent schema and enablement, but are never advertised back to
|
|
571
|
+
// the model as independent tools.
|
|
572
|
+
const schemaTool = tool === 'task' || tool === 'subagent_create' ? 'SubAgent' : tool;
|
|
573
|
+
if (inputSchema === undefined && !(0, nativeTools_1.isNativeToolEnabled)(schemaTool, this.config.nativeToolEnabled())) {
|
|
563
574
|
return { ok: false, error: `[tool disabled] ${tool} is disabled in Settings > Tools.` };
|
|
564
575
|
}
|
|
565
576
|
let parsed;
|
|
@@ -591,12 +602,12 @@ class ToolExecutor {
|
|
|
591
602
|
// catalogs may advertise a narrower enum, but a structurally valid
|
|
592
603
|
// hidden call must reach evaluateToolPolicy so it is classified as a
|
|
593
604
|
// policy denial rather than a misleading schema failure.
|
|
594
|
-
? this.definitions().find(candidate => candidate.function?.name ===
|
|
605
|
+
? this.definitions().find(candidate => candidate.function?.name === schemaTool)
|
|
595
606
|
: { function: { name: tool, parameters: inputSchema } };
|
|
596
607
|
if (!definition) {
|
|
597
608
|
return { ok: false, error: `[tool unsupported] ${tool || '(missing tool)'} is not available for the ${this.hostProfile.kind} host on ${this.hostProfile.platform}.` };
|
|
598
609
|
}
|
|
599
|
-
const validation = this.argumentValidators.validate(
|
|
610
|
+
const validation = this.argumentValidators.validate(schemaTool, definition.function.parameters, args);
|
|
600
611
|
return validation.ok ? { ok: true, args } : { ok: false, error: `[tool schema error] ${validation.error}` };
|
|
601
612
|
}
|
|
602
613
|
async execute(tool, argsStr, wsPath, context = {}) {
|
|
@@ -786,6 +797,44 @@ class ToolExecutor {
|
|
|
786
797
|
result: parsed,
|
|
787
798
|
}, null, 2);
|
|
788
799
|
}
|
|
800
|
+
case 'screen_capture': {
|
|
801
|
+
const target = g('target').toLowerCase() === 'application' ? 'application' : 'desktop';
|
|
802
|
+
if (process.env.NEWMARK_WSL_DISTRO) {
|
|
803
|
+
const result = await (0, wslHostToolBridge_1.requestWindowsHostTool)('screen_capture', args, {
|
|
804
|
+
conversationId: context.conversationId || 'default',
|
|
805
|
+
workspaceId: context.workspaceId || (0, terminalTakeover_1.terminalTakeoverWorkspaceId)(context.workspacePath || wsPath),
|
|
806
|
+
actorId: context.actorId || terminalTakeover_1.ROOT_TERMINAL_ACTOR_ID,
|
|
807
|
+
runtimeKey: browserUseScope(context, wsPath).runtimeKey,
|
|
808
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
809
|
+
mode: context.mode || 'build',
|
|
810
|
+
}, 120_000, context.signal);
|
|
811
|
+
return typeof result === 'string' ? result : JSON.stringify(result);
|
|
812
|
+
}
|
|
813
|
+
if (process.env.NEWMARK_ISOLATED_RUNTIME === '1') {
|
|
814
|
+
const result = await (0, utilityHostToolBridge_1.requestUtilityHostTool)('screen_capture', args, {
|
|
815
|
+
conversationId: context.conversationId || 'default',
|
|
816
|
+
workspaceId: context.workspaceId || (0, terminalTakeover_1.terminalTakeoverWorkspaceId)(context.workspacePath || wsPath),
|
|
817
|
+
actorId: context.actorId || terminalTakeover_1.ROOT_TERMINAL_ACTOR_ID,
|
|
818
|
+
workspacePath: context.workspacePath || wsPath,
|
|
819
|
+
backend: 'utility',
|
|
820
|
+
mode: context.mode || 'build',
|
|
821
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
822
|
+
}, 120_000, context.signal);
|
|
823
|
+
return typeof result === 'string' ? result : JSON.stringify(result);
|
|
824
|
+
}
|
|
825
|
+
return await (0, computerUse_1.runComputerUse)({
|
|
826
|
+
action: target === 'application' ? 'app_observe' : 'observe',
|
|
827
|
+
appTarget: g('app_target'),
|
|
828
|
+
windowHandle: target === 'application' ? g('app_target') : '',
|
|
829
|
+
maxChars: Number(args.max_chars || 30000),
|
|
830
|
+
workspacePath: wsPath,
|
|
831
|
+
allowEphemeralVisionImage: context.allowEphemeralVisionImage === true,
|
|
832
|
+
captureMaxWidth: Number(args.capture_max_width),
|
|
833
|
+
captureMaxHeight: Number(args.capture_max_height),
|
|
834
|
+
invocation: context.invocation,
|
|
835
|
+
ownerId: `screen-capture:${computerUseOwner(context, wsPath)}:${String(context.actorId || 'root')}`,
|
|
836
|
+
});
|
|
837
|
+
}
|
|
789
838
|
case 'computer_use': {
|
|
790
839
|
const action = normalizeComputerUseAction(g('action'));
|
|
791
840
|
const owner = `${computerUseOwner(context, wsPath)}:${String(context.actorId || 'root')}`;
|
|
@@ -918,7 +967,9 @@ class ToolExecutor {
|
|
|
918
967
|
});
|
|
919
968
|
}
|
|
920
969
|
case 'ssh_workspace': return await this.sshWorkspace(args, wsPath, context.signal);
|
|
921
|
-
case 'task':
|
|
970
|
+
case 'task':
|
|
971
|
+
case 'subagent_create':
|
|
972
|
+
case 'SubAgent': return `[SubAgent] SubAgent request accepted: ${g('name')}`;
|
|
922
973
|
case 'subagent_send': return `[subagent_send] Routed to Agent runtime: ${g('name')}`;
|
|
923
974
|
case 'subagent_read': return `[subagent_read] Routed to Agent runtime: ${g('name') || g('id')}`;
|
|
924
975
|
case 'subagent_result': return `[subagent_result] Routed to Agent runtime: ${g('name')}`;
|
|
@@ -970,7 +1021,7 @@ class ToolExecutor {
|
|
|
970
1021
|
hostSupportsTool(name) {
|
|
971
1022
|
if (name.startsWith('browser_') && !this.hostProfile.electronBrowser)
|
|
972
1023
|
return false;
|
|
973
|
-
if (name === 'computer_use' && !this.hostProfile.windowsComputerUse)
|
|
1024
|
+
if ((name === 'computer_use' || name === 'screen_capture') && !this.hostProfile.windowsComputerUse)
|
|
974
1025
|
return false;
|
|
975
1026
|
return true;
|
|
976
1027
|
}
|
|
@@ -26,6 +26,7 @@ exports.NATIVE_TOOL_CATALOG = [
|
|
|
26
26
|
{ name: 'browser_reload', label: 'Browser reload', description: 'Reload the built-in browser.', category: 'browser', defaultEnabled: true },
|
|
27
27
|
{ name: 'browser_cdp', label: 'Browser CDP', description: 'Run an advanced Chrome DevTools Protocol command.', category: 'browser', defaultEnabled: true },
|
|
28
28
|
{ 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 },
|
|
29
|
+
{ 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' },
|
|
29
30
|
{ name: 'computer_use', label: 'Computer Use', description: 'Observe and control Windows desktop UI with screenshots and semantic objects.', category: 'desktop', defaultEnabled: true },
|
|
30
31
|
{ 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' },
|
|
31
32
|
{ 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' },
|
|
@@ -33,7 +34,7 @@ exports.NATIVE_TOOL_CATALOG = [
|
|
|
33
34
|
{ 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' },
|
|
34
35
|
{ name: 'terminal_takeover', label: 'Terminal takeover', description: 'Maintain a persistent Agent-controlled shell session.', category: 'desktop', defaultEnabled: true },
|
|
35
36
|
{ name: 'ssh_workspace', label: 'OpenSSH workspace', description: 'Manage native OpenSSH connections and link remote workspaces by PC_Hash.', category: 'ssh', defaultEnabled: true },
|
|
36
|
-
{ name: '
|
|
37
|
+
{ name: 'SubAgent', label: 'SubAgent', description: 'Create one real same-conversation peer SubAgent.', category: 'agent', defaultEnabled: true, protected: true, availability: 'mode-scoped' },
|
|
37
38
|
{ name: 'subagent_list', label: 'Subagent list', description: 'List same-conversation peer agents.', category: 'agent', defaultEnabled: true, protected: true, availability: 'mode-scoped' },
|
|
38
39
|
{ 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' },
|
|
39
40
|
{ name: 'subagent_send', label: 'Subagent send', description: 'Persist a message to a peer mailbox.', category: 'agent', defaultEnabled: true, protected: true, availability: 'mode-scoped' },
|
package/dist/ui/index.html
CHANGED
|
@@ -428,38 +428,15 @@ button:focus, select:focus, input:focus, textarea:focus, [contenteditable]:focus
|
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
#topbar .logo {
|
|
431
|
-
position: relative;
|
|
432
431
|
display: inline-flex;
|
|
433
432
|
width: 26px;
|
|
434
433
|
height: 26px;
|
|
435
|
-
padding: 1px;
|
|
436
|
-
border-radius: 8px;
|
|
437
434
|
align-items: center;
|
|
438
435
|
justify-content: center;
|
|
439
|
-
overflow: hidden;
|
|
440
|
-
box-shadow: 0 0 12px var(--accent-glow);
|
|
441
436
|
flex-shrink: 0;
|
|
442
437
|
}
|
|
443
438
|
|
|
444
|
-
#topbar .logo::before {
|
|
445
|
-
content: "";
|
|
446
|
-
position: absolute;
|
|
447
|
-
inset: calc(-2 * var(--marquee-width));
|
|
448
|
-
background: conic-gradient(from var(--marquee-angle, 0deg), var(--g1), var(--g2), var(--g3), var(--g4), var(--g1));
|
|
449
|
-
animation: marquee-rotate var(--marquee-speed) linear infinite;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
#topbar .logo::after {
|
|
453
|
-
content: "";
|
|
454
|
-
position: absolute;
|
|
455
|
-
inset: 2px;
|
|
456
|
-
border-radius: 7px;
|
|
457
|
-
background: var(--bg2);
|
|
458
|
-
}
|
|
459
|
-
|
|
460
439
|
#topbar .logo img {
|
|
461
|
-
position: relative;
|
|
462
|
-
z-index: 1;
|
|
463
440
|
display: block;
|
|
464
441
|
width: 22px;
|
|
465
442
|
height: 22px;
|
|
@@ -3832,11 +3809,15 @@ button.todo-item { background: transparent; }
|
|
|
3832
3809
|
linear-gradient(#fff 0 0) content-box,
|
|
3833
3810
|
linear-gradient(#fff 0 0);
|
|
3834
3811
|
mask-composite: exclude;
|
|
3835
|
-
|
|
3812
|
+
/* A masked conic-gradient whose custom angle changes every frame forces a
|
|
3813
|
+
full GPU repaint. Several simultaneous Agent/SubAgent surfaces made that
|
|
3814
|
+
repaint saturate the renderer and GPU, starving ordinary text input. Keep
|
|
3815
|
+
the shared status border visually present, but static; live progress is
|
|
3816
|
+
already communicated by status text, duration, and event updates. */
|
|
3817
|
+
animation: none;
|
|
3836
3818
|
z-index: -1;
|
|
3837
3819
|
pointer-events: none;
|
|
3838
3820
|
transform: translateZ(0);
|
|
3839
|
-
will-change: transform;
|
|
3840
3821
|
}
|
|
3841
3822
|
|
|
3842
3823
|
@supports not (background: conic-gradient(from 0deg, red, blue)) {
|
|
@@ -3844,11 +3825,11 @@ button.todo-item { background: transparent; }
|
|
|
3844
3825
|
background: linear-gradient(var(--marquee-angle, 0deg), var(--g1), var(--g2), var(--g3), var(--g4), var(--g1));
|
|
3845
3826
|
}
|
|
3846
3827
|
@keyframes marquee-rotate-fallback { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } }
|
|
3847
|
-
.marquee-border::before { animation:
|
|
3828
|
+
.marquee-border::before { animation: none; }
|
|
3848
3829
|
}
|
|
3849
3830
|
|
|
3850
3831
|
.working-glow {
|
|
3851
|
-
animation:
|
|
3832
|
+
animation: none;
|
|
3852
3833
|
box-shadow: 0 0 16px var(--accent-glow), 0 0 40px rgba(91,120,255,0.1);
|
|
3853
3834
|
border-color: rgba(91,120,255,0.4) !important;
|
|
3854
3835
|
}
|
|
@@ -5833,7 +5814,7 @@ html.newmark-memory-overview-viewer body {
|
|
|
5833
5814
|
<div id="topbar">
|
|
5834
5815
|
<span class="title" id="title-text">
|
|
5835
5816
|
<span class="logo" id="title-app-logo">
|
|
5836
|
-
<img id="title-app-icon" src="../assets/app-icon-dark
|
|
5817
|
+
<img id="title-app-icon" src="../assets/app-icon-dark.svg" alt="" aria-hidden="true">
|
|
5837
5818
|
</span>
|
|
5838
5819
|
Newmark Agent
|
|
5839
5820
|
</span>
|
|
@@ -6502,10 +6483,10 @@ var NEWMARK_I18N = {
|
|
|
6502
6483
|
'settings.runInWsl': 'Agent runtime environment',
|
|
6503
6484
|
'settings.runInWslDesc': 'Keeps the Windows UI and native desktop tools local while running the persistent Agent kernel, model calls, shell, and file tools inside WSL.',
|
|
6504
6485
|
'settings.remoteTouch': 'Mobile remote-touch',
|
|
6505
|
-
'settings.remoteTouchDesc': 'Allow
|
|
6486
|
+
'settings.remoteTouchDesc': 'Allow mobile access on the same LAN / Tailscale network',
|
|
6506
6487
|
'settings.remoteBehavior': 'Remote behavior',
|
|
6507
6488
|
'settings.remoteConnect': 'Start connection',
|
|
6508
|
-
'settings.remoteConnectDesc': 'Show
|
|
6489
|
+
'settings.remoteConnectDesc': 'Show pairing QR',
|
|
6509
6490
|
'settings.wslDistro': 'WSL distribution',
|
|
6510
6491
|
'settings.wslConnected': 'WSL backend connected',
|
|
6511
6492
|
'settings.wslDisconnected': 'WSL backend unavailable',
|
|
@@ -7030,7 +7011,7 @@ var NEWMARK_I18N = {
|
|
|
7030
7011
|
'option.manualPlaceholder': 'Or type your own answer...',
|
|
7031
7012
|
'option.manualSubmit': 'Submit',
|
|
7032
7013
|
'mobile.pair': 'Pair mobile device',
|
|
7033
|
-
'mobile.pairDesc': 'Scan this QR code with the Newmark mobile app
|
|
7014
|
+
'mobile.pairDesc': 'Scan this QR code with the Newmark mobile app on the same LAN / Tailscale network. The pairing token is saved after the first bind.',
|
|
7034
7015
|
'mobile.pairTokenFile': 'Token file',
|
|
7035
7016
|
'subagent.empty': 'No retained subagent records',
|
|
7036
7017
|
'subagent.openHistory': 'Open subagent history',
|
|
@@ -7229,10 +7210,10 @@ var NEWMARK_I18N = {
|
|
|
7229
7210
|
'settings.runInWsl': 'Agent 运行环境',
|
|
7230
7211
|
'settings.runInWslDesc': 'Windows UI 与桌面原生工具保留在本机,持续 Agent 内核、模型请求、Shell 和文件工具运行在 WSL。',
|
|
7231
7212
|
'settings.remoteTouch': '移动端远程触及',
|
|
7232
|
-
'settings.remoteTouchDesc': '
|
|
7213
|
+
'settings.remoteTouchDesc': '允许移动端通过同一内网 / Tailscale 连接',
|
|
7233
7214
|
'settings.remoteBehavior': '远程行为',
|
|
7234
7215
|
'settings.remoteConnect': '发起连接',
|
|
7235
|
-
'settings.remoteConnectDesc': '
|
|
7216
|
+
'settings.remoteConnectDesc': '显示配对二维码',
|
|
7236
7217
|
'settings.wslDistro': 'WSL 发行版',
|
|
7237
7218
|
'settings.wslConnected': 'WSL 后端已连接',
|
|
7238
7219
|
'settings.wslDisconnected': 'WSL 后端不可用',
|
|
@@ -7757,7 +7738,7 @@ var NEWMARK_I18N = {
|
|
|
7757
7738
|
'option.manualPlaceholder': '或输入自己的答案...',
|
|
7758
7739
|
'option.manualSubmit': '提交',
|
|
7759
7740
|
'mobile.pair': '配对移动设备',
|
|
7760
|
-
'mobile.pairDesc': '使用 Newmark
|
|
7741
|
+
'mobile.pairDesc': '使用 Newmark 移动端在同一内网 / Tailscale 网络下扫描二维码。首次绑定后保存配对令牌。',
|
|
7761
7742
|
'mobile.pairTokenFile': '令牌文件',
|
|
7762
7743
|
'subagent.empty': '暂无保留的 subagent 记录',
|
|
7763
7744
|
'subagent.openHistory': '打开 subagent 历史',
|
|
@@ -10172,7 +10153,7 @@ function workEventIcon(type) {
|
|
|
10172
10153
|
|
|
10173
10154
|
function workToolActivity(event) {
|
|
10174
10155
|
var name = publicToolNameForUi(event && event.toolName).toLowerCase();
|
|
10175
|
-
if (name
|
|
10156
|
+
if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) return { key: 'subagents', type: 'tool_subagent' };
|
|
10176
10157
|
if (name === 'skill' || name === 'skill_load' || name === 'skill_read' || name === 'skill_download') return { key: 'skills', type: 'tool_skill' };
|
|
10177
10158
|
if (name === 'mcp' || name.indexOf('mcp__') === 0 || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) return { key: 'mcp', type: 'tool_mcp' };
|
|
10178
10159
|
if (name === 'context_compression' || name === 'context_compress' || name === 'context_history_manage') return { key: 'context_compression', type: 'tool_context_compression' };
|
|
@@ -10213,8 +10194,8 @@ function workToolCommandLabel(item) {
|
|
|
10213
10194
|
var args = workToolArgsObject(item);
|
|
10214
10195
|
var toolName = publicToolNameForUi(item && item.toolName);
|
|
10215
10196
|
var normalizedName = toolName.toLowerCase();
|
|
10216
|
-
if (normalizedName
|
|
10217
|
-
return (currentLang() === 'zh' ? '调用 Subagent · ' : 'Called Subagent · ') + String(args.
|
|
10197
|
+
if (isSubagentCreateToolName(normalizedName)) {
|
|
10198
|
+
return (currentLang() === 'zh' ? '调用 Subagent · ' : 'Called Subagent · ') + String(args.name || args.nature || args.agent || 'Subagent').trim();
|
|
10218
10199
|
}
|
|
10219
10200
|
if (normalizedName.indexOf('subagent_') === 0) {
|
|
10220
10201
|
return (currentLang() === 'zh' ? 'Subagent 操作 · ' : 'Subagent action · ') + String(args.name || args.id || normalizedName.replace(/^subagent_/, '')).trim();
|
|
@@ -10253,14 +10234,19 @@ function workToolCommandLabel(item) {
|
|
|
10253
10234
|
|
|
10254
10235
|
function workToolRowIcon(item) {
|
|
10255
10236
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10256
|
-
if (name
|
|
10237
|
+
if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) return 'bot';
|
|
10257
10238
|
if (name === 'skill' || name === 'skill_download') return 'sparkles';
|
|
10258
10239
|
if (name === 'mcp' || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) return 'plug';
|
|
10259
10240
|
return 'square-terminal';
|
|
10260
10241
|
}
|
|
10261
10242
|
|
|
10262
|
-
function
|
|
10243
|
+
function isSubagentCreateToolName(name) {
|
|
10263
10244
|
var normalized = String(name || '').trim().toLowerCase();
|
|
10245
|
+
return normalized === 'subagent' || normalized === 'subagent_create' || normalized === 'task';
|
|
10246
|
+
}
|
|
10247
|
+
|
|
10248
|
+
function findSubagentUiRecord(identity) {
|
|
10249
|
+
var normalized = String(identity || '').trim().toLowerCase();
|
|
10264
10250
|
return (state.subagents || []).find(function(item) {
|
|
10265
10251
|
return [item.id, item.name, item.displayName, item.qualifiedName].some(function(value) {
|
|
10266
10252
|
var candidate = String(value || '').trim().toLowerCase();
|
|
@@ -10304,7 +10290,7 @@ function workToolGroupLabel(items, completed) {
|
|
|
10304
10290
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10305
10291
|
if (name === 'skill' || name === 'skill_load' || name === 'skill_read' || name === 'skill_download') skills.push(workToolCommandLabel(item));
|
|
10306
10292
|
else if (name === 'mcp' || name.indexOf('mcp__') === 0 || /^mcp[:._-]/.test(name) || /[:._-]mcp[:._-]/.test(name)) mcps.push(workToolCommandLabel(item));
|
|
10307
|
-
else if (name
|
|
10293
|
+
else if (isSubagentCreateToolName(name) || name.indexOf('subagent_') === 0) subagents.push(workToolCommandLabel(item));
|
|
10308
10294
|
});
|
|
10309
10295
|
var commands = Math.max(0, (items || []).length - files - skills.length - mcps.length - subagents.length);
|
|
10310
10296
|
var parts = [];
|
|
@@ -10337,24 +10323,8 @@ function renderWorkToolGroup(event, eventIndex) {
|
|
|
10337
10323
|
var hasFiles = items.some(function(item) { return !!workToolEditedFile(item); });
|
|
10338
10324
|
var onlySubagents = items.length > 0 && items.every(function(item) {
|
|
10339
10325
|
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10340
|
-
return name
|
|
10326
|
+
return isSubagentCreateToolName(name);
|
|
10341
10327
|
});
|
|
10342
|
-
// A Build Block that spawns several SubAgents is summarized as one chip
|
|
10343
|
-
// ("operated N SubAgents") instead of flooding the block with one chip per
|
|
10344
|
-
// SubAgent. Each name stays available in the tooltip.
|
|
10345
|
-
var subagentTasks = items.map(function(item, itemIndex) {
|
|
10346
|
-
var name = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10347
|
-
if (name !== 'task') return null;
|
|
10348
|
-
var subagentArgs = workToolArgsObject(item);
|
|
10349
|
-
var subagentName = String(subagentArgs.nature || subagentArgs.name || subagentArgs.agent || 'Subagent').trim();
|
|
10350
|
-
var subagentRecord = findSubagentUiRecord(subagentName);
|
|
10351
|
-
return {
|
|
10352
|
-
key: String(item.id || item.toolCallId || ('task-' + itemIndex)),
|
|
10353
|
-
subagentName: subagentName || 'Subagent',
|
|
10354
|
-
status: String(subagentRecord && subagentRecord.status || 'accepted'),
|
|
10355
|
-
};
|
|
10356
|
-
}).filter(Boolean);
|
|
10357
|
-
var collapseSubagents = subagentTasks.length > 1;
|
|
10358
10328
|
var activityRows = items.map(function(item, itemIndex) {
|
|
10359
10329
|
var edited = workToolEditedFile(item);
|
|
10360
10330
|
if (edited) {
|
|
@@ -10367,26 +10337,22 @@ function renderWorkToolGroup(event, eventIndex) {
|
|
|
10367
10337
|
'<div class="conversation-work-file-diff">' + renderWorkFileDiff(edited) + '</div></details>';
|
|
10368
10338
|
}
|
|
10369
10339
|
var toolName = publicToolNameForUi(item && item.toolName).toLowerCase();
|
|
10370
|
-
if (toolName
|
|
10371
|
-
if (collapseSubagents) return '';
|
|
10340
|
+
if (isSubagentCreateToolName(toolName)) {
|
|
10372
10341
|
var subagentArgs = workToolArgsObject(item);
|
|
10373
|
-
var
|
|
10374
|
-
var subagentRecord = findSubagentUiRecord(
|
|
10375
|
-
|
|
10376
|
-
|
|
10377
|
-
|
|
10342
|
+
var requestedName = String(subagentArgs.name || subagentArgs.nature || subagentArgs.agent || 'Subagent').trim();
|
|
10343
|
+
var subagentRecord = findSubagentUiRecord(requestedName);
|
|
10344
|
+
if (!subagentRecord || !subagentRecord.id) {
|
|
10345
|
+
return '<div class="conversation-work-activity-item">' + iconSvg('square-terminal', 'tool', 'tiny') +
|
|
10346
|
+
'<div><div class="conversation-work-command-label" title="' + escAttr(workToolCommandLabel(item)) + '">' + esc(workToolCommandLabel(item)) + '</div></div></div>';
|
|
10347
|
+
}
|
|
10348
|
+
var subagentStatus = String(subagentRecord.status || 'accepted');
|
|
10349
|
+
var createdName = String(subagentRecord.name || subagentRecord.displayName || 'Subagent');
|
|
10350
|
+
return '<button type="button" class="conversation-work-subagent-chip' + (subagentStatus === 'completed' ? ' completed' : '') + '" data-subagent-id="' + escAttr(subagentRecord.id) + '" onclick="window.openSubagentFromBuild(this.getAttribute(\'data-subagent-id\'))" title="' + escAttr(currentLang() === 'zh' ? '查看 Subagent 工作情况' : 'View Subagent work') + '">' +
|
|
10351
|
+
iconSvg('bot', 'Subagent', 'tiny') + '<span class="conversation-work-subagent-name">' + esc(createdName) + '</span><span class="conversation-work-subagent-status">' + esc(subagentUiStatusLabel(subagentStatus)) + '</span></button>';
|
|
10378
10352
|
}
|
|
10379
10353
|
return '<div class="conversation-work-activity-item">' + iconSvg(workToolRowIcon(item), 'tool', 'tiny') +
|
|
10380
10354
|
'<div><div class="conversation-work-command-label" title="' + escAttr(workToolCommandLabel(item)) + '">' + esc(workToolCommandLabel(item)) + '</div>' + renderWorkDisplayImage(item.displayImage) + '</div></div>';
|
|
10381
10355
|
}).join('');
|
|
10382
|
-
if (collapseSubagents) {
|
|
10383
|
-
var allCompleted = subagentTasks.every(function(task) { return task.status === 'completed'; });
|
|
10384
|
-
var names = subagentTasks.map(function(task) { return task.subagentName; });
|
|
10385
|
-
activityRows += '<button type="button" class="conversation-work-subagent-chip conversation-work-subagent-chip-multi' + (allCompleted ? ' completed' : '') + '" title="' + escAttr(names.join(',')) + '">' +
|
|
10386
|
-
iconSvg('bot', 'Subagent', 'tiny') + '<span class="conversation-work-subagent-name">' +
|
|
10387
|
-
esc(currentLang() === 'zh' ? '操作了 ' + subagentTasks.length + ' 个 SubAgent' : 'Operated ' + subagentTasks.length + ' SubAgents') +
|
|
10388
|
-
'</span><span class="conversation-work-subagent-status">' + esc(subagentUiStatusLabel(allCompleted ? 'completed' : subagentTasks[0].status)) + '</span></button>';
|
|
10389
|
-
}
|
|
10390
10356
|
return '<details class="conversation-work-activity" data-activity-key="' + escAttr(activityDomKey) + '"><summary>' +
|
|
10391
10357
|
iconSvg(hasFiles ? 'pencil' : 'square-terminal', 'tools', 'tiny') + '<span>' + esc(workToolGroupLabel(items, !!event.completed)) + '</span>' +
|
|
10392
10358
|
'<span class="conversation-work-activity-chevron" aria-hidden="true"></span></summary><div class="conversation-work-activity-list' + (onlySubagents ? ' conversation-work-subagent-list' : '') + '">' +
|
|
@@ -10688,17 +10654,32 @@ function renderConversationWorkRuns(runs, target) {
|
|
|
10688
10654
|
// every delta can starve Chromium's renderer/CDP event loop.
|
|
10689
10655
|
var pendingConversationWorkRunRenders = {};
|
|
10690
10656
|
var scheduledConversationWorkRunRenders = {};
|
|
10657
|
+
var lastConversationWorkRunRenderAt = {};
|
|
10658
|
+
var WORK_RUN_RENDER_MIN_INTERVAL_MS = 100;
|
|
10659
|
+
function flushConversationWorkRunRender(key) {
|
|
10660
|
+
var latest = pendingConversationWorkRunRenders[key];
|
|
10661
|
+
delete pendingConversationWorkRunRenders[key];
|
|
10662
|
+
delete scheduledConversationWorkRunRenders[key];
|
|
10663
|
+
if (!latest || !isActiveConversationTarget(latest.target)) return;
|
|
10664
|
+
lastConversationWorkRunRenderAt[key] = performance.now();
|
|
10665
|
+
renderConversationWorkRun(latest);
|
|
10666
|
+
}
|
|
10691
10667
|
function scheduleConversationWorkRunRender(run) {
|
|
10692
10668
|
var key = runtimeKeyFor(run.target && run.target.workspaceId, run.target && run.target.conversationId) + '::' + String(run.runId || '');
|
|
10693
10669
|
pendingConversationWorkRunRenders[key] = run;
|
|
10694
10670
|
if (scheduledConversationWorkRunRenders[key]) return;
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10671
|
+
var elapsed = performance.now() - Number(lastConversationWorkRunRenderAt[key] || 0);
|
|
10672
|
+
var delay = Math.max(0, WORK_RUN_RENDER_MIN_INTERVAL_MS - elapsed);
|
|
10673
|
+
scheduledConversationWorkRunRenders[key] = setTimeout(function() {
|
|
10674
|
+
requestAnimationFrame(function() { flushConversationWorkRunRender(key); });
|
|
10675
|
+
}, delay);
|
|
10676
|
+
}
|
|
10677
|
+
|
|
10678
|
+
function renderConversationWorkRunImmediately(run) {
|
|
10679
|
+
var key = runtimeKeyFor(run.target && run.target.workspaceId, run.target && run.target.conversationId) + '::' + String(run.runId || '');
|
|
10680
|
+
pendingConversationWorkRunRenders[key] = run;
|
|
10681
|
+
if (scheduledConversationWorkRunRenders[key]) clearTimeout(scheduledConversationWorkRunRenders[key]);
|
|
10682
|
+
flushConversationWorkRunRender(key);
|
|
10702
10683
|
}
|
|
10703
10684
|
|
|
10704
10685
|
function applyAgentWorkEventToRun(event) {
|
|
@@ -10761,7 +10742,9 @@ function applyAgentWorkEventToRun(event) {
|
|
|
10761
10742
|
if (isActiveConversationTarget(target) && (!branchIds.viewed || !eventBranchId || branchIds.viewed === eventBranchId)) {
|
|
10762
10743
|
state.workRunsByTarget[runtimeKeyFor(target.workspaceId, target.conversationId)] = runs;
|
|
10763
10744
|
var existingElement = findWorkRunElement(run);
|
|
10745
|
+
var terminalRender = ['done', 'error', 'interrupted', 'force_interrupted', 'final_response'].indexOf(type) >= 0;
|
|
10764
10746
|
if (!existingElement || type === 'start') renderConversationWorkRun(run);
|
|
10747
|
+
else if (terminalRender) renderConversationWorkRunImmediately(run);
|
|
10765
10748
|
else scheduleConversationWorkRunRender(run);
|
|
10766
10749
|
}
|
|
10767
10750
|
return run;
|
|
@@ -11499,7 +11482,7 @@ function appendAgentWorkEvent(event) {
|
|
|
11499
11482
|
setWorking(!!runningConversationRecord(activeConversationId()) || currentFlowRunning());
|
|
11500
11483
|
updateSubmitButtonState();
|
|
11501
11484
|
}
|
|
11502
|
-
if (active && event.type === 'tool_result' && ['linked_plan', 'task', 'subagent_send', 'subagent_read', 'subagent_close'].indexOf(String(event.toolName || '')) >= 0 && api.getState) {
|
|
11485
|
+
if (active && event.type === 'tool_result' && ['linked_plan', 'task_read', 'task_create', 'task', 'subagent_create', 'SubAgent', 'subagent_send', 'subagent_read', 'subagent_close'].indexOf(String(event.toolName || '')) >= 0 && api.getState) {
|
|
11503
11486
|
var eventWorkspaceKey = currentWorkspaceKey();
|
|
11504
11487
|
api.getState(target).then(function(snapshot) {
|
|
11505
11488
|
if (!isActiveConversationTarget(target) || eventWorkspaceKey !== currentWorkspaceKey()) return;
|
|
@@ -15557,14 +15540,14 @@ function renderGeneralSettings() {
|
|
|
15557
15540
|
return wslHtml + '<div class="setting-subsection">' +
|
|
15558
15541
|
'<div class="setting-subsection-title">' + esc(t('settings.remoteBehavior')) + '</div>' +
|
|
15559
15542
|
'<div class="setting-row">' +
|
|
15560
|
-
'<label class="setting-label" for="remote-touch-enabled"
|
|
15561
|
-
'<
|
|
15562
|
-
'<
|
|
15543
|
+
'<label class="setting-label" for="remote-touch-enabled" style="display:inline-flex;align-items:center;gap:6px;min-width:120px;">' +
|
|
15544
|
+
'<input type="checkbox" id="remote-touch-enabled"' + (state.remoteTouchEnabled ? ' checked' : '') + ' onchange="window.setRemoteTouchEnabled(this.checked)">' +
|
|
15545
|
+
'<span>' + esc(t('settings.remoteTouch')) + '</span></label>' +
|
|
15546
|
+
'<span class="setting-desc" style="flex:1;min-width:140px;">' + esc(t('settings.remoteTouchDesc')) + '</span>' +
|
|
15563
15547
|
'</div>' +
|
|
15564
|
-
'<div class="setting-row">' +
|
|
15565
|
-
'<
|
|
15566
|
-
'<
|
|
15567
|
-
'<div class="setting-desc">' + esc(t('settings.remoteConnectDesc')) + '</div></div>' +
|
|
15548
|
+
'<div class="setting-row" style="border-bottom:none;">' +
|
|
15549
|
+
'<button type="button" class="sec-btn primary" onclick="window.showMobilePairing()">' + esc(t('settings.remoteConnect')) + '</button>' +
|
|
15550
|
+
'<span class="setting-desc" style="flex:1;">' + esc(t('settings.remoteConnectDesc')) + '</span>' +
|
|
15568
15551
|
'</div>' +
|
|
15569
15552
|
'</div>' +
|
|
15570
15553
|
'<div class="setting-row">' +
|
|
@@ -16221,8 +16204,7 @@ var systemColorScheme = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
16221
16204
|
window.refreshTitlebarThemeIcon = function() {
|
|
16222
16205
|
var icon = document.getElementById('title-app-icon');
|
|
16223
16206
|
if (!icon) return;
|
|
16224
|
-
|
|
16225
|
-
icon.src = useDarkTheme ? '../assets/app-icon-dark-64.png' : '../assets/app-icon-light-64.png';
|
|
16207
|
+
icon.src = '../assets/app-icon-dark.svg';
|
|
16226
16208
|
};
|
|
16227
16209
|
window.refreshTitlebarSystemIcon = window.refreshTitlebarThemeIcon;
|
|
16228
16210
|
if (systemColorScheme.addEventListener) systemColorScheme.addEventListener('change', function() {
|
|
@@ -18503,9 +18485,9 @@ window.renderSubagentList = function() {
|
|
|
18503
18485
|
var unread = Number(a.mailbox && a.mailbox.unread || 0);
|
|
18504
18486
|
var queue = a.status === 'queued' && a.queueSequence ? (' · #' + a.queueSequence) : '';
|
|
18505
18487
|
var meta = esc((a.agentMode || a.mode || 'build') + ' / ' + (a.model || t('common.default')) + ' / ' + ((a.messages || []).length || a.messageCount || 0) + ' ' + t('common.messageShort') + queue + (unread ? (' · ' + t('subagent.unread').replace('{count}', String(unread))) : ''));
|
|
18506
|
-
var display = a.
|
|
18507
|
-
var qualified = a.qualifiedName || a.
|
|
18508
|
-
html += '<button type="button"
|
|
18488
|
+
var display = a.name || a.displayName || a.id || 'Agent';
|
|
18489
|
+
var qualified = a.qualifiedName || a.id || display;
|
|
18490
|
+
html += '<button type="button" data-subagent-id="' + escAttr(a.id || '') + '" onclick="window.openSubagentHistory(this.getAttribute(\'data-subagent-id\'))" title="' + escAttr(t('subagent.openHistory')) + '" style="width:100%;display:flex;align-items:center;gap:6px;padding:7px 8px;font-size:12px;border:0;border-bottom:1px solid var(--glass-border-1);background:transparent;text-align:left;cursor:pointer;">' +
|
|
18509
18491
|
iconSvg('bot', 'Subagent', 'small') +
|
|
18510
18492
|
'<span style="flex:1;min-width:0;color:var(--text);" title="' + escAttr(qualified) + '"><span style="display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + esc(display) + '</span><span style="display:block;color:var(--text-dim);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">' + meta + '</span></span>' +
|
|
18511
18493
|
'<span style="color:var(--accent2);font-size:10px;">' + esc(a.status || t('common.idle')) + '</span>' +
|
|
@@ -18517,10 +18499,10 @@ window.renderSubagentList = function() {
|
|
|
18517
18499
|
};
|
|
18518
18500
|
|
|
18519
18501
|
window.refreshSubagentBuildChips = function() {
|
|
18520
|
-
var chips = document.querySelectorAll('.conversation-work-subagent-chip[data-subagent-
|
|
18502
|
+
var chips = document.querySelectorAll('.conversation-work-subagent-chip[data-subagent-id]');
|
|
18521
18503
|
for (var i = 0; i < chips.length; i++) {
|
|
18522
18504
|
var chip = chips[i];
|
|
18523
|
-
var record = findSubagentUiRecord(chip.getAttribute('data-subagent-
|
|
18505
|
+
var record = findSubagentUiRecord(chip.getAttribute('data-subagent-id'));
|
|
18524
18506
|
var status = String(record && record.status || 'accepted');
|
|
18525
18507
|
chip.classList.toggle('completed', status === 'completed');
|
|
18526
18508
|
var statusEl = chip.querySelector('.conversation-work-subagent-status');
|
|
@@ -18546,15 +18528,15 @@ window.scheduleSubagentStateRefresh = function() {
|
|
|
18546
18528
|
}, 1200);
|
|
18547
18529
|
};
|
|
18548
18530
|
|
|
18549
|
-
window.openSubagentFromBuild = function(
|
|
18550
|
-
var requested = String(
|
|
18531
|
+
window.openSubagentFromBuild = function(id) {
|
|
18532
|
+
var requested = String(id || '').trim();
|
|
18551
18533
|
var openLatest = function() {
|
|
18552
18534
|
var agent = findSubagentUiRecord(requested);
|
|
18553
18535
|
if (!agent) {
|
|
18554
18536
|
showUiNotice((currentLang() === 'zh' ? '尚未找到 Subagent:' : 'Subagent is not available yet: ') + requested, 'error', 'subagent-build-' + requested);
|
|
18555
18537
|
return false;
|
|
18556
18538
|
}
|
|
18557
|
-
window.openSubagentHistory(agent.id
|
|
18539
|
+
window.openSubagentHistory(agent.id);
|
|
18558
18540
|
return true;
|
|
18559
18541
|
};
|
|
18560
18542
|
if (!api.getState) return Promise.resolve(openLatest());
|
|
@@ -18712,13 +18694,17 @@ window.closeSubagentHistory = function() {
|
|
|
18712
18694
|
|
|
18713
18695
|
window.openSubagentHistory = function(id) {
|
|
18714
18696
|
var agents = state.subagents || [];
|
|
18715
|
-
var agent = agents.find(function(a) { return a.id === id
|
|
18716
|
-
|
|
18697
|
+
var agent = agents.find(function(a) { return a.id === id; });
|
|
18698
|
+
if (!agent) {
|
|
18699
|
+
showUiNotice((currentLang() === 'zh' ? '尚未找到真实 Subagent:' : 'Real Subagent is not available: ') + String(id || ''), 'error', 'subagent-history-' + String(id || 'missing'));
|
|
18700
|
+
return false;
|
|
18701
|
+
}
|
|
18702
|
+
state.subagentHistoryActorId = agent.id;
|
|
18717
18703
|
var existing = document.getElementById('subagent-history-overlay');
|
|
18718
18704
|
if (existing) existing.remove();
|
|
18719
18705
|
var lines = [];
|
|
18720
|
-
lines.push('<div style="font-size:13px;color:var(--text);font-weight:600;margin-bottom:4px;">' + esc(agent.
|
|
18721
|
-
lines.push('<div style="font-size:10px;color:var(--text-dim);word-break:break-all;margin-bottom:8px;">' + esc(agent.qualifiedName || agent.
|
|
18706
|
+
lines.push('<div style="font-size:13px;color:var(--text);font-weight:600;margin-bottom:4px;">' + esc(agent.name || agent.displayName || t('subagent.historyTitle')) + '</div>');
|
|
18707
|
+
lines.push('<div style="font-size:10px;color:var(--text-dim);word-break:break-all;margin-bottom:8px;">' + esc(agent.qualifiedName || agent.id || '') + '</div>');
|
|
18722
18708
|
lines.push('<div id="subagent-history-meta" style="font-size:11px;color:var(--text-dim);margin-bottom:10px;">' + esc((agent.status || t('common.idle')) + ' / ' + (agent.agentMode || agent.mode || 'build') + ' / ' + (agent.model || t('common.default')) + (agent.mailbox && agent.mailbox.unread ? (' / ' + agent.mailbox.unread + ' unread') : '')) + '</div>');
|
|
18723
18709
|
var compression = agent.metadata && agent.metadata.contextCompression;
|
|
18724
18710
|
if (compression) {
|
|
@@ -18748,6 +18734,7 @@ window.openSubagentHistory = function(id) {
|
|
|
18748
18734
|
for (var i = 0; i < cached.length; i++) renderSubagentPeerEvent(cached[i]);
|
|
18749
18735
|
autoScrollSubagentHistory(body);
|
|
18750
18736
|
window.scheduleSubagentStateRefresh();
|
|
18737
|
+
return true;
|
|
18751
18738
|
};
|
|
18752
18739
|
|
|
18753
18740
|
// === Browser ===
|