@ai-matrx/coding-sessions 0.2.0 → 0.3.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/engine/index.cjs +57 -11
  3. package/dist/engine/index.cjs.map +1 -1
  4. package/dist/engine/index.d.cts +1 -1
  5. package/dist/engine/index.d.ts +1 -1
  6. package/dist/engine/index.js +57 -11
  7. package/dist/engine/index.js.map +1 -1
  8. package/dist/{index-29t7n472.d.cts → index-Bbe11HoB.d.cts} +30 -3
  9. package/dist/{index-29t7n472.d.ts → index-Bbe11HoB.d.ts} +30 -3
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +12 -3
  12. package/dist/index.d.ts +12 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/react/index.cjs +34 -5
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.d.cts +15 -1
  17. package/dist/react/index.d.ts +15 -1
  18. package/dist/react/index.js +34 -5
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/server/index.cjs +47 -10
  21. package/dist/server/index.cjs.map +1 -1
  22. package/dist/server/index.d.cts +2 -2
  23. package/dist/server/index.d.ts +2 -2
  24. package/dist/server/index.js +47 -10
  25. package/dist/server/index.js.map +1 -1
  26. package/dist/sessions/index.cjs +26 -1
  27. package/dist/sessions/index.cjs.map +1 -1
  28. package/dist/sessions/index.d.cts +13 -5
  29. package/dist/sessions/index.d.ts +13 -5
  30. package/dist/sessions/index.js +26 -1
  31. package/dist/sessions/index.js.map +1 -1
  32. package/dist/{titles-eCnA5sY7.d.cts → titles-DjxUb0ji.d.cts} +8 -1
  33. package/dist/{titles-eCnA5sY7.d.ts → titles-DjxUb0ji.d.ts} +8 -1
  34. package/dist/ui/assets/index-BqzTnRFe.css +2 -0
  35. package/dist/ui/assets/{index-SuRr0-D2.js → index-U98AY8r-.js} +17 -17
  36. package/dist/ui/index.html +2 -2
  37. package/package.json +4 -4
  38. package/dist/ui/assets/index-BqpVx_My.css +0 -2
@@ -140,7 +140,7 @@ interface DiscoveredSession {
140
140
  */
141
141
  title: string;
142
142
  /** Where `title` came from (`TITLE_PRECEDENCE`). */
143
- titleSource?: TitleSource | undefined;
143
+ titleSource?: TitleSource | "unknown" | undefined;
144
144
  /** The app's title is still on its way (hints not loaded yet); `title` is the transcript's for now. */
145
145
  titlePending?: boolean | undefined;
146
146
  /** Archived in the app (hidden by default, like Code › Chats). */
@@ -263,6 +263,11 @@ type TranscriptItem = {
263
263
  id: string;
264
264
  text: string;
265
265
  };
266
+ interface TitleStatus {
267
+ owner: boolean;
268
+ pending: boolean;
269
+ problem: string | null;
270
+ }
266
271
  /** Everything the engine pushes to a listener. */
267
272
  type CodingEvent = {
268
273
  type: "session";
@@ -432,6 +437,10 @@ interface CodingSessionsApi {
432
437
  discoverSessions(options?: {
433
438
  limit?: number;
434
439
  }): Promise<DiscoveredSession[]>;
440
+ /** Where the apps' own titles stand: an owner supplies them (`owner`), still loading, or failing (`problem`, shown with Retry). */
441
+ titleStatus(): Promise<TitleStatus>;
442
+ /** Ask the owner of the apps' titles again (the Retry). */
443
+ retryTitles(): Promise<void>;
435
444
  recentFolders(): Promise<RecentFolder[]>;
436
445
  listSessions(): Promise<CodingSession[]>;
437
446
  listRuns(sessionId: string): Promise<RunRecord[]>;
@@ -556,6 +565,8 @@ interface CodingSessionsState {
556
565
  preferences: Record<string, ChatPreference>;
557
566
  /** How many of "Your other chats" to list (grows with "Show more"). */
558
567
  discoveredLimit: number;
568
+ /** Where the apps' own titles stand (null until first asked; an engine without the method says nothing). */
569
+ titles: TitleStatus | null;
559
570
  }
560
571
  /** A run that just ended — for the tab badge and the desktop notification. */
561
572
  interface RunFinished {
@@ -618,6 +629,9 @@ declare class CodingSessionsClient {
618
629
  private load;
619
630
  refreshProviders: () => Promise<void>;
620
631
  refreshDiscovered: () => Promise<void>;
632
+ refreshTitleStatus: () => Promise<void>;
633
+ /** The Retry beside "app titles unavailable". */
634
+ retryTitles: () => Promise<void>;
621
635
  /** List more of "Your other chats". */
622
636
  showMoreDiscovered: () => Promise<void>;
623
637
  refreshPreferences: () => Promise<void>;
@@ -140,7 +140,7 @@ interface DiscoveredSession {
140
140
  */
141
141
  title: string;
142
142
  /** Where `title` came from (`TITLE_PRECEDENCE`). */
143
- titleSource?: TitleSource | undefined;
143
+ titleSource?: TitleSource | "unknown" | undefined;
144
144
  /** The app's title is still on its way (hints not loaded yet); `title` is the transcript's for now. */
145
145
  titlePending?: boolean | undefined;
146
146
  /** Archived in the app (hidden by default, like Code › Chats). */
@@ -263,6 +263,11 @@ type TranscriptItem = {
263
263
  id: string;
264
264
  text: string;
265
265
  };
266
+ interface TitleStatus {
267
+ owner: boolean;
268
+ pending: boolean;
269
+ problem: string | null;
270
+ }
266
271
  /** Everything the engine pushes to a listener. */
267
272
  type CodingEvent = {
268
273
  type: "session";
@@ -432,6 +437,10 @@ interface CodingSessionsApi {
432
437
  discoverSessions(options?: {
433
438
  limit?: number;
434
439
  }): Promise<DiscoveredSession[]>;
440
+ /** Where the apps' own titles stand: an owner supplies them (`owner`), still loading, or failing (`problem`, shown with Retry). */
441
+ titleStatus(): Promise<TitleStatus>;
442
+ /** Ask the owner of the apps' titles again (the Retry). */
443
+ retryTitles(): Promise<void>;
435
444
  recentFolders(): Promise<RecentFolder[]>;
436
445
  listSessions(): Promise<CodingSession[]>;
437
446
  listRuns(sessionId: string): Promise<RunRecord[]>;
@@ -556,6 +565,8 @@ interface CodingSessionsState {
556
565
  preferences: Record<string, ChatPreference>;
557
566
  /** How many of "Your other chats" to list (grows with "Show more"). */
558
567
  discoveredLimit: number;
568
+ /** Where the apps' own titles stand (null until first asked; an engine without the method says nothing). */
569
+ titles: TitleStatus | null;
559
570
  }
560
571
  /** A run that just ended — for the tab badge and the desktop notification. */
561
572
  interface RunFinished {
@@ -618,6 +629,9 @@ declare class CodingSessionsClient {
618
629
  private load;
619
630
  refreshProviders: () => Promise<void>;
620
631
  refreshDiscovered: () => Promise<void>;
632
+ refreshTitleStatus: () => Promise<void>;
633
+ /** The Retry beside "app titles unavailable". */
634
+ retryTitles: () => Promise<void>;
621
635
  /** List more of "Your other chats". */
622
636
  showMoreDiscovered: () => Promise<void>;
623
637
  refreshPreferences: () => Promise<void>;
@@ -1271,6 +1271,14 @@ function ChooseAgentDialog(props) {
1271
1271
  ] }) });
1272
1272
  }
1273
1273
 
1274
+ // src/sessions/titles.ts
1275
+ var DISPLAY_MAX = 100;
1276
+ var LEADING_NOISE = /^(?:\s*(?:\d{1,3}[.)]|[-*•]|#{1,6}|>)\s+|\s*["“'‘`]+)+/;
1277
+ function displayTitle(title, max = DISPLAY_MAX) {
1278
+ const stripped = title.replace(LEADING_NOISE, "").replace(/["”'’`]+$/, "").trim() || title.trim();
1279
+ return stripped.length > max ? `${stripped.slice(0, max - 1).trimEnd()}\u2026` : stripped;
1280
+ }
1281
+
1274
1282
  // src/react/sidebar.tsx
1275
1283
  import { useCallback, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2, useState as useState5 } from "react";
1276
1284
  import {
@@ -1384,7 +1392,7 @@ function Row(props) {
1384
1392
  /* @__PURE__ */ jsx6("span", { className: "pointer-events-none mt-0.5 shrink-0", children: props.live ? /* @__PURE__ */ jsx6(SpinnerIcon, { size: 16, className: "text-primary" }) : /* @__PURE__ */ jsx6(ProviderMark, { provider: entry.provider, size: 16 }) }),
1385
1393
  /* @__PURE__ */ jsxs6("span", { className: "cs-row__body", children: [
1386
1394
  renaming ? /* @__PURE__ */ jsx6("span", { className: "pointer-events-auto relative z-10 block", children: /* @__PURE__ */ jsx6(RenameInput, { initial: entry.title, onDone: rename }) }) : /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-1", children: [
1387
- /* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: entry.title }),
1395
+ /* @__PURE__ */ jsx6("span", { className: "min-w-0 truncate text-[13px] font-medium leading-5", children: displayTitle(entry.title) }),
1388
1396
  entry.pinned ? /* @__PURE__ */ jsx6(PinIcon, { size: 11, className: "shrink-0 text-muted-foreground", "aria-label": "Pinned" }) : null
1389
1397
  ] }),
1390
1398
  /* @__PURE__ */ jsx6("span", { className: "block truncate text-[11.5px] leading-4 text-muted-foreground", children: props.meta }),
@@ -1486,7 +1494,8 @@ function Sidebar(props) {
1486
1494
  const [search, searchMore] = useContentSearch(query);
1487
1495
  const [groupMode, setGroupMode] = useState5(() => readLocal("coding-sessions.group", ["date", "folder"], "date"));
1488
1496
  const [showHidden, setShowHidden] = useState5(false);
1489
- const titlesUpdating = state.discovered.data.some((d) => d.titlePending === true);
1497
+ const titlesProblem = state.titles?.problem ?? null;
1498
+ const titlesUpdating = !titlesProblem && state.discovered.data.some((d) => d.titlePending === true);
1490
1499
  const [takingOver, setTakingOver] = useState5(null);
1491
1500
  const [takeoverError, setTakeoverError] = useState5(null);
1492
1501
  const prefs = state.preferences;
@@ -1660,7 +1669,12 @@ function Sidebar(props) {
1660
1669
  ] }),
1661
1670
  children: [
1662
1671
  "Your other chats",
1663
- titlesUpdating ? /* @__PURE__ */ jsx6("span", { className: "ml-1 font-normal normal-case text-muted-foreground", "data-cs-titles": "updating", children: "\xB7 titles updating" }) : null
1672
+ titlesUpdating ? /* @__PURE__ */ jsx6("span", { className: "ml-1 font-normal normal-case text-muted-foreground", "data-cs-titles": "updating", children: "\xB7 titles updating" }) : null,
1673
+ titlesProblem ? /* @__PURE__ */ jsxs6("span", { className: "ml-1 font-normal normal-case text-destructive", "data-cs-titles": "unavailable", title: titlesProblem, children: [
1674
+ "\xB7 app titles unavailable \u2014",
1675
+ " ",
1676
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cs-link", onClick: () => void client.retryTitles(), children: "Retry" })
1677
+ ] }) : null
1664
1678
  ]
1665
1679
  }
1666
1680
  ),
@@ -2130,7 +2144,8 @@ var CodingSessionsClient = class {
2130
2144
  folders: loadable([]),
2131
2145
  runs: {},
2132
2146
  preferences: {},
2133
- discoveredLimit: DISCOVERED_PAGE
2147
+ discoveredLimit: DISCOVERED_PAGE,
2148
+ titles: null
2134
2149
  };
2135
2150
  transport.onStatus((connection) => {
2136
2151
  const wasOpen = this.state.connection.state === "open";
@@ -2199,7 +2214,21 @@ var CodingSessionsClient = class {
2199
2214
  }
2200
2215
  }
2201
2216
  refreshProviders = () => this.load("providers", () => this.transport.call("providers"));
2202
- refreshDiscovered = () => this.load("discovered", () => this.transport.call("discoverSessions", { limit: this.state.discoveredLimit }));
2217
+ refreshDiscovered = async () => {
2218
+ void this.refreshTitleStatus();
2219
+ await this.load("discovered", () => this.transport.call("discoverSessions", { limit: this.state.discoveredLimit }));
2220
+ };
2221
+ refreshTitleStatus = async () => {
2222
+ try {
2223
+ this.set({ titles: await this.transport.call("titleStatus") });
2224
+ } catch {
2225
+ }
2226
+ };
2227
+ /** The Retry beside "app titles unavailable". */
2228
+ retryTitles = async () => {
2229
+ await this.transport.call("retryTitles").catch(() => void 0);
2230
+ await this.refreshTitleStatus();
2231
+ };
2203
2232
  /** List more of "Your other chats". */
2204
2233
  showMoreDiscovered = async () => {
2205
2234
  this.set({ discoveredLimit: this.state.discoveredLimit + DISCOVERED_PAGE });