Skip to content

Fixes #9169 : Support AI chat providers beyond LangChain4j, with GitH… - #9186

Open
bamaer wants to merge 1 commit into
apache:mainfrom
bamaer:9169
Open

bamaer wants to merge 1 commit into
apache:mainfrom
bamaer:9169

Conversation

@bamaer

@bamaer bamaer commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

…ub Copilot

Core gets provider-neutral chat types (AiChatMessage, AiChatRequest, AiChatResponse, IAiChatProvider) and IAiProvider flags for the options a provider supports. The AI Assistant and Refresh models hand requests for such a provider to the provider itself; Language Model Chat, Structured Extract and Extract Graph refuse it with a clear message.

The new hop-tech-copilot plugin talks to the GitHub Copilot CLI through the GitHub Copilot Java SDK (MIT). Authentication stays with the CLI. The session gets no tools and every permission request is refused.

The AI provider editor now shows a provider type's own options on a tab named after the type.

Please add a meaningful description for your change here


Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:

  • Run mvn clean install apache-rat:check to make sure basic checks pass. A more thorough check will be performed on your pull request automatically.
  • If you have a group of commits related to the same change, please squash your commits into one and force push your branch using git rebase -i.
  • Mention the appropriate issue in your description (for example: addresses #123), if applicable.

To make clear that you license your contribution under the Apache License Version 2.0, January 2004
you have to acknowledge this by using the following check-box.

…h GitHub Copilot

Core gets provider-neutral chat types (AiChatMessage, AiChatRequest, AiChatResponse, IAiChatProvider) and IAiProvider flags for the options a provider supports. The AI Assistant and Refresh models hand requests for such a provider to the provider itself; Language Model Chat, Structured Extract and Extract Graph refuse it with a clear message.

The new hop-tech-copilot plugin talks to the GitHub Copilot CLI through the GitHub Copilot Java SDK (MIT). Authentication stays with the CLI. The session gets no tools and every permission request is refused.

The AI provider editor now shows a provider type's own options on a tab named after the type.

Co-authored-by: John Ballment <john@ballment.family>
<dependencies>
<dependency>
<groupId>com.github</groupId>
<artifactId>copilot-sdk-java</artifactId>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[bug] copilot-sdk-java 1.0.28 initializes its JSON-RPC mapper with new JavaTimeModule() (JsonRpcClient.createObjectMapper). That class lives in jackson-datatype-jsr310, which is not on Hop's core classpath, and plugins/pom.xml always drops artifact jackson-datatype-jsr310 from stage-plugin-lib. The hop.pluginlib.exclude* properties only drop databind, annotations, and JNA; they do not put jsr310 back. The first CopilotClient use therefore fails with NoClassDefFoundError: com/fasterxml/jackson/datatype/jsr310/JavaTimeModule (an Error, so chat / listModelNames do not turn it into a HopException). Unit tests never construct a client, so they stay green.

Databind and annotations are parent-first (com.fasterxml.jackson.databind. / .annotation.), so Hop's Jackson 2.21.7 is what the SDK actually runs on even if 2.22 jars were bundled.

Suggestion: Ship jackson-datatype-jsr310 at Hop's Jackson version inside this plugin and override the stage-plugin-lib exclude list so that artifact is copied. Adding the dependency alone is not enough while the parent exclude stays in place.

try (session) {
AssistantMessageEvent response =
await(
session.sendAndWait(new MessageOptions().setPrompt(prompt(request))),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[bug] CopilotSession.sendAndWait(MessageOptions) always waits 60 seconds (sendAndWait(options, 60000) in SDK 1.0.28). The provider timeout (the editor's Timeout field, carried on AiChatRequest.timeout and enforced by await) is ignored for the model call. A value above 60 seconds still dies at 60 seconds. The SDK completes that future with TimeoutException, so Future.get throws ExecutionException, not TimeoutException. The outer catch (TimeoutException) never runs and the user sees GitHubCopilotProvider.Failed instead of the timeout message. timeoutMs <= 0 on the two-arg overload means no SDK timeout.

Suggestion: Call sendAndWait(message, remainingMillis) with the time still left in timeoutSeconds (at least 1 ms). Keep the outer await as a backstop for CLI startup and session creation.

timeoutSeconds,
"waiting for a Copilot response");
return new AiChatResponse(
Utils.isEmpty(response.getData().content()) ? "" : response.getData().content(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[bug] sendAndWait is documented to complete with null when the session goes idle without an assistant message (lastAssistantMessage stays null and the future completes normally). This line calls response.getData() with no null check, so that outcome is an uncaught NullPointerException rather than an empty answer or a HopException. The same line NPEs if the event is non-null but getData() is null. AiChatResponse already turns a null text into "".

Suggestion: If response or response.getData() is null, throw a HopException that says the CLI returned no assistant message (or return an empty AiChatResponse). Only then read content().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants