bertrand 0.21.0 → 0.22.1

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.
@@ -29,6 +29,13 @@
29
29
  "when": 1781474706585,
30
30
  "tag": "0003_categories_rename",
31
31
  "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "6",
36
+ "when": 1781546596070,
37
+ "tag": "0004_dapper_apocalypse",
38
+ "breakpoints": true
32
39
  }
33
40
  ]
34
41
  }
@@ -760,6 +760,7 @@ var sessions = sqliteTable("sessions", {
760
760
  enum: ["active", "waiting", "paused", "archived"]
761
761
  }).notNull().default("paused"),
762
762
  summary: text("summary"),
763
+ rating: integer("rating"),
763
764
  pid: integer("pid"),
764
765
  startedAt: text("started_at").notNull().default(sql`(datetime('now'))`),
765
766
  endedAt: text("ended_at"),
@@ -899,6 +900,9 @@ function getAllSessions(opts) {
899
900
  function updateSessionStatus(id, status) {
900
901
  return getDb().update(sessions).set({ status, updatedAt: sql2`(datetime('now'))` }).where(eq(sessions.id, id)).returning().get();
901
902
  }
903
+ function setSessionRating(id, rating) {
904
+ return getDb().update(sessions).set({ rating, updatedAt: sql2`(datetime('now'))` }).where(eq(sessions.id, id)).returning().get();
905
+ }
902
906
 
903
907
  // src/lib/session-archive.ts
904
908
  var ACTIVE_STATUSES = ["active", "waiting"];
@@ -960,6 +964,7 @@ function formatAgo(isoOrDate) {
960
964
  }
961
965
 
962
966
  // src/lib/parse-session-name.ts
967
+ var SEGMENT_PATTERN = /^[a-z0-9][a-z0-9._-]*$/i;
963
968
  function parseSessionName(input) {
964
969
  const trimmed = input.trim().replace(/^\/+|\/+$/g, "");
965
970
  if (!trimmed) {
@@ -970,12 +975,12 @@ function parseSessionName(input) {
970
975
  throw new Error(`Session name must include at least one category: "category/session" (got "${trimmed}")`);
971
976
  }
972
977
  for (const segment of segments) {
973
- if (!/^[a-z0-9][a-z0-9._-]*$/i.test(segment)) {
978
+ if (!SEGMENT_PATTERN.test(segment)) {
974
979
  throw new Error(`Invalid segment "${segment}": must start with alphanumeric and contain only letters, digits, dots, underscores, or dashes`);
975
980
  }
976
981
  }
977
- const slug = segments[segments.length - 1];
978
- const categoryPath = segments.slice(0, -1).join("/");
982
+ const categoryPath = segments[0];
983
+ const slug = segments.slice(1).join("/");
979
984
  return { categoryPath, slug };
980
985
  }
981
986
 
@@ -1333,10 +1338,19 @@ function Exit({ sessionId, onAction }) {
1333
1338
  const [cursor, setCursor] = useState4(0);
1334
1339
  const session = getSession(sessionId);
1335
1340
  const conversations2 = session ? getConversationsBySession(session.id) : [];
1341
+ const [rating, setRating] = useState4(session?.rating ?? null);
1342
+ const persistRating = (next) => {
1343
+ setRating(next);
1344
+ setSessionRating(sessionId, next);
1345
+ };
1336
1346
  useInput3((e) => {
1337
1347
  if (e.key === "c" && e.ctrl)
1338
1348
  exit();
1339
- if (e.key === "up" || e.key === "k") {
1349
+ if (e.key >= "1" && e.key <= "5") {
1350
+ persistRating(Number(e.key));
1351
+ } else if (e.key === "0" || e.key === "backspace") {
1352
+ persistRating(null);
1353
+ } else if (e.key === "up" || e.key === "k") {
1340
1354
  setCursor((c) => Math.max(0, c - 1));
1341
1355
  } else if (e.key === "down" || e.key === "j") {
1342
1356
  setCursor((c) => Math.min(OPTIONS.length - 1, c + 1));
@@ -1400,6 +1414,29 @@ function Exit({ sessionId, onAction }) {
1400
1414
  }, undefined, true, undefined, this)
1401
1415
  ]
1402
1416
  }, undefined, true, undefined, this),
1417
+ /* @__PURE__ */ jsxDEV7(Box6, {
1418
+ flexDirection: "column",
1419
+ children: [
1420
+ /* @__PURE__ */ jsxDEV7(Text7, {
1421
+ dim: true,
1422
+ children: "How effective was this session?"
1423
+ }, undefined, false, undefined, this),
1424
+ /* @__PURE__ */ jsxDEV7(Box6, {
1425
+ flexDirection: "row",
1426
+ gap: 1,
1427
+ children: [
1428
+ /* @__PURE__ */ jsxDEV7(Text7, {
1429
+ color: "#FFD580",
1430
+ children: [1, 2, 3, 4, 5].map((n) => rating !== null && n <= rating ? "\u2605" : "\u2606").join(" ")
1431
+ }, undefined, false, undefined, this),
1432
+ /* @__PURE__ */ jsxDEV7(Text7, {
1433
+ dim: true,
1434
+ children: rating !== null ? `${rating} star${rating === 1 ? "" : "s"}` : "unrated"
1435
+ }, undefined, false, undefined, this)
1436
+ ]
1437
+ }, undefined, true, undefined, this)
1438
+ ]
1439
+ }, undefined, true, undefined, this),
1403
1440
  /* @__PURE__ */ jsxDEV7(Box6, {
1404
1441
  flexDirection: "column",
1405
1442
  children: OPTIONS.map((opt, i) => /* @__PURE__ */ jsxDEV7(Box6, {
@@ -1423,7 +1460,7 @@ function Exit({ sessionId, onAction }) {
1423
1460
  /* @__PURE__ */ jsxDEV7(Box6, {
1424
1461
  children: /* @__PURE__ */ jsxDEV7(Text7, {
1425
1462
  dim: true,
1426
- children: "\u2191\u2193 navigate \xB7 enter select \xB7 q save & quit"
1463
+ children: "1-5 rate \xB7 0/backspace clear \xB7 \u2191\u2193 navigate \xB7 enter select \xB7 q save & quit"
1427
1464
  }, undefined, false, undefined, this)
1428
1465
  }, undefined, false, undefined, this)
1429
1466
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bertrand",
3
- "version": "0.21.0",
3
+ "version": "0.22.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },