@tekmidian/pai 0.51.0 → 0.52.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.
@@ -1,7 +1,7 @@
1
1
  import { a as paiHomePath, o as resolvePaiFile, r as migratePaiFile } from "./pai-home-ChAOupZc.mjs";
2
2
  import { _ as warn, c as ok, g as smartDecodeDir, i as err, n as dim, o as header, u as renderTable } from "./utils-CJymHkYm.mjs";
3
3
  import { C as readWorkersSection } from "./config-DYXARgk8.mjs";
4
- import { a as switchToSession, n as fetchLiveSessions } from "./aibroker-client-CDIXmq-e.mjs";
4
+ import { a as switchToSession, n as fetchLiveSessions } from "./aibroker-client-DzkTpVjx.mjs";
5
5
  import { closeSync, copyFileSync, createReadStream, existsSync, linkSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, renameSync, statSync, writeFileSync } from "node:fs";
6
6
  import { homedir } from "node:os";
7
7
  import { basename, join } from "node:path";
@@ -1379,14 +1379,33 @@ function resolveSessionDir(session) {
1379
1379
  tried
1380
1380
  };
1381
1381
  }
1382
- function launchSession(session, allSessions, dryRun) {
1383
- let resumableUuid;
1384
- if (session.resumable) resumableUuid = session.uuid;
1385
- else if (session.encodedDir) {
1386
- const sameProject = allSessions.filter((s) => s.encodedDir === session.encodedDir && s.resumable);
1387
- sameProject.sort((a, b) => b.mtime - a.mtime);
1388
- if (sameProject.length > 0) resumableUuid = sameProject[0].uuid;
1389
- }
1382
+ /**
1383
+ * Which transcript a launch resumes, if any.
1384
+ *
1385
+ * `pai <name>` used to resume the newest transcript for the name whenever one
1386
+ * existed. That is the wrong default twice over. A wanted resume pins the
1387
+ * engine to claude, so with a worker provider active the same name opened on
1388
+ * different engines depending on whether an old transcript happened to be on
1389
+ * disk. And a resumed transcript arrives with its whole context window, so a
1390
+ * long-dead session came back already at the autocompact threshold and spent
1391
+ * its first turn compacting - while the handover it was resumed FOR lives in
1392
+ * TODO.md and is read by the `go` prompt of a fresh session anyway.
1393
+ *
1394
+ * So a name means the directory: fresh, on the configured route, exactly what
1395
+ * `cd <dir> && pai worker run` does. Resume is an explicit ask - a UUID query,
1396
+ * `--resume`, or `pai resume <name>` - and only then does the transcript hunt
1397
+ * below run.
1398
+ */
1399
+ function resumeTargetFor(session, allSessions, resume) {
1400
+ if (!resume) return void 0;
1401
+ if (session.resumable) return session.uuid;
1402
+ if (!session.encodedDir) return void 0;
1403
+ const sameProject = allSessions.filter((s) => s.encodedDir === session.encodedDir && s.resumable);
1404
+ sameProject.sort((a, b) => b.mtime - a.mtime);
1405
+ return sameProject[0]?.uuid;
1406
+ }
1407
+ function launchSession(session, allSessions, dryRun, resume) {
1408
+ const resumableUuid = resumeTargetFor(session, allSessions, resume);
1390
1409
  const { dir: projectDir } = resolveSessionDir(session);
1391
1410
  if (projectDir === void 0) return false;
1392
1411
  launchInDir(projectDir, session.friendlyName ?? (basename(projectDir) || session.shortId), {
@@ -1474,11 +1493,11 @@ async function doSwitch(entry, dryRun) {
1474
1493
  * Returns false only when there is genuinely nothing to open, which is the one
1475
1494
  * case where falling through to a history search is the right thing to do.
1476
1495
  */
1477
- async function openMatch(entry, allSessions, dryRun) {
1496
+ async function openMatch(entry, allSessions, dryRun, resume) {
1478
1497
  if (entry.status === "live") {
1479
1498
  if (await doSwitch(entry, dryRun)) return true;
1480
1499
  }
1481
- if (entry.diskSession && launchSession(entry.diskSession, allSessions, dryRun)) return true;
1500
+ if (entry.diskSession && launchSession(entry.diskSession, allSessions, dryRun, resume)) return true;
1482
1501
  if (entry.project && existsSync(entry.project)) {
1483
1502
  launchInDir(entry.project, entry.name, { dryRun });
1484
1503
  return true;
@@ -1522,7 +1541,7 @@ async function cmdMain(db, query, pickN, opts) {
1522
1541
  if (/^[0-9a-f-]{8,36}$/i.test(query)) {
1523
1542
  const byUuid = allSessions.filter((s) => s.uuid.startsWith(query.toLowerCase()));
1524
1543
  if (byUuid.length === 1) {
1525
- launchSession(byUuid[0], allSessions, opts.dryRun ?? false);
1544
+ launchSession(byUuid[0], allSessions, opts.dryRun ?? false, true);
1526
1545
  return;
1527
1546
  }
1528
1547
  if (byUuid.length > 1) {
@@ -1543,7 +1562,7 @@ async function cmdMain(db, query, pickN, opts) {
1543
1562
  const nameIncludes = (e, q) => e.name.toLowerCase().includes(q) || e.slug !== void 0 && e.slug.toLowerCase().includes(qSlug);
1544
1563
  const newestFirst = (a, b) => b.lastActivity - a.lastActivity;
1545
1564
  const exactMatches = deduped.filter((e) => nameMatches(e, qNorm)).sort(newestFirst);
1546
- for (const match of exactMatches) if (await openMatch(match, allSessions, opts.dryRun ?? false)) return;
1565
+ for (const match of exactMatches) if (await openMatch(match, allSessions, opts.dryRun ?? false, opts.resume ?? false)) return;
1547
1566
  let partialMatches = deduped.filter((e) => nameIncludes(e, qNorm));
1548
1567
  if (partialMatches.length === 0) {
1549
1568
  const qWords = qNorm.split(/\s+/).filter(Boolean);
@@ -1554,7 +1573,7 @@ async function cmdMain(db, query, pickN, opts) {
1554
1573
  }
1555
1574
  partialMatches.sort(newestFirst);
1556
1575
  if (partialMatches.length === 1) {
1557
- if (await openMatch(partialMatches[0], allSessions, opts.dryRun ?? false)) return;
1576
+ if (await openMatch(partialMatches[0], allSessions, opts.dryRun ?? false, opts.resume ?? false)) return;
1558
1577
  }
1559
1578
  if (partialMatches.length > 1) {
1560
1579
  console.log("\n" + header(`Sessions matching "${query}"`) + "\n");
@@ -1579,7 +1598,7 @@ async function cmdMain(db, query, pickN, opts) {
1579
1598
  console.log(renderTable(headers, rows));
1580
1599
  console.log();
1581
1600
  const pickMatch = async (match) => {
1582
- if (await openMatch(match, allSessions, opts.dryRun ?? false)) return;
1601
+ if (await openMatch(match, allSessions, opts.dryRun ?? false, opts.resume ?? false)) return;
1583
1602
  console.error(err(`Nothing to open for "${match.name}" — no live session, no transcript, no directory.`));
1584
1603
  process.exitCode = 1;
1585
1604
  };
@@ -1661,7 +1680,7 @@ async function cmdMain(db, query, pickN, opts) {
1661
1680
  process.exitCode = 1;
1662
1681
  return;
1663
1682
  }
1664
- launchSession(session, allSessions, opts.dryRun ?? false);
1683
+ launchSession(session, allSessions, opts.dryRun ?? false, true);
1665
1684
  };
1666
1685
  if (pickN !== void 0) {
1667
1686
  const idx = pickN - 1;
@@ -1682,5 +1701,5 @@ async function cmdMain(db, query, pickN, opts) {
1682
1701
  }
1683
1702
 
1684
1703
  //#endregion
1685
- export { renderDedupedSessions as a, probeResume as c, fmtAge as d, migrateSessionScanCache as f, scanSessions as h, normalizeName as i, restoreTopLevel as l, scanCacheFilePath as m, resolveSessionDir as n, hasConversation as o, resolveSessionByNameOrId as p, buildDeduped as r, launchInDir as s, cmdMain as t, printExitDir as u };
1686
- //# sourceMappingURL=main-resolver-BmZPCmgj.mjs.map
1704
+ export { normalizeName as a, launchInDir as c, printExitDir as d, fmtAge as f, scanSessions as g, scanCacheFilePath as h, buildDeduped as i, probeResume as l, resolveSessionByNameOrId as m, resolveSessionDir as n, renderDedupedSessions as o, migrateSessionScanCache as p, resumeTargetFor as r, hasConversation as s, cmdMain as t, restoreTopLevel as u };
1705
+ //# sourceMappingURL=main-resolver-Dv-oC46Z.mjs.map