Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1a2212b

Browse files
authored
impl: support for Toolbox 2.7 (#135)
Things that were changed or added to TBX 2.7:**Support for Proxy Authentication**The new API introduced in TBX 2.7, and HTTP proxy authentication worksflawlessly. However, SOCKS5 proxy authentication does not appear to beproperly supported in the current TBX implementation.While users can configure a SOCKS5 proxy with basic authentication,Toolbox fails to authenticate successfully. Coder uses OkHttp as theHTTP client, which in turn delegates SOCKS5 authentication to the JVM(java.net.SocksSocketImpl). We can configure a java.net.Authenticatorwith the credentials exposed by the new TBX API. However, since theAuthenticator is set globally, doing so would affect all plugins —including TBX itself — which may not be desirable.**Customizable messages while loading the workspaces**The new TBX 2.7 API allows us to change the message displayed whileloading the workspaces from "Loading environments" to "Loadingworkspaces"**UI pages with customizable titles****Support for custom aliases in the URI handling protocol**
1 parentdbf40e6 commit1a2212b

16 files changed

+93
-90
lines changed

‎CHANGELOG.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
##Unreleased
44

5+
###Added
6+
7+
- support for basic authentication for HTTP/HTTPS proxy
8+
- support for Toolbox 2.7 release
9+
10+
###Changed
11+
12+
- improved message while loading the workspace
13+
14+
###Fixed
15+
16+
- URI protocol handler is now able to switch to the Coder provider even if the last opened provider was something else
17+
518
##0.3.2 - 2025-06-25
619

720
###Changed

‎README.md‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ jetbrains://gateway/com.coder.toolbox
8282
&folder=<absolute-path-to-a-project-folder>
8383
```
8484

85+
Starting from Toolbox 2.7, you can use`coder` as a shortcut in place of the full plugin ID. The URI can be simplified as:
86+
```text
87+
jetbrains://gateway/coder?url=http(s)://<your-coder-deployment>
88+
```
89+
8590
| Query param| Description| Mandatory|
8691
|------------------|------------------------------------------------------------------------------|-----------|
8792
| url| Your Coder deployment URL (encoded)| Yes|
@@ -104,7 +109,7 @@ experience, it’s recommended to ensure the workspace is running prior to initi
104109

105110
##Configuring and Testing workspace polling with HTTP & SOCKS5 Proxy
106111

107-
This section explains how to set up a local proxy(without authentication which is not yet supported)and verify that
112+
This section explains how to set up a local proxy and verify that
108113
the plugin’s REST client works correctly when routed through it.
109114

110115
We’ll use[mitmproxy](https://mitmproxy.org/) for this — it can act as both an HTTP and SOCKS5 proxy with SSL
@@ -127,6 +132,12 @@ mitmproxy can do HTTP and SOCKS5 proxying. To configure one or the other:
127132
2. Navigate to`Options -> Edit Options`
128133
3. Update the`Mode` field to`regular` in order to activate HTTP/HTTPS or to`socks5`
129134
4. Proxy authentication can be enabled by updating the`proxyauth` to`username:password`
135+
5. Alternatively you can run the following commands:
136+
137+
```bash
138+
mitmweb --ssl-insecure --set stream_large_bodies="10m" --mode regular --proxyauth proxyUsername:proxyPassword
139+
mitmweb --ssl-insecure --set stream_large_bodies="10m" --mode socks5
140+
```
130141

131142
###Configure Proxy in Toolbox
132143

@@ -137,6 +148,11 @@ mitmproxy can do HTTP and SOCKS5 proxying. To configure one or the other:
137148
5. Before authenticating to the Coder deployment we need to tell the plugin where can we find mitmproxy
138149
certificates. In Coder's Settings page, set the`TLS CA path` to`~/.mitmproxy/mitmproxy-ca-cert.pem`
139150

151+
>[!NOTE]
152+
>Coder Toolbox plugin handles only HTTP/HTTPS proxy authentication.
153+
>SOCKS5 proxy authentication is currently not supported due to limitations
154+
>described in:https://youtrack.jetbrains.com/issue/TBX-14532/Missing-proxy-authentication-settings#focus=Comments-27-12265861.0-0
155+
140156
##Debugging and Reporting issues
141157

142158
Enabling debug logging is essential for diagnosing issues with the Toolbox plugin, especially when SSH

‎gradle.properties‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
version=0.3.2
1+
version=0.4.0
22
group=com.coder.toolbox
33
name=coder-toolbox

‎gradle/libs.versions.toml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[versions]
2-
toolbox-plugin-api ="1.1.41749"
3-
kotlin ="2.1.10"
4-
coroutines ="1.10.1"
5-
serialization ="1.8.0"
2+
toolbox-plugin-api ="1.3.47293"
3+
kotlin ="2.1.20"
4+
coroutines ="1.10.2"
5+
serialization ="1.8.1"
66
okhttp ="4.12.0"
77
dependency-license-report ="2.9"
88
marketplace-client ="2.0.46"
99
gradle-wrapper ="0.14.0"
1010
exec ="1.12"
1111
moshi ="1.15.2"
12-
ksp ="2.1.10-1.0.31"
12+
ksp ="2.1.20-2.0.1"
1313
retrofit ="3.0.0"
1414
changelog ="2.2.1"
1515
gettext ="0.7.0"

‎src/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,6 @@ class CoderRemoteEnvironment(
157157

158158
overridefunbeforeConnection() {
159159
context.logger.info("Connecting to$id...")
160-
context.cs.launch {
161-
state.update {
162-
wsRawStatus.toSshConnectingEnvState(context)
163-
}
164-
}
165160
isConnected.update {true }
166161
pollJob= pollNetworkMetrics()
167162
}

‎src/main/kotlin/com/coder/toolbox/CoderRemoteProvider.kt‎

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.coder.toolbox.sdk.ex.APIResponseException
77
importcom.coder.toolbox.sdk.v2.models.WorkspaceStatus
88
importcom.coder.toolbox.util.CoderProtocolHandler
99
importcom.coder.toolbox.util.DialogUi
10+
importcom.coder.toolbox.util.waitForTrue
1011
importcom.coder.toolbox.util.withPath
1112
importcom.coder.toolbox.views.Action
1213
importcom.coder.toolbox.views.CoderCliSetupWizardPage
@@ -63,9 +64,10 @@ class CoderRemoteProvider(
6364
// On the first load, automatically log in if we can.
6465
privatevar firstRun=true
6566
privateval isInitialized:MutableStateFlow<Boolean>=MutableStateFlow(false)
66-
privatevar coderHeaderPage=NewEnvironmentPage(context,context.i18n.pnotr(context.deploymentUrl.toString()))
67+
privateval coderHeaderPage=NewEnvironmentPage(context.i18n.pnotr(context.deploymentUrl.toString()))
6768
privateval linkHandler=CoderProtocolHandler(context, dialogUi, isInitialized)
6869

70+
overrideval loadingEnvironmentsDescription:LocalizableString= context.i18n.ptrl("Loading workspaces...")
6971
overrideval environments:MutableStateFlow<LoadableState<List<CoderRemoteEnvironment>>>=MutableStateFlow(
7072
LoadableState.Loading
7173
)
@@ -167,7 +169,7 @@ class CoderRemoteProvider(
167169
close()
168170
// force auto-login
169171
firstRun=true
170-
goToEnvironmentsPage()
172+
context.envPageManager.showPluginEnvironmentsPage()
171173
break
172174
}
173175
}
@@ -315,27 +317,19 @@ class CoderRemoteProvider(
315317
) { restClient, cli->
316318
// stop polling and de-initialize resources
317319
close()
320+
isInitialized.update {
321+
false
322+
}
318323
// start initialization with the new settings
319324
this@CoderRemoteProvider.client= restClient
320-
coderHeaderPage=NewEnvironmentPage(context,context.i18n.pnotr(restClient.url.toString()))
325+
coderHeaderPage.setTitle(context.i18n.pnotr(restClient.url.toString()))
321326

322327
environments.showLoadingMessage()
323328
pollJob= poll(restClient, cli)
329+
isInitialized.waitForTrue()
324330
}
325331
}
326332

327-
/**
328-
* Make Toolbox ask for the page again. Use any time we need to change the
329-
* root page (for example, sign-in or the environment list).
330-
*
331-
* When moving between related pages, instead use ui.showUiPage() and
332-
* ui.hideUiPage() which stacks and has built-in back navigation, rather
333-
* than using multiple root pages.
334-
*/
335-
privatefungoToEnvironmentsPage() {
336-
context.envPageManager.showPluginEnvironmentsPage()
337-
}
338-
339333
/**
340334
* Return the sign-in page if we do not have a valid client.
341335
@@ -377,7 +371,7 @@ class CoderRemoteProvider(
377371

378372
privatefunshouldDoAutoSetup():Boolean= firstRun&& context.secrets.rememberMe==true
379373

380-
privatesuspendfunonConnect(client:CoderRestClient,cli:CoderCLIManager) {
374+
privatefunonConnect(client:CoderRestClient,cli:CoderCLIManager) {
381375
// Store the URL and token for use next time.
382376
context.secrets.lastDeploymentURL= client.url.toString()
383377
context.secrets.lastToken= client.token?:""
@@ -387,9 +381,9 @@ class CoderRemoteProvider(
387381
this.client= client
388382
pollJob?.cancel()
389383
environments.showLoadingMessage()
390-
coderHeaderPage=NewEnvironmentPage(context,context.i18n.pnotr(client.url.toString()))
384+
coderHeaderPage.setTitle(context.i18n.pnotr(client.url.toString()))
391385
pollJob= poll(client, cli)
392-
context.refreshMainPage()
386+
context.envPageManager.showPluginEnvironmentsPage()
393387
}
394388

395389
privatefun MutableStateFlow<LoadableState<List<CoderRemoteEnvironment>>>.showLoadingMessage() {

‎src/main/kotlin/com/coder/toolbox/CoderToolboxContext.kt‎

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.coder.toolbox
33
importcom.coder.toolbox.store.CoderSecretsStore
44
importcom.coder.toolbox.store.CoderSettingsStore
55
importcom.coder.toolbox.util.toURL
6-
importcom.coder.toolbox.views.CoderPage
76
importcom.jetbrains.toolbox.api.core.diagnostics.Logger
87
importcom.jetbrains.toolbox.api.core.os.LocalDesktopManager
98
importcom.jetbrains.toolbox.api.localization.LocalizableStringFactory
@@ -14,10 +13,8 @@ import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentStateColorPalette
1413
importcom.jetbrains.toolbox.api.remoteDev.ui.EnvironmentUiPageManager
1514
importcom.jetbrains.toolbox.api.ui.ToolboxUi
1615
importkotlinx.coroutines.CoroutineScope
17-
importkotlinx.coroutines.delay
1816
importjava.net.URL
1917
importjava.util.UUID
20-
importkotlin.time.Duration.Companion.milliseconds
2118

2219
@Suppress("UnstableApiUsage")
2320
data classCoderToolboxContext(
@@ -91,26 +88,4 @@ data class CoderToolboxContext(
9188
i18n.ptrl("OK")
9289
)
9390
}
94-
95-
/**
96-
* Forces the title bar on the main page to be refreshed
97-
*/
98-
suspendfunrefreshMainPage() {
99-
// the url/title on the main page is only refreshed if
100-
// we're navigating to the main env page from another page.
101-
// If TBX is already on the main page the title is not refreshed
102-
// hence we force a navigation from a blank page.
103-
ui.showUiPage(CoderPage.emptyPage(this))
104-
105-
106-
// Toolbox uses an internal shared flow with a buffer of 4 items and a DROP_OLDEST strategy.
107-
// Both showUiPage and showPluginEnvironmentsPage send events to this flow.
108-
// If we emit two events back-to-back, the first one often gets dropped and only the second is shown.
109-
// To reduce this risk, we add a small delay to let the UI coroutine process the first event.
110-
// Simply yielding the coroutine isn't reliable, especially right after Toolbox starts via URI handling.
111-
// Based on my testing, a 5–10 ms delay is enough to ensure the blank page is processed,
112-
// while still short enough to be invisible to users.
113-
delay(10.milliseconds)
114-
envPageManager.showPluginEnvironmentsPage()
115-
}
11691
}

‎src/main/kotlin/com/coder/toolbox/models/WorkspaceAndAgentStatus.kt‎

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
6565
returnCustomRemoteEnvironmentStateV2(
6666
context.i18n.pnotr(label),
6767
color= getStateColor(context),
68-
reachable= ready()|| unhealthy(),
68+
isReachable= ready()|| unhealthy(),
6969
// TODO@JB: How does this work? Would like a spinner for pending states.
70-
icon= getStateIcon()
70+
iconId= getStateIcon().id,
71+
isPriorityShow=true
7172
)
7273
}
7374

@@ -90,16 +91,6 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
9091
elseEnvironmentStateIcons.NoIcon
9192
}
9293

93-
funtoSshConnectingEnvState(context:CoderToolboxContext):CustomRemoteEnvironmentStateV2 {
94-
val existingState= toRemoteEnvironmentState(context)
95-
returnCustomRemoteEnvironmentStateV2(
96-
context.i18n.pnotr("SSHing"),
97-
existingState.color,
98-
existingState.isReachable,
99-
EnvironmentStateIcons.Connecting
100-
)
101-
}
102-
10394
/**
10495
* Return true if the agent is in a connectable state.
10596
*/

‎src/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt‎

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import com.coder.toolbox.util.coderTrustManagers
2424
importcom.coder.toolbox.util.getArch
2525
importcom.coder.toolbox.util.getHeaders
2626
importcom.coder.toolbox.util.getOS
27+
importcom.jetbrains.toolbox.api.remoteDev.connection.ProxyAuth
2728
importcom.squareup.moshi.Moshi
29+
importokhttp3.Credentials
2830
importokhttp3.OkHttpClient
2931
importretrofit2.Response
3032
importretrofit2.Retrofit
@@ -78,18 +80,19 @@ open class CoderRestClient(
7880
builder.proxySelector(context.proxySettings.getProxySelector()!!)
7981
}
8082

81-
//TODO - add support for proxy auth. when Toolbox exposes them
82-
// builder.proxyAuthenticator { _, response ->
83-
// if (proxyValues.useAuth && proxyValues.username != null && proxyValues.password != null) {
84-
// val credentials = Credentials.basic(proxyValues.username, proxyValues.password)
85-
// response.request.newBuilder()
86-
// .header("Proxy-Authorization", credentials)
87-
// .build()
88-
// } else {
89-
// null
90-
// }
91-
// }
92-
// }
83+
// Note: This handles only HTTP/HTTPS proxy authentication.
84+
// SOCKS5 proxy authentication is currently not supported due to limitations described in:
85+
// https://youtrack.jetbrains.com/issue/TBX-14532/Missing-proxy-authentication-settings#focus=Comments-27-12265861.0-0
86+
builder.proxyAuthenticator { _, response->
87+
val proxyAuth= context.proxySettings.getProxyAuth()
88+
if (proxyAuth==null|| proxyAuth!isProxyAuth.Basic) {
89+
return@proxyAuthenticatornull
90+
}
91+
val credentials=Credentials.basic(proxyAuth.username, proxyAuth.password)
92+
response.request.newBuilder()
93+
.header("Proxy-Authorization", credentials)
94+
.build()
95+
}
9396

9497
if (token!=null) {
9598
builder= builder.addInterceptor {

‎src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ open class CoderProtocolHandler(
5454
context.logAndShowInfo("URI will not be handled","No query parameters were provided")
5555
return
5656
}
57-
57+
// this switches to the main plugin screen, even
58+
// if last opened provider was not Coder
59+
context.envPageManager.showPluginEnvironmentsPage()
60+
markAsBusy()
5861
if (shouldWaitForAutoLogin) {
5962
isInitialized.waitForTrue()
6063
}
@@ -67,12 +70,11 @@ open class CoderProtocolHandler(
6770
val workspace= restClient.workspaces().matchName(workspaceName, deploymentURL)?:return
6871

6972
val cli= configureCli(deploymentURL, restClient)
70-
reInitialize(restClient, cli)
7173

7274
var agent:WorkspaceAgent
7375
try {
74-
markAsBusy()
75-
context.refreshMainPage()
76+
reInitialize(restClient, cli)
77+
context.envPageManager.showPluginEnvironmentsPage()
7678
if (!prepareWorkspace(workspace, restClient, workspaceName, deploymentURL))return
7779
// we resolve the agent after the workspace is started otherwise we can get misleading
7880
// errors like: no agent available while workspace is starting or stopping
@@ -86,6 +88,7 @@ open class CoderProtocolHandler(
8688
}finally {
8789
unmarkAsBusy()
8890
}
91+
delay(2.seconds)
8992
val environmentId="${workspace.name}.${agent.name}"
9093
context.showEnvironmentPage(environmentId)
9194

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp