@principal-ai/subsystems-studio 0.20.2 → 0.20.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.
@@ -10751,13 +10751,7 @@ function trimSessionEventRows(events) {
10751
10751
  }));
10752
10752
  }
10753
10753
 
10754
- // src/bun/session-pipeline.ts
10755
- import { statSync as statSync3 } from "fs";
10756
-
10757
10754
  // src/bun/maintain-sessions.ts
10758
- function isMaintainSessionTitle(title) {
10759
- return /^Maintain\s*[\u2014\u2013-]/.test(title.trim());
10760
- }
10761
10755
  var MAINTAIN_AGENT_NAMES = new Set([
10762
10756
  "construct-verifier",
10763
10757
  "package-module-verifier",
@@ -10771,16 +10765,6 @@ var MAINTAIN_AGENT_NAMES = new Set([
10771
10765
  "topology-gap-filler",
10772
10766
  "boundary-gap-filler"
10773
10767
  ]);
10774
- function isMaintainAgentName(agent) {
10775
- return !!agent && MAINTAIN_AGENT_NAMES.has(agent);
10776
- }
10777
- function isMaintainSession(opts) {
10778
- if (isMaintainAgentName(opts.agent))
10779
- return true;
10780
- if (opts.title && isMaintainSessionTitle(opts.title))
10781
- return true;
10782
- return false;
10783
- }
10784
10768
 
10785
10769
  // src/bun/opencode-v2-messages.ts
10786
10770
  import { Database } from "bun:sqlite";
@@ -11580,327 +11564,6 @@ function firstUserPromptText(db, aggregateId) {
11580
11564
  return part.text.replace(/\s+/g, " ").trim();
11581
11565
  }
11582
11566
  var indexCache = new Map;
11583
- var INDEX_CACHE_MAX = 4;
11584
- function dbFingerprint(dbPath) {
11585
- const stats = [];
11586
- for (const p of [dbPath, `${dbPath}-wal`]) {
11587
- try {
11588
- const st = statSync3(p);
11589
- stats.push({ mtimeMs: st.mtimeMs, size: st.size });
11590
- } catch {}
11591
- }
11592
- return stats.length > 0 ? stats.map((s) => `${s.mtimeMs}:${s.size}`).join("|") : "missing";
11593
- }
11594
- async function buildSessionIndex({ days }) {
11595
- const dayCount = Math.max(1, Math.floor(days ?? 7));
11596
- const cutoff = Date.now() - dayCount * 86400000;
11597
- const dbPath = openCodeDBPath2();
11598
- const cacheKey = `${dayCount}|${dbFingerprint(dbPath)}`;
11599
- const cached = indexCache.get(cacheKey);
11600
- if (cached)
11601
- return cached;
11602
- let result;
11603
- let db = null;
11604
- try {
11605
- const { Database: Database2 } = await import("bun:sqlite");
11606
- db = new Database2(dbPath, { readonly: true });
11607
- const firstEvents = db.prepare(`SELECT
11608
- e.aggregate_id,
11609
- e.data
11610
- FROM event e
11611
- WHERE e.seq IN (SELECT MIN(seq) FROM event GROUP BY aggregate_id)
11612
- ORDER BY e.seq DESC`).all();
11613
- const idToSummary = new Map;
11614
- let hasOlder = false;
11615
- for (const row of firstEvents) {
11616
- let title = row.aggregate_id.slice(0, 12);
11617
- let slug = "";
11618
- let createdAtStr = "";
11619
- let agentFromInfo;
11620
- const durationMs = 0;
11621
- try {
11622
- const parsed = JSON.parse(row.data);
11623
- const info = parsed["info"];
11624
- const rawTitle = info?.["title"];
11625
- if (typeof rawTitle === "string") {
11626
- title = rawTitle;
11627
- }
11628
- const rawSlug = info?.["slug"];
11629
- if (typeof rawSlug === "string") {
11630
- slug = rawSlug;
11631
- }
11632
- const rawAgent = info?.["agent"];
11633
- if (typeof rawAgent === "string") {
11634
- agentFromInfo = rawAgent;
11635
- }
11636
- const rawTime = info?.["time"];
11637
- const rawCreated = rawTime?.["created"];
11638
- if (typeof rawCreated === "number") {
11639
- createdAtStr = new Date(rawCreated).toISOString();
11640
- }
11641
- } catch {}
11642
- if (isMaintainSession({ title, agent: agentFromInfo }))
11643
- continue;
11644
- const createdMs = createdAtStr ? new Date(createdAtStr).getTime() : 0;
11645
- if (!createdMs)
11646
- continue;
11647
- if (createdMs <= cutoff) {
11648
- hasOlder = true;
11649
- continue;
11650
- }
11651
- if (title.startsWith("New session")) {
11652
- const promptText = firstUserPromptText(db, row.aggregate_id);
11653
- if (promptText)
11654
- title = promptText;
11655
- }
11656
- idToSummary.set(row.aggregate_id, {
11657
- id: row.aggregate_id,
11658
- title,
11659
- slug,
11660
- createdAt: createdAtStr,
11661
- durationMs,
11662
- eventCount: 0,
11663
- isFinished: false,
11664
- models: undefined
11665
- });
11666
- }
11667
- const windowIds = Array.from(idToSummary.keys());
11668
- const windowIdsSql = windowIds.length > 0 ? `(${windowIds.map((id) => JSON.stringify(id)).join(",")})` : null;
11669
- const modelRows = windowIdsSql ? db.prepare(`SELECT
11670
- aggregate_id,
11671
- json_extract(data, '$.info.model.id') AS model_id
11672
- FROM event
11673
- WHERE aggregate_id IN ${windowIdsSql}
11674
- AND type IN ('session.created.1', 'session.updated.1')
11675
- AND json_extract(data, '$.info.model.id') IS NOT NULL
11676
- GROUP BY aggregate_id`).all() : [];
11677
- for (const m of modelRows) {
11678
- const summary = idToSummary.get(m.aggregate_id);
11679
- if (summary && m.model_id)
11680
- summary.models = [m.model_id];
11681
- }
11682
- const lastEventRows = windowIdsSql ? db.prepare(`SELECT
11683
- e.aggregate_id,
11684
- json_extract(e.data, '$.info.time.created') AS last_created
11685
- FROM event e
11686
- WHERE (e.aggregate_id, e.seq) IN (
11687
- SELECT aggregate_id, MAX(seq)
11688
- FROM event
11689
- WHERE aggregate_id IN ${windowIdsSql}
11690
- GROUP BY aggregate_id
11691
- )`).all() : [];
11692
- for (const row of lastEventRows) {
11693
- const summary = idToSummary.get(row.aggregate_id);
11694
- if (summary && typeof row.last_created === "number") {
11695
- summary.lastEventAt = new Date(row.last_created).toISOString();
11696
- }
11697
- }
11698
- const relations = windowIdsSql ? db.prepare(`SELECT
11699
- json_extract(data, '$.part.state.metadata.parentSessionId') AS parent_id,
11700
- json_extract(data, '$.part.state.metadata.sessionId') AS child_id,
11701
- json_extract(data, '$.part.state.status') AS status
11702
- FROM event
11703
- WHERE aggregate_id IN ${windowIdsSql}
11704
- AND seq IN (
11705
- SELECT MAX(seq)
11706
- FROM event
11707
- WHERE aggregate_id IN ${windowIdsSql}
11708
- AND type = 'message.part.updated.1'
11709
- AND json_extract(data, '$.part.tool') = 'task'
11710
- AND json_extract(data, '$.part.state.metadata.sessionId') IS NOT NULL
11711
- GROUP BY json_extract(data, '$.part.state.metadata.sessionId')
11712
- )`).all() : [];
11713
- const childIds = new Set;
11714
- const groups = [];
11715
- for (const rel of relations) {
11716
- if (!rel.parent_id || !rel.child_id)
11717
- continue;
11718
- const child = idToSummary.get(rel.child_id);
11719
- if (!child)
11720
- continue;
11721
- if (rel.status === "completed" || rel.status === "error") {
11722
- child.isFinished = true;
11723
- }
11724
- childIds.add(rel.child_id);
11725
- }
11726
- for (const summary of idToSummary.values()) {
11727
- if (childIds.has(summary.id))
11728
- continue;
11729
- const childList = [];
11730
- for (const rel of relations) {
11731
- if (rel.parent_id === summary.id) {
11732
- const child = idToSummary.get(rel.child_id);
11733
- if (child)
11734
- childList.push(child);
11735
- }
11736
- }
11737
- if (childList.length > 0) {
11738
- groups.push({ parent: { ...summary }, children: childList });
11739
- }
11740
- }
11741
- const standalone = [];
11742
- for (const summary of idToSummary.values()) {
11743
- if (childIds.has(summary.id))
11744
- continue;
11745
- if (!groups.some((g) => g.parent.id === summary.id)) {
11746
- standalone.push(summary);
11747
- }
11748
- }
11749
- for (const clineSession of clineReader.listSessions()) {
11750
- const meta = clineSession.metadata;
11751
- const promptText = cleanClinePrompt(meta.prompt ?? "");
11752
- const title = promptText ? promptText.length > 80 ? `${promptText.slice(0, 80)}\u2026` : promptText : "Cline session";
11753
- const createdAtStr = meta.started_at ?? "";
11754
- const durationMs = meta.ended_at ? new Date(meta.ended_at).getTime() - new Date(meta.started_at ?? meta.ended_at).getTime() : 0;
11755
- const eventCount = clineReader.readMessages(clineSession.sessionId)?.messages.length ?? 0;
11756
- standalone.push({
11757
- id: clineSession.sessionId,
11758
- title,
11759
- slug: "",
11760
- createdAt: createdAtStr,
11761
- lastEventAt: meta.ended_at ?? meta.started_at ?? undefined,
11762
- durationMs,
11763
- eventCount,
11764
- isFinished: meta.status === "completed" || meta.status === "failed",
11765
- models: meta.model ? [meta.model] : undefined,
11766
- agent: "cline"
11767
- });
11768
- }
11769
- for (const piSession of piReader.listSessions()) {
11770
- const promptText = piSession.firstPrompt;
11771
- const title = promptText ? promptText.length > 80 ? `${promptText.slice(0, 80)}\u2026` : promptText : "pi session";
11772
- const createdAtStr = piSession.header.timestamp ?? "";
11773
- const durationMs = Math.max(0, piSession.lastActivity - new Date(createdAtStr || 0).getTime());
11774
- standalone.push({
11775
- id: piSession.sessionId,
11776
- title,
11777
- slug: "",
11778
- createdAt: createdAtStr,
11779
- lastEventAt: new Date(piSession.lastActivity).toISOString(),
11780
- durationMs,
11781
- eventCount: piSession.messageCount,
11782
- isFinished: false,
11783
- agent: "pi"
11784
- });
11785
- }
11786
- for (const grokSession of grokReader.listSessions()) {
11787
- const createdAtStr = grokSession.createdAt ?? "";
11788
- const durationMs = Math.max(0, grokSession.lastActivity - new Date(createdAtStr || 0).getTime());
11789
- standalone.push({
11790
- id: grokSession.sessionId,
11791
- title: grokSession.title || "Grok session",
11792
- slug: "",
11793
- createdAt: createdAtStr,
11794
- lastEventAt: new Date(grokSession.lastActivity).toISOString(),
11795
- durationMs,
11796
- eventCount: grokSession.messageCount,
11797
- isFinished: false,
11798
- models: grokSession.modelId ? [grokSession.modelId] : undefined,
11799
- agent: "grok"
11800
- });
11801
- }
11802
- for (const codexSession of codexReader.listSessions()) {
11803
- const createdAtStr = typeof codexSession.meta.timestamp === "string" ? codexSession.meta.timestamp : new Date(codexSession.lastActivity).toISOString();
11804
- standalone.push({
11805
- id: codexSession.sessionId,
11806
- title: codexSession.firstPrompt || "Codex session",
11807
- slug: "",
11808
- createdAt: createdAtStr,
11809
- lastEventAt: new Date(codexSession.lastActivity).toISOString(),
11810
- durationMs: 0,
11811
- eventCount: codexSession.messageCount,
11812
- isFinished: false,
11813
- models: typeof codexSession.meta.model_provider === "string" ? [codexSession.meta.model_provider] : undefined,
11814
- agent: "codex"
11815
- });
11816
- }
11817
- for (const cursorSession of cursorReader.listSessions()) {
11818
- const createdAtStr = cursorSession.createdAt || new Date(cursorSession.lastActivity).toISOString();
11819
- const durationMs = Math.max(0, cursorSession.lastActivity - new Date(createdAtStr || 0).getTime());
11820
- standalone.push({
11821
- id: cursorSession.sessionId,
11822
- title: cursorSession.title || "Cursor session",
11823
- slug: "",
11824
- createdAt: createdAtStr,
11825
- lastEventAt: new Date(cursorSession.lastActivity).toISOString(),
11826
- durationMs,
11827
- eventCount: cursorSession.messageCount,
11828
- isFinished: false,
11829
- agent: "cursor"
11830
- });
11831
- }
11832
- result = { groups, standalone, hasMore: hasOlder };
11833
- } catch (err) {
11834
- console.warn(`[principal-studio] listSessions failed: ${err.message}`);
11835
- const standalone = [];
11836
- try {
11837
- for (const clineSession of clineReader.listSessions()) {
11838
- const meta = clineSession.metadata;
11839
- const promptText = cleanClinePrompt(meta.prompt ?? "");
11840
- const title = promptText ? promptText.length > 80 ? `${promptText.slice(0, 80)}\u2026` : promptText : "Cline session";
11841
- standalone.push({
11842
- id: clineSession.sessionId,
11843
- title,
11844
- slug: "",
11845
- createdAt: meta.started_at ?? "",
11846
- durationMs: 0,
11847
- eventCount: clineReader.readMessages(clineSession.sessionId)?.messages.length ?? 0,
11848
- isFinished: meta.status === "completed" || meta.status === "failed",
11849
- agent: "cline"
11850
- });
11851
- }
11852
- for (const piSession of piReader.listSessions()) {
11853
- const promptText = piSession.firstPrompt;
11854
- const title = promptText ? promptText.length > 80 ? `${promptText.slice(0, 80)}\u2026` : promptText : "pi session";
11855
- standalone.push({
11856
- id: piSession.sessionId,
11857
- title,
11858
- slug: "",
11859
- createdAt: piSession.header.timestamp ?? "",
11860
- durationMs: 0,
11861
- eventCount: piSession.messageCount,
11862
- isFinished: false,
11863
- agent: "pi"
11864
- });
11865
- }
11866
- for (const grokSession of grokReader.listSessions()) {
11867
- standalone.push({
11868
- id: grokSession.sessionId,
11869
- title: grokSession.title || "Grok session",
11870
- slug: "",
11871
- createdAt: grokSession.createdAt ?? "",
11872
- durationMs: 0,
11873
- eventCount: grokSession.messageCount,
11874
- isFinished: false,
11875
- agent: "grok"
11876
- });
11877
- }
11878
- for (const codexSession of codexReader.listSessions()) {
11879
- standalone.push({
11880
- id: codexSession.sessionId,
11881
- title: codexSession.firstPrompt || "Codex session",
11882
- slug: "",
11883
- createdAt: typeof codexSession.meta.timestamp === "string" ? codexSession.meta.timestamp : "",
11884
- durationMs: 0,
11885
- eventCount: codexSession.messageCount,
11886
- isFinished: false,
11887
- agent: "codex"
11888
- });
11889
- }
11890
- } catch {}
11891
- result = { groups: [], standalone, hasMore: false };
11892
- } finally {
11893
- db?.close();
11894
- }
11895
- indexCache.set(cacheKey, result);
11896
- while (indexCache.size > INDEX_CACHE_MAX) {
11897
- const oldest = indexCache.keys().next().value;
11898
- if (oldest === undefined)
11899
- break;
11900
- indexCache.delete(oldest);
11901
- }
11902
- return result;
11903
- }
11904
11567
  async function processSessionEvents(sessionId, opts) {
11905
11568
  const includeRaw = opts.includeRaw === true;
11906
11569
  const useCache = opts.useCache !== false;
@@ -12117,29 +11780,6 @@ async function processSessionEvents(sessionId, opts) {
12117
11780
  function post(msg) {
12118
11781
  self.postMessage(msg);
12119
11782
  }
12120
- async function runWarmup(days) {
12121
- const index = await buildSessionIndex({ days });
12122
- const sessions = [];
12123
- for (const g of index.groups)
12124
- sessions.push(g.parent);
12125
- sessions.push(...index.standalone);
12126
- const total = sessions.length;
12127
- let done = 0;
12128
- for (const s of sessions) {
12129
- try {
12130
- const res = await processSessionEvents(s.id, {
12131
- includeRaw: false,
12132
- useCache: true
12133
- });
12134
- if (res.ok)
12135
- done++;
12136
- } catch (err) {
12137
- post({ type: "error", message: err.message });
12138
- }
12139
- post({ type: "progress", sessionId: s.id, done, total });
12140
- }
12141
- post({ type: "done", processed: done, total });
12142
- }
12143
11783
  async function runRefresh(sessionIds) {
12144
11784
  const total = sessionIds.length;
12145
11785
  let done = 0;
@@ -12160,8 +11800,6 @@ async function runRefresh(sessionIds) {
12160
11800
  }
12161
11801
  self.addEventListener("message", (ev) => {
12162
11802
  const msg = ev.data;
12163
- if (msg.type === "warmup")
12164
- runWarmup(msg.days);
12165
- else if (msg.type === "refresh")
11803
+ if (msg.type === "refresh")
12166
11804
  runRefresh(msg.sessionIds);
12167
11805
  });
@@ -2,5 +2,5 @@
2
2
  "identifier": "ai.principal.subsystems-studio",
3
3
  "name": "Subsystems Studio",
4
4
  "channel": "stable",
5
- "hash": "1cnku1crxvoup"
5
+ "hash": "2q1ypn2xhmen"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@principal-ai/subsystems-studio",
3
- "version": "0.20.2",
3
+ "version": "0.20.4",
4
4
  "description": "Subsystems Studio — desktop host for subsystem models, trails, tours, and agent sessions. Pairs with the principal-ai CLI.",
5
5
  "type": "module",
6
6
  "os": [
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "devDependencies": {
40
40
  "@excalidraw/excalidraw": "^0.18.0",
41
- "@industry-theme/file-city-panel": "^0.10.2",
41
+ "@industry-theme/file-city-panel": "^0.10.3",
42
42
  "@pierre/diffs": "^1.6.2",
43
43
  "@principal-ade/dynamic-file-tree": "^0.3.0",
44
44
  "@principal-ade/industry-theme": "^0.1.25",
@@ -47,7 +47,7 @@
47
47
  "@principal-ade/utcp-panel-event": "^0.1.0",
48
48
  "@principal-ai/alexandria-core-library": "^0.7.1",
49
49
  "@principal-ai/file-city-builder": "^0.5.5",
50
- "@principal-ai/file-city-react": "^0.6.4",
50
+ "@principal-ai/file-city-react": "^0.6.5",
51
51
  "@principal-ai/logo-component": "^0.1.23",
52
52
  "@principal-ai/repository-abstraction": "^0.5.7",
53
53
  "@storybook/addon-docs": "10.1.2",