copilot-statusline 0.1.9 → 0.1.10

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.
@@ -52913,7 +52913,7 @@ import { execSync as execSync3 } from "child_process";
52913
52913
  import * as fs5 from "fs";
52914
52914
  import * as path4 from "path";
52915
52915
  var __dirname = "/Users/ts/workspace/active/statusline/copilot_statusline/src/utils";
52916
- var PACKAGE_VERSION = "0.1.9";
52916
+ var PACKAGE_VERSION = "0.1.10";
52917
52917
  function getPackageVersion() {
52918
52918
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
52919
52919
  return PACKAGE_VERSION;
@@ -53915,8 +53915,22 @@ class SessionIdWidget {
53915
53915
  }
53916
53916
  }
53917
53917
  // src/utils/display-name-parser.ts
53918
- var EFFORT_LEVELS = new Set(["low", "medium", "high"]);
53918
+ var THINKING_EFFORT_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"];
53919
+ var EFFORT_LEVELS = new Set(THINKING_EFFORT_LEVELS);
53920
+ var EFFORT_LEVEL_PATTERN = THINKING_EFFORT_LEVELS.join("|");
53919
53921
  var MULTIPLIER_REGEX = /^(\d+)x$/;
53922
+ var LABELED_EFFORT_REGEX = new RegExp(`^(?:thinking|reasoning|effort)(?:[-_ ](?:effort|level))?\\s*[:=]\\s*(${EFFORT_LEVEL_PATTERN})$`);
53923
+ function normalizeThinkingEffort(value) {
53924
+ if (!value) {
53925
+ return null;
53926
+ }
53927
+ const normalized = value.trim().toLowerCase();
53928
+ if (EFFORT_LEVELS.has(normalized)) {
53929
+ return normalized;
53930
+ }
53931
+ const match = LABELED_EFFORT_REGEX.exec(normalized);
53932
+ return match?.[1] ? match[1] : null;
53933
+ }
53920
53934
  function parseDisplayName(displayName) {
53921
53935
  if (!displayName) {
53922
53936
  return { thinkingEffort: null, multiplier: null, multiplierValue: null };
@@ -53934,9 +53948,19 @@ function parseDisplayName(displayName) {
53934
53948
  let multiplier = null;
53935
53949
  let multiplierValue = null;
53936
53950
  for (let i = groups.length - 1;i >= 0; i--) {
53937
- const group = groups[i]?.toLowerCase();
53938
- if (group && EFFORT_LEVELS.has(group)) {
53939
- thinkingEffort = group;
53951
+ const group = groups[i];
53952
+ if (!group) {
53953
+ continue;
53954
+ }
53955
+ const parts = group.split(/[,;|]/).map((part) => part.trim());
53956
+ for (let partIndex = parts.length - 1;partIndex >= 0; partIndex--) {
53957
+ const effort = normalizeThinkingEffort(parts[partIndex]);
53958
+ if (effort) {
53959
+ thinkingEffort = effort;
53960
+ break;
53961
+ }
53962
+ }
53963
+ if (thinkingEffort) {
53940
53964
  break;
53941
53965
  }
53942
53966
  }
@@ -53944,10 +53968,16 @@ function parseDisplayName(displayName) {
53944
53968
  if (!group) {
53945
53969
  continue;
53946
53970
  }
53947
- const multMatch = MULTIPLIER_REGEX.exec(group);
53948
- if (multMatch?.[1]) {
53949
- multiplier = group;
53950
- multiplierValue = parseInt(multMatch[1], 10);
53971
+ const parts = group.split(/[,;|]/).map((part) => part.trim());
53972
+ for (const part of parts) {
53973
+ const multMatch = MULTIPLIER_REGEX.exec(part);
53974
+ if (multMatch?.[1]) {
53975
+ multiplier = part;
53976
+ multiplierValue = parseInt(multMatch[1], 10);
53977
+ break;
53978
+ }
53979
+ }
53980
+ if (multiplier) {
53951
53981
  break;
53952
53982
  }
53953
53983
  }
@@ -53960,7 +53990,7 @@ class ThinkingEffortWidget {
53960
53990
  return "magenta";
53961
53991
  }
53962
53992
  getDescription() {
53963
- return "Displays the thinking effort level parsed from model.display_name (low, medium, high)";
53993
+ return "Displays the thinking effort level from the Copilot model payload";
53964
53994
  }
53965
53995
  getDisplayName() {
53966
53996
  return "Thinking Effort";
@@ -53975,9 +54005,10 @@ class ThinkingEffortWidget {
53975
54005
  if (context.isPreview) {
53976
54006
  return item.rawValue ? "high" : "Thinking: high";
53977
54007
  }
53978
- const parsed = parseDisplayName(context.data?.model?.display_name);
53979
- if (parsed.thinkingEffort) {
53980
- return item.rawValue ? parsed.thinkingEffort : `Thinking: ${parsed.thinkingEffort}`;
54008
+ const model = context.data?.model;
54009
+ const thinkingEffort = normalizeThinkingEffort(model?.thinking_effort_level) ?? normalizeThinkingEffort(model?.thinking_effort) ?? normalizeThinkingEffort(model?.reasoning_effort) ?? parseDisplayName(model?.display_name).thinkingEffort;
54010
+ if (thinkingEffort) {
54011
+ return item.rawValue ? thinkingEffort : `Thinking: ${thinkingEffort}`;
53981
54012
  }
53982
54013
  return null;
53983
54014
  }
@@ -54983,51 +55014,131 @@ function getGitShortSha(context) {
54983
55014
  return runGit("rev-parse --short HEAD", context);
54984
55015
  }
54985
55016
 
54986
- // src/utils/hyperlink.ts
54987
- var IDE_LINK_MODES = [
54988
- "vscode",
54989
- "cursor"
54990
- ];
54991
- function renderOsc8Link(url2, text) {
54992
- return `\x1B]8;;${url2}\x1B\\${text}\x1B]8;;\x1B\\`;
54993
- }
54994
- function parseGitHubRepositoryPath(pathname) {
54995
- const trimmedPath = pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
54996
- const segments = trimmedPath.split("/").filter(Boolean);
54997
- if (segments.length !== 2) {
54998
- return null;
54999
- }
55000
- return `${segments[0]}/${segments[1]}`;
55001
- }
55002
- function parseGitHubBaseUrl(remoteUrl) {
55003
- const trimmed = remoteUrl.trim();
55017
+ // src/utils/git-remote.ts
55018
+ function parseRemoteUrl(url2) {
55019
+ const trimmed = url2.trim();
55004
55020
  if (trimmed.length === 0) {
55005
55021
  return null;
55006
55022
  }
55007
- const sshMatch = /^(?:[^@]+@)?github\.com:([^/]+\/[^/]+?)(?:\.git)?\/?$/.exec(trimmed);
55008
- if (sshMatch?.[1]) {
55009
- return `https://github.com/${sshMatch[1]}`;
55023
+ const sshMatch = !trimmed.includes("://") ? /^(?:[^@]+@)?([^:]+):(.+?)(?:\.git)?\/?$/.exec(trimmed) : null;
55024
+ if (sshMatch?.[1] && sshMatch[2]) {
55025
+ const pathSegments = sshMatch[2].split("/").filter(Boolean);
55026
+ const repo = pathSegments.at(-1);
55027
+ const owner = pathSegments.slice(0, -1).join("/");
55028
+ if (!owner || !repo) {
55029
+ return null;
55030
+ }
55031
+ return {
55032
+ host: sshMatch[1],
55033
+ owner,
55034
+ repo
55035
+ };
55010
55036
  }
55011
55037
  try {
55012
55038
  const parsedUrl = new URL(trimmed);
55013
- const supportedProtocols = new Set([
55014
- "http:",
55015
- "https:",
55016
- "ssh:",
55017
- "git:"
55018
- ]);
55019
- if (parsedUrl.hostname.toLowerCase() !== "github.com" || !supportedProtocols.has(parsedUrl.protocol)) {
55039
+ const supportedProtocols = new Set(["http:", "https:", "ssh:", "git:"]);
55040
+ if (!supportedProtocols.has(parsedUrl.protocol)) {
55020
55041
  return null;
55021
55042
  }
55022
- const repoPath = parseGitHubRepositoryPath(parsedUrl.pathname);
55023
- if (!repoPath) {
55043
+ const pathname = parsedUrl.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
55044
+ const segments = pathname.split("/").filter(Boolean);
55045
+ const repo = segments.at(-1);
55046
+ const owner = segments.slice(0, -1).join("/");
55047
+ if (!owner || !repo) {
55024
55048
  return null;
55025
55049
  }
55026
- return `https://github.com/${repoPath}`;
55050
+ return {
55051
+ host: parsedUrl.hostname,
55052
+ owner,
55053
+ repo
55054
+ };
55027
55055
  } catch {
55028
55056
  return null;
55029
55057
  }
55030
55058
  }
55059
+ function getRemoteInfo(remoteName, context) {
55060
+ const url2 = runGit(`remote get-url ${remoteName}`, context);
55061
+ if (!url2) {
55062
+ return null;
55063
+ }
55064
+ const parsed = parseRemoteUrl(url2);
55065
+ if (!parsed) {
55066
+ return null;
55067
+ }
55068
+ return {
55069
+ name: remoteName,
55070
+ url: url2,
55071
+ host: parsed.host,
55072
+ owner: parsed.owner,
55073
+ repo: parsed.repo
55074
+ };
55075
+ }
55076
+ function getTrackingRemoteName(context) {
55077
+ const upstreamRef = runGit("rev-parse --abbrev-ref --symbolic-full-name @{upstream}", context);
55078
+ if (!upstreamRef) {
55079
+ return null;
55080
+ }
55081
+ const remotes = listRemotes(context).slice().sort((left, right) => right.length - left.length);
55082
+ return remotes.find((remote) => upstreamRef === remote || upstreamRef.startsWith(`${remote}/`)) ?? null;
55083
+ }
55084
+ function getUpstreamRemoteInfo(context) {
55085
+ const namedUpstream = getRemoteInfo("upstream", context);
55086
+ if (namedUpstream) {
55087
+ return namedUpstream;
55088
+ }
55089
+ const trackingRemoteName = getTrackingRemoteName(context);
55090
+ if (!trackingRemoteName) {
55091
+ return null;
55092
+ }
55093
+ return getRemoteInfo(trackingRemoteName, context);
55094
+ }
55095
+ function getForkStatus(context) {
55096
+ const origin = getRemoteInfo("origin", context);
55097
+ const upstream = getRemoteInfo("upstream", context);
55098
+ const isFork = Boolean(origin && upstream && (origin.owner !== upstream.owner || origin.repo !== upstream.repo));
55099
+ return {
55100
+ isFork,
55101
+ origin,
55102
+ upstream
55103
+ };
55104
+ }
55105
+ function listRemotes(context) {
55106
+ const output = runGit("remote", context);
55107
+ if (!output) {
55108
+ return [];
55109
+ }
55110
+ return output.split(`
55111
+ `).filter(Boolean);
55112
+ }
55113
+ function buildRepoWebUrl(remote) {
55114
+ let webHost = remote.host;
55115
+ try {
55116
+ const parsedUrl = new URL(remote.url);
55117
+ if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
55118
+ webHost = parsedUrl.host;
55119
+ }
55120
+ } catch {}
55121
+ return `https://${webHost}/${remote.owner}/${remote.repo}`;
55122
+ }
55123
+ function getBranchWebPath(remote) {
55124
+ const host = remote.host.toLowerCase().replace(/:\d+$/, "");
55125
+ if (host === "gitlab.com" || /^[^.]+\.gitlab\.com$/.test(host)) {
55126
+ return "/-/tree/";
55127
+ }
55128
+ return "/tree/";
55129
+ }
55130
+ function buildBranchWebUrl(remote, encodedBranch) {
55131
+ return `${buildRepoWebUrl(remote)}${getBranchWebPath(remote)}${encodedBranch}`;
55132
+ }
55133
+
55134
+ // src/utils/hyperlink.ts
55135
+ var IDE_LINK_MODES = [
55136
+ "vscode",
55137
+ "cursor"
55138
+ ];
55139
+ function renderOsc8Link(url2, text) {
55140
+ return `\x1B]8;;${url2}\x1B\\${text}\x1B]8;;\x1B\\`;
55141
+ }
55031
55142
  function encodeGitRefForUrlPath(ref) {
55032
55143
  return ref.split("/").map((segment) => encodeURIComponent(segment)).join("/");
55033
55144
  }
@@ -55074,8 +55185,30 @@ function getHideNoGitKeybinds() {
55074
55185
  }
55075
55186
 
55076
55187
  // src/widgets/GitBranch.ts
55077
- var LINK_KEY = "linkToGitHub";
55188
+ var LINK_KEY = "linkToRepo";
55189
+ var LEGACY_LINK_KEY = "linkToGitHub";
55078
55190
  var TOGGLE_LINK_ACTION = "toggle-link";
55191
+ var PREVIEW_REMOTE = {
55192
+ name: "origin",
55193
+ url: "https://example.com/owner/repo.git",
55194
+ host: "example.com",
55195
+ owner: "owner",
55196
+ repo: "repo"
55197
+ };
55198
+ function isLinkEnabled(item) {
55199
+ return isMetadataFlagEnabled(item, LINK_KEY) || item.metadata?.[LINK_KEY] === undefined && isMetadataFlagEnabled(item, LEGACY_LINK_KEY);
55200
+ }
55201
+ function toggleLink(item) {
55202
+ const nextEnabled = !isLinkEnabled(item);
55203
+ const nextMetadata = Object.fromEntries(Object.entries(item.metadata ?? {}).filter(([key]) => key !== LINK_KEY && key !== LEGACY_LINK_KEY));
55204
+ if (nextEnabled) {
55205
+ nextMetadata[LINK_KEY] = "true";
55206
+ }
55207
+ return {
55208
+ ...item,
55209
+ metadata: Object.keys(nextMetadata).length > 0 ? nextMetadata : undefined
55210
+ };
55211
+ }
55079
55212
 
55080
55213
  class GitBranchWidget {
55081
55214
  getDefaultColor() {
@@ -55091,13 +55224,13 @@ class GitBranchWidget {
55091
55224
  return "Git";
55092
55225
  }
55093
55226
  getEditorDisplay(item) {
55094
- const isLink = isMetadataFlagEnabled(item, LINK_KEY);
55227
+ const isLink = isLinkEnabled(item);
55095
55228
  const modifiers = [];
55096
55229
  const noGitText = getHideNoGitModifierText(item);
55097
55230
  if (noGitText)
55098
55231
  modifiers.push("hide 'no git'");
55099
55232
  if (isLink)
55100
- modifiers.push("GitHub link");
55233
+ modifiers.push("repo link");
55101
55234
  return {
55102
55235
  displayText: this.getDisplayName(),
55103
55236
  modifierText: makeModifierText(modifiers)
@@ -55105,16 +55238,16 @@ class GitBranchWidget {
55105
55238
  }
55106
55239
  handleEditorAction(action, item) {
55107
55240
  if (action === TOGGLE_LINK_ACTION) {
55108
- return toggleMetadataFlag(item, LINK_KEY);
55241
+ return toggleLink(item);
55109
55242
  }
55110
55243
  return handleToggleNoGitAction(action, item);
55111
55244
  }
55112
55245
  render(item, context, settings) {
55113
55246
  const hideNoGit = isHideNoGitEnabled(item);
55114
- const isLink = isMetadataFlagEnabled(item, LINK_KEY);
55247
+ const isLink = isLinkEnabled(item);
55115
55248
  if (context.isPreview) {
55116
55249
  const text = item.rawValue ? "main" : "⎇ main";
55117
- return isLink ? renderOsc8Link("https://github.com/owner/repo/tree/main", text) : text;
55250
+ return isLink ? renderOsc8Link(buildBranchWebUrl(PREVIEW_REMOTE, "main"), text) : text;
55118
55251
  }
55119
55252
  if (!isInsideGitWorkTree(context)) {
55120
55253
  return hideNoGit ? null : "⎇ no git";
@@ -55125,10 +55258,9 @@ class GitBranchWidget {
55125
55258
  }
55126
55259
  const displayText = item.rawValue ? branch : `⎇ ${branch}`;
55127
55260
  if (isLink) {
55128
- const remoteUrl = runGit("remote get-url origin", context);
55129
- const baseUrl = remoteUrl ? parseGitHubBaseUrl(remoteUrl) : null;
55130
- if (baseUrl) {
55131
- return renderOsc8Link(`${baseUrl}/tree/${encodeGitRefForUrlPath(branch)}`, displayText);
55261
+ const origin = getRemoteInfo("origin", context);
55262
+ if (origin) {
55263
+ return renderOsc8Link(buildBranchWebUrl(origin, encodeGitRefForUrlPath(branch)), displayText);
55132
55264
  }
55133
55265
  }
55134
55266
  return displayText;
@@ -55139,7 +55271,7 @@ class GitBranchWidget {
55139
55271
  getCustomKeybinds() {
55140
55272
  return [
55141
55273
  ...getHideNoGitKeybinds(),
55142
- { key: "l", label: "(l)ink to GitHub", action: TOGGLE_LINK_ACTION }
55274
+ { key: "l", label: "(l)ink to repo", action: TOGGLE_LINK_ACTION }
55143
55275
  ];
55144
55276
  }
55145
55277
  supportsRawValue() {
@@ -56064,106 +56196,6 @@ class GitShaWidget {
56064
56196
  return true;
56065
56197
  }
56066
56198
  }
56067
- // src/utils/git-remote.ts
56068
- function parseRemoteUrl(url2) {
56069
- const trimmed = url2.trim();
56070
- if (trimmed.length === 0) {
56071
- return null;
56072
- }
56073
- const sshMatch = !trimmed.includes("://") ? /^(?:[^@]+@)?([^:]+):(.+?)(?:\.git)?\/?$/.exec(trimmed) : null;
56074
- if (sshMatch?.[1] && sshMatch[2]) {
56075
- const pathSegments = sshMatch[2].split("/").filter(Boolean);
56076
- const repo = pathSegments.at(-1);
56077
- const owner = pathSegments.slice(0, -1).join("/");
56078
- if (!owner || !repo) {
56079
- return null;
56080
- }
56081
- return {
56082
- host: sshMatch[1],
56083
- owner,
56084
- repo
56085
- };
56086
- }
56087
- try {
56088
- const parsedUrl = new URL(trimmed);
56089
- const supportedProtocols = new Set(["http:", "https:", "ssh:", "git:"]);
56090
- if (!supportedProtocols.has(parsedUrl.protocol)) {
56091
- return null;
56092
- }
56093
- const pathname = parsedUrl.pathname.replace(/^\/+|\/+$/g, "").replace(/\.git$/, "");
56094
- const segments = pathname.split("/").filter(Boolean);
56095
- const repo = segments.at(-1);
56096
- const owner = segments.slice(0, -1).join("/");
56097
- if (!owner || !repo) {
56098
- return null;
56099
- }
56100
- return {
56101
- host: parsedUrl.hostname,
56102
- owner,
56103
- repo
56104
- };
56105
- } catch {
56106
- return null;
56107
- }
56108
- }
56109
- function getRemoteInfo(remoteName, context) {
56110
- const url2 = runGit(`remote get-url ${remoteName}`, context);
56111
- if (!url2) {
56112
- return null;
56113
- }
56114
- const parsed = parseRemoteUrl(url2);
56115
- if (!parsed) {
56116
- return null;
56117
- }
56118
- return {
56119
- name: remoteName,
56120
- url: url2,
56121
- host: parsed.host,
56122
- owner: parsed.owner,
56123
- repo: parsed.repo
56124
- };
56125
- }
56126
- function getTrackingRemoteName(context) {
56127
- const upstreamRef = runGit("rev-parse --abbrev-ref --symbolic-full-name @{upstream}", context);
56128
- if (!upstreamRef) {
56129
- return null;
56130
- }
56131
- const remotes = listRemotes(context).slice().sort((left, right) => right.length - left.length);
56132
- return remotes.find((remote) => upstreamRef === remote || upstreamRef.startsWith(`${remote}/`)) ?? null;
56133
- }
56134
- function getUpstreamRemoteInfo(context) {
56135
- const namedUpstream = getRemoteInfo("upstream", context);
56136
- if (namedUpstream) {
56137
- return namedUpstream;
56138
- }
56139
- const trackingRemoteName = getTrackingRemoteName(context);
56140
- if (!trackingRemoteName) {
56141
- return null;
56142
- }
56143
- return getRemoteInfo(trackingRemoteName, context);
56144
- }
56145
- function getForkStatus(context) {
56146
- const origin = getRemoteInfo("origin", context);
56147
- const upstream = getRemoteInfo("upstream", context);
56148
- const isFork = Boolean(origin && upstream && (origin.owner !== upstream.owner || origin.repo !== upstream.repo));
56149
- return {
56150
- isFork,
56151
- origin,
56152
- upstream
56153
- };
56154
- }
56155
- function listRemotes(context) {
56156
- const output = runGit("remote", context);
56157
- if (!output) {
56158
- return [];
56159
- }
56160
- return output.split(`
56161
- `).filter(Boolean);
56162
- }
56163
- function buildRepoWebUrl(remote) {
56164
- return `https://${remote.host}/${remote.owner}/${remote.repo}`;
56165
- }
56166
-
56167
56199
  // src/widgets/shared/git-remote.ts
56168
56200
  var HIDE_NO_REMOTE_KEY = "hideNoRemote";
56169
56201
  var TOGGLE_NO_REMOTE_ACTION = "toggle-no-remote";
@@ -58336,7 +58368,7 @@ function List({
58336
58368
  initialSelection = 0,
58337
58369
  showBackButton,
58338
58370
  color,
58339
- wrapNavigation = false,
58371
+ wrapNavigation = true,
58340
58372
  ...boxProps
58341
58373
  }) {
58342
58374
  const [selectedIndex, setSelectedIndex] = import_react34.useState(initialSelection);
@@ -58364,6 +58396,9 @@ function List({
58364
58396
  }
58365
58397
  }, [selectedIndex, selectedValue]);
58366
58398
  use_input_default((_, key) => {
58399
+ if (selectableItems.length === 0) {
58400
+ return;
58401
+ }
58367
58402
  if (key.upArrow) {
58368
58403
  const prev = selectedIndex - 1;
58369
58404
  const prevIndex = prev < 0 ? wrapNavigation ? selectableItems.length - 1 : 0 : prev;
@@ -59532,6 +59567,21 @@ function setPickerState(setWidgetPicker, normalizeState, updater) {
59532
59567
  function getPickerCategories(widgetCategories) {
59533
59568
  return [...widgetCategories];
59534
59569
  }
59570
+ function wrapIndex(index, length) {
59571
+ if (length === 0) {
59572
+ return -1;
59573
+ }
59574
+ if (index < 0) {
59575
+ return length - 1;
59576
+ }
59577
+ if (index > length - 1) {
59578
+ return 0;
59579
+ }
59580
+ return index;
59581
+ }
59582
+ function getAdjacentIndex(currentIndex, length, isForward) {
59583
+ return wrapIndex(currentIndex + (isForward ? 1 : -1), length);
59584
+ }
59535
59585
  function normalizePickerState(state, widgetCatalog, widgetCategories) {
59536
59586
  const filteredCategories = getPickerCategories(widgetCategories);
59537
59587
  const selectedCategory = state.selectedCategory && filteredCategories.includes(state.selectedCategory) ? state.selectedCategory : filteredCategories[0] ?? null;
@@ -59614,7 +59664,7 @@ function handlePickerInputMode({
59614
59664
  if (currentIndex === -1) {
59615
59665
  currentIndex = 0;
59616
59666
  }
59617
- const nextIndex = key.downArrow ? Math.min(topLevelSearchEntries.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
59667
+ const nextIndex = getAdjacentIndex(currentIndex, topLevelSearchEntries.length, Boolean(key.downArrow));
59618
59668
  const nextType = topLevelSearchEntries[nextIndex]?.type ?? null;
59619
59669
  setPickerState(setWidgetPicker, normalizeState, (prev) => ({
59620
59670
  ...prev,
@@ -59628,7 +59678,7 @@ function handlePickerInputMode({
59628
59678
  if (currentIndex === -1) {
59629
59679
  currentIndex = 0;
59630
59680
  }
59631
- const nextIndex = key.downArrow ? Math.min(filteredCategories.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
59681
+ const nextIndex = getAdjacentIndex(currentIndex, filteredCategories.length, Boolean(key.downArrow));
59632
59682
  const nextCategory = filteredCategories[nextIndex] ?? null;
59633
59683
  setPickerState(setWidgetPicker, normalizeState, (prev) => ({
59634
59684
  ...prev,
@@ -59673,7 +59723,7 @@ function handlePickerInputMode({
59673
59723
  if (currentIndex === -1) {
59674
59724
  currentIndex = 0;
59675
59725
  }
59676
- const nextIndex = key.downArrow ? Math.min(filteredWidgets.length - 1, currentIndex + 1) : Math.max(0, currentIndex - 1);
59726
+ const nextIndex = getAdjacentIndex(currentIndex, filteredWidgets.length, Boolean(key.downArrow));
59677
59727
  const nextType = filteredWidgets[nextIndex]?.type ?? null;
59678
59728
  setPickerState(setWidgetPicker, normalizeState, (prev) => ({
59679
59729
  ...prev,
@@ -59702,24 +59752,26 @@ function handleMoveInputMode({
59702
59752
  setSelectedIndex,
59703
59753
  setMoveMode
59704
59754
  }) {
59705
- if (key.upArrow && selectedIndex > 0) {
59755
+ if (key.upArrow && widgets.length > 1) {
59706
59756
  const newWidgets = [...widgets];
59757
+ const targetIndex = getAdjacentIndex(selectedIndex, widgets.length, false);
59707
59758
  const temp = newWidgets[selectedIndex];
59708
- const prev = newWidgets[selectedIndex - 1];
59759
+ const prev = newWidgets[targetIndex];
59709
59760
  if (temp && prev) {
59710
- [newWidgets[selectedIndex], newWidgets[selectedIndex - 1]] = [prev, temp];
59761
+ [newWidgets[selectedIndex], newWidgets[targetIndex]] = [prev, temp];
59711
59762
  }
59712
59763
  onUpdate(newWidgets);
59713
- setSelectedIndex(selectedIndex - 1);
59714
- } else if (key.downArrow && selectedIndex < widgets.length - 1) {
59764
+ setSelectedIndex(targetIndex);
59765
+ } else if (key.downArrow && widgets.length > 1) {
59715
59766
  const newWidgets = [...widgets];
59767
+ const targetIndex = getAdjacentIndex(selectedIndex, widgets.length, true);
59716
59768
  const temp = newWidgets[selectedIndex];
59717
- const next = newWidgets[selectedIndex + 1];
59769
+ const next = newWidgets[targetIndex];
59718
59770
  if (temp && next) {
59719
- [newWidgets[selectedIndex], newWidgets[selectedIndex + 1]] = [next, temp];
59771
+ [newWidgets[selectedIndex], newWidgets[targetIndex]] = [next, temp];
59720
59772
  }
59721
59773
  onUpdate(newWidgets);
59722
- setSelectedIndex(selectedIndex + 1);
59774
+ setSelectedIndex(targetIndex);
59723
59775
  } else if (key.escape || key.return) {
59724
59776
  setMoveMode(false);
59725
59777
  }
@@ -59737,12 +59789,13 @@ function handleNormalInputMode({
59737
59789
  setShowClearConfirm,
59738
59790
  openWidgetPicker,
59739
59791
  getCustomKeybindsForWidget,
59740
- setCustomEditorWidget
59792
+ setCustomEditorWidget,
59793
+ getUniqueBackgroundColor
59741
59794
  }) {
59742
59795
  if (key.upArrow && widgets.length > 0) {
59743
- setSelectedIndex(Math.max(0, selectedIndex - 1));
59796
+ setSelectedIndex(getAdjacentIndex(selectedIndex, widgets.length, false));
59744
59797
  } else if (key.downArrow && widgets.length > 0) {
59745
- setSelectedIndex(Math.min(widgets.length - 1, selectedIndex + 1));
59798
+ setSelectedIndex(getAdjacentIndex(selectedIndex, widgets.length, true));
59746
59799
  } else if (key.leftArrow && widgets.length > 0) {
59747
59800
  openWidgetPicker("change");
59748
59801
  } else if (key.rightArrow && widgets.length > 0) {
@@ -59759,6 +59812,26 @@ function handleNormalInputMode({
59759
59812
  if (selectedIndex >= newWidgets.length && selectedIndex > 0) {
59760
59813
  setSelectedIndex(selectedIndex - 1);
59761
59814
  }
59815
+ } else if (input === "k" && widgets.length > 0) {
59816
+ const source = widgets[selectedIndex];
59817
+ if (!source) {
59818
+ return;
59819
+ }
59820
+ const cloneInsertPosition = selectedIndex + 1;
59821
+ const uniqueBackgroundColor = getUniqueBackgroundColor?.(cloneInsertPosition);
59822
+ const clone3 = {
59823
+ ...source,
59824
+ id: generateGuid(),
59825
+ ...source.metadata ? { metadata: { ...source.metadata } } : {},
59826
+ ...uniqueBackgroundColor && { backgroundColor: uniqueBackgroundColor }
59827
+ };
59828
+ const newWidgets = [
59829
+ ...widgets.slice(0, cloneInsertPosition),
59830
+ clone3,
59831
+ ...widgets.slice(cloneInsertPosition)
59832
+ ];
59833
+ onUpdate(newWidgets);
59834
+ setSelectedIndex(cloneInsertPosition);
59762
59835
  } else if (input === "c") {
59763
59836
  if (widgets.length > 0) {
59764
59837
  setShowClearConfirm(true);
@@ -59959,7 +60032,8 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
59959
60032
  setShowClearConfirm,
59960
60033
  openWidgetPicker,
59961
60034
  getCustomKeybindsForWidget,
59962
- setCustomEditorWidget
60035
+ setCustomEditorWidget,
60036
+ getUniqueBackgroundColor
59963
60037
  });
59964
60038
  });
59965
60039
  const getWidgetDisplay = (widget) => {
@@ -60007,7 +60081,7 @@ var ItemsEditor = ({ widgets, onUpdate, onBack, lineNumber, settings }) => {
60007
60081
  helpText += ", Space edit separator";
60008
60082
  }
60009
60083
  if (hasWidgets) {
60010
- helpText += ", Enter to move, (a)dd via picker, (i)nsert via picker, (d)elete, (c)lear line";
60084
+ helpText += ", Enter to move, (a)dd via picker, (i)nsert via picker, (d)elete, (k)lone, (c)lear line";
60011
60085
  }
60012
60086
  if (canToggleRaw) {
60013
60087
  helpText += ", (r)aw value";
@@ -60440,26 +60514,28 @@ var LineSelector = ({
60440
60514
  return;
60441
60515
  }
60442
60516
  if (moveMode) {
60443
- if (key.upArrow && selectedIndex > 0) {
60517
+ if (key.upArrow && localLines.length > 1) {
60444
60518
  const newLines = [...localLines];
60519
+ const targetIndex = selectedIndex - 1 < 0 ? localLines.length - 1 : selectedIndex - 1;
60445
60520
  const temp = newLines[selectedIndex];
60446
- const prev = newLines[selectedIndex - 1];
60521
+ const prev = newLines[targetIndex];
60447
60522
  if (temp && prev) {
60448
- [newLines[selectedIndex], newLines[selectedIndex - 1]] = [prev, temp];
60523
+ [newLines[selectedIndex], newLines[targetIndex]] = [prev, temp];
60449
60524
  }
60450
60525
  setLocalLines(newLines);
60451
60526
  onLinesUpdate(newLines);
60452
- setSelectedIndex(selectedIndex - 1);
60453
- } else if (key.downArrow && selectedIndex < localLines.length - 1) {
60527
+ setSelectedIndex(targetIndex);
60528
+ } else if (key.downArrow && localLines.length > 1) {
60454
60529
  const newLines = [...localLines];
60530
+ const targetIndex = selectedIndex + 1 > localLines.length - 1 ? 0 : selectedIndex + 1;
60455
60531
  const temp = newLines[selectedIndex];
60456
- const next = newLines[selectedIndex + 1];
60532
+ const next = newLines[targetIndex];
60457
60533
  if (temp && next) {
60458
- [newLines[selectedIndex], newLines[selectedIndex + 1]] = [next, temp];
60534
+ [newLines[selectedIndex], newLines[targetIndex]] = [next, temp];
60459
60535
  }
60460
60536
  setLocalLines(newLines);
60461
60537
  onLinesUpdate(newLines);
60462
- setSelectedIndex(selectedIndex + 1);
60538
+ setSelectedIndex(targetIndex);
60463
60539
  } else if (key.escape || key.return) {
60464
60540
  setMoveMode(false);
60465
60541
  }
@@ -63223,7 +63299,10 @@ var CopilotPayloadSchema = exports_external.object({
63223
63299
  transcript_path: exports_external.string().optional(),
63224
63300
  model: exports_external.object({
63225
63301
  id: exports_external.string().nullable().optional(),
63226
- display_name: exports_external.string().nullable().optional()
63302
+ display_name: exports_external.string().nullable().optional(),
63303
+ thinking_effort: exports_external.string().nullable().optional(),
63304
+ thinking_effort_level: exports_external.string().nullable().optional(),
63305
+ reasoning_effort: exports_external.string().nullable().optional()
63227
63306
  }).optional(),
63228
63307
  workspace: exports_external.object({ current_dir: exports_external.string().optional() }).optional(),
63229
63308
  version: exports_external.string().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-statusline",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "A customizable status line formatter for GitHub Copilot CLI — based on ccstatusline",
5
5
  "module": "src/copilot-statusline.ts",
6
6
  "type": "module",