letmecook 0.0.15 → 0.0.17

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.
@@ -27,11 +27,10 @@ export function showNewSessionPrompt(
27
27
 
28
28
  repos.forEach((repo, i) => {
29
29
  const branch = repo.branch ? ` (${repo.branch})` : " (default)";
30
- const roMarker = repo.readOnly ? " [RO]" : "";
31
- const latestMarker = repo.latest ? " [Latest]" : "";
30
+ const refMarker = repo.reference ? " [Ref]" : "";
32
31
  const repoText = new TextRenderable(renderer, {
33
32
  id: `repo-${i}`,
34
- content: ` - ${repo.owner}/${repo.name}${branch}${roMarker}${latestMarker}`,
33
+ content: ` - ${repo.owner}/${repo.name}${branch}${refMarker}`,
35
34
  fg: "#94a3b8",
36
35
  });
37
36
  content.add(repoText);
@@ -52,7 +52,7 @@ function getPhasePresentation(phase: ProgressPhase): { content: string; fg: stri
52
52
  case "installing-skills":
53
53
  return { content: "Installing skills...", fg: "#38bdf8" };
54
54
  case "refreshing":
55
- return { content: "Refreshing latest repositories...", fg: "#38bdf8" };
55
+ return { content: "Refreshing reference repositories...", fg: "#38bdf8" };
56
56
  case "done":
57
57
  return { content: "Ready!", fg: "#22c55e" };
58
58
  default:
@@ -208,7 +208,7 @@ export function showSessionSettings(
208
208
  if (selectedTarget === "goal") {
209
209
  customActions.push("Enter Edit");
210
210
  } else if (selectedTarget === "repo") {
211
- customActions.push("r Toggle RO", "l Toggle Latest", "a Add repos");
211
+ customActions.push("r Toggle Ref", "a Add repos");
212
212
  } else if (selectedTarget === "skill") {
213
213
  customActions.push("x Remove", "a Add repos");
214
214
  }
@@ -342,22 +342,7 @@ export function showSessionSettings(
342
342
  if (key.name === "r" && selectedTarget === "repo") {
343
343
  const repo = updatedRepos[selectedRepoIndex];
344
344
  if (repo) {
345
- repo.readOnly = !repo.readOnly;
346
- if (!repo.readOnly) {
347
- repo.latest = false;
348
- }
349
- updateReposList();
350
- }
351
- return;
352
- }
353
-
354
- if (key.name === "l" && selectedTarget === "repo") {
355
- const repo = updatedRepos[selectedRepoIndex];
356
- if (repo) {
357
- repo.latest = !repo.latest;
358
- if (repo.latest) {
359
- repo.readOnly = true;
360
- }
345
+ repo.reference = !repo.reference;
361
346
  updateReposList();
362
347
  }
363
348
  return;
@@ -51,6 +51,12 @@ interface ReadProcessOutputWithBufferOptions {
51
51
  onBufferUpdate?: (buffer: string[]) => void;
52
52
  }
53
53
 
54
+ export interface ReadWithControlOptions {
55
+ maxBufferLines?: number;
56
+ onBufferUpdate?: (buffer: string[]) => void;
57
+ shouldStop?: () => boolean; // Check if we should stop early
58
+ }
59
+
54
60
  export async function readProcessOutputWithBuffer(
55
61
  proc: ReturnType<typeof Bun.spawn>,
56
62
  options?: ReadProcessOutputWithBufferOptions,
@@ -106,3 +112,86 @@ export async function readProcessOutputWithBuffer(
106
112
  fullOutput: fullOutputParts.join(""),
107
113
  };
108
114
  }
115
+
116
+ export async function readProcessOutputWithControl(
117
+ proc: ReturnType<typeof Bun.spawn>,
118
+ options?: ReadWithControlOptions,
119
+ ): Promise<{ success: boolean; output: string[]; fullOutput: string; wasInterrupted: boolean }> {
120
+ const { maxBufferLines, onBufferUpdate, shouldStop } = options || {};
121
+ const outputBuffer: string[] = [];
122
+ let wasInterrupted = false;
123
+
124
+ const addLine = (line: string) => {
125
+ const trimmed = line.trim();
126
+ if (trimmed) {
127
+ outputBuffer.push(trimmed);
128
+ if (maxBufferLines && outputBuffer.length > maxBufferLines) {
129
+ outputBuffer.shift();
130
+ }
131
+ onBufferUpdate?.([...outputBuffer]);
132
+ }
133
+ };
134
+
135
+ const fullOutputParts: string[] = [];
136
+
137
+ const readStream = async (stream: ReadableStream<Uint8Array> | number | undefined) => {
138
+ if (!stream || typeof stream === "number") return;
139
+
140
+ const reader = stream.getReader();
141
+ const decoder = new TextDecoder();
142
+ let buffer = "";
143
+
144
+ try {
145
+ while (true) {
146
+ // Check if we should stop before each read
147
+ if (shouldStop?.()) {
148
+ wasInterrupted = true;
149
+ reader.releaseLock();
150
+ return;
151
+ }
152
+
153
+ const { done, value } = await reader.read();
154
+ if (done) break;
155
+
156
+ const chunk = decoder.decode(value, { stream: true });
157
+ fullOutputParts.push(chunk);
158
+ buffer += chunk;
159
+
160
+ const lines = buffer.split(/[\r\n]+/);
161
+ buffer = lines.pop() || "";
162
+
163
+ for (const line of lines) {
164
+ addLine(line);
165
+ }
166
+
167
+ // Check again after processing
168
+ if (shouldStop?.()) {
169
+ wasInterrupted = true;
170
+ reader.releaseLock();
171
+ return;
172
+ }
173
+ }
174
+
175
+ if (buffer.trim()) {
176
+ addLine(buffer);
177
+ }
178
+ } catch {
179
+ // Stream may have been cancelled, that's ok
180
+ }
181
+ };
182
+
183
+ await Promise.all([readStream(proc.stdout), readStream(proc.stderr)]);
184
+
185
+ // Only wait for exit if not interrupted
186
+ let exitCode = 1;
187
+ if (!wasInterrupted) {
188
+ exitCode = await proc.exited;
189
+ }
190
+
191
+ return {
192
+ success: !wasInterrupted && exitCode === 0,
193
+ output: outputBuffer,
194
+ fullOutput: fullOutputParts.join(""),
195
+ wasInterrupted,
196
+ };
197
+ }