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,229 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { createWriteStream, unlinkSync, type WriteStream } from "node:fs";
3
+ import { createRequire } from "node:module";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import { processStreamChunk, type StreamState } from "@gsd/native";
7
+ import { getShellConfig, getShellEnv, sanitizeCommand } from "../utils/shell.js";
8
+ import { DEFAULT_MAX_BYTES, truncateTail } from "./tools/truncate.js";
9
+ import type { BashResult } from "./bash-executor.js";
10
+
11
+ export interface PtyExecutorOptions {
12
+ onChunk?: (chunk: string) => void;
13
+ signal?: AbortSignal;
14
+ cols?: number;
15
+ rows?: number;
16
+ cwd?: string;
17
+ loginShell?: boolean;
18
+ }
19
+
20
+ export interface PtyExecutionHandle {
21
+ pid: number;
22
+ write(data: string): void;
23
+ resize(cols: number, rows: number): void;
24
+ kill(): void;
25
+ isActive(): boolean;
26
+ }
27
+
28
+ export interface PtyExecutionSession {
29
+ handle: PtyExecutionHandle;
30
+ result: Promise<BashResult>;
31
+ }
32
+
33
+ type PtyModule = {
34
+ spawn: (
35
+ file: string,
36
+ args?: string[],
37
+ options?: {
38
+ name?: string;
39
+ cols?: number;
40
+ rows?: number;
41
+ cwd?: string;
42
+ env?: Record<string, string>;
43
+ },
44
+ ) => {
45
+ pid: number;
46
+ write(data: string): void;
47
+ resize(cols: number, rows: number): void;
48
+ kill(signal?: string): void;
49
+ onData(cb: (data: string) => void): { dispose(): void } | void;
50
+ onExit(cb: (event: { exitCode: number; signal?: number }) => void): { dispose(): void } | void;
51
+ };
52
+ };
53
+
54
+ const ptyTempFiles = new Set<string>();
55
+ let cleanupRegistered = false;
56
+
57
+ function registerTempCleanup(): void {
58
+ if (cleanupRegistered) return;
59
+ cleanupRegistered = true;
60
+ process.on("exit", () => {
61
+ for (const file of ptyTempFiles) {
62
+ try {
63
+ unlinkSync(file);
64
+ } catch {
65
+ // Best-effort cleanup
66
+ }
67
+ }
68
+ });
69
+ }
70
+
71
+ export async function loadPtyModule(): Promise<PtyModule | null> {
72
+ const cjsRequire = createRequire(import.meta.url);
73
+ for (const name of ["@lydell/node-pty", "node-pty"]) {
74
+ try {
75
+ return cjsRequire(name) as PtyModule;
76
+ } catch {
77
+ // Try next implementation
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+
83
+ export async function isPtyAvailable(): Promise<boolean> {
84
+ return (await loadPtyModule()) !== null;
85
+ }
86
+
87
+ export async function executeBashInPty(command: string, options: PtyExecutorOptions = {}): Promise<PtyExecutionSession> {
88
+ const pty = await loadPtyModule();
89
+ if (!pty) {
90
+ throw new Error("PTY support is unavailable (install @lydell/node-pty or node-pty)");
91
+ }
92
+
93
+ let shell: string;
94
+ let args: string[];
95
+ if (options.loginShell) {
96
+ shell = process.env.SHELL || "/bin/bash";
97
+ args = ["-l", "-c"];
98
+ } else {
99
+ ({ shell, args } = getShellConfig());
100
+ }
101
+
102
+ const child = pty.spawn(shell, [...args, sanitizeCommand(command)], {
103
+ name: "xterm-256color",
104
+ cols: Math.max(20, options.cols ?? 80),
105
+ rows: Math.max(5, options.rows ?? 24),
106
+ cwd: options.cwd ?? process.cwd(),
107
+ env: {
108
+ ...Object.fromEntries(
109
+ Object.entries(getShellEnv()).map(([key, value]) => [key, String(value ?? "")]),
110
+ ),
111
+ TERM: "xterm-256color",
112
+ },
113
+ });
114
+
115
+ let active = true;
116
+ let cancelled = false;
117
+ const outputChunks: string[] = [];
118
+ let outputBytes = 0;
119
+ const maxOutputBytes = DEFAULT_MAX_BYTES * 2;
120
+ let tempFilePath: string | undefined;
121
+ let tempFileStream: WriteStream | undefined;
122
+ let totalBytes = 0;
123
+ let streamState: StreamState | undefined;
124
+
125
+ const handleData = (data: string) => {
126
+ const buffer = Buffer.from(data, "utf8");
127
+ totalBytes += buffer.length;
128
+
129
+ const result = processStreamChunk(buffer, streamState);
130
+ streamState = result.state;
131
+ const text = result.text;
132
+
133
+ if (totalBytes > DEFAULT_MAX_BYTES && !tempFilePath) {
134
+ registerTempCleanup();
135
+ const id = randomBytes(8).toString("hex");
136
+ tempFilePath = join(tmpdir(), `pi-pty-${id}.log`);
137
+ ptyTempFiles.add(tempFilePath);
138
+ tempFileStream = createWriteStream(tempFilePath);
139
+ for (const chunk of outputChunks) {
140
+ tempFileStream.write(chunk);
141
+ }
142
+ }
143
+
144
+ if (tempFileStream) {
145
+ tempFileStream.write(text);
146
+ }
147
+
148
+ outputChunks.push(text);
149
+ outputBytes += text.length;
150
+ while (outputBytes > maxOutputBytes && outputChunks.length > 1) {
151
+ const removed = outputChunks.shift()!;
152
+ outputBytes -= removed.length;
153
+ }
154
+
155
+ options.onChunk?.(data);
156
+ };
157
+
158
+ const dataDisposable = child.onData(handleData);
159
+
160
+ const result = new Promise<BashResult>((resolve) => {
161
+ const onAbort = () => {
162
+ cancelled = true;
163
+ try {
164
+ child.kill();
165
+ } catch {
166
+ // Best-effort
167
+ }
168
+ };
169
+
170
+ if (options.signal) {
171
+ if (options.signal.aborted) {
172
+ onAbort();
173
+ } else {
174
+ options.signal.addEventListener("abort", onAbort, { once: true });
175
+ }
176
+ }
177
+
178
+ const finish = (exitCode: number | undefined) => {
179
+ active = false;
180
+ if (options.signal) {
181
+ options.signal.removeEventListener("abort", onAbort);
182
+ }
183
+ dataDisposable?.dispose?.();
184
+ tempFileStream?.end();
185
+
186
+ const fullOutput = outputChunks.join("");
187
+ const truncationResult = truncateTail(fullOutput);
188
+ resolve({
189
+ output: truncationResult.truncated ? truncationResult.content : fullOutput,
190
+ exitCode: cancelled ? undefined : exitCode,
191
+ cancelled,
192
+ truncated: truncationResult.truncated,
193
+ fullOutputPath: tempFilePath,
194
+ });
195
+ };
196
+
197
+ const exitDisposable = child.onExit(({ exitCode }) => {
198
+ exitDisposable?.dispose?.();
199
+ finish(exitCode);
200
+ });
201
+ });
202
+
203
+ return {
204
+ handle: {
205
+ pid: child.pid,
206
+ write(data: string) {
207
+ if (!active) return;
208
+ child.write(data);
209
+ },
210
+ resize(cols: number, rows: number) {
211
+ if (!active) return;
212
+ child.resize(Math.max(20, cols), Math.max(5, rows));
213
+ },
214
+ kill() {
215
+ if (!active) return;
216
+ cancelled = true;
217
+ try {
218
+ child.kill();
219
+ } catch {
220
+ // Best-effort
221
+ }
222
+ },
223
+ isActive() {
224
+ return active;
225
+ },
226
+ },
227
+ result,
228
+ };
229
+ }
@@ -254,8 +254,20 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
254
254
 
255
255
  const editMode = settingsManager.getEditMode();
256
256
  const defaultActiveToolNames: ToolName[] = editMode === "hashline"
257
- ? ["hashline_read", "bash", "hashline_edit", "write", "lsp"]
258
- : ["read", "bash", "edit", "write", "lsp"];
257
+ ? [
258
+ "hashline_read",
259
+ "bash",
260
+ "hashline_edit",
261
+ "write",
262
+ "lsp",
263
+ "pty_start",
264
+ "pty_send",
265
+ "pty_read",
266
+ "pty_wait",
267
+ "pty_resize",
268
+ "pty_kill",
269
+ ]
270
+ : ["read", "bash", "edit", "write", "lsp", "pty_start", "pty_send", "pty_read", "pty_wait", "pty_resize", "pty_kill"];
259
271
  const initialActiveToolNames: ToolName[] = options.tools
260
272
  ? options.tools.map((t) => t.name).filter((n): n is ToolName => n in allTools)
261
273
  : defaultActiveToolNames;
@@ -344,8 +356,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
344
356
  // (e.g., OAuth token refresh failing due to brief connectivity loss).
345
357
  const maxAttempts = 3;
346
358
  const baseDelayMs = 2000;
359
+ const sid = sessionManager.getSessionId();
347
360
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
348
- const key = await modelRegistry.getApiKeyForProvider(resolvedProvider);
361
+ const key = await modelRegistry.getApiKeyForProvider(resolvedProvider, sid);
349
362
  if (key) return key;
350
363
 
351
364
  // On the last attempt, fall through to error handling below
@@ -152,6 +152,7 @@ export interface Settings {
152
152
  enabledModels?: string[]; // Model patterns for cycling (same format as --models CLI flag)
153
153
  codexRotate?: boolean; // Enable the bundled codex-rotate extension (default: false)
154
154
  cacheTimer?: boolean; // Show elapsed time since last response in the footer (default: true)
155
+ pinLastPrompt?: boolean; // Pin last sent prompt above the editor as a reminder (default: false)
155
156
  doubleEscapeAction?: "fork" | "tree" | "none"; // Action for double-escape with empty editor (default: "tree")
156
157
  treeFilterMode?: "default" | "no-tools" | "user-only" | "labeled-only" | "all"; // Default filter when opening /tree
157
158
  thinkingBudgets?: ThinkingBudgetsSettings; // Custom token budgets for thinking levels
@@ -175,6 +176,8 @@ export interface Settings {
175
176
  lspInstalledServers?: string[]; // list of server names installed via the onboarding wizard
176
177
  rtk?: boolean; // default: false — enable RTK shell-command compression (requires restart)
177
178
  editorScheme?: "auto" | "vscode" | "cursor" | "zed" | "jetbrains" | "sublime" | "file"; // URI scheme for Cmd+click file links (default: "auto")
179
+ autoDream?: boolean; // default: false — enable automatic memory consolidation (dream) after sessions
180
+ autoMemory?: boolean; // default: false — enable automatic memory extraction from session transcripts
178
181
  }
179
182
 
180
183
  function isQualifiedProviderModelRef(value: unknown): value is string {
@@ -1069,6 +1072,14 @@ export class SettingsManager {
1069
1072
  this.setGlobalSetting("cacheTimer", enabled);
1070
1073
  }
1071
1074
 
1075
+ getPinLastPrompt(): boolean {
1076
+ return this.settings.pinLastPrompt ?? false;
1077
+ }
1078
+
1079
+ setPinLastPrompt(enabled: boolean): void {
1080
+ this.setGlobalSetting("pinLastPrompt", enabled);
1081
+ }
1082
+
1072
1083
  getDoubleEscapeAction(): "fork" | "tree" | "none" {
1073
1084
  return this.settings.doubleEscapeAction ?? "tree";
1074
1085
  }
@@ -1294,4 +1305,20 @@ export class SettingsManager {
1294
1305
  setEditorScheme(scheme: "auto" | "vscode" | "cursor" | "zed" | "jetbrains" | "sublime" | "file"): void {
1295
1306
  this.setGlobalSetting("editorScheme", scheme);
1296
1307
  }
1308
+
1309
+ getAutoDream(): boolean {
1310
+ return this.settings.autoDream ?? false;
1311
+ }
1312
+
1313
+ setAutoDream(enabled: boolean): void {
1314
+ this.setGlobalSetting("autoDream", enabled);
1315
+ }
1316
+
1317
+ getAutoMemory(): boolean {
1318
+ return this.settings.autoMemory ?? false;
1319
+ }
1320
+
1321
+ setAutoMemory(enabled: boolean): void {
1322
+ this.setGlobalSetting("autoMemory", enabled);
1323
+ }
1297
1324
  }
@@ -1,7 +1,7 @@
1
1
  export type PermissionMode = "danger-full-access" | "accept-on-edit" | "auto" | "plan";
2
2
 
3
- export const READ_ONLY_TOOLS = new Set(["read", "grep", "find", "ls", "lsp", "hashline_read"]);
4
- export const MUTATING_TOOLS = new Set(["bash", "edit", "write", "hashline_edit"]);
3
+ export const READ_ONLY_TOOLS = new Set(["read", "grep", "find", "ls", "lsp", "hashline_read", "pty_read", "pty_wait"]);
4
+ export const MUTATING_TOOLS = new Set(["bash", "edit", "write", "hashline_edit", "pty_start", "pty_send", "pty_resize", "pty_kill"]);
5
5
 
6
6
  export interface FileChangeApprovalRequest {
7
7
  action: "write" | "edit" | "delete" | "move";
@@ -91,6 +91,17 @@ export {
91
91
  type HashlineReadToolOptions,
92
92
  hashlineReadTool,
93
93
  } from "./hashline-read.js";
94
+ export {
95
+ createPtyTools,
96
+ type PtyKillInput,
97
+ type PtyReadInput,
98
+ type PtyResizeInput,
99
+ type PtySendInput,
100
+ type PtyStartInput,
101
+ type PtyToolDetails,
102
+ type PtyWaitInput,
103
+ ptyToolNames,
104
+ } from "./pty.js";
94
105
  export {
95
106
  type Anchor,
96
107
  applyHashlineEdits,
@@ -121,6 +132,7 @@ import { createGrepTool, grepTool } from "./grep.js";
121
132
  import { createHashlineEditTool, hashlineEditTool } from "./hashline-edit.js";
122
133
  import { createHashlineReadTool, hashlineReadTool } from "./hashline-read.js";
123
134
  import { createLsTool, lsTool } from "./ls.js";
135
+ import { createPtyTools } from "./pty.js";
124
136
  import { createReadTool, type ReadToolOptions, readTool } from "./read.js";
125
137
  import { createWriteTool, writeTool } from "./write.js";
126
138
  import { createLspTool, lspTool } from "../lsp/index.js";
@@ -134,6 +146,8 @@ export const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];
134
146
  // Read-only tools for exploration without modification (using process.cwd())
135
147
  export const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];
136
148
 
149
+ const ptyBuiltinTools = createPtyTools(process.cwd());
150
+
137
151
  // All available tools (using process.cwd())
138
152
  export const allTools = {
139
153
  read: readTool,
@@ -146,6 +160,12 @@ export const allTools = {
146
160
  lsp: lspTool,
147
161
  hashline_edit: hashlineEditTool,
148
162
  hashline_read: hashlineReadTool,
163
+ pty_start: ptyBuiltinTools.pty_start,
164
+ pty_send: ptyBuiltinTools.pty_send,
165
+ pty_read: ptyBuiltinTools.pty_read,
166
+ pty_wait: ptyBuiltinTools.pty_wait,
167
+ pty_resize: ptyBuiltinTools.pty_resize,
168
+ pty_kill: ptyBuiltinTools.pty_kill,
149
169
  };
150
170
 
151
171
  // Hashline-mode coding tools — read with hash anchors, edit with hash references
@@ -160,6 +180,19 @@ export interface ToolsOptions {
160
180
  bash?: BashToolOptions;
161
181
  }
162
182
 
183
+ function addPtyTools<T extends Record<string, Tool>>(target: T, cwd: string): T & Record<string, Tool> {
184
+ const ptyTools = createPtyTools(cwd);
185
+ return {
186
+ ...target,
187
+ pty_start: ptyTools.pty_start,
188
+ pty_send: ptyTools.pty_send,
189
+ pty_read: ptyTools.pty_read,
190
+ pty_wait: ptyTools.pty_wait,
191
+ pty_resize: ptyTools.pty_resize,
192
+ pty_kill: ptyTools.pty_kill,
193
+ };
194
+ }
195
+
163
196
  /**
164
197
  * Create coding tools configured for a specific working directory.
165
198
  */
@@ -183,7 +216,7 @@ export function createReadOnlyTools(cwd: string, options?: ToolsOptions): Tool[]
183
216
  * Create all tools configured for a specific working directory.
184
217
  */
185
218
  export function createAllTools(cwd: string, options?: ToolsOptions): Record<ToolName, Tool> {
186
- return {
219
+ return addPtyTools({
187
220
  read: createReadTool(cwd, options?.read),
188
221
  bash: createBashTool(cwd, options?.bash),
189
222
  edit: createEditTool(cwd),
@@ -194,7 +227,7 @@ export function createAllTools(cwd: string, options?: ToolsOptions): Record<Tool
194
227
  lsp: createLspTool(cwd),
195
228
  hashline_edit: createHashlineEditTool(cwd),
196
229
  hashline_read: createHashlineReadTool(cwd, options?.read),
197
- };
230
+ }, cwd) as Record<ToolName, Tool>;
198
231
  }
199
232
 
200
233
  /**