Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 7 additions & 7 deletions src/OneWare.Copilot/CopilotModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,13 @@ ABSOLUTE PROHIBITIONS
[
new PackageVersion()
{
Version = "1.0.37",
Version = "1.0.54",
Targets =
[
new PackageTarget()
{
Target = "win-x64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-win32-x64.zip",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-win32-x64.zip",
AutoSetting =
[
new PackageAutoSetting
Expand All @@ -181,7 +181,7 @@ ABSOLUTE PROHIBITIONS
new PackageTarget()
{
Target = "win-arm64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-win32-arm64.zip",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-win32-arm64.zip",
AutoSetting =
[
new PackageAutoSetting
Expand All @@ -194,7 +194,7 @@ ABSOLUTE PROHIBITIONS
new PackageTarget()
{
Target = "linux-x64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-linux-x64.tar.gz",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-linux-x64.tar.gz",
AutoSetting =
[
new PackageAutoSetting
Expand All @@ -207,7 +207,7 @@ ABSOLUTE PROHIBITIONS
new PackageTarget()
{
Target = "linux-arm64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-linux-arm64.tar.gz",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-linux-arm64.tar.gz",
AutoSetting =
[
new PackageAutoSetting
Expand All @@ -220,7 +220,7 @@ ABSOLUTE PROHIBITIONS
new PackageTarget()
{
Target = "osx-x64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-darwin-x64.tar.gz",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-darwin-x64.tar.gz",
AutoSetting =
[
new PackageAutoSetting
Expand All @@ -233,7 +233,7 @@ ABSOLUTE PROHIBITIONS
new PackageTarget()
{
Target = "osx-arm64",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.37/copilot-darwin-arm64.tar.gz",
Url = "https://github.com/github/copilot-cli/releases/download/v1.0.54/copilot-darwin-arm64.tar.gz",
AutoSetting =
[
new PackageAutoSetting
Expand Down
3 changes: 2 additions & 1 deletion src/OneWare.Copilot/OneWare.Copilot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

<PropertyGroup>
<CopilotSkipCliDownload>true</CopilotSkipCliDownload>
<NoWarn>$(NoWarn);GHCP001</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GitHub.Copilot.SDK" Version="0.3.0" />
<PackageReference Include="GitHub.Copilot.SDK" Version="1.0.0-beta.7" />
</ItemGroup>

</Project>
85 changes: 65 additions & 20 deletions src/OneWare.Copilot/Services/CopilotChatService.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Avalonia.Controls;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DynamicData;
using GitHub.Copilot.SDK;
using GitHub.Copilot;
using GitHub.Copilot.Rpc;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Logging;
using OneWare.Copilot.Models;
using OneWare.Copilot.ViewModels;
Expand Down Expand Up @@ -36,6 +39,20 @@ public sealed class CopilotChatService(
private string? _requestedSessionId;
private readonly HashSet<string> _allowedPermissionScopes = new(StringComparer.OrdinalIgnoreCase);

// Usage tracking
public long LastInputTokens { get; private set => SetProperty(ref field, value); }
public long LastOutputTokens { get; private set => SetProperty(ref field, value); }
public long? LastReasoningTokens { get; private set => SetProperty(ref field, value); }
public long SessionTotalRequests { get; private set => SetProperty(ref field, value); }
public long SessionTotalInputTokens { get; private set => SetProperty(ref field, value); }
public long SessionTotalOutputTokens { get; private set => SetProperty(ref field, value); }
public long ContextCurrentTokens { get; private set => SetProperty(ref field, value); }
public long ContextTokenLimit { get; private set => SetProperty(ref field, value); }
public double? QuotaRemainingPercent { get; private set => SetProperty(ref field, value); }
public bool QuotaIsUnlimited { get; private set => SetProperty(ref field, value); }
public DateTimeOffset? QuotaResetDate { get; private set => SetProperty(ref field, value); }
public bool HasUsageData { get; private set => SetProperty(ref field, value); }

private static readonly Regex DeviceLoginUrlRegex = new(@"https?://\S+", RegexOptions.Compiled);
private static readonly Regex DeviceLoginCodeRegex = new(@"\bcode\s+([A-Z0-9\-]+)\b",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
Expand Down Expand Up @@ -197,8 +214,8 @@ public async Task<bool> InitializeAsync()

_client = new CopilotClient(new CopilotClientOptions()
{
Cwd = paths.ProjectsDirectory,
CliPath = cliPath
WorkingDirectory = paths.ProjectsDirectory,
Connection = RuntimeConnection.ForStdio(cliPath, [])
});

bool isAuthenticated;
Expand Down Expand Up @@ -279,7 +296,7 @@ private async Task InitializeSessionAsync()

if (string.IsNullOrWhiteSpace(sessionId))
{
var tools = toolProvider.GetTools();
var tools = toolProvider.GetTools().Cast<AIFunctionDeclaration>().ToList();
_session = await _client.CreateSessionAsync(new SessionConfig
{
Model = SelectedModel.Id,
Expand All @@ -304,7 +321,7 @@ private async Task InitializeSessionAsync()
{
Streaming = true,
IncludeSubAgentStreamingEvents = false,
Tools = toolProvider.GetTools(),
Tools = toolProvider.GetTools().Cast<AIFunctionDeclaration>().ToList(),
OnPermissionRequest = OnPermissionRequestAsync,
OnUserInputRequest = OnUserInputRequestAsync
});
Expand All @@ -320,7 +337,7 @@ private async Task InitializeSessionAsync()
return;
}

_subscription = _session.On(HandleSessionEvent);
_subscription = _session.On<SessionEvent>(HandleSessionEvent);
}

private string BuildSystemMessage()
Expand Down Expand Up @@ -429,6 +446,23 @@ private async Task DisposeSessionAsync()
}

CurrentSessionId = null;
ResetUsageStats();
}

private void ResetUsageStats()
{
LastInputTokens = 0;
LastOutputTokens = 0;
LastReasoningTokens = null;
SessionTotalRequests = 0;
SessionTotalInputTokens = 0;
SessionTotalOutputTokens = 0;
ContextCurrentTokens = 0;
ContextTokenLimit = 0;
QuotaRemainingPercent = null;
QuotaIsUnlimited = false;
QuotaResetDate = null;
HasUsageData = false;
}

private void HandleSessionEvent(SessionEvent evt)
Expand Down Expand Up @@ -478,10 +512,29 @@ private void HandleSessionEvent(SessionEvent evt)
case SessionIdleEvent:
EventReceived?.Invoke(this, new ChatIdleEvent());
break;
case AssistantUsageEvent usage:
UpdateUsageFromAssistantEvent(usage.Data);
break;
case SessionUsageInfoEvent info:
ContextCurrentTokens = info.Data.CurrentTokens;
ContextTokenLimit = info.Data.TokenLimit;
break;
}
}

private Task<PermissionRequestResult> OnPermissionRequestAsync(
private void UpdateUsageFromAssistantEvent(AssistantUsageData data)
{
LastInputTokens = data.InputTokens ?? 0;
LastOutputTokens = data.OutputTokens ?? 0;
LastReasoningTokens = data.ReasoningTokens is > 0 ? data.ReasoningTokens : null;
SessionTotalRequests++;
SessionTotalInputTokens += data.InputTokens ?? 0;
SessionTotalOutputTokens += data.OutputTokens ?? 0;

HasUsageData = true;
}

private Task<PermissionDecision> OnPermissionRequestAsync(
PermissionRequest request,
PermissionInvocation invocation)
{
Expand All @@ -496,7 +549,7 @@ private Task<PermissionRequestResult> OnPermissionRequestAsync(
return Task.FromResult(CreateAllowPermissionResult());
}

var responseSource = new TaskCompletionSource<PermissionRequestResult>(
var responseSource = new TaskCompletionSource<PermissionDecision>(
TaskCreationOptions.RunContinuationsAsynchronously);

var context = BuildPermissionContext(request, invocation);
Expand Down Expand Up @@ -611,22 +664,14 @@ private static void AddDetail(ICollection<string> details, string label, string?
details.Add($"{label}: `{trimmed}`");
}

private static PermissionRequestResult CreateAllowPermissionResult()
private static PermissionDecision CreateAllowPermissionResult()
{
return new PermissionRequestResult
{
Kind = PermissionRequestResultKind.Approved,
Rules = null
};
return PermissionDecision.ApproveOnce();
}

private static PermissionRequestResult CreateDenyPermissionResult()
private static PermissionDecision CreateDenyPermissionResult()
{
return new PermissionRequestResult
{
Kind = PermissionRequestResultKind.Rejected,
Rules = null
};
return PermissionDecision.Reject("");
}

private static bool IsCustomToolPermissionRequest(PermissionRequest request)
Expand Down
Loading
Loading