@fclef819/cdx 0.1.2 → 0.1.4

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 (2) hide show
  1. package/bin/cdx.js +55 -79
  2. package/package.json +1 -1
package/bin/cdx.js CHANGED
@@ -153,6 +153,14 @@ function getNewestHistorySessionIdSince(previousId, verbose) {
153
153
 
154
154
  function runCodex(args, cwd, verbose) {
155
155
  logVerbose(`Running codex ${args.join(" ")}`.trim(), verbose);
156
+ if (process.stdin.isTTY) {
157
+ try {
158
+ process.stdin.setRawMode(false);
159
+ } catch {
160
+ // ignore if not supported
161
+ }
162
+ process.stdin.pause();
163
+ }
156
164
  const result = spawnSync("codex", args, { stdio: "inherit", cwd });
157
165
  if (result.error) {
158
166
  if (result.error.code === "ENOENT" && process.platform === "win32") {
@@ -167,8 +175,7 @@ function runCodex(args, cwd, verbose) {
167
175
  cwd
168
176
  });
169
177
  if (!psResult.error) {
170
- if (psResult.status !== 0) process.exit(psResult.status ?? 1);
171
- return;
178
+ return { status: psResult.status ?? 0 };
172
179
  }
173
180
  }
174
181
  console.error(
@@ -176,14 +183,18 @@ function runCodex(args, cwd, verbose) {
176
183
  );
177
184
  process.exit(1);
178
185
  }
179
- if (result.status !== 0) process.exit(result.status ?? 1);
186
+ return { status: result.status ?? 0 };
180
187
  }
181
188
 
182
- function printSessionList(entries) {
183
- console.log("0: new");
184
- entries.forEach((entry, index) => {
185
- console.log(`${index + 1}: ${entry.label} (${entry.uuid})`);
186
- });
189
+ function suggestByNumber(input, choices) {
190
+ const term = (input || "").trim();
191
+ if (!term) return choices;
192
+ if (/^\d+$/.test(term)) {
193
+ const number = Number.parseInt(term, 10);
194
+ return choices.filter((choice) => choice.number === number);
195
+ }
196
+ const lower = term.toLowerCase();
197
+ return choices.filter((choice) => choice.title.toLowerCase().includes(lower));
187
198
  }
188
199
 
189
200
  async function selectSession(entries) {
@@ -191,41 +202,21 @@ async function selectSession(entries) {
191
202
  return { type: "new" };
192
203
  }
193
204
 
194
- printSessionList(entries);
195
- while (true) {
196
- const numberInput = await prompts({
197
- type: "text",
198
- name: "value",
199
- message: "Select by number (Enter for list selection)",
200
- validate: (value) => {
201
- if (!value || !value.trim()) return true;
202
- if (!/^\d+$/.test(value.trim())) return "Enter a number";
203
- const index = Number.parseInt(value.trim(), 10);
204
- if (index < 0 || index > entries.length) return "Out of range";
205
- return true;
206
- }
207
- });
208
-
209
- if (!numberInput.value && numberInput.value !== "0") break;
210
- const index = Number.parseInt(String(numberInput.value).trim(), 10);
211
- if (Number.isNaN(index)) break;
212
- if (index === 0) return { type: "new" };
213
- return { type: "resume", entry: entries[index - 1] };
214
- }
215
-
216
205
  const choices = [
217
- { title: "new", value: { type: "new" } },
218
- ...entries.map((entry) => ({
219
- title: `${entry.label} (${entry.uuid})`,
220
- value: { type: "resume", entry }
206
+ { title: "0: new", value: { type: "new" }, number: 0 },
207
+ ...entries.map((entry, index) => ({
208
+ title: `${index + 1}: ${entry.label} (${entry.uuid})`,
209
+ value: { type: "resume", entry },
210
+ number: index + 1
221
211
  }))
222
212
  ];
223
213
 
224
214
  const response = await prompts({
225
- type: "select",
215
+ type: "autocomplete",
226
216
  name: "selection",
227
- message: "Select a session",
228
- choices
217
+ message: "Select a session (arrow keys or number+Enter)",
218
+ choices,
219
+ suggest: suggestByNumber
229
220
  });
230
221
 
231
222
  return response.selection;
@@ -269,7 +260,7 @@ async function runDefault(startDir, options) {
269
260
  const label = sanitizeLabel(labelInput);
270
261
  const previousHistoryId = getLastHistorySessionId(options.verbose);
271
262
  const previousSession = getLatestSessionSnapshot(options.verbose);
272
- runCodex([], workDir, options.verbose);
263
+ const codexResult = runCodex([], workDir, options.verbose);
273
264
  const latestSession = getLatestSessionSnapshot(options.verbose);
274
265
  let newId = null;
275
266
  if (
@@ -285,14 +276,27 @@ async function runDefault(startDir, options) {
285
276
  }
286
277
  if (!newId) {
287
278
  console.error("Could not determine new session UUID; not updating .cdx.");
279
+ if (codexResult && codexResult.status !== 0) {
280
+ process.exit(codexResult.status);
281
+ }
288
282
  return;
289
283
  }
290
284
  appendEntry(cdxPath, { uuid: newId, label }, options.verbose);
285
+ if (codexResult && codexResult.status !== 0) {
286
+ process.exit(codexResult.status);
287
+ }
291
288
  return;
292
289
  }
293
290
 
294
291
  if (selection.type === "resume") {
295
- runCodex(["resume", selection.entry.uuid], workDir, options.verbose);
292
+ const codexResult = runCodex(
293
+ ["resume", selection.entry.uuid],
294
+ workDir,
295
+ options.verbose
296
+ );
297
+ if (codexResult && codexResult.status !== 0) {
298
+ process.exit(codexResult.status);
299
+ }
296
300
  }
297
301
  }
298
302
 
@@ -310,48 +314,20 @@ async function runRemove(startDir, verbose) {
310
314
  }
311
315
 
312
316
  console.log(`.cdx: ${targetPath}`);
313
- entries.forEach((entry, index) => {
314
- console.log(`${index + 1}: ${entry.label} (${entry.uuid})`);
317
+ const response = await prompts({
318
+ type: "autocomplete",
319
+ name: "selection",
320
+ message: "Select a session to remove (arrow keys or number+Enter)",
321
+ choices: entries.map((entry, index) => ({
322
+ title: `${index + 1}: ${entry.label} (${entry.uuid})`,
323
+ value: entry.uuid,
324
+ number: index + 1
325
+ })),
326
+ suggest: suggestByNumber
315
327
  });
316
328
 
317
- let selectedUuid = null;
318
- while (true) {
319
- const numberInput = await prompts({
320
- type: "text",
321
- name: "value",
322
- message: "Select by number (Enter for list selection)",
323
- validate: (value) => {
324
- if (!value || !value.trim()) return true;
325
- if (!/^\d+$/.test(value.trim())) return "Enter a number";
326
- const index = Number.parseInt(value.trim(), 10);
327
- if (index < 1 || index > entries.length) return "Out of range";
328
- return true;
329
- }
330
- });
331
-
332
- if (!numberInput.value) break;
333
- const index = Number.parseInt(String(numberInput.value).trim(), 10);
334
- if (!Number.isNaN(index)) {
335
- selectedUuid = entries[index - 1].uuid;
336
- }
337
- break;
338
- }
339
-
340
- if (!selectedUuid) {
341
- const response = await prompts({
342
- type: "select",
343
- name: "selection",
344
- message: "Select a session to remove",
345
- choices: entries.map((entry) => ({
346
- title: `${entry.label} (${entry.uuid})`,
347
- value: entry.uuid
348
- }))
349
- });
350
- if (!response.selection) return;
351
- selectedUuid = response.selection;
352
- }
353
-
354
- const remaining = entries.filter((entry) => entry.uuid !== selectedUuid);
329
+ if (!response.selection) return;
330
+ const remaining = entries.filter((entry) => entry.uuid !== response.selection);
355
331
  writeEntries(targetPath, remaining, verbose);
356
332
  }
357
333
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fclef819/cdx",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Codex session wrapper",
5
5
  "keywords": [
6
6
  "codex",