Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/OpenClaw.Shared/IOperatorGatewayClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public interface IOperatorGatewayClient
event EventHandler<JsonElement>? AgentsListUpdated;
event EventHandler<JsonElement>? AgentFilesListUpdated;
event EventHandler<JsonElement>? AgentFileContentUpdated;
event EventHandler<AgentEventInfo>? ChatEventReceived;

// ─── Query ───
string? OperatorDeviceId { get; }
Expand All @@ -53,6 +54,7 @@ public interface IOperatorGatewayClient

// ─── Request Methods ───
Task SendChatMessageAsync(string message, string? sessionKey = null);
Task<ChatSendResult> SendChatMessageForRunAsync(string message, string? sessionKey = null);
Task CheckHealthAsync();
Task RequestSessionsAsync(string? agentId = null);
Task RequestUsageAsync();
Expand Down
7 changes: 7 additions & 0 deletions src/OpenClaw.Shared/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1660,6 +1660,13 @@ public string DataJson
}
}

public sealed class ChatSendResult
{
public string? RunId { get; init; }
public string? SessionKey { get; init; }
public bool Cached { get; init; }
}

// ── Node/Device Pairing ──

public class PairingRequest
Expand Down
82 changes: 76 additions & 6 deletions src/OpenClaw.Shared/OpenClawGatewayClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class OpenClawGatewayClient : WebSocketClientBase, IOperatorGatewayClient
private GatewayUsageStatusInfo? _usageStatus;
private GatewayCostUsageInfo? _usageCost;
private readonly Dictionary<string, string> _pendingRequestMethods = new();
private readonly Dictionary<string, TaskCompletionSource<bool>> _pendingChatSendRequests = new();
private readonly Dictionary<string, TaskCompletionSource<ChatSendResult>> _pendingChatSendRequests = new();
private readonly object _pendingRequestLock = new();
private readonly object _pendingChatSendLock = new();
private readonly object _sessionsLock = new();
Expand Down Expand Up @@ -175,6 +175,7 @@ protected override void OnDisposing()
public event EventHandler<JsonElement>? AgentsListUpdated;
public event EventHandler<JsonElement>? AgentFilesListUpdated;
public event EventHandler<JsonElement>? AgentFileContentUpdated;
public event EventHandler<AgentEventInfo>? ChatEventReceived;

/// <summary>Raised when a device token is received from the gateway during hello-ok handshake.</summary>
public event EventHandler<DeviceTokenReceivedEventArgs>? DeviceTokenReceived;
Expand Down Expand Up @@ -251,6 +252,11 @@ public async Task CheckHealthAsync()
}

public async Task SendChatMessageAsync(string message, string? sessionKey = null)
{
_ = await SendChatMessageForRunAsync(message, sessionKey).ConfigureAwait(false);
}

public async Task<ChatSendResult> SendChatMessageForRunAsync(string message, string? sessionKey = null)
{
if (!IsConnected)
throw new InvalidOperationException("Gateway connection is not open");
Expand All @@ -262,7 +268,7 @@ public async Task SendChatMessageAsync(string message, string? sessionKey = null
: sessionKey.Trim();

var requestId = Guid.NewGuid().ToString();
var completion = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
var completion = new TaskCompletionSource<ChatSendResult>(TaskCreationOptions.RunContinuationsAsynchronously);
TrackPendingChatSend(requestId, completion);

var req = new
Expand All @@ -287,8 +293,9 @@ public async Task SendChatMessageAsync(string message, string? sessionKey = null
throw new TimeoutException("Timed out waiting for chat.send response from gateway");
}

await completion.Task;
var result = await completion.Task.ConfigureAwait(false);
_logger.Info($"Sent chat message ({message.Length} chars)");
return result;
}

/// <summary>
Expand Down Expand Up @@ -886,7 +893,7 @@ private void ClearPendingRequests()
_pendingWizardResponses.Clear();
}

private void TrackPendingChatSend(string requestId, TaskCompletionSource<bool> completion)
private void TrackPendingChatSend(string requestId, TaskCompletionSource<ChatSendResult> completion)
{
lock (_pendingChatSendLock)
{
Expand All @@ -902,7 +909,7 @@ private void RemovePendingChatSend(string requestId)
}
}

private TaskCompletionSource<bool>? TakePendingChatSend(string? requestId)
private TaskCompletionSource<ChatSendResult>? TakePendingChatSend(string? requestId)
{
if (string.IsNullOrWhiteSpace(requestId))
{
Expand Down Expand Up @@ -975,7 +982,7 @@ private void HandleResponse(JsonElement root)
return;
}

pendingChatSend.TrySetResult(true);
pendingChatSend.TrySetResult(ParseChatSendResult(root));
return;
}

Expand Down Expand Up @@ -1205,6 +1212,36 @@ private bool HandleKnownResponse(string method, JsonElement payload)
}
}

private static ChatSendResult ParseChatSendResult(JsonElement root)
{
string? runId = null;
string? sessionKey = null;
var cached = false;

if (root.TryGetProperty("payload", out var payload) && payload.ValueKind == JsonValueKind.Object)
{
if (payload.TryGetProperty("runId", out var runIdProp))
runId = runIdProp.GetString();
if (payload.TryGetProperty("sessionKey", out var sessionKeyProp))
sessionKey = sessionKeyProp.GetString();
}

if (root.TryGetProperty("meta", out var meta) &&
meta.ValueKind == JsonValueKind.Object &&
meta.TryGetProperty("cached", out var cachedProp) &&
cachedProp.ValueKind is JsonValueKind.True or JsonValueKind.False)
{
cached = cachedProp.GetBoolean();
}

return new ChatSendResult
{
RunId = runId,
SessionKey = sessionKey,
Cached = cached
};
}

private void HandleRequestError(string? method, JsonElement root)
{
var message = TryGetErrorMessage(root) ?? "request failed";
Expand Down Expand Up @@ -1979,6 +2016,7 @@ private void HandleChatEvent(JsonElement root)
_logger.Debug($"Chat event received: {rawText[..Math.Min(200, rawText.Length)]}");

if (!root.TryGetProperty("payload", out var payload)) return;
EmitRawChatEvent(payload);

// Try new format: payload.message.role + payload.message.content[].text
if (payload.TryGetProperty("message", out var message))
Expand Down Expand Up @@ -2021,6 +2059,38 @@ private void HandleChatEvent(JsonElement root)
}
}

private void EmitRawChatEvent(JsonElement payload)
{
try
{
var stream = "chat";
if (payload.TryGetProperty("message", out var message) &&
message.TryGetProperty("role", out var roleProp))
{
stream = roleProp.GetString() ?? stream;
}
else if (payload.TryGetProperty("role", out var legacyRoleProp))
{
stream = legacyRoleProp.GetString() ?? stream;
}

var evt = new AgentEventInfo
{
RunId = payload.TryGetProperty("runId", out var rid) ? rid.GetString() ?? "" : "",
Seq = payload.TryGetProperty("seq", out var seqProp) && seqProp.ValueKind == JsonValueKind.Number ? seqProp.GetInt32() : 0,
Stream = stream,
Ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
Data = payload.Clone(),
SessionKey = payload.TryGetProperty("sessionKey", out var sk) ? sk.GetString() : null
};
ChatEventReceived?.Invoke(this, evt);
}
catch (Exception ex)
{
_logger.Warn($"Failed to emit chat event: {ex.Message}");
}
}

private void EmitChatNotification(string text)
{
var displayText = text.Length > 200 ? text[..200] + "…" : text;
Expand Down
24 changes: 23 additions & 1 deletion src/OpenClaw.Tray.WinUI/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
/// Ensures the managed SSH tunnel is started using the current settings.
/// Used by the onboarding ConnectionPage when the user picks the SSH topology.
/// </summary>
public void EnsureSshTunnelStarted() => _sshTunnelService?.EnsureStarted(_settings);

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-x64)

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

Check warning on line 66 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

Possible null reference argument for parameter 'settings' in 'void SshTunnelService.EnsureStarted(SettingsManager settings)'.

/// <summary>
/// Creates the WSL local gateway setup engine using the current tray settings.
Expand Down Expand Up @@ -243,7 +243,7 @@
if (allowedLocales.Contains(langOverride.ToLowerInvariant()))
LocalizationHelper.SetLanguageOverride(langOverride);
else
Logger.Warn($"[App] Ignoring invalid OPENCLAW_LANGUAGE value: {langOverride}");

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 246 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
}

InitializeComponent();
Expand Down Expand Up @@ -280,7 +280,7 @@
MarkRunEnded();
try
{
Logger.Info($"Process exiting (ExitCode={Environment.ExitCode})");

Check warning on line 283 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 283 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 283 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 283 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 283 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
}
catch { }
}
Expand All @@ -302,11 +302,11 @@
{
if (ex != null)
{
Logger.Error($"CRASH {source}: {ex}");

Check warning on line 305 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 305 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 305 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 305 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
}
else
{
Logger.Error($"CRASH {source}");

Check warning on line 309 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 309 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 309 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
}
}
catch { /* Ignore logging failures */ }
Expand All @@ -319,7 +319,7 @@
if (File.Exists(RunMarkerPath))
{
var startedAt = File.ReadAllText(RunMarkerPath);
Logger.Error($"Previous session did not exit cleanly (started {startedAt})");

Check warning on line 322 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / test

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 322 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 322 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
File.Delete(RunMarkerPath);
}
}
Expand Down Expand Up @@ -482,7 +482,8 @@
nodeConnector: nodeConnector,
isNodeEnabled: ShouldInitializeNodeService,
diagnostics: diagnostics,
tunnelManager: tunnelManager);
tunnelManager: tunnelManager,
shouldStartNodeConnection: ShouldInitializeNodeService);
_connectionManager.OperatorClientChanged += OnOperatorClientChanged;
_connectionManager.StateChanged += OnManagerStateChanged;

Expand Down Expand Up @@ -2189,6 +2190,27 @@
return _settings?.EnableNodeMode == true || _settings?.EnableMcpServer == true;
}

private bool ShouldInitializeNodeService(GatewayRecord activeGateway, string managerIdentityPath)
{
if (!ShouldInitializeNodeService()) return false;

if (LocalNodeServiceOwnsIdentityFor(activeGateway))
{
Logger.Info("[ConnMgr] Suppressing manager-owned NodeConnector because local NodeService owns the active local gateway identity");
return false;
}

return true;
}

private bool LocalNodeServiceOwnsIdentityFor(GatewayRecord activeGateway)
{
if (!activeGateway.IsLocal || _settings == null) return false;
if (!StartupSetupState.HasStoredNodeDeviceToken(IdentityDataPath)) return false;

return EnsureNodeServiceForLocalGatewaySetup(_settings) != null;
}

private void OnNodeStatusChanged(object? sender, ConnectionStatus status)
{
Logger.Info($"Node status: {status}");
Expand Down Expand Up @@ -4391,9 +4413,9 @@

internal class AppLogger : IOpenClawLogger
{
public void Info(string message) => Logger.Info(message);

Check warning on line 4416 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4416 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4416 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
public void Debug(string message) => Logger.Debug(message);

Check warning on line 4417 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4417 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4417 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
public void Warn(string message) => Logger.Warn(message);

Check warning on line 4418 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4418 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4418 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build-msix (win-arm64)

The type 'Logger' in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'C:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
public void Error(string message, Exception? ex = null) =>
Logger.Error(ex != null ? $"{message}: {ex.Message}" : message);

Check warning on line 4420 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.

Check warning on line 4420 in src/OpenClaw.Tray.WinUI/App.xaml.cs

View workflow job for this annotation

GitHub Actions / build (win-x64)

The type 'Logger' in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs' conflicts with the imported type 'Logger' in 'OpenClawTray.FunctionalUI, Version=0.5.1.0, Culture=neutral, PublicKeyToken=null'. Using the type defined in 'D:\a\openclaw-windows-node\openclaw-windows-node\src\OpenClaw.Tray.WinUI\Services\Logger.cs'.
}
20 changes: 0 additions & 20 deletions src/OpenClaw.Tray.WinUI/Onboarding/OnboardingWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,6 @@ private async Task InitializeChatWebViewAsync()
})();
");

_ = SendBootstrapMessageAsync();
}
});
};
Expand Down Expand Up @@ -517,25 +516,6 @@ private void ShowChatError(string message)
}
}

private bool _bootstrapSent;

/// <summary>
/// Auto-sends the bootstrap kickoff message after the web chat loads.
/// Delegates to <see cref="BootstrapMessageInjector"/> so the same gated
/// kickoff fires from both the (legacy) onboarding chat overlay and from
/// post-wizard HubWindow chat navigation — guarded by
/// <see cref="SettingsManager.HasInjectedFirstRunBootstrap"/>.
/// </summary>
private async Task SendBootstrapMessageAsync()
{
if (_bootstrapSent || _chatWebView?.CoreWebView2 == null) return;
_bootstrapSent = true;

await BootstrapMessageInjector.InjectAsync(
script => _chatWebView.CoreWebView2.ExecuteScriptAsync(script).AsTask(),
_settings);
}

/// <summary>
/// Captures the current window content to a PNG file.
/// Called automatically on page navigation when OPENCLAW_VISUAL_TEST=1.
Expand Down
18 changes: 17 additions & 1 deletion src/OpenClaw.Tray.WinUI/Pages/ChatPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,23 @@

<!-- Loading -->
<ProgressRing x:Name="LoadingRing" Grid.Row="1" IsActive="False"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
HorizontalAlignment="Center" VerticalAlignment="Center"/>

<StackPanel x:Name="WaitingPanel" Grid.Row="1"
Visibility="Collapsed"
VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="12">
<TextBlock Text="💬" FontSize="48" HorizontalAlignment="Center"/>
<TextBlock Text="Waiting for chat to start…"
Style="{StaticResource SubtitleTextBlockStyle}"
HorizontalAlignment="Center"/>
<TextBlock x:Name="WaitingStatusText"
Text="The gateway is connected; the chat surface is still coming online."
Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center" TextWrapping="Wrap" MaxWidth="360"/>
<Button x:Name="RetryChatButton" Content="Retry" Click="OnRetryChat" Visibility="Collapsed"
HorizontalAlignment="Center"/>
</StackPanel>

<!-- Placeholder (shown when not connected) -->
<StackPanel x:Name="PlaceholderPanel" Grid.Row="1"
Expand Down
Loading
Loading