Skip to content

翻訳モジュールとしてGitHub Copilotの対応#584

Open
Copilot wants to merge 7 commits intomasterfrom
copilot/add-translation-module-plugin
Open

翻訳モジュールとしてGitHub Copilotの対応#584
Copilot wants to merge 7 commits intomasterfrom
copilot/add-translation-module-plugin

Conversation

Copy link
Contributor

Copilot AI commented Mar 1, 2026

GitHub.Copilot.SDK を利用した新しい翻訳プラグインを追加。LLMPlugin/GoogleAIPluginと同様の構造で、補正モードなし・翻訳コンテキスト・用語集に対応。

新規プラグイン: WindowTranslator.Plugin.GitHubCopilotPlugin

  • GitHubCopilotTranslator: ITranslateModule + IAsyncDisposable を実装

    • CopilotClient をライフタイム管理、SendAndWaitAsync でレスポンス取得
    • RegisterContext / RegisterGlossaryAsync でコンテキスト・用語集をサポート
    • インスタンス単位で1セッションのみ使用(初回 TranslateAsync 呼び出し時に AsyncLazy<CopilotSession> で lazy initialization)
    • セッションのシステムメッセージに基本的な翻訳指示を設定し、用語集は翻訳リクエストごとにプロンプトへ含める
  • GitHubCopilotOptions: モデル選択(コンボボックス、デフォルト gpt-4o)、翻訳コンテキスト、用語集CSVパスを設定

    • プラグインロード時に CopilotClient.ListModelsAsync() でSDKからモデル一覧を非同期取得し、コンボボックスに表示
    • CLIが未インストールの場合は gpt-4oclaude-sonnet-4.5 等のデフォルト一覧にフォールバック
  • GitHubCopilotValidator: copilot CLIが PATH に存在するかチェックし、未インストール時にガイダンスを表示

  • 18言語分のローカライズリソース作成済み

// AsyncLazy でセッションをインスタンス単位で1度だけ作成し、以降再利用
private readonly AsyncLazy<CopilotSession> session;

private async ValueTask<CopilotSession> CreateSessionAsync()
{
    var system = string.Join(Environment.NewLine, [this.preSystem, this.context, this.userContext, this.postSystem]);
    var s = await this.client.CreateSessionAsync(new()
    {
        Model = this.model,
        SystemMessage = new() { Mode = SystemMessageMode.Replace, Content = system },
        OnPermissionRequest = PermissionHandler.ApproveAll,
        ReasoningEffort = "low",
    }).ConfigureAwait(false);
    this.sessionStarted = true;
    return s;
}

var session = await this.session.AsValueTask().ConfigureAwait(false);
var response = await session.SendAndWaitAsync(new MessageOptions { Prompt = content }).ConfigureAwait(false);

本体側の変更

  • MainWindowModule: ウィンドウクローズ時のスコープ破棄を provider.CreateAsyncScope() + DisposeAsync() に変更
    • 従来の同期 scope.Dispose() では IAsyncDisposable のみを実装するサービスに対して InvalidOperationException が発生するため修正
    • GitHubCopilotTranslator.DisposeAsync() がウィンドウクローズ時に適切に呼び出されるよう対応

依存関係の変更

  • GitHub.Copilot.SDK 0.1.29 を追加
  • ValueTaskSupplementGitHubCopilotPlugin に追加(AsyncLazy<T> の利用のため)
  • Microsoft.Extensions.Logging.Abstractions10.0.010.0.2 に更新(SDK要件)
Original prompt

This section details on the original issue you should resolve

<issue_title>翻訳モジュールとしてGitHub Copilotの対応</issue_title>
<issue_description>https://www.nuget.org/packages/GitHub.Copilot.SDK を利用して新しい翻訳モジュールプラグインを実装する。

  • Pluginsフォルダに新しいプロジェクトとしてプラグインを利用する
  • LLMプラグインやGoogleAIプラグインを参考に実装する
    • 補正モードは対応しない
    • 翻訳コンテキスト、用語集には対応する
  • モデルをオプションで選択できるようにする
    • モデル一覧はSDKから取得する

参考資料

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: Freeesia <9002657+Freeesia@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement translation module plugin using GitHub Copilot SDK 翻訳モジュールとしてGitHub Copilotの対応 Mar 1, 2026
@Freeesia Freeesia requested a review from Copilot March 1, 2026 16:11
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

このPRは、GitHub.Copilot.SDK を利用した新しい翻訳プラグイン WindowTranslator.Plugin.GitHubCopilotPlugin を追加するものです。LLMPlugin/GoogleAIPluginと同様の構造に従い、翻訳コンテキスト・用語集・18言語のローカライズに対応します。

Changes:

  • 新プラグイン GitHubCopilotTranslator の追加:ITranslateModule + IAsyncDisposable を実装し、GitHub Copilot SDK を使ってセッションごとに翻訳を実行
  • GitHubCopilotOptions / GitHubCopilotValidator の追加:モデル文字列(デフォルト gpt-4o)とCLIの存在チェックを実装
  • 18言語分のローカライズリソース追加、および Microsoft.Extensions.Logging.Abstractions のバージョン更新(10.0.010.0.2

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
WindowTranslator.sln 新プロジェクトをソリューションに追加
Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/WindowTranslator.Plugin.GitHubCopilotPlugin.csproj プロジェクト定義・依存パッケージ
Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/GitHubCopilotTranslator.cs 翻訳モジュールのコア実装
Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/GitHubCopilotOptions.cs オプション・バリデーター
Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/Properties/Resources.*.resx ローカライズリソース(18言語)
Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/Properties/Resources.Designer.cs 自動生成リソースクラス
Directory.Packages.props GitHub.Copilot.SDK 追加、Logging.Abstractions バージョン更新
Files not reviewed (1)
  • Plugins/WindowTranslator.Plugin.GitHubCopilotPlugin/Properties/Resources.Designer.cs: Language not supported

public class GitHubCopilotOptions : IPluginParam
{
[LocalizedDescription(typeof(Resources), $"{nameof(Model)}_Desc")]
public string Model { get; set; } = "gpt-4o";
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

元のissue要件では「モデル一覧はSDKから取得する」と明記されています。しかし、現在の実装では Model プロパティは自由入力の文字列型(デフォルト gpt-4o)となっており、GitHub Copilot SDKからのモデル一覧取得が実装されていません。

issueの要件とPRの実装の間に乖離があります。SDKに GetModelsAsync などのモデル一覧取得APIが存在する場合、コンボボックスなどで選択できるようにする必要がある可能性があります。

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ed5d345 で対応しました。

CopilotClient.ListModelsAsync() を使い、プラグインロード時にバックグラウンドでSDKからモデル一覧を非同期取得します。ItemsSourcePropertyAttribute を使って Model プロパティをコンボボックスとして表示します。CLIが未インストールの場合などは gpt-4o, claude-sonnet-4.5 等のデフォルトモデル一覧にフォールバックします。

Comment on lines +96 to +100
/// "GitHub Copilot機能が初期化されていません。..." に類似しているローカライズされた文字列を検索します。
/// </summary>
public static string NotInitialized => ResourceManager.GetString("NotInitialized", resourceCulture) ?? string.Empty;

/// <summary>
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NotInitialized というリソース文字列(「GitHub Copilot機能が初期化されていません。GitHub Copilot CLIがインストールされているか確認してください。」)はすべてのロケールファイルと Resources.Designer.cs で定義されていますが、GitHubCopilotTranslator.cs の実装内では参照されていません。

CopilotClient はコンストラクターで直接インスタンス化されており、nullチェックが不要なため、このリソースを使用する機会がありません。不要なリソースを全ロケールファイルから削除することを検討してください。

Suggested change
/// "GitHub Copilot機能が初期化されていません。..." に類似しているローカライズされた文字列を検索します。
/// </summary>
public static string NotInitialized => ResourceManager.GetString("NotInitialized", resourceCulture) ?? string.Empty;
/// <summary>

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ed5d345 で対応しました。全言語ファイル(19ファイル)と Resources.Designer.cs から未使用の NotInitialized リソースを削除しました。

Comment on lines +25 to +29
<value>「Terjemahan GitHub Copilot」telah dipilih sebagai modul terjemahan.

Untuk menggunakan terjemahan GitHub Copilot, GitHub Copilot CLI mesti dipasang dan log masuk.

Untuk pemasangan GitHub Copilot CLI, sila rujuk [dokumentasi GitHub Copilot CLI](https://docs.github.com/ms/copilot/github-copilot-in-the-cli).</value>
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub Docs では特定の言語コードのみがサポートされています(ar, de, en, es, fr, ja, ko, pt, ru, zh, zh-TW など)。Resources.ms.resx の URL https://docs.github.com/ms/copilot/github-copilot-in-the-cli で使用されている ms(マレー語)のロケールコードは GitHub Docs では正式にサポートされておらず、リンクが壊れている可能性があります。同様の問題が fa, fil, id, pl, th, tr, vi ロケールのリソースファイルにも存在します。サポートされていないロケールには en のURLを使用することを検討してください。

Suggested change
<value>Terjemahan GitHub Copilottelah dipilih sebagai modul terjemahan.
Untuk menggunakan terjemahan GitHub Copilot, GitHub Copilot CLI mesti dipasang dan log masuk.
Untuk pemasangan GitHub Copilot CLI, sila rujuk [dokumentasi GitHub Copilot CLI](https://docs.github.com/ms/copilot/github-copilot-in-the-cli).</value>
<value>Terjemahan GitHub Copilot telah dipilih sebagai modul terjemahan.
Untuk menggunakan terjemahan GitHub Copilot, GitHub Copilot CLI mesti dipasang dan log masuk.
Untuk pemasangan GitHub Copilot CLI, sila rujuk [dokumentasi GitHub Copilot CLI](https://docs.github.com/en/copilot/github-copilot-in-the-cli).</value>

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ed5d345 で対応しました。GitHub Docs がサポートしていないロケール(ms/fa/fil/id/pl/th/tr/vi)の InvalidOptions 内 URL をすべて en に変更しました。

@Freeesia
Copy link
Owner

Freeesia commented Mar 2, 2026

@copilot レビューの指摘点を確認して、修正が必要な所は直して

…otInitialized resource, fix unsupported locale URLs

Co-authored-by: Freeesia <9002657+Freeesia@users.noreply.github.com>
@Freeesia
Copy link
Owner

Freeesia commented Mar 2, 2026

@copilot セッションを引き継げる?

Copy link
Contributor Author

Copilot AI commented Mar 2, 2026

@copilot セッションを引き継げる?

はい、引き継げます。前回セッションで対応済みのレビューコメント(モデル一覧のSDK取得・NotInitializedリソース削除・URL修正)はコミット ed5d345 に含まれており、現在のブランチ最新コミットは 02c7d77 です。追加で対応が必要なことがあればお知らせください。

@Freeesia
Copy link
Owner

Freeesia commented Mar 3, 2026

@copilot
トランスレーターのインスタンス単位に1セッションだけ使うように修正して。

Co-authored-by: Freeesia <9002657+Freeesia@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot
トランスレーターのインスタンス単位に1セッションだけ使うように修正して。

4c0be1e で対応しました。

CopilotSession をインスタンスフィールドとして保持し、GetOrCreateSessionAsync() による double-checked locking パターンで最初の TranslateAsync 呼び出し時に1度だけセッションを作成し、以降は同じセッションを再利用します。用語集(glossary/common terms)は翻訳ごとの動的フィルタリングを維持するため、セッションのシステムメッセージではなくプロンプトに含めています。DisposeAsync でセッションも適切に破棄します。

@Freeesia
Copy link
Owner

Freeesia commented Mar 3, 2026

@copilot

DisposeAsyncって本体側で適切に破棄されるようになってる?

Co-authored-by: Freeesia <9002657+Freeesia@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 3, 2026

@copilot

DisposeAsyncって本体側で適切に破棄されるようになってる?

c729cf3 で修正しました。

MainWindowModule.csscope.Dispose()(同期)を調べたところ、IAsyncDisposable のみ実装するサービスに対して同期的に Dispose() を呼ぶと InvalidOperationException がスローされる問題がありました。

provider.CreateScope()new AsyncServiceScope(provider.CreateScope()) に変更し、ウィンドウ Closed 時は scope.DisposeAsync().AsTask().Forget()、catch ブロックでは await scope.DisposeAsync() を使うよう修正しました。これにより GitHubCopilotTranslator.DisposeAsync() が適切に呼び出されます。


private record Response(string[] Translated);

private async ValueTask<CopilotSession> GetOrCreateSessionAsync()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot

AsyncLazy使って

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

d6fb6a1 で修正しました。SemaphoreSlim + double-checked locking を AsyncLazy<CopilotSession> に置き換えました。volatile bool sessionStarted でセッション作成完了を追跡し、DisposeAsync でセッションが作成済みの場合のみ破棄します。

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

作成済みかどうかは、AsyncLazyのプロパティで判定できない?

Co-authored-by: Freeesia <9002657+Freeesia@users.noreply.github.com>
@Freeesia Freeesia marked this pull request as ready for review March 3, 2026 16:17
@Freeesia Freeesia self-requested a review March 9, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

翻訳モジュールとしてGitHub Copilotの対応

3 participants