newmark-agent 0.4.8 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/conversation-utility-host.bundle.cjs +238 -29
- package/dist/core/agent.d.ts +1 -0
- package/dist/core/agent.js +102 -10
- package/dist/core/agentKernelRunner.js +1 -1
- package/dist/core/autoRouter.d.ts +1 -1
- package/dist/core/autoRouter.js +16 -7
- package/dist/core/conversationKernel.d.ts +13 -8
- package/dist/core/conversationKernel.js +111 -10
- package/dist/core/electronUtilityAgentClient.d.ts +2 -8
- package/dist/core/electronUtilityRuntimePool.d.ts +3 -15
- package/dist/core/utilityAgentProtocol.d.ts +2 -8
- package/dist/core/workEventCoalescer.d.ts +16 -0
- package/dist/core/workEventCoalescer.js +52 -0
- package/dist/core/wslAgentClient.d.ts +2 -8
- package/dist/core/wslAgentProtocol.d.ts +2 -8
- package/dist/core/wslAgentRuntimePool.d.ts +3 -15
- package/dist/llm/provider.d.ts +5 -0
- package/dist/llm/provider.js +63 -1
- package/dist/main.js +221 -175
- package/dist/preload.js +2 -0
- package/dist/server.d.ts +17 -1
- package/dist/server.js +331 -9
- package/dist/ui/index.html +295 -51
- package/dist/wsl-agent-host.bundle.cjs +238 -29
- package/package.json +10 -5
package/dist/main.js
CHANGED
|
@@ -76,6 +76,7 @@ const runtimeLifecycle_1 = require("./core/runtimeLifecycle");
|
|
|
76
76
|
const compat_1 = require("./core/compat");
|
|
77
77
|
const dshCompatibility_1 = require("./core/dshCompatibility");
|
|
78
78
|
const mcpManager_1 = require("./core/mcpManager");
|
|
79
|
+
const workEventCoalescer_1 = require("./core/workEventCoalescer");
|
|
79
80
|
const cli_help_1 = require("./cli-help");
|
|
80
81
|
const APP_NAME = 'Newmark Agent';
|
|
81
82
|
const APP_ID = 'ai.newmark.agent';
|
|
@@ -289,7 +290,7 @@ async function resetWslAgentClient() {
|
|
|
289
290
|
if (wslAgentClient)
|
|
290
291
|
await wslAgentClient.resetAgent();
|
|
291
292
|
}
|
|
292
|
-
function
|
|
293
|
+
function dispatchAgentWorkEvent(event, mirrorToMobile = true) {
|
|
293
294
|
const workEvent = event;
|
|
294
295
|
if ((workEvent.type === 'done' || workEvent.type === 'error') && workEvent.runtimeKey) {
|
|
295
296
|
browserUseEngine?.clearRuntime(workEvent.runtimeKey);
|
|
@@ -309,6 +310,20 @@ function broadcastAgentWorkEvent(event, mirrorToMobile = true) {
|
|
|
309
310
|
}
|
|
310
311
|
}
|
|
311
312
|
}
|
|
313
|
+
const workEventCoalescer = new workEventCoalescer_1.WorkEventCoalescer(event => dispatchAgentWorkEvent(event, true));
|
|
314
|
+
const workEventNoMobileCoalescer = new workEventCoalescer_1.WorkEventCoalescer(event => dispatchAgentWorkEvent(event, false));
|
|
315
|
+
function broadcastAgentWorkEvent(event, mirrorToMobile = true) {
|
|
316
|
+
const workEvent = event;
|
|
317
|
+
// Text deltas are the only high-frequency event. They are coalesced at the
|
|
318
|
+
// IPC/SSE boundary; all lifecycle/tool events retain immediate ordering.
|
|
319
|
+
if (workEvent.type === 'text') {
|
|
320
|
+
(mirrorToMobile ? workEventCoalescer : workEventNoMobileCoalescer).push(workEvent);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
workEventCoalescer.flushAll();
|
|
324
|
+
workEventNoMobileCoalescer.flushAll();
|
|
325
|
+
dispatchAgentWorkEvent(event, mirrorToMobile);
|
|
326
|
+
}
|
|
312
327
|
function ensureConversationKernel(root) {
|
|
313
328
|
if (!agent)
|
|
314
329
|
return null;
|
|
@@ -1891,189 +1906,199 @@ else {
|
|
|
1891
1906
|
ensureWorkspaceRegistryWatcher();
|
|
1892
1907
|
restoreStoredFlowSuspension();
|
|
1893
1908
|
recordStartup('agent-ready');
|
|
1894
|
-
//
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1909
|
+
// GUI 始终注册 mobile server 的运行时桥接;开关打开时才开始监听。
|
|
1910
|
+
// 这样从关闭态切到开启态时也能在当前 GUI 进程中原地重启服务。
|
|
1911
|
+
try {
|
|
1912
|
+
const { configureHostedServer, runServer } = require('./server');
|
|
1913
|
+
configureHostedServer(root, {
|
|
1914
|
+
agent,
|
|
1915
|
+
automation,
|
|
1916
|
+
onWorkEvent: event => broadcastAgentWorkEvent(event, false),
|
|
1917
|
+
subscribeWorkEvents: listener => {
|
|
1918
|
+
mobileServerWorkEventSubscribers.add(listener);
|
|
1919
|
+
return () => mobileServerWorkEventSubscribers.delete(listener);
|
|
1920
|
+
},
|
|
1921
|
+
conversationUiState: async (requested) => {
|
|
1922
|
+
const target = conversationRuntimeTarget(requested);
|
|
1923
|
+
const snapshot = wslBackendEnabled()
|
|
1924
|
+
? await ensureWslConversationPool().snapshot(target)
|
|
1925
|
+
: await ensureElectronUtilityPool().snapshot(target);
|
|
1926
|
+
const flowRunning = flowRunningForTarget(target);
|
|
1927
|
+
const flowSuspension = flowSuspensionForTarget(target);
|
|
1928
|
+
return {
|
|
1929
|
+
...snapshot,
|
|
1930
|
+
flow: flowRunning ? {
|
|
1931
|
+
running: true,
|
|
1932
|
+
paused: false,
|
|
1933
|
+
name: flowRunning.name,
|
|
1934
|
+
promptText: String(activeFlowStateFor(target)?.input || ''),
|
|
1935
|
+
message: '',
|
|
1936
|
+
} : flowSuspension ? {
|
|
1937
|
+
running: true,
|
|
1938
|
+
paused: true,
|
|
1939
|
+
name: flowSuspension.workflowName || '',
|
|
1940
|
+
promptText: String(flowSuspension.input || ''),
|
|
1941
|
+
message: String(flowSuspension.message || ''),
|
|
1942
|
+
reason: flowSuspension.reason || '',
|
|
1943
|
+
} : null,
|
|
1944
|
+
};
|
|
1945
|
+
},
|
|
1946
|
+
conversationUiAction: async (requested, action, value, input) => {
|
|
1947
|
+
const target = conversationRuntimeTarget(requested);
|
|
1948
|
+
if (action.startsWith('queue_')) {
|
|
1949
|
+
const queueAction = action === 'queue_enqueue' ? 'enqueue'
|
|
1950
|
+
: action === 'queue_update' ? 'update'
|
|
1951
|
+
: action === 'queue_delete' ? 'delete'
|
|
1952
|
+
: action === 'queue_reorder' ? 'reorder'
|
|
1953
|
+
: action === 'queue_toggle_pause' ? 'toggle_pause'
|
|
1954
|
+
: 'guide';
|
|
1955
|
+
const queueInput = {
|
|
1956
|
+
id: String(input?.id || ''),
|
|
1957
|
+
text: String(input?.text || value || ''),
|
|
1958
|
+
requestedMode: String(input?.requestedMode || 'build'),
|
|
1959
|
+
goalObjective: String(input?.goalObjective || ''),
|
|
1960
|
+
createdAt: String(input?.createdAt || ''),
|
|
1961
|
+
orderedIds: Array.isArray(input?.orderedIds)
|
|
1962
|
+
? input.orderedIds.map((id) => String(id || ''))
|
|
1963
|
+
: undefined,
|
|
1964
|
+
};
|
|
1965
|
+
return wslBackendEnabled()
|
|
1966
|
+
? await ensureWslConversationPool().queueAction(target, queueAction, queueInput)
|
|
1967
|
+
: await ensureElectronUtilityPool().queueAction(target, queueAction, queueInput);
|
|
1968
|
+
}
|
|
1969
|
+
if (action === 'goal_update') {
|
|
1970
|
+
return { goal: await mutateTargetConversation(target, () => {
|
|
1971
|
+
const isolated = isolatedConversationAgent(target);
|
|
1972
|
+
isolated.updateGoal(String(value || '').trim());
|
|
1973
|
+
isolated.setMode('goal');
|
|
1974
|
+
isolated.saveWorkspaceConversationState(true);
|
|
1975
|
+
return isolated.getConversationSnapshot(target.conversationId).goal;
|
|
1976
|
+
}) };
|
|
1977
|
+
}
|
|
1978
|
+
if (action === 'goal_guide' || action === 'conversation_guide') {
|
|
1979
|
+
const objective = action === 'goal_guide' ? String(value || '').trim() : '';
|
|
1980
|
+
const guideText = String(value || '').trim();
|
|
1908
1981
|
const snapshot = wslBackendEnabled()
|
|
1909
1982
|
? await ensureWslConversationPool().snapshot(target)
|
|
1910
1983
|
: await ensureElectronUtilityPool().snapshot(target);
|
|
1911
|
-
const
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
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 };
|
|
1987
|
-
}
|
|
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);
|
|
1984
|
+
const runtime = snapshot.runtime;
|
|
1985
|
+
// `running` may turn false one IPC task before a finalization-
|
|
1986
|
+
// window Guide reaches the worker. Preserve the authoritative
|
|
1987
|
+
// runId and let ConversationKernel decide whether that run can
|
|
1988
|
+
// be reactivated or must reject a genuinely stale request.
|
|
1989
|
+
if (!guideText || !runtime?.runId) {
|
|
1990
|
+
return { ok: false, error: action === 'goal_guide'
|
|
1991
|
+
? 'There is no active Build for this Goal Guide.'
|
|
1992
|
+
: 'Target conversation is not running.' };
|
|
2015
1993
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
1994
|
+
const prefix = 'Goal for the current Build:\n';
|
|
1995
|
+
const now = new Date().toISOString();
|
|
1996
|
+
const envelope = {
|
|
1997
|
+
clientMessageId: (0, crypto_1.randomUUID)(),
|
|
1998
|
+
guideId: (0, crypto_1.randomUUID)(),
|
|
1999
|
+
target: { workspaceId: target.workspaceId, conversationId: target.conversationId },
|
|
2000
|
+
runId: runtime.runId,
|
|
2001
|
+
deliveryMode: 'steer',
|
|
2002
|
+
text: objective ? prefix + objective : guideText,
|
|
2003
|
+
goalObjective: objective || undefined,
|
|
2004
|
+
createdAt: now,
|
|
2005
|
+
};
|
|
2006
|
+
const receipt = wslBackendEnabled()
|
|
2007
|
+
? await ensureWslConversationPool().enqueueGuide(envelope)
|
|
2008
|
+
: await ensureElectronUtilityPool().enqueueGuide(envelope);
|
|
2009
|
+
return { ok: receipt.status !== 'rejected', receipt };
|
|
2010
|
+
}
|
|
2011
|
+
if (action === 'goal_toggle_pause') {
|
|
2012
|
+
const resident = wslBackendEnabled()
|
|
2013
|
+
? await ensureWslConversationPool().toggleGoalPause(target)
|
|
2014
|
+
: await ensureElectronUtilityPool().toggleGoalPause(target);
|
|
2015
|
+
const paused = resident !== null ? resident : await mutateTargetConversation(target, () => isolatedConversationAgent(target).toggleGoalPause());
|
|
2016
|
+
return { ok: true, paused };
|
|
2017
|
+
}
|
|
2018
|
+
if (action === 'goal_clear') {
|
|
2019
|
+
const resident = wslBackendEnabled()
|
|
2020
|
+
? await ensureWslConversationPool().clearGoal(target)
|
|
2021
|
+
: await ensureElectronUtilityPool().clearGoal(target);
|
|
2022
|
+
if (resident === null)
|
|
2023
|
+
await mutateTargetConversation(target, () => isolatedConversationAgent(target).clearGoal());
|
|
2024
|
+
return { ok: true, cleared: true };
|
|
2025
|
+
}
|
|
2026
|
+
if (action === 'flow_pause')
|
|
2027
|
+
return await stopFlowForTarget(target);
|
|
2028
|
+
if (action === 'flow_resume')
|
|
2029
|
+
return await resumeFlowForTarget(String(value || ''), target);
|
|
2030
|
+
if (action === 'conversation_stop') {
|
|
2033
2031
|
const snapshot = wslBackendEnabled()
|
|
2034
2032
|
? await ensureWslConversationPool().snapshot(target)
|
|
2035
2033
|
: await ensureElectronUtilityPool().snapshot(target);
|
|
2036
|
-
const
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
};
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2034
|
+
const runtime = snapshot.runtime;
|
|
2035
|
+
return wslBackendEnabled()
|
|
2036
|
+
? await ensureWslConversationPool().requestStop(target, runtime?.runId)
|
|
2037
|
+
: await ensureElectronUtilityPool().requestStop(target, runtime?.runId);
|
|
2038
|
+
}
|
|
2039
|
+
if (action === 'input_mode') {
|
|
2040
|
+
const mode = String(value || '') === 'next' ? 'next' : 'guide';
|
|
2041
|
+
const selected = wslBackendEnabled()
|
|
2042
|
+
? await ensureWslConversationPool().setInputMode(target, mode)
|
|
2043
|
+
: await ensureElectronUtilityPool().setInputMode(target, mode);
|
|
2044
|
+
return { ok: true, inputMode: selected || mode };
|
|
2045
|
+
}
|
|
2046
|
+
const flow = activeFlowStateFor(target);
|
|
2047
|
+
if (!flow?.abortController || !flow.flowAgent)
|
|
2048
|
+
return { ok: false, error: 'No active Flow accepts Guide input.' };
|
|
2049
|
+
const accepted = flow.flowAgent.queueActiveKernelMessage(String(value || '').trim(), 'steer') || false;
|
|
2050
|
+
return accepted ? { ok: true, accepted: true, flow: flow.name } : { ok: false, error: 'The current Flow Build is not accepting Guide input.' };
|
|
2051
|
+
},
|
|
2052
|
+
conversationPrompt: async (requested, message, requestedOptions) => {
|
|
2053
|
+
const target = conversationRuntimeTarget(requested);
|
|
2054
|
+
if (activeFlowStateFor(target))
|
|
2055
|
+
clearFlowSuspensionForNewWork(target);
|
|
2056
|
+
const snapshot = wslBackendEnabled()
|
|
2057
|
+
? await ensureWslConversationPool().snapshot(target)
|
|
2058
|
+
: await ensureElectronUtilityPool().snapshot(target);
|
|
2059
|
+
const requestedMode = String(requestedOptions?.requestedMode || '').toLowerCase();
|
|
2060
|
+
const goalObjective = String(requestedOptions?.goalObjective || '').trim();
|
|
2061
|
+
const mode = (goalObjective || requestedMode === 'goal') ? 'build' : String(snapshot.mode || 'build');
|
|
2062
|
+
const inputMode = String(requestedOptions?.inputMode || snapshot.inputMode || 'guide') === 'next' ? 'next' : 'guide';
|
|
2063
|
+
const options = {
|
|
2064
|
+
mode,
|
|
2065
|
+
model: String(snapshot.model || agent.ensureUsableModelSelection()),
|
|
2066
|
+
intelligence: String(snapshot.intelligence || agent.intelligence),
|
|
2067
|
+
inputMode,
|
|
2068
|
+
engine: agent.engine,
|
|
2069
|
+
};
|
|
2070
|
+
const queueMode = inputMode === 'guide' ? 'steer' : 'followUp';
|
|
2071
|
+
const promptMessage = goalObjective ? {
|
|
2072
|
+
text: message,
|
|
2073
|
+
visibleMode: 'goal',
|
|
2074
|
+
goalObjective,
|
|
2075
|
+
} : message;
|
|
2076
|
+
const result = wslBackendEnabled()
|
|
2077
|
+
? await ensureWslConversationPool().prompt({
|
|
2078
|
+
message: promptMessage,
|
|
2079
|
+
target,
|
|
2080
|
+
conversationId: target.conversationId,
|
|
2081
|
+
options,
|
|
2082
|
+
queueMode,
|
|
2083
|
+
workspace: target.workspace ? {
|
|
2084
|
+
id: target.workspace.id,
|
|
2085
|
+
name: target.workspace.name,
|
|
2086
|
+
path: target.workspace.path,
|
|
2087
|
+
isInternal: target.workspace.isInternal,
|
|
2088
|
+
kind: target.workspace.kind,
|
|
2089
|
+
} : null,
|
|
2090
|
+
})
|
|
2091
|
+
: await ensureElectronUtilityPool().prompt({ message: promptMessage, target, options, queueMode });
|
|
2092
|
+
return { ...result };
|
|
2093
|
+
},
|
|
2094
|
+
});
|
|
2095
|
+
if (agent.config.getBool('remote', 'touch_enabled')) {
|
|
2096
|
+
runServer(root);
|
|
2072
2097
|
recordStartup('mobile-server-hosted');
|
|
2073
2098
|
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2099
|
+
}
|
|
2100
|
+
catch (error) {
|
|
2101
|
+
console.error('[Newmark] hosted mobile server failed:', error instanceof Error ? error.message : String(error));
|
|
2077
2102
|
}
|
|
2078
2103
|
}
|
|
2079
2104
|
};
|
|
@@ -3878,10 +3903,31 @@ else {
|
|
|
3878
3903
|
electronUtilityRuntimePool?.updateSetting(section, key, value),
|
|
3879
3904
|
wslAgentRuntimePool?.updateSetting(section, key, value),
|
|
3880
3905
|
]);
|
|
3906
|
+
if (section === 'remote' && key === 'touch_enabled') {
|
|
3907
|
+
const { setHostedServerEnabled } = require('./server');
|
|
3908
|
+
await setHostedServerEnabled(value === true || value === 'on');
|
|
3909
|
+
}
|
|
3881
3910
|
return true;
|
|
3882
3911
|
}
|
|
3883
3912
|
return false;
|
|
3884
3913
|
});
|
|
3914
|
+
electron_1.ipcMain.handle('mobile:serverStatus', async () => {
|
|
3915
|
+
if (!agent)
|
|
3916
|
+
return { enabled: false, listening: false, reachable: false, state: 'off', host: '', port: 47890, error: 'Agent not initialized', checkedAt: new Date().toISOString(), startedAt: 0 };
|
|
3917
|
+
const enabled = agent.config.getBool('remote', 'touch_enabled');
|
|
3918
|
+
const { hostedServerStatus } = require('./server');
|
|
3919
|
+
return await hostedServerStatus(enabled);
|
|
3920
|
+
});
|
|
3921
|
+
electron_1.ipcMain.handle('mobile:setRemoteTouchEnabled', async (_event, value) => {
|
|
3922
|
+
if (!agent)
|
|
3923
|
+
return { ok: false, error: 'Agent not initialized' };
|
|
3924
|
+
const enabled = value === true;
|
|
3925
|
+
agent.config.set('remote', 'touch_enabled', enabled);
|
|
3926
|
+
agent.config.save();
|
|
3927
|
+
const { setHostedServerEnabled } = require('./server');
|
|
3928
|
+
const status = await setHostedServerEnabled(enabled);
|
|
3929
|
+
return { ok: true, ...status };
|
|
3930
|
+
});
|
|
3885
3931
|
electron_1.ipcMain.handle('agent:openGlobalConfig', async () => {
|
|
3886
3932
|
if (!agent)
|
|
3887
3933
|
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,22 @@ 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 const MOBILE_WORKSPACE_UPLOAD_MAX_BYTES: number;
|
|
42
|
+
export declare function configureHostedServer(root: string, options?: HostedMobileServerOptions): void;
|
|
43
|
+
export declare function stopHostedServer(): Promise<void>;
|
|
44
|
+
export declare function hostedServerStatus(enabled?: boolean, probeHost?: string): Promise<HostedMobileServerStatus>;
|
|
45
|
+
export declare function setHostedServerEnabled(enabled: boolean, probeHost?: string): Promise<HostedMobileServerStatus>;
|
|
30
46
|
/** 托管启动 server(GUI/TUI 内嵌调用;幂等防重入,进程常驻即服务常驻) */
|
|
31
47
|
export declare function runServer(root: string, options?: HostedMobileServerOptions): void;
|
|
32
48
|
/** Attach the GUI-owned automation manager after deferred startup. */
|