xtralab 0.15.0 → 0.15.2

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.
Files changed (237) hide show
  1. package/README.md +65 -30
  2. package/lib/about/icons.d.ts +0 -5
  3. package/lib/about/icons.js +0 -5
  4. package/lib/about/index.d.ts +4 -8
  5. package/lib/about/index.js +6 -17
  6. package/lib/agentSessions.d.ts +9 -29
  7. package/lib/agentSessions.js +2 -7
  8. package/lib/askAgent/editorSelection.d.ts +20 -26
  9. package/lib/askAgent/editorSelection.js +11 -26
  10. package/lib/askAgent/icons.d.ts +2 -3
  11. package/lib/askAgent/icons.js +2 -3
  12. package/lib/askAgent/index.d.ts +4 -26
  13. package/lib/askAgent/index.js +54 -158
  14. package/lib/askAgent/popup.d.ts +12 -16
  15. package/lib/askAgent/popup.js +18 -37
  16. package/lib/askAgent/prompt.d.ts +3 -5
  17. package/lib/askAgent/prompt.js +6 -19
  18. package/lib/askAgent/queue.d.ts +11 -21
  19. package/lib/askAgent/queue.js +9 -19
  20. package/lib/askAgent/queuePanel.d.ts +13 -18
  21. package/lib/askAgent/queuePanel.js +15 -37
  22. package/lib/askAgent/targetPicker.d.ts +2 -9
  23. package/lib/askAgent/targetPicker.js +6 -11
  24. package/lib/askAgent/tokens.d.ts +32 -46
  25. package/lib/askAgent/tokens.js +4 -6
  26. package/lib/commandBar/index.d.ts +4 -13
  27. package/lib/commandBar/index.js +21 -39
  28. package/lib/customPanel/index.js +15 -0
  29. package/lib/editorBreadcrumbs/index.d.ts +3 -6
  30. package/lib/editorBreadcrumbs/index.js +10 -6
  31. package/lib/editorBreadcrumbs/widget.d.ts +17 -4
  32. package/lib/editorBreadcrumbs/widget.js +11 -17
  33. package/lib/editorIndent/index.d.ts +4 -12
  34. package/lib/editorIndent/index.js +8 -23
  35. package/lib/fileBrowser/commands.d.ts +29 -19
  36. package/lib/fileBrowser/commands.js +83 -97
  37. package/lib/fileBrowser/contents.d.ts +3 -0
  38. package/lib/fileBrowser/dragAndDrop.d.ts +17 -4
  39. package/lib/fileBrowser/dragAndDrop.js +2 -7
  40. package/lib/fileBrowser/fileBrowser.d.ts +19 -9
  41. package/lib/fileBrowser/fileBrowser.js +70 -222
  42. package/lib/fileBrowser/gitStatus.d.ts +16 -10
  43. package/lib/fileBrowser/gitStatus.js +31 -30
  44. package/lib/fileBrowser/gitignore.d.ts +4 -17
  45. package/lib/fileBrowser/gitignore.js +4 -25
  46. package/lib/fileBrowser/icons.d.ts +7 -17
  47. package/lib/fileBrowser/icons.js +25 -80
  48. package/lib/fileBrowser/index.js +2 -4
  49. package/lib/fileBrowser/widget.d.ts +141 -48
  50. package/lib/fileBrowser/widget.js +102 -4
  51. package/lib/fileTypeIcons/index.js +0 -10
  52. package/lib/git/api.d.ts +5 -13
  53. package/lib/git/api.js +10 -36
  54. package/lib/git/askRequest.d.ts +4 -8
  55. package/lib/git/askRequest.js +6 -20
  56. package/lib/git/commands.d.ts +45 -5
  57. package/lib/git/commands.js +20 -13
  58. package/lib/git/diffModel.js +4 -0
  59. package/lib/git/diffPreferences.d.ts +90 -0
  60. package/lib/git/diffPreferences.js +107 -0
  61. package/lib/git/diffProvider.js +10 -2
  62. package/lib/git/diffSurface.d.ts +64 -63
  63. package/lib/git/diffSurface.js +72 -213
  64. package/lib/git/diffTheme.d.ts +7 -0
  65. package/lib/git/diffTheme.js +23 -0
  66. package/lib/git/diffWidget.d.ts +70 -14
  67. package/lib/git/diffWidget.js +100 -94
  68. package/lib/git/imageDiff.d.ts +14 -6
  69. package/lib/git/imageDiff.js +19 -75
  70. package/lib/git/index.d.ts +0 -3
  71. package/lib/git/index.js +44 -10
  72. package/lib/git/notebookDiff.d.ts +110 -33
  73. package/lib/git/notebookDiff.js +55 -197
  74. package/lib/git/tokens.d.ts +73 -31
  75. package/lib/git/tokens.js +2 -3
  76. package/lib/highlight/index.d.ts +4 -10
  77. package/lib/highlight/index.js +10 -41
  78. package/lib/index.d.ts +0 -9
  79. package/lib/index.js +0 -9
  80. package/lib/launcher/agents.d.ts +55 -51
  81. package/lib/launcher/agents.js +15 -57
  82. package/lib/launcher/availability.d.ts +3 -9
  83. package/lib/launcher/availability.js +3 -9
  84. package/lib/launcher/commands.d.ts +7 -32
  85. package/lib/launcher/commands.js +14 -45
  86. package/lib/launcher/dashboard.d.ts +19 -24
  87. package/lib/launcher/dashboard.js +21 -67
  88. package/lib/launcher/editorRegistry.d.ts +10 -22
  89. package/lib/launcher/editorRegistry.js +14 -18
  90. package/lib/launcher/editors.d.ts +39 -45
  91. package/lib/launcher/editors.js +8 -34
  92. package/lib/launcher/icons.d.ts +0 -12
  93. package/lib/launcher/icons.js +5 -39
  94. package/lib/launcher/index.js +12 -55
  95. package/lib/launcher/invocation.d.ts +4 -10
  96. package/lib/launcher/invocation.js +7 -22
  97. package/lib/launcher/registry.d.ts +9 -7
  98. package/lib/launcher/registry.js +9 -7
  99. package/lib/launcher/tokens.d.ts +10 -22
  100. package/lib/launcher/tokens.js +5 -8
  101. package/lib/menuBar/index.d.ts +3 -10
  102. package/lib/menuBar/index.js +11 -28
  103. package/lib/menus/index.d.ts +3 -9
  104. package/lib/menus/index.js +14 -30
  105. package/lib/omnibox/files.d.ts +2 -4
  106. package/lib/omnibox/files.js +5 -11
  107. package/lib/omnibox/index.d.ts +4 -14
  108. package/lib/omnibox/index.js +9 -27
  109. package/lib/omnibox/model.d.ts +38 -10
  110. package/lib/omnibox/model.js +15 -33
  111. package/lib/omnibox/recents.d.ts +15 -17
  112. package/lib/omnibox/recents.js +12 -17
  113. package/lib/omnibox/tokens.d.ts +5 -10
  114. package/lib/omnibox/tokens.js +2 -6
  115. package/lib/omnibox/widget.d.ts +11 -7
  116. package/lib/omnibox/widget.js +8 -16
  117. package/lib/searchReplace/index.d.ts +4 -20
  118. package/lib/searchReplace/index.js +7 -27
  119. package/lib/showOutput/index.d.ts +3 -12
  120. package/lib/showOutput/index.js +6 -22
  121. package/lib/sidebar/index.d.ts +4 -7
  122. package/lib/sidebar/index.js +5 -12
  123. package/lib/terminalNotifications/index.d.ts +4 -10
  124. package/lib/terminalNotifications/index.js +6 -20
  125. package/lib/terminals/agentTerminals.d.ts +12 -5
  126. package/lib/terminals/agentTerminals.js +25 -44
  127. package/lib/terminals/detection.d.ts +4 -8
  128. package/lib/terminals/detection.js +4 -8
  129. package/lib/terminals/index.d.ts +0 -35
  130. package/lib/terminals/index.js +12 -101
  131. package/lib/terminals/model.d.ts +64 -139
  132. package/lib/terminals/model.js +80 -220
  133. package/lib/terminals/tokens.d.ts +11 -22
  134. package/lib/terminals/tokens.js +2 -2
  135. package/lib/terminals/widget.d.ts +43 -13
  136. package/lib/terminals/widget.js +33 -18
  137. package/lib/topBar/icons.d.ts +3 -8
  138. package/lib/topBar/icons.js +3 -8
  139. package/lib/topBar/index.d.ts +4 -11
  140. package/lib/topBar/index.js +10 -38
  141. package/lib/walkthrough/index.d.ts +4 -9
  142. package/lib/walkthrough/index.js +6 -20
  143. package/lib/walkthrough/panel.d.ts +40 -9
  144. package/lib/walkthrough/panel.js +4 -10
  145. package/package.json +5 -3
  146. package/schema/git-diff-preferences.json +42 -0
  147. package/src/about/icons.ts +0 -5
  148. package/src/about/index.tsx +6 -17
  149. package/src/agentSessions.ts +9 -29
  150. package/src/askAgent/editorSelection.ts +22 -29
  151. package/src/askAgent/icons.ts +2 -3
  152. package/src/askAgent/index.ts +54 -158
  153. package/src/askAgent/popup.tsx +23 -45
  154. package/src/askAgent/prompt.ts +6 -19
  155. package/src/askAgent/queue.ts +13 -24
  156. package/src/askAgent/queuePanel.tsx +21 -46
  157. package/src/askAgent/targetPicker.tsx +5 -15
  158. package/src/askAgent/tokens.ts +32 -46
  159. package/src/commandBar/index.ts +24 -39
  160. package/src/customPanel/index.ts +15 -0
  161. package/src/editorBreadcrumbs/index.ts +10 -6
  162. package/src/editorBreadcrumbs/widget.ts +23 -17
  163. package/src/editorIndent/index.ts +17 -23
  164. package/src/fileBrowser/commands.ts +119 -96
  165. package/src/fileBrowser/contents.ts +3 -0
  166. package/src/fileBrowser/dragAndDrop.ts +17 -7
  167. package/src/fileBrowser/fileBrowser.tsx +86 -230
  168. package/src/fileBrowser/gitStatus.ts +36 -33
  169. package/src/fileBrowser/gitignore.ts +4 -25
  170. package/src/fileBrowser/icons.ts +25 -80
  171. package/src/fileBrowser/index.ts +2 -4
  172. package/src/fileBrowser/widget.tsx +171 -50
  173. package/src/fileTypeIcons/index.ts +0 -10
  174. package/src/git/api.ts +10 -36
  175. package/src/git/askRequest.ts +6 -20
  176. package/src/git/commands.ts +83 -11
  177. package/src/git/diffModel.ts +25 -0
  178. package/src/git/diffPreferences.ts +192 -0
  179. package/src/git/diffProvider.tsx +11 -2
  180. package/src/git/diffSurface.tsx +165 -286
  181. package/src/git/diffTheme.ts +24 -0
  182. package/src/git/diffWidget.tsx +194 -134
  183. package/src/git/imageDiff.tsx +56 -84
  184. package/src/git/index.ts +54 -10
  185. package/src/git/notebookDiff.tsx +214 -240
  186. package/src/git/tokens.ts +73 -31
  187. package/src/highlight/index.ts +10 -41
  188. package/src/index.ts +0 -9
  189. package/src/launcher/agents.ts +64 -95
  190. package/src/launcher/availability.ts +3 -9
  191. package/src/launcher/commands.ts +14 -51
  192. package/src/launcher/dashboard.tsx +49 -88
  193. package/src/launcher/editorRegistry.ts +21 -29
  194. package/src/launcher/editors.ts +39 -58
  195. package/src/launcher/icons.ts +5 -39
  196. package/src/launcher/index.ts +12 -55
  197. package/src/launcher/invocation.ts +7 -22
  198. package/src/launcher/registry.ts +9 -7
  199. package/src/launcher/tokens.ts +10 -22
  200. package/src/menuBar/index.ts +11 -28
  201. package/src/menus/index.ts +14 -30
  202. package/src/omnibox/files.ts +10 -14
  203. package/src/omnibox/index.ts +9 -27
  204. package/src/omnibox/model.ts +50 -38
  205. package/src/omnibox/recents.ts +17 -22
  206. package/src/omnibox/tokens.ts +5 -10
  207. package/src/omnibox/widget.tsx +14 -19
  208. package/src/searchReplace/index.ts +7 -27
  209. package/src/showOutput/index.ts +6 -22
  210. package/src/sidebar/index.ts +20 -12
  211. package/src/terminalNotifications/index.ts +42 -25
  212. package/src/terminals/agentTerminals.ts +25 -49
  213. package/src/terminals/detection.ts +4 -8
  214. package/src/terminals/index.ts +12 -101
  215. package/src/terminals/model.ts +130 -246
  216. package/src/terminals/tokens.ts +11 -22
  217. package/src/terminals/widget.tsx +48 -31
  218. package/src/topBar/icons.ts +3 -8
  219. package/src/topBar/index.ts +21 -44
  220. package/src/walkthrough/index.ts +6 -20
  221. package/src/walkthrough/panel.ts +40 -10
  222. package/style/about.css +2 -7
  223. package/style/askAgent.css +8 -40
  224. package/style/base.css +9 -45
  225. package/style/chrome.css +108 -308
  226. package/style/commandBar.css +4 -20
  227. package/style/customPanel.css +1 -4
  228. package/style/git.css +26 -186
  229. package/style/highlight.css +1 -3
  230. package/style/launcher.css +6 -70
  231. package/style/omnibox.css +2 -14
  232. package/style/showOutput.css +0 -6
  233. package/style/sidebar.css +29 -9
  234. package/style/tabs.css +5 -13
  235. package/style/terminals.css +6 -53
  236. package/style/topBar.css +2 -22
  237. package/style/walkthrough.css +0 -8
@@ -2,13 +2,9 @@ import { URLExt } from '@jupyterlab/coreutils';
2
2
  import { ServerConnection } from '@jupyterlab/services';
3
3
  /**
4
4
  * Fetch and flatten the workspace file list from `jupyterlab-quickopen`'s
5
- * server endpoint (`GET {base}/jupyterlab-quickopen/api/files`).
6
- *
7
- * We reuse quickopen's endpoint rather than walking the contents API so the
8
- * listing honors the same server-side `.gitignore` filtering quickopen does
9
- * (xtralab ships `respectGitignore: true`) in a single request. The endpoint
10
- * only exists when quickopen's server extension is installed and the server
11
- * reads a local filesystem; callers treat a rejection as "no file results".
5
+ * server endpoint, which applies server-side `.gitignore` filtering in one
6
+ * request. Rejects when the server extension is absent; callers treat that as
7
+ * "no file results".
12
8
  */
13
9
  async function fetchWorkspaceFiles(respectGitignore = true) {
14
10
  const settings = ServerConnection.makeSettings();
@@ -36,10 +32,8 @@ async function fetchWorkspaceFiles(respectGitignore = true) {
36
32
  const CACHE_TTL_MS = 15000;
37
33
  let cache = null;
38
34
  /**
39
- * The workspace file list, cached briefly so reopening the omnibox in quick
40
- * succession reuses one scan. A failed fetch (e.g. quickopen's server
41
- * extension is absent) resolves to an empty list so file search degrades to
42
- * "no results" instead of surfacing an error.
35
+ * The workspace file list, cached briefly so reopening the omnibox reuses one
36
+ * scan. A failed fetch resolves to an empty list.
43
37
  */
44
38
  export function loadWorkspaceFiles() {
45
39
  const now = Date.now();
@@ -1,20 +1,10 @@
1
1
  import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
2
  import { IOmnibox } from './tokens';
3
3
  /**
4
- * The omnibox: a single launcher overlay that fuzzy-searches workspace files
5
- * (via jupyterlab-quickopen's gitignore-aware endpoint) and JupyterLab
6
- * commands (the command palette's entries plus registry commands the palette
7
- * doesn't list), and routes a typed prompt to one of the configured agents
8
- * (running it in a fresh terminal through the launcher's
9
- * `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
10
- * bar.
11
- *
12
- * Commands run and files opened through the overlay are remembered (persisted
13
- * in the state database) and offered again at the top while the query is
14
- * empty; the `maxNumberRecents` setting caps how many of each are kept.
15
- *
16
- * The agent rows come from the launcher's `IAgentRegistry`; when the launcher
17
- * is disabled the omnibox still searches files and commands.
4
+ * The omnibox: a launcher overlay that fuzzy-searches workspace files and
5
+ * commands and routes a typed prompt to a configured agent in a fresh
6
+ * terminal. Recently used commands and files persist in the state database;
7
+ * without the launcher it still searches files and commands.
18
8
  */
19
9
  declare const plugin: JupyterFrontEndPlugin<IOmnibox>;
20
10
  export default plugin;
@@ -9,20 +9,10 @@ import { IOmnibox, OMNIBOX_OPEN_COMMAND } from './tokens';
9
9
  import { OmniboxWidget } from './widget';
10
10
  const PLUGIN_ID = 'xtralab:omnibox';
11
11
  /**
12
- * The omnibox: a single launcher overlay that fuzzy-searches workspace files
13
- * (via jupyterlab-quickopen's gitignore-aware endpoint) and JupyterLab
14
- * commands (the command palette's entries plus registry commands the palette
15
- * doesn't list), and routes a typed prompt to one of the configured agents
16
- * (running it in a fresh terminal through the launcher's
17
- * `xtralab:start-agent:<id>` commands). It is opened by the top-bar command
18
- * bar.
19
- *
20
- * Commands run and files opened through the overlay are remembered (persisted
21
- * in the state database) and offered again at the top while the query is
22
- * empty; the `maxNumberRecents` setting caps how many of each are kept.
23
- *
24
- * The agent rows come from the launcher's `IAgentRegistry`; when the launcher
25
- * is disabled the omnibox still searches files and commands.
12
+ * The omnibox: a launcher overlay that fuzzy-searches workspace files and
13
+ * commands and routes a typed prompt to a configured agent in a fresh
14
+ * terminal. Recently used commands and files persist in the state database;
15
+ * without the launcher it still searches files and commands.
26
16
  */
27
17
  const plugin = {
28
18
  id: PLUGIN_ID,
@@ -40,21 +30,15 @@ const plugin = {
40
30
  const { commands, docRegistry } = app;
41
31
  const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyterlab');
42
32
  const placeholder = trans.__('Search files and commands, or ask an agent…');
43
- // The palette's items carry per-item args (e.g. one "Use Theme: …" per
44
- // theme) that a raw command-registry scan can't see, but `ICommandPalette`
45
- // exposes no item list and the widget itself is unreachable through the
46
- // shell (`LabShell.add` defers it until layout restore, after which the
47
- // modal setting re-parents it out of the left area). The wrapper's
48
- // `_palette` field is private in TypeScript only, so read it guarded.
33
+ // `ICommandPalette` exposes no item list and the palette widget is
34
+ // unreachable through the shell; duck-read the wrapper's TS-only-private `_palette`.
49
35
  const paletteItems = () => {
50
36
  const widget = palette === null || palette === void 0 ? void 0 : palette._palette;
51
37
  return widget instanceof CommandPalette ? [...widget.items] : [];
52
38
  };
53
39
  const recents = new OmniboxRecents({ state });
54
- // Restore the persisted recents only after the configured cap is known:
55
- // `restore` trims to `maxItems`, so restoring at the constructor default
56
- // would permanently drop entries beyond it whenever the user configured a
57
- // larger cap and the state fetch won the race against the settings load.
40
+ // Restore only after the configured cap is known: `restore` trims to
41
+ // `maxItems`, so restoring at the default could permanently drop entries.
58
42
  if (settingRegistry) {
59
43
  void settingRegistry
60
44
  .load(PLUGIN_ID)
@@ -85,7 +69,7 @@ const plugin = {
85
69
  };
86
70
  const open = (query) => {
87
71
  // Reopen fresh each time so the input resets and the agent snapshot is
88
- // current; the file list is cached separately (see files.ts).
72
+ // current; the file list stays cached (files.ts).
89
73
  close();
90
74
  const widget = new OmniboxWidget({
91
75
  commands,
@@ -110,7 +94,6 @@ const plugin = {
110
94
  label: trans.__('Search…'),
111
95
  caption: trans.__('Search files and commands, or ask an agent'),
112
96
  execute: args => {
113
- // Toggle: a second press (e.g. of the keyboard shortcut) closes it.
114
97
  if (current && !current.isDisposed) {
115
98
  close();
116
99
  return;
@@ -119,7 +102,6 @@ const plugin = {
119
102
  open(typeof query === 'string' ? query : undefined);
120
103
  }
121
104
  });
122
- // Open the omnibox with Cmd/Ctrl+K, the common "command center" chord.
123
105
  commands.addKeyBinding({
124
106
  command: OMNIBOX_OPEN_COMMAND,
125
107
  keys: ['Accel K'],
@@ -5,14 +5,14 @@ import type { CommandRegistry } from '@lumino/commands';
5
5
  import type { CommandPalette } from '@lumino/widgets';
6
6
  import type { IAgent } from '../launcher/agents';
7
7
  import type { OmniboxRecents } from './recents';
8
- /**
9
- * The source a result row came from, used to group rows under a header.
10
- */
11
8
  type OmniboxItemKind = 'command' | 'file' | 'agent';
12
9
  /**
13
10
  * A single result row, with the action it runs when chosen.
14
11
  */
15
12
  export interface IOmniboxItem {
13
+ /**
14
+ * The source category of the row: command, file, or agent.
15
+ */
16
16
  kind: OmniboxItemKind;
17
17
  /**
18
18
  * Stable React key.
@@ -47,34 +47,62 @@ interface IOmniboxSections {
47
47
  * Recently used commands and files, shown while the term is empty.
48
48
  */
49
49
  recent: IOmniboxItem[];
50
+ /**
51
+ * Commands matching the term.
52
+ */
50
53
  commands: IOmniboxItem[];
54
+ /**
55
+ * Workspace files matching the term.
56
+ */
51
57
  files: IOmniboxItem[];
58
+ /**
59
+ * Per-agent "Ask" rows carrying the term as a prompt.
60
+ */
52
61
  agents: IOmniboxItem[];
53
62
  }
63
+ /**
64
+ * Inputs for {@link computeSections}.
65
+ */
54
66
  interface IComputeOptions {
67
+ /**
68
+ * Raw query text from the input.
69
+ */
55
70
  query: string;
71
+ /**
72
+ * The command registry used to look up and execute commands.
73
+ */
56
74
  commands: CommandRegistry;
57
75
  /**
58
- * The command palette's items, whose labels are computed with each item's
59
- * args — the only form in which entries like "Use Theme: …" exist.
76
+ * Palette items, whose labels are computed with each item's args — the only
77
+ * form in which entries like "Use Theme: …" exist.
60
78
  */
61
79
  paletteItems: ReadonlyArray<CommandPalette.IItem>;
80
+ /**
81
+ * The document registry used to pick file icons.
82
+ */
62
83
  docRegistry: DocumentRegistry;
84
+ /**
85
+ * The available agents; prompt-capable ones get "Ask" rows.
86
+ */
63
87
  agents: IAgent[];
88
+ /**
89
+ * Workspace-relative file paths to match against.
90
+ */
64
91
  files: string[];
65
92
  /**
66
93
  * Recently-used tracker; `null` disables the recent rows and recording.
67
94
  */
68
95
  recents: OmniboxRecents | null;
96
+ /**
97
+ * Translation bundle for row labels.
98
+ */
69
99
  trans: TranslationBundle;
70
100
  }
71
101
  /**
72
102
  * Build the grouped result set for a query. A leading `>` searches only
73
- * commands and a leading `/` only files; otherwise commands and files are
74
- * fuzzy-matched and every prompt-capable agent is offered an "Ask" row
75
- * carrying the query as its prompt. An empty term yields the recently used
76
- * rows for the active mode instead (and the widget shows a hint when there
77
- * are none).
103
+ * commands, `/` only files; otherwise every prompt-capable agent also gets an
104
+ * "Ask" row carrying the query as its prompt. An empty term yields the
105
+ * recently used rows for the active mode.
78
106
  */
79
107
  export declare function computeSections(options: IComputeOptions): IOmniboxSections;
80
108
  export {};
@@ -3,20 +3,14 @@ import { StringExt } from '@lumino/algorithm';
3
3
  import { agentCommandId } from '../launcher/tokens';
4
4
  const COMMAND_LIMIT = 7;
5
5
  const FILE_LIMIT = 10;
6
- /**
7
- * Prefixes that narrow the search to a single source: a leading `>` to
8
- * commands, a leading `/` to files (relative paths never start with `/`, so it
9
- * is unambiguous). Without a prefix, every source is searched.
10
- */
11
6
  const COMMAND_PREFIX = '>';
7
+ // Unambiguous: workspace-relative paths never start with '/'.
12
8
  const FILE_PREFIX = '/';
13
9
  /**
14
10
  * Build the grouped result set for a query. A leading `>` searches only
15
- * commands and a leading `/` only files; otherwise commands and files are
16
- * fuzzy-matched and every prompt-capable agent is offered an "Ask" row
17
- * carrying the query as its prompt. An empty term yields the recently used
18
- * rows for the active mode instead (and the widget shows a hint when there
19
- * are none).
11
+ * commands, `/` only files; otherwise every prompt-capable agent also gets an
12
+ * "Ask" row carrying the query as its prompt. An empty term yields the
13
+ * recently used rows for the active mode.
20
14
  */
21
15
  export function computeSections(options) {
22
16
  const { query, commands, agents, trans } = options;
@@ -43,13 +37,11 @@ export function computeSections(options) {
43
37
  recent: [],
44
38
  commands: mode === 'files' ? [] : matchCommands(options, term),
45
39
  files: mode === 'commands' ? [] : matchFiles(options, term),
46
- // Agents only in the unprefixed view; the prompt is the full typed query.
47
40
  agents: mode === 'all' ? buildAgentItems(commands, agents, term, trans) : []
48
41
  };
49
42
  }
50
43
  /**
51
- * Run a command and record the use on success, so failed commands never enter
52
- * the recents list.
44
+ * Run a command and record the use on success, so failures never enter the recents.
53
45
  */
54
46
  function executeCommand(commands, recents, id, args) {
55
47
  void commands
@@ -61,9 +53,6 @@ function executeCommand(commands, recents, id, args) {
61
53
  console.error(`xtralab omnibox: command "${id}" failed`, reason);
62
54
  });
63
55
  }
64
- /**
65
- * Open a file and record the use on success.
66
- */
67
56
  function openFile(commands, recents, path) {
68
57
  void commands
69
58
  .execute('docmanager:open', { path })
@@ -76,9 +65,8 @@ function openFile(commands, recents, path) {
76
65
  }
77
66
  /**
78
67
  * Read a command's label, visibility and caption, or `null` when the command
79
- * is missing, hidden, label-less, or its accessors throw (a command's
80
- * accessors can assume a context — e.g. an active notebook — the omnibox
81
- * doesn't provide).
68
+ * is missing, hidden, label-less, or its accessors throw (they can assume a
69
+ * context the omnibox doesn't provide).
82
70
  */
83
71
  function commandDisplay(commands, id, args) {
84
72
  if (!commands.hasCommand(id)) {
@@ -97,10 +85,9 @@ function commandDisplay(commands, id, args) {
97
85
  }
98
86
  /**
99
87
  * The recently used rows for the empty term: both kinds interleaved by
100
- * recency in the unprefixed view, or only the mode's kind under a bare `>` or
101
- * `/`. Commands that no longer resolve are dropped, as are files missing from
102
- * the loaded workspace listing (while the listing is still loading — or
103
- * unavailable — file entries are shown as recorded).
88
+ * recency, or only the mode's kind under a bare `>` or `/`. Unresolvable
89
+ * commands are dropped, as are files absent from the workspace listing once
90
+ * it loads.
104
91
  */
105
92
  function buildRecentItems(options, mode) {
106
93
  var _a;
@@ -147,11 +134,10 @@ function buildRecentItems(options, mode) {
147
134
  return items;
148
135
  }
149
136
  /**
150
- * Match the query against the palette's items first — their labels carry each
151
- * item's args (one "Use Theme: …" per theme, one row per font-size key), which
152
- * a raw registry scan can never produce — then against registry commands the
153
- * palette doesn't present. Palette-covered ids are skipped in the registry
154
- * pass so a command never also surfaces under its argless label.
137
+ * Match palette items first — their labels carry per-item args (one "Use
138
+ * Theme: …" per theme), which a registry scan can never produce — then
139
+ * registry commands the palette doesn't present, skipping palette-covered ids
140
+ * so a command never also surfaces under its argless label.
155
141
  */
156
142
  function matchCommands(options, term) {
157
143
  const { commands, paletteItems, recents } = options;
@@ -166,8 +152,6 @@ function matchCommands(options, term) {
166
152
  let visible = true;
167
153
  let caption = '';
168
154
  try {
169
- // An item's accessors can throw if the command assumes a context (e.g.
170
- // an active notebook) the omnibox doesn't provide; skip those.
171
155
  label = item.label;
172
156
  visible = item.isVisible;
173
157
  caption = item.caption;
@@ -209,8 +193,6 @@ function matchCommands(options, term) {
209
193
  let visible = true;
210
194
  let caption = '';
211
195
  try {
212
- // A command's accessors can throw if they assume a context (e.g. an
213
- // active notebook) the omnibox doesn't provide; skip those.
214
196
  label = commands.label(id);
215
197
  visible = commands.isVisible(id);
216
198
  caption = commands.caption(id);
@@ -276,7 +258,7 @@ function buildAgentItems(commands, agents, prompt, trans) {
276
258
  const items = [];
277
259
  for (const agent of agents) {
278
260
  // Agents without `promptArgs` can't take an inline prompt (the launcher
279
- // would drop it), so they don't belong in an "Ask …" row.
261
+ // would drop it).
280
262
  if (agent.promptArgs === undefined) {
281
263
  continue;
282
264
  }
@@ -1,52 +1,50 @@
1
1
  import type { IStateDB } from '@jupyterlab/statedb';
2
2
  import type { ReadonlyPartialJSONObject } from '@lumino/coreutils';
3
- /**
4
- * Kinds of omnibox results whose uses are recorded.
5
- */
6
3
  export type RecentKind = 'command' | 'file';
7
4
  /**
8
5
  * A single recorded use: a command that was run or a file that was opened.
9
6
  */
10
7
  interface IRecentEntry {
8
+ /**
9
+ * Whether the entry records a command run or a file opened.
10
+ */
11
11
  kind: RecentKind;
12
12
  /**
13
13
  * The command id, or the workspace-relative file path.
14
14
  */
15
15
  id: string;
16
16
  /**
17
- * Arguments the command ran with, for palette-style entries whose label
18
- * and behavior depend on them (e.g. one "Use Theme: …" per theme).
17
+ * Arguments the command ran with, for palette-style entries whose label and
18
+ * behavior depend on them.
19
19
  */
20
20
  args?: ReadonlyPartialJSONObject;
21
21
  }
22
22
  /**
23
- * A most-recently-used list of omnibox results, generic over the result kind
24
- * so commands and files (and future kinds) share one store. Entries are kept
25
- * most-recent-first, capped at `maxItems` per kind, and persisted through the
26
- * state database so they survive reloads. Without a state database the list
27
- * still works for the lifetime of the page.
23
+ * A most-recently-used list of omnibox results, most-recent-first, capped at
24
+ * `maxItems` per kind and persisted through the state database. Without a
25
+ * state database it still works for the lifetime of the page.
28
26
  */
29
27
  export declare class OmniboxRecents {
30
28
  constructor(options?: OmniboxRecents.IOptions);
31
29
  /**
32
- * Maximum number of entries remembered per kind. Lowering it trims the list
33
- * immediately; `0` disables recents entirely.
30
+ * Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
34
31
  */
35
32
  get maxItems(): number;
33
+ /**
34
+ * Set the maximum entries kept per kind.
35
+ */
36
36
  set maxItems(value: number);
37
37
  /**
38
- * The recorded entries, most recent first — all of them, or only those of
39
- * one kind.
38
+ * The recorded entries, most recent first, optionally filtered to one kind.
40
39
  */
41
40
  entries(kind?: RecentKind): IRecentEntry[];
42
41
  /**
43
- * Record a use of `id` (with the args it ran with, if any), moving it to
44
- * the front of its kind's list.
42
+ * Record a use, moving the entry to the front of its kind's list.
45
43
  */
46
44
  touch(kind: RecentKind, id: string, args?: ReadonlyPartialJSONObject): void;
47
45
  /**
48
46
  * Load the persisted list. Entries recorded before the load completes stay
49
- * at the front, ahead of the restored history.
47
+ * ahead of the restored history.
50
48
  */
51
49
  restore(): Promise<void>;
52
50
  /**
@@ -1,21 +1,16 @@
1
1
  /**
2
- * Identity of an entry: two uses only match when kind, id and args all do,
3
- * so runs of one command with different args stay distinct entries.
2
+ * Identity of an entry: two uses only match when kind, id and args all do, so
3
+ * runs of one command with different args stay distinct.
4
4
  */
5
5
  function entryKey(entry) {
6
6
  var _a;
7
7
  return `${entry.kind}\0${entry.id}\0${JSON.stringify((_a = entry.args) !== null && _a !== void 0 ? _a : null)}`;
8
8
  }
9
- /**
10
- * State database key the recents list is persisted under.
11
- */
12
9
  const STATE_KEY = 'xtralab:omnibox:recents';
13
10
  /**
14
- * A most-recently-used list of omnibox results, generic over the result kind
15
- * so commands and files (and future kinds) share one store. Entries are kept
16
- * most-recent-first, capped at `maxItems` per kind, and persisted through the
17
- * state database so they survive reloads. Without a state database the list
18
- * still works for the lifetime of the page.
11
+ * A most-recently-used list of omnibox results, most-recent-first, capped at
12
+ * `maxItems` per kind and persisted through the state database. Without a
13
+ * state database it still works for the lifetime of the page.
19
14
  */
20
15
  export class OmniboxRecents {
21
16
  constructor(options = {}) {
@@ -25,12 +20,14 @@ export class OmniboxRecents {
25
20
  this._state = (_a = options.state) !== null && _a !== void 0 ? _a : null;
26
21
  }
27
22
  /**
28
- * Maximum number of entries remembered per kind. Lowering it trims the list
29
- * immediately; `0` disables recents entirely.
23
+ * Maximum entries kept per kind; lowering trims immediately, `0` disables recents.
30
24
  */
31
25
  get maxItems() {
32
26
  return this._maxItems;
33
27
  }
28
+ /**
29
+ * Set the maximum entries kept per kind.
30
+ */
34
31
  set maxItems(value) {
35
32
  const normalized = Math.max(0, Math.floor(value));
36
33
  if (normalized === this._maxItems) {
@@ -44,8 +41,7 @@ export class OmniboxRecents {
44
41
  }
45
42
  }
46
43
  /**
47
- * The recorded entries, most recent first — all of them, or only those of
48
- * one kind.
44
+ * The recorded entries, most recent first, optionally filtered to one kind.
49
45
  */
50
46
  entries(kind) {
51
47
  return kind
@@ -53,8 +49,7 @@ export class OmniboxRecents {
53
49
  : [...this._entries];
54
50
  }
55
51
  /**
56
- * Record a use of `id` (with the args it ran with, if any), moving it to
57
- * the front of its kind's list.
52
+ * Record a use, moving the entry to the front of its kind's list.
58
53
  */
59
54
  touch(kind, id, args) {
60
55
  const entry = args === undefined ? { kind, id } : { kind, id, args };
@@ -65,7 +60,7 @@ export class OmniboxRecents {
65
60
  }
66
61
  /**
67
62
  * Load the persisted list. Entries recorded before the load completes stay
68
- * at the front, ahead of the restored history.
63
+ * ahead of the restored history.
69
64
  */
70
65
  async restore() {
71
66
  if (!this._state) {
@@ -1,9 +1,8 @@
1
1
  import { Token } from '@lumino/coreutils';
2
2
  /**
3
- * A launcher overlay that fuzzy-searches across multiple sources — workspace
4
- * files, JupyterLab commands — and routes a typed prompt to one of the
5
- * configured agents. Provided by `xtralab:omnibox` and consumed (optionally)
6
- * by the top-bar command bar, which opens it on click.
3
+ * A launcher overlay that fuzzy-searches workspace files and commands and
4
+ * routes a typed prompt to a configured agent. Provided by `xtralab:omnibox`;
5
+ * opened by the top-bar command bar.
7
6
  */
8
7
  export interface IOmnibox {
9
8
  /**
@@ -15,13 +14,9 @@ export interface IOmnibox {
15
14
  */
16
15
  close(): void;
17
16
  }
18
- /**
19
- * DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
20
- * `xtralab:command-bar` so the top-bar pill opens the omnibox.
21
- */
22
17
  export declare const IOmnibox: Token<IOmnibox>;
23
18
  /**
24
- * Command id that opens the omnibox (registered by `xtralab:omnibox`). Shared
25
- * here so the command bar can look up its keybinding and show a shortcut hint.
19
+ * Command id that opens the omnibox, shared so the command bar can look up
20
+ * its keybinding for the shortcut hint.
26
21
  */
27
22
  export declare const OMNIBOX_OPEN_COMMAND = "xtralab:omnibox:open";
@@ -1,11 +1,7 @@
1
1
  import { Token } from '@lumino/coreutils';
2
- /**
3
- * DI token for {@link IOmnibox}. Provided by `xtralab:omnibox`; consumed by
4
- * `xtralab:command-bar` so the top-bar pill opens the omnibox.
5
- */
6
2
  export const IOmnibox = new Token('xtralab:IOmnibox', 'Opens the omnibox overlay that searches files and commands and prompts agents.');
7
3
  /**
8
- * Command id that opens the omnibox (registered by `xtralab:omnibox`). Shared
9
- * here so the command bar can look up its keybinding and show a shortcut hint.
4
+ * Command id that opens the omnibox, shared so the command bar can look up
5
+ * its keybinding for the shortcut hint.
10
6
  */
11
7
  export const OMNIBOX_OPEN_COMMAND = 'xtralab:omnibox:open';
@@ -6,30 +6,34 @@ import type { CommandPalette } from '@lumino/widgets';
6
6
  import type { IAgent } from '../launcher/agents';
7
7
  import type { OmniboxRecents } from './recents';
8
8
  /**
9
- * The omnibox overlay widget. Hosts {@link OmniboxComponent} in a React root
10
- * attached to `document.body`. It carries `jp-ThemedContainer` so JupyterLab's
11
- * theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
12
- * class for the overlay/panel styling (style/omnibox.css).
9
+ * The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
10
+ * makes JupyterLab's theme CSS variables resolve outside the shell.
13
11
  */
14
12
  export declare class OmniboxWidget extends ReactWidget {
15
13
  constructor(options: OmniboxWidget.IOptions);
14
+ /**
15
+ * Render the omnibox overlay content.
16
+ */
16
17
  render(): JSX.Element;
17
18
  private _options;
18
19
  }
19
- /**
20
- * A namespace for `OmniboxWidget` statics.
21
- */
22
20
  export declare namespace OmniboxWidget {
23
21
  /**
24
22
  * Construction options for {@link OmniboxWidget}.
25
23
  */
26
24
  interface IOptions {
25
+ /**
26
+ * The command registry used to look up and execute commands.
27
+ */
27
28
  commands: CommandRegistry;
28
29
  /**
29
30
  * Snapshot of the command palette's items, read once when the overlay
30
31
  * opens; empty when the palette isn't available.
31
32
  */
32
33
  paletteItems: ReadonlyArray<CommandPalette.IItem>;
34
+ /**
35
+ * The document registry used to pick file icons.
36
+ */
33
37
  docRegistry: DocumentRegistry;
34
38
  /**
35
39
  * Snapshot of the available agents, read once when the overlay opens.
@@ -2,19 +2,13 @@ import { ReactWidget } from '@jupyterlab/ui-components';
2
2
  import * as React from 'react';
3
3
  import { computeSections } from './model';
4
4
  import { loadWorkspaceFiles } from './files';
5
- /**
6
- * DOM id of the results listbox, referenced by the input's `aria-controls`.
7
- */
8
5
  const LIST_ID = 'jp-xtralab-Omnibox-list';
9
- /**
10
- * Stable DOM id for the result row at `index`, for `aria-activedescendant`.
11
- */
12
6
  function optionId(index) {
13
7
  return `jp-xtralab-Omnibox-option-${index}`;
14
8
  }
15
9
  /**
16
10
  * Render `text` with the fuzzy-matched characters at `indices` wrapped in a
17
- * highlight span, leaving the rest as plain text.
11
+ * highlight span.
18
12
  */
19
13
  function renderHighlight(text, indices) {
20
14
  if (indices.length === 0) {
@@ -77,19 +71,16 @@ function OmniboxComponent(props) {
77
71
  ...sections.agents
78
72
  ], [sections]);
79
73
  const hasResults = flat.length > 0;
80
- // Reset the highlighted row whenever the result set changes, and keep the
81
- // index in range when results shrink.
82
74
  React.useEffect(() => {
83
75
  setActive(current => (current < flat.length ? current : 0));
84
76
  }, [flat]);
85
- // Keep the highlighted row scrolled into view as it moves.
86
77
  React.useEffect(() => {
87
78
  var _a, _b;
88
79
  (_b = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.jp-mod-active')) === null || _b === void 0 ? void 0 : _b.scrollIntoView({ block: 'nearest' });
89
80
  }, [active, flat]);
90
81
  const dismiss = React.useCallback(() => {
91
- // Defer so unmounting this React root (via onClose) never happens
92
- // synchronously inside the event handler that triggered it.
82
+ // Defer so unmounting this React root never happens synchronously inside
83
+ // the event handler that triggered it.
93
84
  window.setTimeout(onClose, 0);
94
85
  }, [onClose]);
95
86
  const run = React.useCallback((item) => {
@@ -162,10 +153,8 @@ function OmniboxComponent(props) {
162
153
  : trans.__('Search files and commands, or type a prompt and pick an agent. Prefix with > for commands or / for files.')))))));
163
154
  }
164
155
  /**
165
- * The omnibox overlay widget. Hosts {@link OmniboxComponent} in a React root
166
- * attached to `document.body`. It carries `jp-ThemedContainer` so JupyterLab's
167
- * theme CSS variables resolve outside the shell, and its own `jp-xtralab-Omnibox`
168
- * class for the overlay/panel styling (style/omnibox.css).
156
+ * The omnibox overlay widget, attached to `document.body`; `jp-ThemedContainer`
157
+ * makes JupyterLab's theme CSS variables resolve outside the shell.
169
158
  */
170
159
  export class OmniboxWidget extends ReactWidget {
171
160
  constructor(options) {
@@ -175,6 +164,9 @@ export class OmniboxWidget extends ReactWidget {
175
164
  this.addClass('jp-xtralab-Omnibox');
176
165
  this.addClass('jp-ThemedContainer');
177
166
  }
167
+ /**
168
+ * Render the omnibox overlay content.
169
+ */
178
170
  render() {
179
171
  return React.createElement(OmniboxComponent, { ...this._options });
180
172
  }