open-multi-agent-kit 0.96.2 → 0.97.0

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 (138) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +4 -2
  3. package/dist/core/agent-session.d.ts +9 -1
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +84 -7
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/attachment-store.d.ts +39 -0
  8. package/dist/core/attachment-store.d.ts.map +1 -0
  9. package/dist/core/attachment-store.js +81 -0
  10. package/dist/core/attachment-store.js.map +1 -0
  11. package/dist/core/command-safety.d.ts +8 -0
  12. package/dist/core/command-safety.d.ts.map +1 -1
  13. package/dist/core/command-safety.js +140 -14
  14. package/dist/core/command-safety.js.map +1 -1
  15. package/dist/core/compaction/compaction.d.ts +6 -1
  16. package/dist/core/compaction/compaction.d.ts.map +1 -1
  17. package/dist/core/compaction/compaction.js +35 -1
  18. package/dist/core/compaction/compaction.js.map +1 -1
  19. package/dist/core/context-budget-governor-v2.d.ts +1 -1
  20. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  21. package/dist/core/context-budget-governor-v2.js +1 -1
  22. package/dist/core/context-budget-governor-v2.js.map +1 -1
  23. package/dist/core/context-budget-v2-cache-keys.d.ts +3 -0
  24. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
  25. package/dist/core/context-budget-v2-cache-keys.js +2 -0
  26. package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
  27. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
  28. package/dist/core/context-budget-v2-plan-cache-keys.js +3 -0
  29. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
  30. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  31. package/dist/core/context-budget-v2-planner.js +2 -1
  32. package/dist/core/context-budget-v2-planner.js.map +1 -1
  33. package/dist/core/context-budget-v2-scoring.d.ts +17 -0
  34. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  35. package/dist/core/context-budget-v2-scoring.js +25 -8
  36. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  37. package/dist/core/context-budget-v2-selection.d.ts +2 -2
  38. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  39. package/dist/core/context-budget-v2-selection.js +18 -1
  40. package/dist/core/context-budget-v2-selection.js.map +1 -1
  41. package/dist/core/context-budget-v2-types.d.ts +17 -0
  42. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  43. package/dist/core/context-budget-v2-types.js +15 -0
  44. package/dist/core/context-budget-v2-types.js.map +1 -1
  45. package/dist/core/extensions/builtin/command-safety-gate.d.ts +3 -1
  46. package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
  47. package/dist/core/extensions/builtin/command-safety-gate.js +7 -0
  48. package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
  49. package/dist/core/extensions/types.d.ts +12 -1
  50. package/dist/core/extensions/types.d.ts.map +1 -1
  51. package/dist/core/extensions/types.js.map +1 -1
  52. package/dist/core/model-registry.d.ts +8 -3
  53. package/dist/core/model-registry.d.ts.map +1 -1
  54. package/dist/core/model-registry.js +71 -1
  55. package/dist/core/model-registry.js.map +1 -1
  56. package/dist/core/package-doctor-source-scan.d.ts +9 -0
  57. package/dist/core/package-doctor-source-scan.d.ts.map +1 -1
  58. package/dist/core/package-doctor-source-scan.js +77 -4
  59. package/dist/core/package-doctor-source-scan.js.map +1 -1
  60. package/dist/core/prompt-attachment.d.ts +51 -0
  61. package/dist/core/prompt-attachment.d.ts.map +1 -0
  62. package/dist/core/prompt-attachment.js +186 -0
  63. package/dist/core/prompt-attachment.js.map +1 -0
  64. package/dist/core/provider-resilience.d.ts +28 -0
  65. package/dist/core/provider-resilience.d.ts.map +1 -1
  66. package/dist/core/provider-resilience.js +50 -0
  67. package/dist/core/provider-resilience.js.map +1 -1
  68. package/dist/core/provider-retry.d.ts +1 -1
  69. package/dist/core/provider-retry.d.ts.map +1 -1
  70. package/dist/core/provider-retry.js +1 -1
  71. package/dist/core/provider-retry.js.map +1 -1
  72. package/dist/core/provider-usage.d.ts.map +1 -1
  73. package/dist/core/provider-usage.js +68 -2
  74. package/dist/core/provider-usage.js.map +1 -1
  75. package/dist/core/reasoning-router-promotion.d.ts +84 -0
  76. package/dist/core/reasoning-router-promotion.d.ts.map +1 -0
  77. package/dist/core/reasoning-router-promotion.js +92 -0
  78. package/dist/core/reasoning-router-promotion.js.map +1 -0
  79. package/dist/core/session-bash-service.d.ts.map +1 -1
  80. package/dist/core/session-bash-service.js +4 -3
  81. package/dist/core/session-bash-service.js.map +1 -1
  82. package/dist/core/session-termination.d.ts +1 -1
  83. package/dist/core/session-termination.d.ts.map +1 -1
  84. package/dist/core/session-termination.js +11 -2
  85. package/dist/core/session-termination.js.map +1 -1
  86. package/dist/core/tools/bash.d.ts.map +1 -1
  87. package/dist/core/tools/bash.js +3 -7
  88. package/dist/core/tools/bash.js.map +1 -1
  89. package/dist/core/tools/grep.d.ts.map +1 -1
  90. package/dist/core/tools/grep.js +13 -48
  91. package/dist/core/tools/grep.js.map +1 -1
  92. package/dist/core/tools/read.d.ts.map +1 -1
  93. package/dist/core/tools/read.js +1 -34
  94. package/dist/core/tools/read.js.map +1 -1
  95. package/dist/index.d.ts +1 -1
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +1 -1
  98. package/dist/index.js.map +1 -1
  99. package/dist/modes/interactive/components/attachment-strip.d.ts +21 -0
  100. package/dist/modes/interactive/components/attachment-strip.d.ts.map +1 -0
  101. package/dist/modes/interactive/components/attachment-strip.js +136 -0
  102. package/dist/modes/interactive/components/attachment-strip.js.map +1 -0
  103. package/dist/modes/interactive/components/footer.d.ts +6 -0
  104. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  105. package/dist/modes/interactive/components/footer.js +26 -1
  106. package/dist/modes/interactive/components/footer.js.map +1 -1
  107. package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -1
  108. package/dist/modes/interactive/components/status-sidebar.js +12 -1
  109. package/dist/modes/interactive/components/status-sidebar.js.map +1 -1
  110. package/dist/modes/interactive/interactive-mode.d.ts +23 -4
  111. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  112. package/dist/modes/interactive/interactive-mode.js +174 -53
  113. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  114. package/docs/compaction.md +1 -1
  115. package/docs/extensions.md +12 -3
  116. package/docs/index.md +4 -1
  117. package/docs/metrics.md +74 -2
  118. package/docs/provider-resilience.md +11 -0
  119. package/docs/usage.md +1 -1
  120. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  121. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  122. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  123. package/examples/extensions/gondolin/package-lock.json +2 -2
  124. package/examples/extensions/gondolin/package.json +1 -1
  125. package/examples/extensions/sandbox/package-lock.json +2 -2
  126. package/examples/extensions/sandbox/package.json +1 -1
  127. package/examples/extensions/with-deps/package-lock.json +2 -2
  128. package/examples/extensions/with-deps/package.json +1 -1
  129. package/npm-shrinkwrap.json +18 -18
  130. package/package.json +7 -7
  131. package/dist/core/tools/omp-pure-seams.d.ts +0 -41
  132. package/dist/core/tools/omp-pure-seams.d.ts.map +0 -1
  133. package/dist/core/tools/omp-pure-seams.js +0 -142
  134. package/dist/core/tools/omp-pure-seams.js.map +0 -1
  135. package/dist/core/tools/omp-seam-runtime.d.ts +0 -100
  136. package/dist/core/tools/omp-seam-runtime.d.ts.map +0 -1
  137. package/dist/core/tools/omp-seam-runtime.js +0 -40
  138. package/dist/core/tools/omp-seam-runtime.js.map +0 -1
@@ -3,12 +3,14 @@
3
3
  * allow: SIZE_OK - legacy TUI coordinator; this change only adds a two-line CONTROL status bridge.
4
4
  * Handles TUI rendering and user interaction, delegating business logic to AgentSession.
5
5
  */
6
- import * as crypto from "node:crypto";
7
6
  import * as fs from "node:fs";
8
7
  import * as os from "node:os";
9
8
  import * as path from "node:path";
10
9
  import { spawn, spawnSync } from "child_process";
11
10
  import { getProviders, } from "omk-ai";
11
+ import { AttachmentStore } from "../../core/attachment-store.js";
12
+ import { describePromptImageAttachment } from "../../core/prompt-attachment.js";
13
+ import { createAttachmentStrip } from "./components/attachment-strip.js";
12
14
  import { CombinedAutocompleteProvider, Container, fuzzyFilter, getCapabilities, hyperlink, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "omk-tui";
13
15
  import { APP_NAME, APP_TITLE, getAgentDir, getAuthPath, getDebugLogPath, getDocsPath, getShareViewerUrl, VERSION, } from "../../config.js";
14
16
  import { parseSkillBlock } from "../../core/agent-session.js";
@@ -33,7 +35,7 @@ import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
33
35
  import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
34
36
  import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
35
37
  import { copyToClipboard } from "../../utils/clipboard.js";
36
- import { extensionForImageMimeType, readClipboardImage } from "../../utils/clipboard-image.js";
38
+ import { readClipboardImage } from "../../utils/clipboard-image.js";
37
39
  import { parseGitUrl } from "../../utils/git.js";
38
40
  import { openBrowser } from "../../utils/open-browser.js";
39
41
  import { getCwdRelativePath } from "../../utils/paths.js";
@@ -219,7 +221,11 @@ export class InteractiveMode {
219
221
  version;
220
222
  isInitialized = false;
221
223
  onInputCallback;
222
- pendingUserInputs = [];
224
+ pendingPromptPayloads = [];
225
+ attachmentStore = new AttachmentStore();
226
+ draftAttachmentIds = [];
227
+ attachmentStripContainer = new Container();
228
+ interactiveLoopActive = true;
223
229
  loadingAnimation = undefined;
224
230
  // Wall-clock start of the current agent turn, for the working loader elapsed suffix
225
231
  workingStartedAt = undefined;
@@ -652,6 +658,7 @@ export class InteractiveMode {
652
658
  this.ui.addChild(this.statusContainer);
653
659
  this.renderWidgets(); // Initialize with default spacer
654
660
  this.ui.addChild(this.widgetContainerAbove);
661
+ this.ui.addChild(this.attachmentStripContainer);
655
662
  this.ui.addChild(this.editorContainer);
656
663
  this.ui.addChild(this.widgetContainerBelow);
657
664
  this.ui.addChild(this.noticeContainer);
@@ -780,13 +787,17 @@ export class InteractiveMode {
780
787
  }
781
788
  }
782
789
  // Main interactive loop
783
- while (true) {
784
- const userInput = await this.getUserInput();
790
+ while (this.interactiveLoopActive) {
791
+ const payload = await this.getUserInput();
785
792
  const previousTermination = this.session.lastTermination;
786
793
  try {
787
- await this.session.prompt(userInput);
794
+ await this.session.prompt(payload.text, payload.images ? { images: payload.images } : undefined);
795
+ // Acceptance: release exactly the attachments that were sent.
796
+ if (payload.imageIds && payload.imageIds.length > 0)
797
+ this.consumeDraftAttachments(payload.imageIds);
788
798
  }
789
799
  catch (error) {
800
+ // Preflight/model failure: attachments stay attached for retry.
790
801
  this.showPromptError(error, previousTermination);
791
802
  }
792
803
  }
@@ -1234,9 +1245,10 @@ export class InteractiveMode {
1234
1245
  const body = visibleLabels.length > 0 ? `${visibleLabels.join(", ")}${suffix}` : "(none)";
1235
1246
  return theme.fg("dim", ` ${body}`);
1236
1247
  };
1237
- const addLoadedSection = (name, collapsedBody, expandedBody = collapsedBody, color = "mdHeading") => {
1248
+ const addLoadedSection = (name, collapsedBody, expandedBody, color = "mdHeading") => {
1249
+ const resolvedExpandedBody = expandedBody ?? collapsedBody;
1238
1250
  const getCollapsedBody = typeof collapsedBody === "function" ? collapsedBody : () => collapsedBody;
1239
- const getExpandedBody = typeof expandedBody === "function" ? expandedBody : () => expandedBody;
1251
+ const getExpandedBody = typeof resolvedExpandedBody === "function" ? resolvedExpandedBody : () => resolvedExpandedBody;
1240
1252
  const section = new ExpandableText(() => `${sectionHeader(name, color)}\n${getCollapsedBody()}`, () => `${sectionHeader(name, color)}\n${getExpandedBody()}`, this.getStartupExpansionState(), 0, 0);
1241
1253
  this.chatContainer.addChild(section);
1242
1254
  this.chatContainer.addChild(new Spacer(1));
@@ -2216,18 +2228,98 @@ export class InteractiveMode {
2216
2228
  if (!image) {
2217
2229
  return;
2218
2230
  }
2219
- // Write to temp file
2220
- const tmpDir = os.tmpdir();
2221
- const ext = extensionForImageMimeType(image.mimeType) ?? "png";
2222
- const fileName = `omk-clipboard-${crypto.randomUUID()}.${ext}`;
2223
- const filePath = path.join(tmpDir, fileName);
2224
- fs.writeFileSync(filePath, Buffer.from(image.bytes));
2225
- // Insert file path directly
2226
- this.editor.insertTextAtCursor?.(filePath);
2227
- this.ui.requestRender();
2231
+ let attachment;
2232
+ try {
2233
+ attachment = this.attachmentStore.put(new Uint8Array(image.bytes), "clipboard");
2234
+ }
2235
+ catch (error) {
2236
+ this.showWarning(error instanceof Error ? error.message : String(error));
2237
+ return;
2238
+ }
2239
+ this.draftAttachmentIds.push(attachment.id);
2240
+ this.refreshAttachmentStrip();
2228
2241
  }
2229
- catch {
2230
- // Silently ignore clipboard errors (may not have permission, etc.)
2242
+ catch (error) {
2243
+ this.showWarning(`Clipboard paste failed: ${error instanceof Error ? error.message : String(error)}`);
2244
+ }
2245
+ }
2246
+ /** Rebuild the preview strip above the editor from the current draft ids. */
2247
+ refreshAttachmentStrip() {
2248
+ this.attachmentStripContainer.clear();
2249
+ const items = this.draftAttachmentIds
2250
+ .map((id) => this.attachmentStore.get(id))
2251
+ .filter((item) => item !== undefined);
2252
+ if (items.length > 0) {
2253
+ this.attachmentStripContainer.addChild(createAttachmentStrip(items, (id) => this.attachmentStore.getBytes(id)));
2254
+ }
2255
+ this.ui.requestRender();
2256
+ }
2257
+ materializeDraftImages(ids) {
2258
+ return this.attachmentStore.materializeImages(ids);
2259
+ }
2260
+ /** Release exactly the attachments that were accepted with a sent prompt. */
2261
+ consumeDraftAttachments(ids) {
2262
+ for (const id of ids) {
2263
+ this.attachmentStore.remove(id);
2264
+ const index = this.draftAttachmentIds.indexOf(id);
2265
+ if (index >= 0)
2266
+ this.draftAttachmentIds.splice(index, 1);
2267
+ }
2268
+ this.refreshAttachmentStrip();
2269
+ }
2270
+ clearDraftAttachments() {
2271
+ this.draftAttachmentIds = [];
2272
+ this.attachmentStore.clear();
2273
+ this.refreshAttachmentStrip();
2274
+ }
2275
+ removeLastDraftAttachment() {
2276
+ const id = this.draftAttachmentIds.pop();
2277
+ if (id)
2278
+ this.attachmentStore.remove(id);
2279
+ this.refreshAttachmentStrip();
2280
+ }
2281
+ isVisionCapable() {
2282
+ const model = this.session.model;
2283
+ return Array.isArray(model?.input) ? model.input.includes("image") : true;
2284
+ }
2285
+ handleAttachCommand(argument) {
2286
+ const [verb, rest] = argument.split(/\s+/);
2287
+ switch (verb ?? "") {
2288
+ case "":
2289
+ case "list": {
2290
+ const items = this.draftAttachmentIds
2291
+ .map((id) => this.attachmentStore.get(id))
2292
+ .filter((item) => item !== undefined);
2293
+ if (items.length === 0) {
2294
+ this.showStatus("No image attachments.");
2295
+ }
2296
+ else {
2297
+ this.showStatus(items.map((item, index) => `${index + 1}. ${describePromptImageAttachment(item)}`).join(" · "));
2298
+ }
2299
+ break;
2300
+ }
2301
+ case "clear":
2302
+ this.clearDraftAttachments();
2303
+ this.showStatus("Image attachments cleared.");
2304
+ break;
2305
+ case "remove":
2306
+ case "rm": {
2307
+ const position = Number.parseInt(rest ?? "", 10);
2308
+ if (Number.isFinite(position) && position >= 1 && position <= this.draftAttachmentIds.length) {
2309
+ const id = this.draftAttachmentIds.splice(position - 1, 1)[0];
2310
+ if (id)
2311
+ this.attachmentStore.remove(id);
2312
+ }
2313
+ else {
2314
+ this.removeLastDraftAttachment();
2315
+ }
2316
+ this.refreshAttachmentStrip();
2317
+ this.showStatus("Image attachment removed.");
2318
+ break;
2319
+ }
2320
+ default:
2321
+ this.showStatus("Usage: /attach [list|clear|remove [n]]");
2322
+ break;
2231
2323
  }
2232
2324
  }
2233
2325
  parseBangInput(text) {
@@ -2245,9 +2337,16 @@ export class InteractiveMode {
2245
2337
  setupEditorSubmitHandler() {
2246
2338
  this.defaultEditor.onSubmit = async (text) => {
2247
2339
  text = text.trim();
2248
- if (!text)
2340
+ const draftImageIds = [...(this.draftAttachmentIds ?? [])];
2341
+ const hasAttachments = draftImageIds.length > 0;
2342
+ if (!text && !hasAttachments)
2249
2343
  return;
2250
2344
  // Handle commands
2345
+ if (text === "/attach" || text.startsWith("/attach ")) {
2346
+ this.editor.setText("");
2347
+ this.handleAttachCommand(text.slice("/attach".length).trim());
2348
+ return;
2349
+ }
2251
2350
  if (text === "/settings") {
2252
2351
  this.showSettingsSelector();
2253
2352
  this.editor.setText("");
@@ -2409,8 +2508,26 @@ export class InteractiveMode {
2409
2508
  return;
2410
2509
  }
2411
2510
  }
2511
+ let draftImages;
2512
+ if (hasAttachments) {
2513
+ try {
2514
+ draftImages = this.materializeDraftImages(draftImageIds);
2515
+ }
2516
+ catch (error) {
2517
+ this.showWarning(error instanceof Error ? error.message : String(error));
2518
+ return;
2519
+ }
2520
+ if (!this.isVisionCapable()) {
2521
+ this.showWarning("The selected model cannot accept images. Switch model (/model) or run /attach clear.");
2522
+ return;
2523
+ }
2524
+ }
2412
2525
  // Queue input during compaction (extension commands execute immediately)
2413
2526
  if (this.session.isCompacting) {
2527
+ if (hasAttachments) {
2528
+ this.showWarning("Attachments are held while compaction finishes — resubmit after it completes.");
2529
+ return;
2530
+ }
2414
2531
  if (this.isExtensionCommand(text)) {
2415
2532
  this.editor.addToHistory?.(text);
2416
2533
  this.editor.setText("");
@@ -2426,7 +2543,10 @@ export class InteractiveMode {
2426
2543
  if (this.session.isStreaming) {
2427
2544
  this.editor.addToHistory?.(text);
2428
2545
  this.editor.setText("");
2429
- await this.session.prompt(text, { streamingBehavior: "steer" });
2546
+ await this.session.prompt(text, draftImages ? { images: draftImages, streamingBehavior: "steer" } : { streamingBehavior: "steer" });
2547
+ // Queued without throwing: acceptance — release exactly what was sent.
2548
+ if (draftImageIds.length > 0)
2549
+ this.consumeDraftAttachments(draftImageIds);
2430
2550
  this.updatePendingMessagesDisplay();
2431
2551
  this.ui.requestRender();
2432
2552
  return;
@@ -2434,11 +2554,14 @@ export class InteractiveMode {
2434
2554
  // Normal message submission
2435
2555
  // First, move any pending bash components to chat
2436
2556
  this.flushPendingBashComponents();
2557
+ const payload = draftImages
2558
+ ? { text, images: draftImages, imageIds: draftImageIds }
2559
+ : { text };
2437
2560
  if (this.onInputCallback) {
2438
- this.onInputCallback(text);
2561
+ this.onInputCallback(payload);
2439
2562
  }
2440
2563
  else {
2441
- this.pendingUserInputs.push(text);
2564
+ this.pendingPromptPayloads.push(payload);
2442
2565
  }
2443
2566
  this.editor.addToHistory?.(text);
2444
2567
  };
@@ -2978,14 +3101,14 @@ export class InteractiveMode {
2978
3101
  }
2979
3102
  }
2980
3103
  async getUserInput() {
2981
- const queuedInput = this.pendingUserInputs.shift();
2982
- if (queuedInput !== undefined) {
2983
- return queuedInput;
3104
+ const queuedPayload = this.pendingPromptPayloads.shift();
3105
+ if (queuedPayload !== undefined) {
3106
+ return queuedPayload;
2984
3107
  }
2985
3108
  return new Promise((resolve) => {
2986
- this.onInputCallback = (text) => {
3109
+ this.onInputCallback = (payload) => {
2987
3110
  this.onInputCallback = undefined;
2988
- resolve(text);
3111
+ resolve(payload);
2989
3112
  };
2990
3113
  });
2991
3114
  }
@@ -3028,6 +3151,7 @@ export class InteractiveMode {
3028
3151
  */
3029
3152
  isShuttingDown = false;
3030
3153
  async shutdown(options) {
3154
+ this.interactiveLoopActive = false;
3031
3155
  if (this.isShuttingDown)
3032
3156
  return;
3033
3157
  this.isShuttingDown = true;
@@ -5022,34 +5146,31 @@ export class InteractiveMode {
5022
5146
  /**
5023
5147
  * Get capitalized display string for an editor keybinding action.
5024
5148
  */
5025
- getEditorKeyDisplay(action) {
5026
- return keyDisplayText(action);
5027
- }
5028
5149
  handleHotkeysCommand() {
5029
5150
  // Navigation keybindings
5030
- const cursorUp = this.getEditorKeyDisplay("tui.editor.cursorUp");
5031
- const cursorDown = this.getEditorKeyDisplay("tui.editor.cursorDown");
5032
- const cursorLeft = this.getEditorKeyDisplay("tui.editor.cursorLeft");
5033
- const cursorRight = this.getEditorKeyDisplay("tui.editor.cursorRight");
5034
- const cursorWordLeft = this.getEditorKeyDisplay("tui.editor.cursorWordLeft");
5035
- const cursorWordRight = this.getEditorKeyDisplay("tui.editor.cursorWordRight");
5036
- const cursorLineStart = this.getEditorKeyDisplay("tui.editor.cursorLineStart");
5037
- const cursorLineEnd = this.getEditorKeyDisplay("tui.editor.cursorLineEnd");
5038
- const jumpForward = this.getEditorKeyDisplay("tui.editor.jumpForward");
5039
- const jumpBackward = this.getEditorKeyDisplay("tui.editor.jumpBackward");
5040
- const pageUp = this.getEditorKeyDisplay("tui.editor.pageUp");
5041
- const pageDown = this.getEditorKeyDisplay("tui.editor.pageDown");
5151
+ const cursorUp = keyDisplayText("tui.editor.cursorUp");
5152
+ const cursorDown = keyDisplayText("tui.editor.cursorDown");
5153
+ const cursorLeft = keyDisplayText("tui.editor.cursorLeft");
5154
+ const cursorRight = keyDisplayText("tui.editor.cursorRight");
5155
+ const cursorWordLeft = keyDisplayText("tui.editor.cursorWordLeft");
5156
+ const cursorWordRight = keyDisplayText("tui.editor.cursorWordRight");
5157
+ const cursorLineStart = keyDisplayText("tui.editor.cursorLineStart");
5158
+ const cursorLineEnd = keyDisplayText("tui.editor.cursorLineEnd");
5159
+ const jumpForward = keyDisplayText("tui.editor.jumpForward");
5160
+ const jumpBackward = keyDisplayText("tui.editor.jumpBackward");
5161
+ const pageUp = keyDisplayText("tui.editor.pageUp");
5162
+ const pageDown = keyDisplayText("tui.editor.pageDown");
5042
5163
  // Editing keybindings
5043
- const submit = this.getEditorKeyDisplay("tui.input.submit");
5044
- const newLine = this.getEditorKeyDisplay("tui.input.newLine");
5045
- const deleteWordBackward = this.getEditorKeyDisplay("tui.editor.deleteWordBackward");
5046
- const deleteWordForward = this.getEditorKeyDisplay("tui.editor.deleteWordForward");
5047
- const deleteToLineStart = this.getEditorKeyDisplay("tui.editor.deleteToLineStart");
5048
- const deleteToLineEnd = this.getEditorKeyDisplay("tui.editor.deleteToLineEnd");
5049
- const yank = this.getEditorKeyDisplay("tui.editor.yank");
5050
- const yankPop = this.getEditorKeyDisplay("tui.editor.yankPop");
5051
- const undo = this.getEditorKeyDisplay("tui.editor.undo");
5052
- const tab = this.getEditorKeyDisplay("tui.input.tab");
5164
+ const submit = keyDisplayText("tui.input.submit");
5165
+ const newLine = keyDisplayText("tui.input.newLine");
5166
+ const deleteWordBackward = keyDisplayText("tui.editor.deleteWordBackward");
5167
+ const deleteWordForward = keyDisplayText("tui.editor.deleteWordForward");
5168
+ const deleteToLineStart = keyDisplayText("tui.editor.deleteToLineStart");
5169
+ const deleteToLineEnd = keyDisplayText("tui.editor.deleteToLineEnd");
5170
+ const yank = keyDisplayText("tui.editor.yank");
5171
+ const yankPop = keyDisplayText("tui.editor.yankPop");
5172
+ const undo = keyDisplayText("tui.editor.undo");
5173
+ const tab = keyDisplayText("tui.input.tab");
5053
5174
  // App keybindings
5054
5175
  const interrupt = this.getAppKeyDisplay("app.interrupt");
5055
5176
  const clear = this.getAppKeyDisplay("app.clear");