newmark-agent 0.4.8 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
2
- import { ConversationQueueAction } from './conversationKernel';
2
+ import { ConversationQueueAction, ConversationQueueActionInput } from './conversationKernel';
3
3
  import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
4
4
  import { UtilityHostToolHandler } from './electronUtilityAgentClient';
5
5
  import { UtilityAgentPromptResult, UtilityAutoRouteRatingResult, UtilityConversationRewindResult, UtilityAgentSnapshotResult, UtilityAgentStopResult, UtilityPromptRequest } from './utilityAgentProtocol';
@@ -11,13 +11,7 @@ export interface ElectronTargetRuntimeClient {
11
11
  rewind(messageIndex: number): Promise<UtilityConversationRewindResult>;
12
12
  requestStop(runId?: string): Promise<UtilityAgentStopResult>;
13
13
  enqueueGuide(envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
14
- queueAction?(action: ConversationQueueAction, input?: {
15
- id?: string;
16
- text?: string;
17
- requestedMode?: string;
18
- goalObjective?: string;
19
- createdAt?: string;
20
- }): Promise<Record<string, unknown>>;
14
+ queueAction?(action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
21
15
  checkpoint(): Promise<Record<string, unknown>>;
22
16
  contextCompress?(options?: {
23
17
  keepRecent?: number;
@@ -79,13 +73,7 @@ export declare class ElectronUtilityRuntimePool {
79
73
  rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<UtilityConversationRewindResult>;
80
74
  requestStop(target: ConversationRuntimeTarget, runId?: string): Promise<ElectronPoolStopResult>;
81
75
  enqueueGuide(envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
82
- queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: {
83
- id?: string;
84
- text?: string;
85
- requestedMode?: string;
86
- goalObjective?: string;
87
- createdAt?: string;
88
- }): Promise<Record<string, unknown>>;
76
+ queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
89
77
  checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
90
78
  contextCompress(target: ConversationRuntimeTarget, options?: {
91
79
  keepRecent?: number;
@@ -1,6 +1,6 @@
1
1
  import { BrowserControlRequest, BrowserControlResult } from './browserControl';
2
2
  import { BrowserUseRequest } from './browserUse';
3
- import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueMode, ConversationRuntimeState, ConversationStopResult } from './conversationKernel';
3
+ import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueActionInput, ConversationQueueMode, ConversationRuntimeState, ConversationStopResult } from './conversationKernel';
4
4
  import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
5
5
  import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
6
6
  import type { AutoRouteRatingResult, ConversationSnapshot } from './agent';
@@ -106,13 +106,7 @@ export type UtilityAgentRequest = {
106
106
  params: {
107
107
  target: ConversationRuntimeTarget;
108
108
  action: ConversationQueueAction;
109
- input?: {
110
- id?: string;
111
- text?: string;
112
- requestedMode?: string;
113
- goalObjective?: string;
114
- createdAt?: string;
115
- };
109
+ input?: ConversationQueueActionInput;
116
110
  };
117
111
  } | {
118
112
  id: string;
@@ -1,5 +1,5 @@
1
1
  import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
2
- import { ConversationQueueAction } from './conversationKernel';
2
+ import { ConversationQueueAction, ConversationQueueActionInput } from './conversationKernel';
3
3
  import { TerminalTakeoverEvent, TerminalTakeoverOwnerFilter, TerminalTakeoverState } from '../tools/terminalTakeover';
4
4
  import { WslAgentPromptRequest, WslAgentPromptResult, WslAutoRouteRatingResult, WslAgentWorkspace, WslAgentStopResult, WslConversationRewindResult, WslHostToolRequest } from './wslAgentProtocol';
5
5
  import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
@@ -72,13 +72,7 @@ export declare class WslAgentClient {
72
72
  snapshotTarget(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
73
73
  rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
74
74
  enqueueGuide(target: ConversationRuntimeTarget, envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
75
- queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: {
76
- id?: string;
77
- text?: string;
78
- requestedMode?: string;
79
- goalObjective?: string;
80
- createdAt?: string;
81
- }): Promise<Record<string, unknown>>;
75
+ queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
82
76
  checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
83
77
  contextCompress(target: ConversationRuntimeTarget, options?: {
84
78
  keepRecent?: number;
@@ -1,5 +1,5 @@
1
1
  import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
2
- import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueMode, ConversationStopResult } from './conversationKernel';
2
+ import { AgentPromptMessage, ConversationContextCompressOptions, ConversationKernelRunOptions, ConversationKernelRunResult, ConversationQueueAction, ConversationQueueActionInput, ConversationQueueMode, ConversationStopResult } from './conversationKernel';
3
3
  import { ConversationRuntimeTarget } from './conversationTarget';
4
4
  import { TerminalTakeoverEvent, TerminalTakeoverOwnerFilter, TerminalTakeoverState } from '../tools/terminalTakeover';
5
5
  import { BrowserUseRequest } from './browserUse';
@@ -117,13 +117,7 @@ export type WslAgentRequest = {
117
117
  params: {
118
118
  target: ConversationRuntimeTarget;
119
119
  action: ConversationQueueAction;
120
- input?: {
121
- id?: string;
122
- text?: string;
123
- requestedMode?: string;
124
- goalObjective?: string;
125
- createdAt?: string;
126
- };
120
+ input?: ConversationQueueActionInput;
127
121
  };
128
122
  } | {
129
123
  id: string;
@@ -1,5 +1,5 @@
1
1
  import { AgentMode, AgentWorkEvent, ConversationInputEnvelope, GuideReceipt } from './types';
2
- import { ConversationQueueAction } from './conversationKernel';
2
+ import { ConversationQueueAction, ConversationQueueActionInput } from './conversationKernel';
3
3
  import { ConversationRuntimeTarget, NormalizedConversationTarget } from './conversationTarget';
4
4
  import { WslHostToolHandler } from './wslAgentClient';
5
5
  import { WslAgentPromptRequest, WslAgentPromptResult, WslAutoRouteRatingResult, WslAgentStopResult, WslConversationRewindResult } from './wslAgentProtocol';
@@ -11,13 +11,7 @@ export interface WslTargetRuntimeClient {
11
11
  rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
12
12
  requestStop(target: ConversationRuntimeTarget, runId?: string): Promise<WslAgentStopResult>;
13
13
  enqueueGuide(target: ConversationRuntimeTarget, envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
14
- queueAction?(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: {
15
- id?: string;
16
- text?: string;
17
- requestedMode?: string;
18
- goalObjective?: string;
19
- createdAt?: string;
20
- }): Promise<Record<string, unknown>>;
14
+ queueAction?(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
21
15
  checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
22
16
  contextCompress?(target: ConversationRuntimeTarget, options?: {
23
17
  keepRecent?: number;
@@ -81,13 +75,7 @@ export declare class WslAgentRuntimePool {
81
75
  rewind(target: ConversationRuntimeTarget, messageIndex: number): Promise<WslConversationRewindResult>;
82
76
  requestStop(target: ConversationRuntimeTarget, runId?: string): Promise<WslPoolStopResult>;
83
77
  enqueueGuide(envelope: ConversationInputEnvelope): Promise<GuideReceipt>;
84
- queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: {
85
- id?: string;
86
- text?: string;
87
- requestedMode?: string;
88
- goalObjective?: string;
89
- createdAt?: string;
90
- }): Promise<Record<string, unknown>>;
78
+ queueAction(target: ConversationRuntimeTarget, action: ConversationQueueAction, input?: ConversationQueueActionInput): Promise<Record<string, unknown>>;
91
79
  checkpoint(target: ConversationRuntimeTarget): Promise<Record<string, unknown>>;
92
80
  contextCompress(target: ConversationRuntimeTarget, options?: {
93
81
  keepRecent?: number;
package/dist/main.js CHANGED
@@ -1891,189 +1891,195 @@ else {
1891
1891
  ensureWorkspaceRegistryWatcher();
1892
1892
  restoreStoredFlowSuspension();
1893
1893
  recordStartup('agent-ready');
1894
- // 远程触及开关开启 → GUI 进程内托管启动 mobile server(托盘常驻不中断)
1895
- if (agent.config.getBool('remote', 'touch_enabled')) {
1896
- try {
1897
- const { runServer } = require('./server');
1898
- runServer(root, {
1899
- agent,
1900
- automation,
1901
- onWorkEvent: event => broadcastAgentWorkEvent(event, false),
1902
- subscribeWorkEvents: listener => {
1903
- mobileServerWorkEventSubscribers.add(listener);
1904
- return () => mobileServerWorkEventSubscribers.delete(listener);
1905
- },
1906
- conversationUiState: async (requested) => {
1907
- const target = conversationRuntimeTarget(requested);
1894
+ // GUI 始终注册 mobile server 的运行时桥接;开关打开时才开始监听。
1895
+ // 这样从关闭态切到开启态时也能在当前 GUI 进程中原地重启服务。
1896
+ try {
1897
+ const { configureHostedServer, runServer } = require('./server');
1898
+ configureHostedServer(root, {
1899
+ agent,
1900
+ automation,
1901
+ onWorkEvent: event => broadcastAgentWorkEvent(event, false),
1902
+ subscribeWorkEvents: listener => {
1903
+ mobileServerWorkEventSubscribers.add(listener);
1904
+ return () => mobileServerWorkEventSubscribers.delete(listener);
1905
+ },
1906
+ conversationUiState: async (requested) => {
1907
+ const target = conversationRuntimeTarget(requested);
1908
+ const snapshot = wslBackendEnabled()
1909
+ ? await ensureWslConversationPool().snapshot(target)
1910
+ : await ensureElectronUtilityPool().snapshot(target);
1911
+ const flowRunning = flowRunningForTarget(target);
1912
+ const flowSuspension = flowSuspensionForTarget(target);
1913
+ return {
1914
+ ...snapshot,
1915
+ flow: flowRunning ? {
1916
+ running: true,
1917
+ paused: false,
1918
+ name: flowRunning.name,
1919
+ promptText: String(activeFlowStateFor(target)?.input || ''),
1920
+ message: '',
1921
+ } : flowSuspension ? {
1922
+ running: true,
1923
+ paused: true,
1924
+ name: flowSuspension.workflowName || '',
1925
+ promptText: String(flowSuspension.input || ''),
1926
+ message: String(flowSuspension.message || ''),
1927
+ reason: flowSuspension.reason || '',
1928
+ } : null,
1929
+ };
1930
+ },
1931
+ conversationUiAction: async (requested, action, value, input) => {
1932
+ const target = conversationRuntimeTarget(requested);
1933
+ if (action.startsWith('queue_')) {
1934
+ const queueAction = action === 'queue_enqueue' ? 'enqueue'
1935
+ : action === 'queue_update' ? 'update'
1936
+ : action === 'queue_delete' ? 'delete'
1937
+ : action === 'queue_reorder' ? 'reorder'
1938
+ : action === 'queue_toggle_pause' ? 'toggle_pause'
1939
+ : 'guide';
1940
+ const queueInput = {
1941
+ id: String(input?.id || ''),
1942
+ text: String(input?.text || value || ''),
1943
+ requestedMode: String(input?.requestedMode || 'build'),
1944
+ goalObjective: String(input?.goalObjective || ''),
1945
+ createdAt: String(input?.createdAt || ''),
1946
+ orderedIds: Array.isArray(input?.orderedIds)
1947
+ ? input.orderedIds.map((id) => String(id || ''))
1948
+ : undefined,
1949
+ };
1950
+ return wslBackendEnabled()
1951
+ ? await ensureWslConversationPool().queueAction(target, queueAction, queueInput)
1952
+ : await ensureElectronUtilityPool().queueAction(target, queueAction, queueInput);
1953
+ }
1954
+ if (action === 'goal_update') {
1955
+ return { goal: await mutateTargetConversation(target, () => {
1956
+ const isolated = isolatedConversationAgent(target);
1957
+ isolated.updateGoal(String(value || '').trim());
1958
+ isolated.setMode('goal');
1959
+ isolated.saveWorkspaceConversationState(true);
1960
+ return isolated.getConversationSnapshot(target.conversationId).goal;
1961
+ }) };
1962
+ }
1963
+ if (action === 'goal_guide' || action === 'conversation_guide') {
1964
+ const objective = action === 'goal_guide' ? String(value || '').trim() : '';
1965
+ const guideText = String(value || '').trim();
1908
1966
  const snapshot = wslBackendEnabled()
1909
1967
  ? await ensureWslConversationPool().snapshot(target)
1910
1968
  : await ensureElectronUtilityPool().snapshot(target);
1911
- const flowRunning = flowRunningForTarget(target);
1912
- const flowSuspension = flowSuspensionForTarget(target);
1913
- return {
1914
- ...snapshot,
1915
- flow: flowRunning ? {
1916
- running: true,
1917
- paused: false,
1918
- name: flowRunning.name,
1919
- promptText: String(activeFlowStateFor(target)?.input || ''),
1920
- message: '',
1921
- } : flowSuspension ? {
1922
- running: true,
1923
- paused: true,
1924
- name: flowSuspension.workflowName || '',
1925
- promptText: String(flowSuspension.input || ''),
1926
- message: String(flowSuspension.message || ''),
1927
- reason: flowSuspension.reason || '',
1928
- } : null,
1929
- };
1930
- },
1931
- conversationUiAction: async (requested, action, value, input) => {
1932
- const target = conversationRuntimeTarget(requested);
1933
- if (action.startsWith('queue_')) {
1934
- const queueAction = action === 'queue_enqueue' ? 'enqueue'
1935
- : action === 'queue_update' ? 'update'
1936
- : action === 'queue_delete' ? 'delete'
1937
- : action === 'queue_toggle_pause' ? 'toggle_pause'
1938
- : 'guide';
1939
- const queueInput = {
1940
- id: String(input?.id || ''),
1941
- text: String(input?.text || value || ''),
1942
- requestedMode: String(input?.requestedMode || 'build'),
1943
- goalObjective: String(input?.goalObjective || ''),
1944
- createdAt: String(input?.createdAt || ''),
1945
- };
1946
- return wslBackendEnabled()
1947
- ? await ensureWslConversationPool().queueAction(target, queueAction, queueInput)
1948
- : await ensureElectronUtilityPool().queueAction(target, queueAction, queueInput);
1949
- }
1950
- if (action === 'goal_update') {
1951
- return { goal: await mutateTargetConversation(target, () => {
1952
- const isolated = isolatedConversationAgent(target);
1953
- isolated.updateGoal(String(value || '').trim());
1954
- isolated.setMode('goal');
1955
- isolated.saveWorkspaceConversationState(true);
1956
- return isolated.getConversationSnapshot(target.conversationId).goal;
1957
- }) };
1958
- }
1959
- if (action === 'goal_guide' || action === 'conversation_guide') {
1960
- const objective = action === 'goal_guide' ? String(value || '').trim() : '';
1961
- const guideText = String(value || '').trim();
1962
- const snapshot = wslBackendEnabled()
1963
- ? await ensureWslConversationPool().snapshot(target)
1964
- : await ensureElectronUtilityPool().snapshot(target);
1965
- const runtime = snapshot.runtime;
1966
- if (!guideText || !runtime?.running || !runtime.runId) {
1967
- return { ok: false, error: action === 'goal_guide'
1968
- ? 'There is no active Build for this Goal Guide.'
1969
- : 'Target conversation is not running.' };
1970
- }
1971
- const prefix = 'Goal for the current Build:\n';
1972
- const now = new Date().toISOString();
1973
- const envelope = {
1974
- clientMessageId: (0, crypto_1.randomUUID)(),
1975
- guideId: (0, crypto_1.randomUUID)(),
1976
- target: { workspaceId: target.workspaceId, conversationId: target.conversationId },
1977
- runId: runtime.runId,
1978
- deliveryMode: 'steer',
1979
- text: objective ? prefix + objective : guideText,
1980
- goalObjective: objective || undefined,
1981
- createdAt: now,
1982
- };
1983
- const receipt = wslBackendEnabled()
1984
- ? await ensureWslConversationPool().enqueueGuide(envelope)
1985
- : await ensureElectronUtilityPool().enqueueGuide(envelope);
1986
- return { ok: receipt.status !== 'rejected', receipt };
1969
+ const runtime = snapshot.runtime;
1970
+ if (!guideText || !runtime?.running || !runtime.runId) {
1971
+ return { ok: false, error: action === 'goal_guide'
1972
+ ? 'There is no active Build for this Goal Guide.'
1973
+ : 'Target conversation is not running.' };
1987
1974
  }
1988
- if (action === 'goal_toggle_pause') {
1989
- const resident = wslBackendEnabled()
1990
- ? await ensureWslConversationPool().toggleGoalPause(target)
1991
- : await ensureElectronUtilityPool().toggleGoalPause(target);
1992
- const paused = resident !== null ? resident : await mutateTargetConversation(target, () => isolatedConversationAgent(target).toggleGoalPause());
1993
- return { ok: true, paused };
1994
- }
1995
- if (action === 'goal_clear') {
1996
- const resident = wslBackendEnabled()
1997
- ? await ensureWslConversationPool().clearGoal(target)
1998
- : await ensureElectronUtilityPool().clearGoal(target);
1999
- if (resident === null)
2000
- await mutateTargetConversation(target, () => isolatedConversationAgent(target).clearGoal());
2001
- return { ok: true, cleared: true };
2002
- }
2003
- if (action === 'flow_pause')
2004
- return await stopFlowForTarget(target);
2005
- if (action === 'flow_resume')
2006
- return await resumeFlowForTarget(String(value || ''), target);
2007
- if (action === 'conversation_stop') {
2008
- const snapshot = wslBackendEnabled()
2009
- ? await ensureWslConversationPool().snapshot(target)
2010
- : await ensureElectronUtilityPool().snapshot(target);
2011
- const runtime = snapshot.runtime;
2012
- return wslBackendEnabled()
2013
- ? await ensureWslConversationPool().requestStop(target, runtime?.runId)
2014
- : await ensureElectronUtilityPool().requestStop(target, runtime?.runId);
2015
- }
2016
- if (action === 'input_mode') {
2017
- const mode = String(value || '') === 'next' ? 'next' : 'guide';
2018
- const selected = wslBackendEnabled()
2019
- ? await ensureWslConversationPool().setInputMode(target, mode)
2020
- : await ensureElectronUtilityPool().setInputMode(target, mode);
2021
- return { ok: true, inputMode: selected || mode };
2022
- }
2023
- const flow = activeFlowStateFor(target);
2024
- if (!flow?.abortController || !flow.flowAgent)
2025
- return { ok: false, error: 'No active Flow accepts Guide input.' };
2026
- const accepted = flow.flowAgent.queueActiveKernelMessage(String(value || '').trim(), 'steer') || false;
2027
- return accepted ? { ok: true, accepted: true, flow: flow.name } : { ok: false, error: 'The current Flow Build is not accepting Guide input.' };
2028
- },
2029
- conversationPrompt: async (requested, message, requestedOptions) => {
2030
- const target = conversationRuntimeTarget(requested);
2031
- if (activeFlowStateFor(target))
2032
- clearFlowSuspensionForNewWork(target);
1975
+ const prefix = 'Goal for the current Build:\n';
1976
+ const now = new Date().toISOString();
1977
+ const envelope = {
1978
+ clientMessageId: (0, crypto_1.randomUUID)(),
1979
+ guideId: (0, crypto_1.randomUUID)(),
1980
+ target: { workspaceId: target.workspaceId, conversationId: target.conversationId },
1981
+ runId: runtime.runId,
1982
+ deliveryMode: 'steer',
1983
+ text: objective ? prefix + objective : guideText,
1984
+ goalObjective: objective || undefined,
1985
+ createdAt: now,
1986
+ };
1987
+ const receipt = wslBackendEnabled()
1988
+ ? await ensureWslConversationPool().enqueueGuide(envelope)
1989
+ : await ensureElectronUtilityPool().enqueueGuide(envelope);
1990
+ return { ok: receipt.status !== 'rejected', receipt };
1991
+ }
1992
+ if (action === 'goal_toggle_pause') {
1993
+ const resident = wslBackendEnabled()
1994
+ ? await ensureWslConversationPool().toggleGoalPause(target)
1995
+ : await ensureElectronUtilityPool().toggleGoalPause(target);
1996
+ const paused = resident !== null ? resident : await mutateTargetConversation(target, () => isolatedConversationAgent(target).toggleGoalPause());
1997
+ return { ok: true, paused };
1998
+ }
1999
+ if (action === 'goal_clear') {
2000
+ const resident = wslBackendEnabled()
2001
+ ? await ensureWslConversationPool().clearGoal(target)
2002
+ : await ensureElectronUtilityPool().clearGoal(target);
2003
+ if (resident === null)
2004
+ await mutateTargetConversation(target, () => isolatedConversationAgent(target).clearGoal());
2005
+ return { ok: true, cleared: true };
2006
+ }
2007
+ if (action === 'flow_pause')
2008
+ return await stopFlowForTarget(target);
2009
+ if (action === 'flow_resume')
2010
+ return await resumeFlowForTarget(String(value || ''), target);
2011
+ if (action === 'conversation_stop') {
2033
2012
  const snapshot = wslBackendEnabled()
2034
2013
  ? await ensureWslConversationPool().snapshot(target)
2035
2014
  : await ensureElectronUtilityPool().snapshot(target);
2036
- const requestedMode = String(requestedOptions?.requestedMode || '').toLowerCase();
2037
- const goalObjective = String(requestedOptions?.goalObjective || '').trim();
2038
- const mode = (goalObjective || requestedMode === 'goal') ? 'build' : String(snapshot.mode || 'build');
2039
- const inputMode = String(requestedOptions?.inputMode || snapshot.inputMode || 'guide') === 'next' ? 'next' : 'guide';
2040
- const options = {
2041
- mode,
2042
- model: String(snapshot.model || agent.ensureUsableModelSelection()),
2043
- intelligence: String(snapshot.intelligence || agent.intelligence),
2044
- inputMode,
2045
- engine: agent.engine,
2046
- };
2047
- const queueMode = inputMode === 'guide' ? 'steer' : 'followUp';
2048
- const promptMessage = goalObjective ? {
2049
- text: message,
2050
- visibleMode: 'goal',
2051
- goalObjective,
2052
- } : message;
2053
- const result = wslBackendEnabled()
2054
- ? await ensureWslConversationPool().prompt({
2055
- message: promptMessage,
2056
- target,
2057
- conversationId: target.conversationId,
2058
- options,
2059
- queueMode,
2060
- workspace: target.workspace ? {
2061
- id: target.workspace.id,
2062
- name: target.workspace.name,
2063
- path: target.workspace.path,
2064
- isInternal: target.workspace.isInternal,
2065
- kind: target.workspace.kind,
2066
- } : null,
2067
- })
2068
- : await ensureElectronUtilityPool().prompt({ message: promptMessage, target, options, queueMode });
2069
- return { ...result };
2070
- },
2071
- });
2015
+ const runtime = snapshot.runtime;
2016
+ return wslBackendEnabled()
2017
+ ? await ensureWslConversationPool().requestStop(target, runtime?.runId)
2018
+ : await ensureElectronUtilityPool().requestStop(target, runtime?.runId);
2019
+ }
2020
+ if (action === 'input_mode') {
2021
+ const mode = String(value || '') === 'next' ? 'next' : 'guide';
2022
+ const selected = wslBackendEnabled()
2023
+ ? await ensureWslConversationPool().setInputMode(target, mode)
2024
+ : await ensureElectronUtilityPool().setInputMode(target, mode);
2025
+ return { ok: true, inputMode: selected || mode };
2026
+ }
2027
+ const flow = activeFlowStateFor(target);
2028
+ if (!flow?.abortController || !flow.flowAgent)
2029
+ return { ok: false, error: 'No active Flow accepts Guide input.' };
2030
+ const accepted = flow.flowAgent.queueActiveKernelMessage(String(value || '').trim(), 'steer') || false;
2031
+ return accepted ? { ok: true, accepted: true, flow: flow.name } : { ok: false, error: 'The current Flow Build is not accepting Guide input.' };
2032
+ },
2033
+ conversationPrompt: async (requested, message, requestedOptions) => {
2034
+ const target = conversationRuntimeTarget(requested);
2035
+ if (activeFlowStateFor(target))
2036
+ clearFlowSuspensionForNewWork(target);
2037
+ const snapshot = wslBackendEnabled()
2038
+ ? await ensureWslConversationPool().snapshot(target)
2039
+ : await ensureElectronUtilityPool().snapshot(target);
2040
+ const requestedMode = String(requestedOptions?.requestedMode || '').toLowerCase();
2041
+ const goalObjective = String(requestedOptions?.goalObjective || '').trim();
2042
+ const mode = (goalObjective || requestedMode === 'goal') ? 'build' : String(snapshot.mode || 'build');
2043
+ const inputMode = String(requestedOptions?.inputMode || snapshot.inputMode || 'guide') === 'next' ? 'next' : 'guide';
2044
+ const options = {
2045
+ mode,
2046
+ model: String(snapshot.model || agent.ensureUsableModelSelection()),
2047
+ intelligence: String(snapshot.intelligence || agent.intelligence),
2048
+ inputMode,
2049
+ engine: agent.engine,
2050
+ };
2051
+ const queueMode = inputMode === 'guide' ? 'steer' : 'followUp';
2052
+ const promptMessage = goalObjective ? {
2053
+ text: message,
2054
+ visibleMode: 'goal',
2055
+ goalObjective,
2056
+ } : message;
2057
+ const result = wslBackendEnabled()
2058
+ ? await ensureWslConversationPool().prompt({
2059
+ message: promptMessage,
2060
+ target,
2061
+ conversationId: target.conversationId,
2062
+ options,
2063
+ queueMode,
2064
+ workspace: target.workspace ? {
2065
+ id: target.workspace.id,
2066
+ name: target.workspace.name,
2067
+ path: target.workspace.path,
2068
+ isInternal: target.workspace.isInternal,
2069
+ kind: target.workspace.kind,
2070
+ } : null,
2071
+ })
2072
+ : await ensureElectronUtilityPool().prompt({ message: promptMessage, target, options, queueMode });
2073
+ return { ...result };
2074
+ },
2075
+ });
2076
+ if (agent.config.getBool('remote', 'touch_enabled')) {
2077
+ runServer(root);
2072
2078
  recordStartup('mobile-server-hosted');
2073
2079
  }
2074
- catch (error) {
2075
- console.error('[Newmark] hosted mobile server failed:', error instanceof Error ? error.message : String(error));
2076
- }
2080
+ }
2081
+ catch (error) {
2082
+ console.error('[Newmark] hosted mobile server failed:', error instanceof Error ? error.message : String(error));
2077
2083
  }
2078
2084
  }
2079
2085
  };
@@ -3878,10 +3884,31 @@ else {
3878
3884
  electronUtilityRuntimePool?.updateSetting(section, key, value),
3879
3885
  wslAgentRuntimePool?.updateSetting(section, key, value),
3880
3886
  ]);
3887
+ if (section === 'remote' && key === 'touch_enabled') {
3888
+ const { setHostedServerEnabled } = require('./server');
3889
+ await setHostedServerEnabled(value === true || value === 'on');
3890
+ }
3881
3891
  return true;
3882
3892
  }
3883
3893
  return false;
3884
3894
  });
3895
+ electron_1.ipcMain.handle('mobile:serverStatus', async () => {
3896
+ if (!agent)
3897
+ return { enabled: false, listening: false, reachable: false, state: 'off', host: '', port: 47890, error: 'Agent not initialized', checkedAt: new Date().toISOString(), startedAt: 0 };
3898
+ const enabled = agent.config.getBool('remote', 'touch_enabled');
3899
+ const { hostedServerStatus } = require('./server');
3900
+ return await hostedServerStatus(enabled);
3901
+ });
3902
+ electron_1.ipcMain.handle('mobile:setRemoteTouchEnabled', async (_event, value) => {
3903
+ if (!agent)
3904
+ return { ok: false, error: 'Agent not initialized' };
3905
+ const enabled = value === true;
3906
+ agent.config.set('remote', 'touch_enabled', enabled);
3907
+ agent.config.save();
3908
+ const { setHostedServerEnabled } = require('./server');
3909
+ const status = await setHostedServerEnabled(enabled);
3910
+ return { ok: true, ...status };
3911
+ });
3885
3912
  electron_1.ipcMain.handle('agent:openGlobalConfig', async () => {
3886
3913
  if (!agent)
3887
3914
  return { error: 'Agent is not initialized' };
package/dist/preload.js CHANGED
@@ -139,6 +139,8 @@ contextBridge.exposeInMainWorld('api', {
139
139
  updateVersion: () => ipcRenderer.invoke('update:version'),
140
140
  mobilePairingQr: () => ipcRenderer.invoke('mobile:pairingQr'),
141
141
  mobilePairingStatus: () => ipcRenderer.invoke('mobile:pairingStatus'),
142
+ mobileServerStatus: () => ipcRenderer.invoke('mobile:serverStatus'),
143
+ setRemoteTouchEnabled: (enabled) => ipcRenderer.invoke('mobile:setRemoteTouchEnabled', enabled),
142
144
  updateCheckGithub: (input) => ipcRenderer.invoke('update:checkGithub', input),
143
145
  updateApplyGithub: (input) => ipcRenderer.invoke('update:applyGithub', input),
144
146
  updateInstallLocal: (input) => ipcRenderer.invoke('update:installLocal', input),
package/dist/server.d.ts CHANGED
@@ -16,7 +16,7 @@ export interface HostedMobileServerOptions {
16
16
  conversationUiAction?: (target: {
17
17
  workspaceId: string;
18
18
  conversationId: string;
19
- }, action: 'goal_update' | 'goal_guide' | 'conversation_guide' | 'goal_toggle_pause' | 'goal_clear' | 'flow_pause' | 'flow_resume' | 'flow_guide' | 'conversation_stop' | 'input_mode' | 'queue_enqueue' | 'queue_update' | 'queue_delete' | 'queue_toggle_pause' | 'queue_guide', value?: string, input?: Record<string, unknown>) => Promise<Record<string, unknown>>;
19
+ }, action: 'goal_update' | 'goal_guide' | 'conversation_guide' | 'goal_toggle_pause' | 'goal_clear' | 'flow_pause' | 'flow_resume' | 'flow_guide' | 'conversation_stop' | 'input_mode' | 'queue_enqueue' | 'queue_update' | 'queue_delete' | 'queue_reorder' | 'queue_toggle_pause' | 'queue_guide', value?: string, input?: Record<string, unknown>) => Promise<Record<string, unknown>>;
20
20
  /** Send through the same GUI runtime pool used by the desktop renderer. */
21
21
  conversationPrompt?: (target: {
22
22
  workspaceId: string;
@@ -27,6 +27,21 @@ export interface HostedMobileServerOptions {
27
27
  inputMode?: string;
28
28
  }) => Promise<Record<string, unknown>>;
29
29
  }
30
+ export interface HostedMobileServerStatus {
31
+ enabled: boolean;
32
+ listening: boolean;
33
+ reachable: boolean;
34
+ state: 'off' | 'listening' | 'error';
35
+ host: string;
36
+ port: number;
37
+ error: string;
38
+ checkedAt: string;
39
+ startedAt: number;
40
+ }
41
+ export declare function configureHostedServer(root: string, options?: HostedMobileServerOptions): void;
42
+ export declare function stopHostedServer(): Promise<void>;
43
+ export declare function hostedServerStatus(enabled?: boolean, probeHost?: string): Promise<HostedMobileServerStatus>;
44
+ export declare function setHostedServerEnabled(enabled: boolean, probeHost?: string): Promise<HostedMobileServerStatus>;
30
45
  /** 托管启动 server(GUI/TUI 内嵌调用;幂等防重入,进程常驻即服务常驻) */
31
46
  export declare function runServer(root: string, options?: HostedMobileServerOptions): void;
32
47
  /** Attach the GUI-owned automation manager after deferred startup. */