lsd-pi 1.1.4 → 1.1.6

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 (175) hide show
  1. package/README.md +2 -1
  2. package/dist/headless-ui.js +2 -0
  3. package/dist/onboarding.js +11 -8
  4. package/dist/resources/extensions/async-jobs/async-bash-tool.js +14 -0
  5. package/dist/resources/extensions/async-jobs/await-tool.js +14 -0
  6. package/dist/resources/extensions/async-jobs/cancel-job-tool.js +7 -0
  7. package/dist/resources/extensions/cache-timer/index.js +5 -0
  8. package/dist/resources/extensions/codex-rotate/IMPLEMENTATION.md +18 -13
  9. package/dist/resources/extensions/codex-rotate/README.md +9 -3
  10. package/dist/resources/extensions/codex-rotate/commands.js +15 -8
  11. package/dist/resources/extensions/codex-rotate/index.js +17 -8
  12. package/dist/resources/extensions/memory/auto-extract.js +196 -80
  13. package/dist/resources/extensions/memory/dream.js +86 -19
  14. package/dist/resources/extensions/shared/rtk.js +89 -87
  15. package/dist/resources/extensions/subagent/index.js +33 -7
  16. package/dist/startup-model-validation.js +12 -2
  17. package/dist/update-check.js +2 -2
  18. package/dist/update-cmd.js +3 -3
  19. package/dist/welcome-screen.js +43 -14
  20. package/package.json +3 -2
  21. package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.d.ts +2 -0
  22. package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.d.ts.map +1 -0
  23. package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.js +46 -0
  24. package/packages/pi-coding-agent/dist/core/agent-session.clear-queue.test.js.map +1 -0
  25. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +8 -0
  26. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  27. package/packages/pi-coding-agent/dist/core/agent-session.js +43 -4
  28. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  29. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +3 -1
  30. package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  31. package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  32. package/packages/pi-coding-agent/dist/core/keybindings.d.ts +1 -1
  33. package/packages/pi-coding-agent/dist/core/keybindings.d.ts.map +1 -1
  34. package/packages/pi-coding-agent/dist/core/keybindings.js +2 -0
  35. package/packages/pi-coding-agent/dist/core/keybindings.js.map +1 -1
  36. package/packages/pi-coding-agent/dist/core/pty-executor.d.ts +48 -0
  37. package/packages/pi-coding-agent/dist/core/pty-executor.d.ts.map +1 -0
  38. package/packages/pi-coding-agent/dist/core/pty-executor.js +173 -0
  39. package/packages/pi-coding-agent/dist/core/pty-executor.js.map +1 -0
  40. package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  41. package/packages/pi-coding-agent/dist/core/sdk.js +16 -3
  42. package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
  43. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +9 -0
  44. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  45. package/packages/pi-coding-agent/dist/core/settings-manager.js +18 -0
  46. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  47. package/packages/pi-coding-agent/dist/core/tool-approval.d.ts.map +1 -1
  48. package/packages/pi-coding-agent/dist/core/tool-approval.js +2 -2
  49. package/packages/pi-coding-agent/dist/core/tool-approval.js.map +1 -1
  50. package/packages/pi-coding-agent/dist/core/tools/index.d.ts +7 -0
  51. package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
  52. package/packages/pi-coding-agent/dist/core/tools/index.js +23 -2
  53. package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
  54. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts +50 -0
  55. package/packages/pi-coding-agent/dist/core/tools/pty.d.ts.map +1 -0
  56. package/packages/pi-coding-agent/dist/core/tools/pty.js +289 -0
  57. package/packages/pi-coding-agent/dist/core/tools/pty.js.map +1 -0
  58. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  59. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  60. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +36 -22
  61. package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
  62. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts +3 -5
  63. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  64. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js +23 -62
  65. package/packages/pi-coding-agent/dist/modes/interactive/components/bash-execution.js.map +1 -1
  66. package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  67. package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js +1 -4
  68. package/packages/pi-coding-agent/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  69. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  70. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js +1 -4
  71. package/packages/pi-coding-agent/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  72. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.d.ts +39 -0
  73. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.d.ts.map +1 -0
  74. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js +182 -0
  75. package/packages/pi-coding-agent/dist/modes/interactive/components/embedded-terminal.js.map +1 -0
  76. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +6 -0
  77. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  78. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +36 -0
  79. package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
  80. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  81. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +2 -4
  82. package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  83. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -2
  84. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  85. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +106 -77
  86. package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
  87. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +2 -5
  88. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  89. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +4 -13
  90. package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  91. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +11 -0
  92. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
  93. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +49 -13
  94. package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
  95. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.d.ts.map +1 -1
  96. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js +1 -0
  97. package/packages/pi-coding-agent/dist/modes/interactive/controllers/extension-ui-controller.js.map +1 -1
  98. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
  99. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +2 -0
  100. package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
  101. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +3 -0
  102. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
  103. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
  104. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +27 -0
  105. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  106. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +251 -39
  107. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  108. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js +2 -2
  109. package/packages/pi-coding-agent/dist/modes/interactive/theme/themes.js.map +1 -1
  110. package/packages/pi-coding-agent/dist/utils/terminal-screen.d.ts +10 -0
  111. package/packages/pi-coding-agent/dist/utils/terminal-screen.d.ts.map +1 -0
  112. package/packages/pi-coding-agent/dist/utils/terminal-screen.js +67 -0
  113. package/packages/pi-coding-agent/dist/utils/terminal-screen.js.map +1 -0
  114. package/packages/pi-coding-agent/dist/utils/terminal-serializer.d.ts +7 -0
  115. package/packages/pi-coding-agent/dist/utils/terminal-serializer.d.ts.map +1 -0
  116. package/packages/pi-coding-agent/dist/utils/terminal-serializer.js +67 -0
  117. package/packages/pi-coding-agent/dist/utils/terminal-serializer.js.map +1 -0
  118. package/packages/pi-coding-agent/package.json +9 -4
  119. package/packages/pi-coding-agent/src/core/agent-session.clear-queue.test.ts +50 -0
  120. package/packages/pi-coding-agent/src/core/agent-session.ts +50 -4
  121. package/packages/pi-coding-agent/src/core/extensions/types.ts +1 -1
  122. package/packages/pi-coding-agent/src/core/keybindings.ts +4 -1
  123. package/packages/pi-coding-agent/src/core/pty-executor.ts +229 -0
  124. package/packages/pi-coding-agent/src/core/sdk.ts +16 -3
  125. package/packages/pi-coding-agent/src/core/settings-manager.ts +27 -0
  126. package/packages/pi-coding-agent/src/core/tool-approval.ts +2 -2
  127. package/packages/pi-coding-agent/src/core/tools/index.ts +35 -2
  128. package/packages/pi-coding-agent/src/core/tools/pty.ts +354 -0
  129. package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +37 -24
  130. package/packages/pi-coding-agent/src/modes/interactive/components/bash-execution.ts +22 -70
  131. package/packages/pi-coding-agent/src/modes/interactive/components/branch-summary-message.ts +1 -3
  132. package/packages/pi-coding-agent/src/modes/interactive/components/compaction-summary-message.ts +1 -3
  133. package/packages/pi-coding-agent/src/modes/interactive/components/embedded-terminal.ts +224 -0
  134. package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +45 -0
  135. package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +2 -3
  136. package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +104 -81
  137. package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +5 -19
  138. package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +55 -13
  139. package/packages/pi-coding-agent/src/modes/interactive/controllers/extension-ui-controller.ts +1 -0
  140. package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +2 -0
  141. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +3 -0
  142. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +296 -48
  143. package/packages/pi-coding-agent/src/modes/interactive/theme/themes.ts +2 -2
  144. package/packages/pi-coding-agent/src/utils/terminal-screen.ts +77 -0
  145. package/packages/pi-coding-agent/src/utils/terminal-serializer.ts +72 -0
  146. package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.d.ts +2 -0
  147. package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.d.ts.map +1 -0
  148. package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.js +105 -0
  149. package/packages/pi-tui/dist/components/__tests__/editor-dropped-image.test.js.map +1 -0
  150. package/packages/pi-tui/dist/components/editor.d.ts +4 -0
  151. package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
  152. package/packages/pi-tui/dist/components/editor.js +57 -3
  153. package/packages/pi-tui/dist/components/editor.js.map +1 -1
  154. package/packages/pi-tui/dist/components/loader.d.ts +26 -6
  155. package/packages/pi-tui/dist/components/loader.d.ts.map +1 -1
  156. package/packages/pi-tui/dist/components/loader.js +178 -18
  157. package/packages/pi-tui/dist/components/loader.js.map +1 -1
  158. package/packages/pi-tui/src/components/editor.ts +65 -3
  159. package/packages/pi-tui/src/components/loader.ts +196 -19
  160. package/pkg/dist/modes/interactive/theme/themes.js +2 -2
  161. package/pkg/dist/modes/interactive/theme/themes.js.map +1 -1
  162. package/pkg/package.json +1 -1
  163. package/src/resources/extensions/async-jobs/async-bash-tool.ts +13 -0
  164. package/src/resources/extensions/async-jobs/await-tool.ts +13 -0
  165. package/src/resources/extensions/async-jobs/cancel-job-tool.ts +8 -0
  166. package/src/resources/extensions/cache-timer/index.ts +102 -96
  167. package/src/resources/extensions/codex-rotate/IMPLEMENTATION.md +18 -13
  168. package/src/resources/extensions/codex-rotate/README.md +9 -3
  169. package/src/resources/extensions/codex-rotate/commands.ts +335 -329
  170. package/src/resources/extensions/codex-rotate/index.ts +85 -75
  171. package/src/resources/extensions/memory/auto-extract.ts +330 -204
  172. package/src/resources/extensions/memory/dream.ts +88 -21
  173. package/src/resources/extensions/memory/tests/auto-extract.test.ts +200 -144
  174. package/src/resources/extensions/shared/rtk.js +112 -0
  175. package/src/resources/extensions/subagent/index.ts +35 -6
@@ -0,0 +1,72 @@
1
+ import stripAnsi from "strip-ansi";
2
+
3
+ function finalizeLine(cells: string[]): string {
4
+ return cells.join("").replace(/[ \t]+$/u, "");
5
+ }
6
+
7
+ /**
8
+ * Convert terminal-style output into stable display lines.
9
+ * Handles ANSI stripping plus carriage-return overwrites and backspaces.
10
+ */
11
+ export function renderTerminalLines(text: string): string[] {
12
+ const stripped = stripAnsi(text).replace(/\r\n/g, "\n");
13
+ const lines: string[] = [];
14
+ let cells: string[] = [];
15
+ let col = 0;
16
+
17
+ const flushLine = () => {
18
+ lines.push(finalizeLine(cells));
19
+ cells = [];
20
+ col = 0;
21
+ };
22
+
23
+ for (let i = 0; i < stripped.length; i++) {
24
+ const ch = stripped[i]!;
25
+
26
+ if (ch === "\n") {
27
+ flushLine();
28
+ continue;
29
+ }
30
+
31
+ if (ch === "\r") {
32
+ col = 0;
33
+ continue;
34
+ }
35
+
36
+ if (ch === "\b") {
37
+ col = Math.max(0, col - 1);
38
+ if (col < cells.length) cells[col] = " ";
39
+ continue;
40
+ }
41
+
42
+ if (ch < " " && ch !== "\t") {
43
+ continue;
44
+ }
45
+
46
+ if (ch === "\t") {
47
+ const spaces = 4 - (col % 4 || 0);
48
+ for (let s = 0; s < spaces; s++) {
49
+ while (cells.length < col) cells.push(" ");
50
+ if (col < cells.length) cells[col] = " ";
51
+ else cells.push(" ");
52
+ col++;
53
+ }
54
+ continue;
55
+ }
56
+
57
+ while (cells.length < col) cells.push(" ");
58
+ if (col < cells.length) cells[col] = ch;
59
+ else cells.push(ch);
60
+ col++;
61
+ }
62
+
63
+ if (cells.length > 0 || stripped.endsWith("\n")) {
64
+ lines.push(finalizeLine(cells));
65
+ }
66
+
67
+ return lines;
68
+ }
69
+
70
+ export function renderTerminalText(text: string): string {
71
+ return renderTerminalLines(text).join("\n");
72
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=editor-dropped-image.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-dropped-image.test.d.ts","sourceRoot":"","sources":["../../../src/components/__tests__/editor-dropped-image.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,105 @@
1
+ // Editor dropped image marker tests
2
+ // Tests for image path handling, spacing, and normalization
3
+ import { describe, it } from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import { Editor } from "../editor.js";
6
+ // Mock TUI for testing
7
+ const mockTUI = {
8
+ requestRender() { },
9
+ terminal: { rows: 24, columns: 80 },
10
+ };
11
+ // Mock theme
12
+ const mockStyle = (s) => s;
13
+ const mockTheme = {
14
+ borderColor: mockStyle,
15
+ selectList: {
16
+ selectedPrefix: mockStyle,
17
+ selectedText: mockStyle,
18
+ description: mockStyle,
19
+ scrollInfo: mockStyle,
20
+ noMatch: mockStyle,
21
+ },
22
+ };
23
+ describe("Editor - dropped image markers", () => {
24
+ describe("handlePaste with image paths", () => {
25
+ it("decodes file:// URIs and expands to filesystem path", () => {
26
+ const editor = new Editor(mockTUI, mockTheme);
27
+ editor.setText("foo");
28
+ editor.handlePaste("file:///tmp/My%20Image.png");
29
+ assert.equal(editor.getText(), "foo <Image1>");
30
+ assert.equal(editor.getExpandedText(), "foo /tmp/My Image.png");
31
+ });
32
+ it("normalizes escaped spaces in paths", () => {
33
+ const editor = new Editor(mockTUI, mockTheme);
34
+ editor.setText("bar");
35
+ editor.handlePaste("/tmp/My\\ Image.png");
36
+ assert.equal(editor.getText(), "bar <Image1>");
37
+ assert.equal(editor.getExpandedText(), "bar /tmp/My Image.png");
38
+ });
39
+ it("preserves leading space when pasting after word character", () => {
40
+ const editor = new Editor(mockTUI, mockTheme);
41
+ editor.setText("foo");
42
+ editor.handlePaste("/tmp/image.png");
43
+ assert.equal(editor.getText(), "foo <Image1>");
44
+ assert.equal(editor.getExpandedText(), "foo /tmp/image.png");
45
+ });
46
+ it("does not add leading space when cursor after space", () => {
47
+ const editor = new Editor(mockTUI, mockTheme);
48
+ editor.setText("foo ");
49
+ editor.handlePaste("/tmp/image.png");
50
+ assert.equal(editor.getText(), "foo <Image1>");
51
+ assert.equal(editor.getExpandedText(), "foo /tmp/image.png");
52
+ });
53
+ it("does not add leading space when cursor at line start", () => {
54
+ const editor = new Editor(mockTUI, mockTheme);
55
+ editor.setText("");
56
+ editor.handlePaste("/tmp/image.png");
57
+ assert.equal(editor.getText(), "<Image1>");
58
+ assert.equal(editor.getExpandedText(), "/tmp/image.png");
59
+ });
60
+ it("handles file:// URI with leading space after word", () => {
61
+ const editor = new Editor(mockTUI, mockTheme);
62
+ editor.setText("test");
63
+ editor.handlePaste("file:///home/user/photo.jpg");
64
+ assert.equal(editor.getText(), "test <Image1>");
65
+ assert.equal(editor.getExpandedText(), "test /home/user/photo.jpg");
66
+ });
67
+ it("handles relative paths with leading space after word", () => {
68
+ const editor = new Editor(mockTUI, mockTheme);
69
+ editor.setText("doc:");
70
+ editor.handlePaste("./images/screenshot.png");
71
+ assert.equal(editor.getText(), "doc: <Image1>");
72
+ assert.equal(editor.getExpandedText(), "doc: ./images/screenshot.png");
73
+ });
74
+ it("handles tilde paths with leading space after word", () => {
75
+ const editor = new Editor(mockTUI, mockTheme);
76
+ editor.setText("look at");
77
+ editor.handlePaste("~/Desktop/Screen%20Shot.png");
78
+ assert.equal(editor.getText(), "look at <Image1>");
79
+ assert.equal(editor.getExpandedText(), "look at ~/Desktop/Screen Shot.png");
80
+ });
81
+ });
82
+ describe("image marker expansion", () => {
83
+ it("expands markers with correct paths on submit", () => {
84
+ const editor = new Editor(mockTUI, mockTheme);
85
+ editor.setText("");
86
+ editor.handlePaste("/tmp/image1.png");
87
+ editor.handlePaste("/tmp/image2.png");
88
+ assert.equal(editor.getText(), "<Image1><Image2>");
89
+ assert.equal(editor.getExpandedText(), "/tmp/image1.png/tmp/image2.png");
90
+ });
91
+ it("clears dropped image state after submit", () => {
92
+ const editor = new Editor(mockTUI, mockTheme);
93
+ editor.setText("");
94
+ editor.handlePaste("/tmp/image.png");
95
+ // Simulate submit
96
+ const { lines, cursorLine, cursorCol } = editor.getCursor();
97
+ editor.submitValue();
98
+ editor.setText("");
99
+ // Paste again - should get Image1, not Image2
100
+ editor.handlePaste("/tmp/image2.png");
101
+ assert.equal(editor.getText(), "<Image1>");
102
+ });
103
+ });
104
+ });
105
+ //# sourceMappingURL=editor-dropped-image.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-dropped-image.test.js","sourceRoot":"","sources":["../../../src/components/__tests__/editor-dropped-image.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Editor dropped image marker tests\n// Tests for image path handling, spacing, and normalization\n\nimport { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { Editor } from \"../editor.js\";\n\n// Mock TUI for testing\nconst mockTUI = {\n\trequestRender() {},\n\tterminal: { rows: 24, columns: 80 },\n};\n\n// Mock theme\nconst mockStyle = (s: string) => s;\nconst mockTheme = {\n\tborderColor: mockStyle,\n\tselectList: {\n\t\tselectedPrefix: mockStyle,\n\t\tselectedText: mockStyle,\n\t\tdescription: mockStyle,\n\t\tscrollInfo: mockStyle,\n\t\tnoMatch: mockStyle,\n\t},\n};\n\ndescribe(\"Editor - dropped image markers\", () => {\n\tdescribe(\"handlePaste with image paths\", () => {\n\t\tit(\"decodes file:// URIs and expands to filesystem path\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"foo\");\n\t\t\teditor.handlePaste(\"file:///tmp/My%20Image.png\");\n\n\t\t\tassert.equal(editor.getText(), \"foo <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"foo /tmp/My Image.png\");\n\t\t});\n\n\t\tit(\"normalizes escaped spaces in paths\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"bar\");\n\t\t\teditor.handlePaste(\"/tmp/My\\\\ Image.png\");\n\n\t\t\tassert.equal(editor.getText(), \"bar <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"bar /tmp/My Image.png\");\n\t\t});\n\n\t\tit(\"preserves leading space when pasting after word character\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"foo\");\n\t\t\teditor.handlePaste(\"/tmp/image.png\");\n\n\t\t\tassert.equal(editor.getText(), \"foo <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"foo /tmp/image.png\");\n\t\t});\n\n\t\tit(\"does not add leading space when cursor after space\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"foo \");\n\t\t\teditor.handlePaste(\"/tmp/image.png\");\n\n\t\t\tassert.equal(editor.getText(), \"foo <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"foo /tmp/image.png\");\n\t\t});\n\n\t\tit(\"does not add leading space when cursor at line start\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"\");\n\t\t\teditor.handlePaste(\"/tmp/image.png\");\n\n\t\t\tassert.equal(editor.getText(), \"<Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"/tmp/image.png\");\n\t\t});\n\n\t\tit(\"handles file:// URI with leading space after word\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"test\");\n\t\t\teditor.handlePaste(\"file:///home/user/photo.jpg\");\n\n\t\t\tassert.equal(editor.getText(), \"test <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"test /home/user/photo.jpg\");\n\t\t});\n\n\t\tit(\"handles relative paths with leading space after word\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"doc:\");\n\t\t\teditor.handlePaste(\"./images/screenshot.png\");\n\n\t\t\tassert.equal(editor.getText(), \"doc: <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"doc: ./images/screenshot.png\");\n\t\t});\n\n\t\tit(\"handles tilde paths with leading space after word\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"look at\");\n\t\t\teditor.handlePaste(\"~/Desktop/Screen%20Shot.png\");\n\n\t\t\tassert.equal(editor.getText(), \"look at <Image1>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"look at ~/Desktop/Screen Shot.png\");\n\t\t});\n\t});\n\n\tdescribe(\"image marker expansion\", () => {\n\t\tit(\"expands markers with correct paths on submit\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"\");\n\t\t\teditor.handlePaste(\"/tmp/image1.png\");\n\t\t\teditor.handlePaste(\"/tmp/image2.png\");\n\n\t\t\tassert.equal(editor.getText(), \"<Image1><Image2>\");\n\t\t\tassert.equal(editor.getExpandedText(), \"/tmp/image1.png/tmp/image2.png\");\n\t\t});\n\n\t\tit(\"clears dropped image state after submit\", () => {\n\t\t\tconst editor = new Editor(mockTUI, mockTheme);\n\t\t\teditor.setText(\"\");\n\t\t\teditor.handlePaste(\"/tmp/image.png\");\n\n\t\t\t// Simulate submit\n\t\t\tconst { lines, cursorLine, cursorCol } = editor.getCursor();\n\t\t\teditor.submitValue();\n\t\t\teditor.setText(\"\");\n\n\t\t\t// Paste again - should get Image1, not Image2\n\t\t\teditor.handlePaste(\"/tmp/image2.png\");\n\t\t\tassert.equal(editor.getText(), \"<Image1>\");\n\t\t});\n\t});\n});\n"]}
@@ -39,6 +39,8 @@ export declare class Editor implements Component, Focusable {
39
39
  private static readonly AUTOCOMPLETE_DEBOUNCE_MS;
40
40
  private pastes;
41
41
  private pasteCounter;
42
+ private droppedImagePaths;
43
+ private droppedImageCounter;
42
44
  private pasteBuffer;
43
45
  private isInPaste;
44
46
  private history;
@@ -85,6 +87,8 @@ export declare class Editor implements Component, Focusable {
85
87
  * Use this when you need the full content (e.g., for external editor).
86
88
  */
87
89
  getExpandedText(): string;
90
+ private expandDroppedImageMarkers;
91
+ private extractDroppedImagePath;
88
92
  getLines(): string[];
89
93
  getCursor(): {
90
94
  line: number;
@@ -1 +1 @@
1
- {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../../src/components/editor.ts"],"names":[],"mappings":"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"}
@@ -95,6 +95,9 @@ export class Editor {
95
95
  // Paste tracking for large pastes
96
96
  this.pastes = new Map();
97
97
  this.pasteCounter = 0;
98
+ // Drag-and-drop image path markers (visual only; expanded back on submit)
99
+ this.droppedImagePaths = new Map();
100
+ this.droppedImageCounter = 0;
98
101
  // Bracketed paste mode buffering
99
102
  this.pasteBuffer = "";
100
103
  this.isInPaste = false;
@@ -723,8 +726,44 @@ export class Editor {
723
726
  const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
724
727
  result = result.replace(markerRegex, pasteContent);
725
728
  }
729
+ return this.expandDroppedImageMarkers(result);
730
+ }
731
+ expandDroppedImageMarkers(text) {
732
+ let result = text;
733
+ for (const [imageId, imagePath] of this.droppedImagePaths) {
734
+ const markerRegex = new RegExp(`<Image${imageId}>`, "g");
735
+ result = result.replace(markerRegex, imagePath);
736
+ }
726
737
  return result;
727
738
  }
739
+ extractDroppedImagePath(pastedText) {
740
+ const trimmed = pastedText.trim();
741
+ if (!trimmed || /[\n\r\t]/.test(trimmed))
742
+ return null;
743
+ const unquoted = (trimmed.startsWith('"') && trimmed.endsWith('"')) ||
744
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))
745
+ ? trimmed.slice(1, -1)
746
+ : trimmed;
747
+ let maybePath = unquoted;
748
+ if (unquoted.startsWith("file://")) {
749
+ try {
750
+ maybePath = decodeURI(unquoted.replace(/^file:\/\//, ""));
751
+ }
752
+ catch {
753
+ return null;
754
+ }
755
+ }
756
+ const normalizedPath = maybePath.replace(/\\ /g, " ");
757
+ if (!/\.(png|jpe?g|gif|webp|bmp|tiff?|svg|heic|heif|avif)$/i.test(normalizedPath)) {
758
+ return null;
759
+ }
760
+ if (!normalizedPath.startsWith("/") && !normalizedPath.startsWith("~/") && !normalizedPath.startsWith("./") && !normalizedPath.startsWith("../")) {
761
+ return null;
762
+ }
763
+ // Return the normalized filesystem path (not the raw trimmed input)
764
+ // This ensures file:// URIs are decoded and escaped spaces are normalized
765
+ return normalizedPath;
766
+ }
728
767
  getLines() {
729
768
  return [...this.state.lines];
730
769
  }
@@ -880,15 +919,27 @@ export class Editor {
880
919
  .split("")
881
920
  .filter((char) => char === "\n" || char.charCodeAt(0) >= 32)
882
921
  .join("");
883
- // If pasting a file path (starts with /, ~, or .) and the character before
884
- // the cursor is a word character, prepend a space for better readability
885
- if (/^[/~.]/.test(filteredText)) {
922
+ // Check if we need a leading space for readability
923
+ // This applies to file:// URIs, absolute paths (~, /), or relative paths (., ..)
924
+ let needsLeadingSpace = false;
925
+ if (/^(file:\/\/|[/~.])/.test(filteredText)) {
886
926
  const currentLine = this.state.lines[this.state.cursorLine] || "";
887
927
  const charBeforeCursor = this.state.cursorCol > 0 ? currentLine[this.state.cursorCol - 1] : "";
888
928
  if (charBeforeCursor && /\w/.test(charBeforeCursor)) {
929
+ needsLeadingSpace = true;
889
930
  filteredText = ` ${filteredText}`;
890
931
  }
891
932
  }
933
+ const droppedImagePath = this.extractDroppedImagePath(filteredText);
934
+ if (droppedImagePath) {
935
+ this.droppedImageCounter++;
936
+ const imageId = this.droppedImageCounter;
937
+ this.droppedImagePaths.set(imageId, droppedImagePath);
938
+ // Preserve leading space for readability (e.g., "foo" -> "foo <Image1>" -> "foo /tmp/image.png")
939
+ const toInsert = needsLeadingSpace ? ` <Image${imageId}>` : `<Image${imageId}>`;
940
+ this.insertTextAtCursorInternal(toInsert);
941
+ return;
942
+ }
892
943
  // Split into lines to check for large paste
893
944
  const pastedLines = filteredText.split("\n");
894
945
  // Check if this is a large paste (> 10 lines or > 1000 characters)
@@ -946,9 +997,12 @@ export class Editor {
946
997
  const markerRegex = new RegExp(`\\[paste #${pasteId}( (\\+\\d+ lines|\\d+ chars))?\\]`, "g");
947
998
  result = result.replace(markerRegex, pasteContent);
948
999
  }
1000
+ result = this.expandDroppedImageMarkers(result);
949
1001
  this.state = { lines: [""], cursorLine: 0, cursorCol: 0 };
950
1002
  this.pastes.clear();
951
1003
  this.pasteCounter = 0;
1004
+ this.droppedImagePaths.clear();
1005
+ this.droppedImageCounter = 0;
952
1006
  this.historyIndex = -1;
953
1007
  this.scrollOffset = 0;
954
1008
  this.undoStack.clear();