@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.
@@ -6870,7 +6870,8 @@ var init_manager3 = __esm({
6870
6870
  ...cmd.env,
6871
6871
  CODER_STUDIO_SESSION_ID: sessionId
6872
6872
  },
6873
- title: req.provider.displayName
6873
+ title: req.provider.displayName,
6874
+ themeBackground: req.themeBackground
6874
6875
  };
6875
6876
  const terminal = this.deps.terminalMgr.create(terminalSpec);
6876
6877
  const active = new ActiveSession({
@@ -12130,6 +12131,39 @@ var init_types2 = __esm({
12130
12131
  function isTerminalTraceEnabled() {
12131
12132
  return process.env.CODER_STUDIO_TERMINAL_TRACE === "1";
12132
12133
  }
12134
+ function parseHexColor(input) {
12135
+ const trimmed = input.trim();
12136
+ if (!trimmed.startsWith("#")) {
12137
+ return null;
12138
+ }
12139
+ const hex = trimmed.slice(1);
12140
+ let r;
12141
+ let g;
12142
+ let b;
12143
+ if (hex.length === 3) {
12144
+ r = Number.parseInt(hex[0] + hex[0], 16);
12145
+ g = Number.parseInt(hex[1] + hex[1], 16);
12146
+ b = Number.parseInt(hex[2] + hex[2], 16);
12147
+ } else if (hex.length === 6 || hex.length === 8) {
12148
+ r = Number.parseInt(hex.slice(0, 2), 16);
12149
+ g = Number.parseInt(hex.slice(2, 4), 16);
12150
+ b = Number.parseInt(hex.slice(4, 6), 16);
12151
+ } else {
12152
+ return null;
12153
+ }
12154
+ if ([r, g, b].some((v) => Number.isNaN(v))) {
12155
+ return null;
12156
+ }
12157
+ return { r, g, b };
12158
+ }
12159
+ function computeColorFgBg(background) {
12160
+ const rgb = parseHexColor(background);
12161
+ if (!rgb) {
12162
+ return void 0;
12163
+ }
12164
+ const luma = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
12165
+ return luma > 0.5 ? "0;15" : "15;0";
12166
+ }
12133
12167
  function countOccurrences(text, needle) {
12134
12168
  return text.split(needle).length - 1;
12135
12169
  }
@@ -12186,6 +12220,7 @@ var init_manager5 = __esm({
12186
12220
  */
12187
12221
  create(spec) {
12188
12222
  const id = generateId();
12223
+ const derivedColorFgBg = spec.themeBackground ? computeColorFgBg(spec.themeBackground) : void 0;
12189
12224
  const terminalEnv = {
12190
12225
  ...Object.fromEntries(
12191
12226
  Object.entries(process.env).filter((e) => e[1] != null)
@@ -12193,8 +12228,16 @@ var init_manager5 = __esm({
12193
12228
  TERM: "xterm-256color",
12194
12229
  COLORTERM: "truecolor",
12195
12230
  FORCE_COLOR: "3",
12231
+ ...derivedColorFgBg ? { COLORFGBG: derivedColorFgBg } : {},
12196
12232
  ...spec.env
12197
12233
  };
12234
+ delete terminalEnv.COLORFGBG;
12235
+ if (derivedColorFgBg) {
12236
+ terminalEnv.COLORFGBG = derivedColorFgBg;
12237
+ }
12238
+ if (spec.env?.COLORFGBG) {
12239
+ terminalEnv.COLORFGBG = spec.env.COLORFGBG;
12240
+ }
12198
12241
  let pty;
12199
12242
  try {
12200
12243
  pty = this.deps.ptyHost.spawn(spec.argv, {
@@ -12594,7 +12637,7 @@ var init_update_service = __esm({
12594
12637
  "packages/server/src/update/update-service.ts"() {
12595
12638
  "use strict";
12596
12639
  init_src3();
12597
- UpdateService = class {
12640
+ UpdateService = class _UpdateService {
12598
12641
  constructor(deps) {
12599
12642
  this.deps = deps;
12600
12643
  this.now = deps.now ?? Date.now;
@@ -12616,12 +12659,14 @@ var init_update_service = __esm({
12616
12659
  this.spawnDetachedWorkerImpl = deps.spawnDetachedWorker;
12617
12660
  }
12618
12661
  deps;
12662
+ static CHECK_TIMEOUT_MS = 15e3;
12619
12663
  now;
12620
12664
  runtime;
12621
12665
  updateWorkerLogFilePath;
12622
12666
  runLatestVersionLookup;
12623
12667
  spawnDetachedWorkerImpl;
12624
12668
  scheduleTimer = null;
12669
+ inFlightCheck = null;
12625
12670
  start() {
12626
12671
  this.reconcileOnStartup();
12627
12672
  this.reloadScheduleFromSettings();
@@ -12652,10 +12697,8 @@ var init_update_service = __esm({
12652
12697
  this.scheduleTimer.unref?.();
12653
12698
  }
12654
12699
  getStateView() {
12655
- return {
12656
- ...this.deps.updateStateRepo.get(),
12657
- ...this.getSupportInfo()
12658
- };
12700
+ const persisted = this.deps.updateStateRepo.get();
12701
+ return this.composeStateView(persisted);
12659
12702
  }
12660
12703
  getPrepareInstallState() {
12661
12704
  const state = this.getStateView();
@@ -12672,36 +12715,15 @@ var init_update_service = __esm({
12672
12715
  if (current.updateStatus === "installing" || current.updateStatus === "restarting") {
12673
12716
  throw createBusyError("Update installation is already in progress");
12674
12717
  }
12675
- if (current.updateStatus === "checking") {
12718
+ if (this.inFlightCheck) {
12676
12719
  throw createBusyError("Update check is already in progress");
12677
12720
  }
12678
- this.persistAndBroadcast({
12679
- updateStatus: "checking",
12680
- finishedAt: null,
12681
- errorSummary: null
12682
- });
12721
+ this.inFlightCheck = this.runCheckForUpdates();
12722
+ this.broadcastStateChange();
12683
12723
  try {
12684
- const latestVersion = await this.runLatestVersionLookup(this.runtime.packageName);
12685
- const availability = compareVersions(latestVersion, this.runtime.currentVersion) > 0 ? "update_available" : "up_to_date";
12686
- return this.persistAndBroadcast({
12687
- currentVersion: this.runtime.currentVersion,
12688
- latestVersion,
12689
- availability,
12690
- updateStatus: "idle",
12691
- lastCheckedAt: this.now(),
12692
- errorSummary: null,
12693
- requiresManualStep: false,
12694
- manualCommand: null
12695
- });
12696
- } catch (error) {
12697
- const message = error instanceof Error ? error.message : String(error);
12698
- return this.persistAndBroadcast({
12699
- currentVersion: this.runtime.currentVersion,
12700
- availability: "check_failed",
12701
- updateStatus: "idle",
12702
- lastCheckedAt: this.now(),
12703
- errorSummary: message
12704
- });
12724
+ return await this.inFlightCheck;
12725
+ } finally {
12726
+ this.inFlightCheck = null;
12705
12727
  }
12706
12728
  }
12707
12729
  prepareInstall() {
@@ -12716,6 +12738,9 @@ var init_update_service = __esm({
12716
12738
  if (state.updateStatus === "installing" || state.updateStatus === "restarting") {
12717
12739
  throw createBusyError("Update installation is already in progress");
12718
12740
  }
12741
+ if (this.inFlightCheck) {
12742
+ throw createBusyError("Update check is already in progress");
12743
+ }
12719
12744
  const targetVersion = input.targetVersion ?? state.latestVersion;
12720
12745
  if (!targetVersion) {
12721
12746
  throw createValidationError("update_no_target", "No target version is available");
@@ -12790,6 +12815,15 @@ var init_update_service = __esm({
12790
12815
  errorSummary: null
12791
12816
  });
12792
12817
  }
12818
+ if (current.updateStatus === "checking") {
12819
+ return this.persistAndBroadcast({
12820
+ currentVersion: this.runtime.currentVersion,
12821
+ availability: "check_failed",
12822
+ updateStatus: "failed",
12823
+ finishedAt: this.now(),
12824
+ errorSummary: "Update check did not complete before the service restarted"
12825
+ });
12826
+ }
12793
12827
  if (current.updateStatus === "installing" || current.updateStatus === "restarting") {
12794
12828
  return this.persistAndBroadcast({
12795
12829
  currentVersion: this.runtime.currentVersion,
@@ -12840,18 +12874,6 @@ var init_update_service = __esm({
12840
12874
  hasActiveWork: runningTerminalCount > 0 || runningSessionCount > 0 || runningSupervisorCount > 0
12841
12875
  };
12842
12876
  }
12843
- persistAndBroadcast(patch) {
12844
- const snapshot = this.deps.updateStateRepo.update((current) => ({
12845
- ...patch,
12846
- currentVersion: patch.currentVersion ?? current.currentVersion
12847
- }));
12848
- const view = {
12849
- ...snapshot,
12850
- ...this.getSupportInfo()
12851
- };
12852
- this.deps.broadcaster.broadcast("update.state.changed", view);
12853
- return view;
12854
- }
12855
12877
  buildManualCommand(targetVersion) {
12856
12878
  return [
12857
12879
  `${this.runtime.npmCommand ?? "npm"} install -g ${this.runtime.packageName}@${targetVersion}`,
@@ -12881,6 +12903,83 @@ var init_update_service = __esm({
12881
12903
  });
12882
12904
  child.unref();
12883
12905
  }
12906
+ composeStateView(snapshot, options) {
12907
+ if (options?.includeInFlightCheck !== false && this.inFlightCheck) {
12908
+ return {
12909
+ ...snapshot,
12910
+ ...this.getSupportInfo(),
12911
+ updateStatus: "checking",
12912
+ errorSummary: null
12913
+ };
12914
+ }
12915
+ return {
12916
+ ...snapshot,
12917
+ ...this.getSupportInfo()
12918
+ };
12919
+ }
12920
+ broadcastStateChange() {
12921
+ this.deps.broadcaster.broadcast("update.state.changed", this.getStateView());
12922
+ }
12923
+ async runCheckForUpdates() {
12924
+ try {
12925
+ const latestVersion = await this.withCheckTimeout(
12926
+ this.runLatestVersionLookup(this.runtime.packageName)
12927
+ );
12928
+ const availability = compareVersions(latestVersion, this.runtime.currentVersion) > 0 ? "update_available" : "up_to_date";
12929
+ return this.persistAndBroadcast(
12930
+ {
12931
+ currentVersion: this.runtime.currentVersion,
12932
+ latestVersion,
12933
+ availability,
12934
+ updateStatus: "idle",
12935
+ lastCheckedAt: this.now(),
12936
+ errorSummary: null,
12937
+ requiresManualStep: false,
12938
+ manualCommand: null
12939
+ },
12940
+ false
12941
+ );
12942
+ } catch (error) {
12943
+ const message = error instanceof Error ? error.message : String(error);
12944
+ return this.persistAndBroadcast(
12945
+ {
12946
+ currentVersion: this.runtime.currentVersion,
12947
+ availability: "check_failed",
12948
+ updateStatus: "idle",
12949
+ lastCheckedAt: this.now(),
12950
+ errorSummary: message
12951
+ },
12952
+ false
12953
+ );
12954
+ }
12955
+ }
12956
+ async withCheckTimeout(promise) {
12957
+ let timeoutHandle = null;
12958
+ try {
12959
+ return await Promise.race([
12960
+ promise,
12961
+ new Promise((_, reject) => {
12962
+ timeoutHandle = setTimeout(() => {
12963
+ reject(new Error(`Update check timed out after ${_UpdateService.CHECK_TIMEOUT_MS}ms`));
12964
+ }, _UpdateService.CHECK_TIMEOUT_MS);
12965
+ timeoutHandle.unref?.();
12966
+ })
12967
+ ]);
12968
+ } finally {
12969
+ if (timeoutHandle) {
12970
+ clearTimeout(timeoutHandle);
12971
+ }
12972
+ }
12973
+ }
12974
+ persistAndBroadcast(patch, includeInFlightCheck = true) {
12975
+ const snapshot = this.deps.updateStateRepo.update((current) => ({
12976
+ ...patch,
12977
+ currentVersion: patch.currentVersion ?? current.currentVersion
12978
+ }));
12979
+ const view = this.composeStateView(snapshot, { includeInFlightCheck });
12980
+ this.deps.broadcaster.broadcast("update.state.changed", view);
12981
+ return view;
12982
+ }
12884
12983
  };
12885
12984
  }
12886
12985
  });
@@ -13737,7 +13836,8 @@ var init_terminal = __esm({
13737
13836
  workspaceId: z6.string(),
13738
13837
  cols: z6.number().int().positive().optional(),
13739
13838
  rows: z6.number().int().positive().optional(),
13740
- cwdPath: z6.string().optional()
13839
+ cwdPath: z6.string().optional(),
13840
+ themeBackground: z6.string().regex(/^#[0-9a-fA-F]{3,8}$/).optional()
13741
13841
  }),
13742
13842
  async (args, ctx) => {
13743
13843
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -13775,7 +13875,8 @@ var init_terminal = __esm({
13775
13875
  title: shell.title,
13776
13876
  cwd,
13777
13877
  cols: args.cols ?? 120,
13778
- rows: args.rows ?? 30
13878
+ rows: args.rows ?? 30,
13879
+ themeBackground: args.themeBackground
13779
13880
  });
13780
13881
  return terminal;
13781
13882
  }
@@ -15347,7 +15448,8 @@ var init_session2 = __esm({
15347
15448
  z12.object({
15348
15449
  workspaceId: z12.string(),
15349
15450
  providerId: z12.string(),
15350
- draft: z12.string().optional()
15451
+ draft: z12.string().optional(),
15452
+ themeBackground: z12.string().regex(/^#[0-9a-fA-F]{3,8}$/).optional()
15351
15453
  }),
15352
15454
  async (args, ctx) => {
15353
15455
  const workspace = ctx.workspaceMgr.get(args.workspaceId);
@@ -15375,7 +15477,8 @@ var init_session2 = __esm({
15375
15477
  workspacePath: workspace.path,
15376
15478
  providerId: args.providerId,
15377
15479
  provider,
15378
- draft: args.draft
15480
+ draft: args.draft,
15481
+ themeBackground: args.themeBackground
15379
15482
  });
15380
15483
  }
15381
15484
  );