@spencer-kit/coder-studio 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/esm/bin.mjs +152 -49
- package/dist/esm/bin.mjs.map +3 -3
- package/dist/esm/server-runner.mjs +152 -49
- package/dist/esm/server-runner.mjs.map +2 -2
- package/dist/web/assets/components-BC_6z_aX.css +1 -0
- package/dist/web/assets/components-ynft7c9H.js +109 -0
- package/dist/web/assets/components-ynft7c9H.js.map +1 -0
- package/dist/web/assets/{main-ShJ51B7m.js → main-BMKYuTcM.js} +2 -2
- package/dist/web/assets/{main-ShJ51B7m.js.map → main-BMKYuTcM.js.map} +1 -1
- package/dist/web/assets/{ui-preview-CKpnmBtY.js → ui-preview-BC1JKu3-.js} +2 -2
- package/dist/web/assets/{ui-preview-CKpnmBtY.js.map → ui-preview-BC1JKu3-.js.map} +1 -1
- package/dist/web/index.html +3 -3
- package/dist/web/ui-preview.html +3 -3
- package/package.json +1 -1
- package/src/update-worker.test.ts +25 -12
- package/dist/web/assets/components-BGEBLvHB.css +0 -1
- package/dist/web/assets/components-CFZItGai.js +0 -109
- package/dist/web/assets/components-CFZItGai.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#64](https://github.com/spencerkit/coder-studio/pull/64) [`d14fe08`](https://github.com/spencerkit/coder-studio/commit/d14fe08d7861652a9290559d5a59aa766c286309) Thanks [@pallyoung](https://github.com/pallyoung)! - Refine workspace theming and session ergonomics by adding pane drag reordering,
|
|
8
|
+
stabilizing update checks, hardening PTY color environment isolation, and
|
|
9
|
+
polishing shared desktop surfaces across the app.
|
|
10
|
+
|
|
11
|
+
## 0.4.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#62](https://github.com/spencerkit/coder-studio/pull/62) [`535c3c0`](https://github.com/spencerkit/coder-studio/commit/535c3c09cc5895e3b3b949067633f8a6bb3644f8) Thanks [@pallyoung](https://github.com/pallyoung)! - Improve desktop workspace ergonomics by adding keyboard pane navigation,
|
|
16
|
+
supporting workspace path drops into terminal sessions, and launching themed
|
|
17
|
+
PTYs with terminal-aware background environment hints.
|
|
18
|
+
|
|
3
19
|
## 0.4.5
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/dist/esm/bin.mjs
CHANGED
|
@@ -6892,7 +6892,8 @@ var init_manager3 = __esm({
|
|
|
6892
6892
|
...cmd.env,
|
|
6893
6893
|
CODER_STUDIO_SESSION_ID: sessionId
|
|
6894
6894
|
},
|
|
6895
|
-
title: req.provider.displayName
|
|
6895
|
+
title: req.provider.displayName,
|
|
6896
|
+
themeBackground: req.themeBackground
|
|
6896
6897
|
};
|
|
6897
6898
|
const terminal = this.deps.terminalMgr.create(terminalSpec);
|
|
6898
6899
|
const active = new ActiveSession({
|
|
@@ -12152,6 +12153,39 @@ var init_types2 = __esm({
|
|
|
12152
12153
|
function isTerminalTraceEnabled() {
|
|
12153
12154
|
return process.env.CODER_STUDIO_TERMINAL_TRACE === "1";
|
|
12154
12155
|
}
|
|
12156
|
+
function parseHexColor(input2) {
|
|
12157
|
+
const trimmed = input2.trim();
|
|
12158
|
+
if (!trimmed.startsWith("#")) {
|
|
12159
|
+
return null;
|
|
12160
|
+
}
|
|
12161
|
+
const hex = trimmed.slice(1);
|
|
12162
|
+
let r;
|
|
12163
|
+
let g;
|
|
12164
|
+
let b;
|
|
12165
|
+
if (hex.length === 3) {
|
|
12166
|
+
r = Number.parseInt(hex[0] + hex[0], 16);
|
|
12167
|
+
g = Number.parseInt(hex[1] + hex[1], 16);
|
|
12168
|
+
b = Number.parseInt(hex[2] + hex[2], 16);
|
|
12169
|
+
} else if (hex.length === 6 || hex.length === 8) {
|
|
12170
|
+
r = Number.parseInt(hex.slice(0, 2), 16);
|
|
12171
|
+
g = Number.parseInt(hex.slice(2, 4), 16);
|
|
12172
|
+
b = Number.parseInt(hex.slice(4, 6), 16);
|
|
12173
|
+
} else {
|
|
12174
|
+
return null;
|
|
12175
|
+
}
|
|
12176
|
+
if ([r, g, b].some((v) => Number.isNaN(v))) {
|
|
12177
|
+
return null;
|
|
12178
|
+
}
|
|
12179
|
+
return { r, g, b };
|
|
12180
|
+
}
|
|
12181
|
+
function computeColorFgBg(background) {
|
|
12182
|
+
const rgb = parseHexColor(background);
|
|
12183
|
+
if (!rgb) {
|
|
12184
|
+
return void 0;
|
|
12185
|
+
}
|
|
12186
|
+
const luma = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
|
|
12187
|
+
return luma > 0.5 ? "0;15" : "15;0";
|
|
12188
|
+
}
|
|
12155
12189
|
function countOccurrences(text, needle) {
|
|
12156
12190
|
return text.split(needle).length - 1;
|
|
12157
12191
|
}
|
|
@@ -12208,6 +12242,7 @@ var init_manager5 = __esm({
|
|
|
12208
12242
|
*/
|
|
12209
12243
|
create(spec) {
|
|
12210
12244
|
const id = generateId();
|
|
12245
|
+
const derivedColorFgBg = spec.themeBackground ? computeColorFgBg(spec.themeBackground) : void 0;
|
|
12211
12246
|
const terminalEnv = {
|
|
12212
12247
|
...Object.fromEntries(
|
|
12213
12248
|
Object.entries(process.env).filter((e) => e[1] != null)
|
|
@@ -12215,8 +12250,16 @@ var init_manager5 = __esm({
|
|
|
12215
12250
|
TERM: "xterm-256color",
|
|
12216
12251
|
COLORTERM: "truecolor",
|
|
12217
12252
|
FORCE_COLOR: "3",
|
|
12253
|
+
...derivedColorFgBg ? { COLORFGBG: derivedColorFgBg } : {},
|
|
12218
12254
|
...spec.env
|
|
12219
12255
|
};
|
|
12256
|
+
delete terminalEnv.COLORFGBG;
|
|
12257
|
+
if (derivedColorFgBg) {
|
|
12258
|
+
terminalEnv.COLORFGBG = derivedColorFgBg;
|
|
12259
|
+
}
|
|
12260
|
+
if (spec.env?.COLORFGBG) {
|
|
12261
|
+
terminalEnv.COLORFGBG = spec.env.COLORFGBG;
|
|
12262
|
+
}
|
|
12220
12263
|
let pty;
|
|
12221
12264
|
try {
|
|
12222
12265
|
pty = this.deps.ptyHost.spawn(spec.argv, {
|
|
@@ -12616,7 +12659,7 @@ var init_update_service = __esm({
|
|
|
12616
12659
|
"packages/server/src/update/update-service.ts"() {
|
|
12617
12660
|
"use strict";
|
|
12618
12661
|
init_src3();
|
|
12619
|
-
UpdateService = class {
|
|
12662
|
+
UpdateService = class _UpdateService {
|
|
12620
12663
|
constructor(deps) {
|
|
12621
12664
|
this.deps = deps;
|
|
12622
12665
|
this.now = deps.now ?? Date.now;
|
|
@@ -12638,12 +12681,14 @@ var init_update_service = __esm({
|
|
|
12638
12681
|
this.spawnDetachedWorkerImpl = deps.spawnDetachedWorker;
|
|
12639
12682
|
}
|
|
12640
12683
|
deps;
|
|
12684
|
+
static CHECK_TIMEOUT_MS = 15e3;
|
|
12641
12685
|
now;
|
|
12642
12686
|
runtime;
|
|
12643
12687
|
updateWorkerLogFilePath;
|
|
12644
12688
|
runLatestVersionLookup;
|
|
12645
12689
|
spawnDetachedWorkerImpl;
|
|
12646
12690
|
scheduleTimer = null;
|
|
12691
|
+
inFlightCheck = null;
|
|
12647
12692
|
start() {
|
|
12648
12693
|
this.reconcileOnStartup();
|
|
12649
12694
|
this.reloadScheduleFromSettings();
|
|
@@ -12674,10 +12719,8 @@ var init_update_service = __esm({
|
|
|
12674
12719
|
this.scheduleTimer.unref?.();
|
|
12675
12720
|
}
|
|
12676
12721
|
getStateView() {
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
...this.getSupportInfo()
|
|
12680
|
-
};
|
|
12722
|
+
const persisted = this.deps.updateStateRepo.get();
|
|
12723
|
+
return this.composeStateView(persisted);
|
|
12681
12724
|
}
|
|
12682
12725
|
getPrepareInstallState() {
|
|
12683
12726
|
const state = this.getStateView();
|
|
@@ -12694,36 +12737,15 @@ var init_update_service = __esm({
|
|
|
12694
12737
|
if (current.updateStatus === "installing" || current.updateStatus === "restarting") {
|
|
12695
12738
|
throw createBusyError("Update installation is already in progress");
|
|
12696
12739
|
}
|
|
12697
|
-
if (
|
|
12740
|
+
if (this.inFlightCheck) {
|
|
12698
12741
|
throw createBusyError("Update check is already in progress");
|
|
12699
12742
|
}
|
|
12700
|
-
this.
|
|
12701
|
-
|
|
12702
|
-
finishedAt: null,
|
|
12703
|
-
errorSummary: null
|
|
12704
|
-
});
|
|
12743
|
+
this.inFlightCheck = this.runCheckForUpdates();
|
|
12744
|
+
this.broadcastStateChange();
|
|
12705
12745
|
try {
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
currentVersion: this.runtime.currentVersion,
|
|
12710
|
-
latestVersion,
|
|
12711
|
-
availability,
|
|
12712
|
-
updateStatus: "idle",
|
|
12713
|
-
lastCheckedAt: this.now(),
|
|
12714
|
-
errorSummary: null,
|
|
12715
|
-
requiresManualStep: false,
|
|
12716
|
-
manualCommand: null
|
|
12717
|
-
});
|
|
12718
|
-
} catch (error) {
|
|
12719
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
12720
|
-
return this.persistAndBroadcast({
|
|
12721
|
-
currentVersion: this.runtime.currentVersion,
|
|
12722
|
-
availability: "check_failed",
|
|
12723
|
-
updateStatus: "idle",
|
|
12724
|
-
lastCheckedAt: this.now(),
|
|
12725
|
-
errorSummary: message
|
|
12726
|
-
});
|
|
12746
|
+
return await this.inFlightCheck;
|
|
12747
|
+
} finally {
|
|
12748
|
+
this.inFlightCheck = null;
|
|
12727
12749
|
}
|
|
12728
12750
|
}
|
|
12729
12751
|
prepareInstall() {
|
|
@@ -12738,6 +12760,9 @@ var init_update_service = __esm({
|
|
|
12738
12760
|
if (state.updateStatus === "installing" || state.updateStatus === "restarting") {
|
|
12739
12761
|
throw createBusyError("Update installation is already in progress");
|
|
12740
12762
|
}
|
|
12763
|
+
if (this.inFlightCheck) {
|
|
12764
|
+
throw createBusyError("Update check is already in progress");
|
|
12765
|
+
}
|
|
12741
12766
|
const targetVersion = input2.targetVersion ?? state.latestVersion;
|
|
12742
12767
|
if (!targetVersion) {
|
|
12743
12768
|
throw createValidationError("update_no_target", "No target version is available");
|
|
@@ -12812,6 +12837,15 @@ var init_update_service = __esm({
|
|
|
12812
12837
|
errorSummary: null
|
|
12813
12838
|
});
|
|
12814
12839
|
}
|
|
12840
|
+
if (current.updateStatus === "checking") {
|
|
12841
|
+
return this.persistAndBroadcast({
|
|
12842
|
+
currentVersion: this.runtime.currentVersion,
|
|
12843
|
+
availability: "check_failed",
|
|
12844
|
+
updateStatus: "failed",
|
|
12845
|
+
finishedAt: this.now(),
|
|
12846
|
+
errorSummary: "Update check did not complete before the service restarted"
|
|
12847
|
+
});
|
|
12848
|
+
}
|
|
12815
12849
|
if (current.updateStatus === "installing" || current.updateStatus === "restarting") {
|
|
12816
12850
|
return this.persistAndBroadcast({
|
|
12817
12851
|
currentVersion: this.runtime.currentVersion,
|
|
@@ -12862,18 +12896,6 @@ var init_update_service = __esm({
|
|
|
12862
12896
|
hasActiveWork: runningTerminalCount > 0 || runningSessionCount > 0 || runningSupervisorCount > 0
|
|
12863
12897
|
};
|
|
12864
12898
|
}
|
|
12865
|
-
persistAndBroadcast(patch) {
|
|
12866
|
-
const snapshot = this.deps.updateStateRepo.update((current) => ({
|
|
12867
|
-
...patch,
|
|
12868
|
-
currentVersion: patch.currentVersion ?? current.currentVersion
|
|
12869
|
-
}));
|
|
12870
|
-
const view = {
|
|
12871
|
-
...snapshot,
|
|
12872
|
-
...this.getSupportInfo()
|
|
12873
|
-
};
|
|
12874
|
-
this.deps.broadcaster.broadcast("update.state.changed", view);
|
|
12875
|
-
return view;
|
|
12876
|
-
}
|
|
12877
12899
|
buildManualCommand(targetVersion) {
|
|
12878
12900
|
return [
|
|
12879
12901
|
`${this.runtime.npmCommand ?? "npm"} install -g ${this.runtime.packageName}@${targetVersion}`,
|
|
@@ -12903,6 +12925,83 @@ var init_update_service = __esm({
|
|
|
12903
12925
|
});
|
|
12904
12926
|
child.unref();
|
|
12905
12927
|
}
|
|
12928
|
+
composeStateView(snapshot, options) {
|
|
12929
|
+
if (options?.includeInFlightCheck !== false && this.inFlightCheck) {
|
|
12930
|
+
return {
|
|
12931
|
+
...snapshot,
|
|
12932
|
+
...this.getSupportInfo(),
|
|
12933
|
+
updateStatus: "checking",
|
|
12934
|
+
errorSummary: null
|
|
12935
|
+
};
|
|
12936
|
+
}
|
|
12937
|
+
return {
|
|
12938
|
+
...snapshot,
|
|
12939
|
+
...this.getSupportInfo()
|
|
12940
|
+
};
|
|
12941
|
+
}
|
|
12942
|
+
broadcastStateChange() {
|
|
12943
|
+
this.deps.broadcaster.broadcast("update.state.changed", this.getStateView());
|
|
12944
|
+
}
|
|
12945
|
+
async runCheckForUpdates() {
|
|
12946
|
+
try {
|
|
12947
|
+
const latestVersion = await this.withCheckTimeout(
|
|
12948
|
+
this.runLatestVersionLookup(this.runtime.packageName)
|
|
12949
|
+
);
|
|
12950
|
+
const availability = compareVersions(latestVersion, this.runtime.currentVersion) > 0 ? "update_available" : "up_to_date";
|
|
12951
|
+
return this.persistAndBroadcast(
|
|
12952
|
+
{
|
|
12953
|
+
currentVersion: this.runtime.currentVersion,
|
|
12954
|
+
latestVersion,
|
|
12955
|
+
availability,
|
|
12956
|
+
updateStatus: "idle",
|
|
12957
|
+
lastCheckedAt: this.now(),
|
|
12958
|
+
errorSummary: null,
|
|
12959
|
+
requiresManualStep: false,
|
|
12960
|
+
manualCommand: null
|
|
12961
|
+
},
|
|
12962
|
+
false
|
|
12963
|
+
);
|
|
12964
|
+
} catch (error) {
|
|
12965
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12966
|
+
return this.persistAndBroadcast(
|
|
12967
|
+
{
|
|
12968
|
+
currentVersion: this.runtime.currentVersion,
|
|
12969
|
+
availability: "check_failed",
|
|
12970
|
+
updateStatus: "idle",
|
|
12971
|
+
lastCheckedAt: this.now(),
|
|
12972
|
+
errorSummary: message
|
|
12973
|
+
},
|
|
12974
|
+
false
|
|
12975
|
+
);
|
|
12976
|
+
}
|
|
12977
|
+
}
|
|
12978
|
+
async withCheckTimeout(promise) {
|
|
12979
|
+
let timeoutHandle = null;
|
|
12980
|
+
try {
|
|
12981
|
+
return await Promise.race([
|
|
12982
|
+
promise,
|
|
12983
|
+
new Promise((_, reject) => {
|
|
12984
|
+
timeoutHandle = setTimeout(() => {
|
|
12985
|
+
reject(new Error(`Update check timed out after ${_UpdateService.CHECK_TIMEOUT_MS}ms`));
|
|
12986
|
+
}, _UpdateService.CHECK_TIMEOUT_MS);
|
|
12987
|
+
timeoutHandle.unref?.();
|
|
12988
|
+
})
|
|
12989
|
+
]);
|
|
12990
|
+
} finally {
|
|
12991
|
+
if (timeoutHandle) {
|
|
12992
|
+
clearTimeout(timeoutHandle);
|
|
12993
|
+
}
|
|
12994
|
+
}
|
|
12995
|
+
}
|
|
12996
|
+
persistAndBroadcast(patch, includeInFlightCheck = true) {
|
|
12997
|
+
const snapshot = this.deps.updateStateRepo.update((current) => ({
|
|
12998
|
+
...patch,
|
|
12999
|
+
currentVersion: patch.currentVersion ?? current.currentVersion
|
|
13000
|
+
}));
|
|
13001
|
+
const view = this.composeStateView(snapshot, { includeInFlightCheck });
|
|
13002
|
+
this.deps.broadcaster.broadcast("update.state.changed", view);
|
|
13003
|
+
return view;
|
|
13004
|
+
}
|
|
12906
13005
|
};
|
|
12907
13006
|
}
|
|
12908
13007
|
});
|
|
@@ -13759,7 +13858,8 @@ var init_terminal = __esm({
|
|
|
13759
13858
|
workspaceId: z6.string(),
|
|
13760
13859
|
cols: z6.number().int().positive().optional(),
|
|
13761
13860
|
rows: z6.number().int().positive().optional(),
|
|
13762
|
-
cwdPath: z6.string().optional()
|
|
13861
|
+
cwdPath: z6.string().optional(),
|
|
13862
|
+
themeBackground: z6.string().regex(/^#[0-9a-fA-F]{3,8}$/).optional()
|
|
13763
13863
|
}),
|
|
13764
13864
|
async (args, ctx) => {
|
|
13765
13865
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -13797,7 +13897,8 @@ var init_terminal = __esm({
|
|
|
13797
13897
|
title: shell.title,
|
|
13798
13898
|
cwd,
|
|
13799
13899
|
cols: args.cols ?? 120,
|
|
13800
|
-
rows: args.rows ?? 30
|
|
13900
|
+
rows: args.rows ?? 30,
|
|
13901
|
+
themeBackground: args.themeBackground
|
|
13801
13902
|
});
|
|
13802
13903
|
return terminal;
|
|
13803
13904
|
}
|
|
@@ -15369,7 +15470,8 @@ var init_session2 = __esm({
|
|
|
15369
15470
|
z12.object({
|
|
15370
15471
|
workspaceId: z12.string(),
|
|
15371
15472
|
providerId: z12.string(),
|
|
15372
|
-
draft: z12.string().optional()
|
|
15473
|
+
draft: z12.string().optional(),
|
|
15474
|
+
themeBackground: z12.string().regex(/^#[0-9a-fA-F]{3,8}$/).optional()
|
|
15373
15475
|
}),
|
|
15374
15476
|
async (args, ctx) => {
|
|
15375
15477
|
const workspace = ctx.workspaceMgr.get(args.workspaceId);
|
|
@@ -15397,7 +15499,8 @@ var init_session2 = __esm({
|
|
|
15397
15499
|
workspacePath: workspace.path,
|
|
15398
15500
|
providerId: args.providerId,
|
|
15399
15501
|
provider,
|
|
15400
|
-
draft: args.draft
|
|
15502
|
+
draft: args.draft,
|
|
15503
|
+
themeBackground: args.themeBackground
|
|
15401
15504
|
});
|
|
15402
15505
|
}
|
|
15403
15506
|
);
|