@pasko70/pibo 1.7.3 → 1.7.5

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 (187) hide show
  1. package/README.md +0 -0
  2. package/context/codex-base-prompt.md +0 -0
  3. package/context/compute-worker.md +0 -0
  4. package/context/pibo-compaction-prompt.md +0 -0
  5. package/context/pibo-native-tooling.md +0 -0
  6. package/context/pibo-system-prompt.md +0 -0
  7. package/dist/apps/chat/chat-api-routes.js +14 -0
  8. package/dist/apps/chat/data/session-query-service.js +66 -3
  9. package/dist/apps/chat/data/timeline-query-service.js +8 -2
  10. package/dist/apps/chat/trace.js +63 -4
  11. package/dist/apps/chat/web-app.js +130 -5
  12. package/dist/apps/chat/workflow-manual-trigger-runtime.js +223 -0
  13. package/dist/apps/chat-ui/assets/{dist-CQt6ULIj.js → dist-9reC6CRy.js} +1 -1
  14. package/dist/apps/chat-ui/assets/{dist-CESPWSQ-.js → dist-B3s0osfY.js} +1 -1
  15. package/dist/apps/chat-ui/assets/{dist-0VZenZBV.js → dist-BFDieA29.js} +1 -1
  16. package/dist/apps/chat-ui/assets/{dist-DnhVsXHZ.js → dist-CD2PBsXa.js} +1 -1
  17. package/dist/apps/chat-ui/assets/{dist-BMjRcU4S.js → dist-CKfKOLLy.js} +1 -1
  18. package/dist/apps/chat-ui/assets/{dist-BxwcyegP.js → dist-CrBAoz7q.js} +1 -1
  19. package/dist/apps/chat-ui/assets/{dist-Ih0wkIep.js → dist-DY6s8EGj.js} +1 -1
  20. package/dist/apps/chat-ui/assets/{dist-CjbsWko8.js → dist-Jx6fE2Hb.js} +1 -1
  21. package/dist/apps/chat-ui/assets/{dist-DYqe5Zvc.js → dist-TfPabg6A.js} +1 -1
  22. package/dist/apps/chat-ui/assets/{dist-DSDqYG1O.js → dist-b5e4NjPA.js} +1 -1
  23. package/dist/apps/chat-ui/assets/{dist-Bbb6cmLt.js → dist-kiXdn9N3.js} +1 -1
  24. package/dist/apps/chat-ui/assets/index-BLY-pTWm.css +1 -0
  25. package/dist/apps/chat-ui/assets/{index-j2BTjmvp.js → index-DN6wYo-Z.js} +20 -20
  26. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-144x144.png +0 -0
  27. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-192x192.png +0 -0
  28. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-48x48.png +0 -0
  29. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-512x512.png +0 -0
  30. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-72x72.png +0 -0
  31. package/dist/apps/chat-ui/assets/pwa-images/android/launchericon-96x96.png +0 -0
  32. package/dist/apps/chat-ui/assets/pwa-images/ios/100.png +0 -0
  33. package/dist/apps/chat-ui/assets/pwa-images/ios/1024.png +0 -0
  34. package/dist/apps/chat-ui/assets/pwa-images/ios/114.png +0 -0
  35. package/dist/apps/chat-ui/assets/pwa-images/ios/120.png +0 -0
  36. package/dist/apps/chat-ui/assets/pwa-images/ios/128.png +0 -0
  37. package/dist/apps/chat-ui/assets/pwa-images/ios/144.png +0 -0
  38. package/dist/apps/chat-ui/assets/pwa-images/ios/152.png +0 -0
  39. package/dist/apps/chat-ui/assets/pwa-images/ios/16.png +0 -0
  40. package/dist/apps/chat-ui/assets/pwa-images/ios/167.png +0 -0
  41. package/dist/apps/chat-ui/assets/pwa-images/ios/180.png +0 -0
  42. package/dist/apps/chat-ui/assets/pwa-images/ios/192.png +0 -0
  43. package/dist/apps/chat-ui/assets/pwa-images/ios/20.png +0 -0
  44. package/dist/apps/chat-ui/assets/pwa-images/ios/256.png +0 -0
  45. package/dist/apps/chat-ui/assets/pwa-images/ios/29.png +0 -0
  46. package/dist/apps/chat-ui/assets/pwa-images/ios/32.png +0 -0
  47. package/dist/apps/chat-ui/assets/pwa-images/ios/40.png +0 -0
  48. package/dist/apps/chat-ui/assets/pwa-images/ios/50.png +0 -0
  49. package/dist/apps/chat-ui/assets/pwa-images/ios/512.png +0 -0
  50. package/dist/apps/chat-ui/assets/pwa-images/ios/57.png +0 -0
  51. package/dist/apps/chat-ui/assets/pwa-images/ios/58.png +0 -0
  52. package/dist/apps/chat-ui/assets/pwa-images/ios/60.png +0 -0
  53. package/dist/apps/chat-ui/assets/pwa-images/ios/64.png +0 -0
  54. package/dist/apps/chat-ui/assets/pwa-images/ios/72.png +0 -0
  55. package/dist/apps/chat-ui/assets/pwa-images/ios/76.png +0 -0
  56. package/dist/apps/chat-ui/assets/pwa-images/ios/80.png +0 -0
  57. package/dist/apps/chat-ui/assets/pwa-images/ios/87.png +0 -0
  58. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-100.png +0 -0
  59. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-125.png +0 -0
  60. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-150.png +0 -0
  61. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-200.png +0 -0
  62. package/dist/apps/chat-ui/assets/pwa-images/windows/LargeTile.scale-400.png +0 -0
  63. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-100.png +0 -0
  64. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-125.png +0 -0
  65. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-150.png +0 -0
  66. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-200.png +0 -0
  67. package/dist/apps/chat-ui/assets/pwa-images/windows/SmallTile.scale-400.png +0 -0
  68. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-100.png +0 -0
  69. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-125.png +0 -0
  70. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-150.png +0 -0
  71. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-200.png +0 -0
  72. package/dist/apps/chat-ui/assets/pwa-images/windows/SplashScreen.scale-400.png +0 -0
  73. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-100.png +0 -0
  74. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-125.png +0 -0
  75. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-150.png +0 -0
  76. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-200.png +0 -0
  77. package/dist/apps/chat-ui/assets/pwa-images/windows/Square150x150Logo.scale-400.png +0 -0
  78. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-16.png +0 -0
  79. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-20.png +0 -0
  80. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-24.png +0 -0
  81. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-256.png +0 -0
  82. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-30.png +0 -0
  83. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-32.png +0 -0
  84. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-36.png +0 -0
  85. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-40.png +0 -0
  86. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-44.png +0 -0
  87. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-48.png +0 -0
  88. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-60.png +0 -0
  89. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-64.png +0 -0
  90. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-72.png +0 -0
  91. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-80.png +0 -0
  92. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-lightunplated_targetsize-96.png +0 -0
  93. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-16.png +0 -0
  94. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-20.png +0 -0
  95. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-24.png +0 -0
  96. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-256.png +0 -0
  97. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-30.png +0 -0
  98. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-32.png +0 -0
  99. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-36.png +0 -0
  100. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-40.png +0 -0
  101. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-44.png +0 -0
  102. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-48.png +0 -0
  103. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-60.png +0 -0
  104. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-64.png +0 -0
  105. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-72.png +0 -0
  106. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-80.png +0 -0
  107. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.altform-unplated_targetsize-96.png +0 -0
  108. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-100.png +0 -0
  109. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-125.png +0 -0
  110. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-150.png +0 -0
  111. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-200.png +0 -0
  112. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.scale-400.png +0 -0
  113. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-16.png +0 -0
  114. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-20.png +0 -0
  115. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-24.png +0 -0
  116. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-256.png +0 -0
  117. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-30.png +0 -0
  118. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-32.png +0 -0
  119. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-36.png +0 -0
  120. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-40.png +0 -0
  121. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-44.png +0 -0
  122. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-48.png +0 -0
  123. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-60.png +0 -0
  124. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-64.png +0 -0
  125. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-72.png +0 -0
  126. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-80.png +0 -0
  127. package/dist/apps/chat-ui/assets/pwa-images/windows/Square44x44Logo.targetsize-96.png +0 -0
  128. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-100.png +0 -0
  129. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-125.png +0 -0
  130. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-150.png +0 -0
  131. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-200.png +0 -0
  132. package/dist/apps/chat-ui/assets/pwa-images/windows/StoreLogo.scale-400.png +0 -0
  133. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-100.png +0 -0
  134. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-125.png +0 -0
  135. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-150.png +0 -0
  136. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-200.png +0 -0
  137. package/dist/apps/chat-ui/assets/pwa-images/windows/Wide310x150Logo.scale-400.png +0 -0
  138. package/dist/apps/chat-ui/index.html +2 -2
  139. package/dist/apps/chat-ui/manifest.webmanifest +0 -0
  140. package/dist/apps/chat-ui/sw.js +0 -0
  141. package/dist/apps/chat-vscode-web/assets/index-B4Jk2P5o.js +41 -0
  142. package/dist/apps/chat-vscode-web/index.html +1 -1
  143. package/dist/apps/vscode-artifacts/latest.vsix +0 -0
  144. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.7.5.vsix +0 -0
  145. package/dist/bin/pibo.js +0 -0
  146. package/dist/bin/rg.js +0 -0
  147. package/dist/data/schema.js +2 -0
  148. package/dist/plugins/builtin.js +2 -0
  149. package/dist/ralph/cli.js +2 -1
  150. package/dist/web/http.js +7 -1
  151. package/docs/README.md +0 -0
  152. package/docs/ops/install-developer-host.md +0 -0
  153. package/docs/ops/install-user-host.md +0 -0
  154. package/docs/ops/upgrade-user-to-developer-host.md +0 -0
  155. package/docs/ops/vscode-extension-release.md +0 -0
  156. package/package.json +1 -1
  157. package/skills/builtin/graphify/SKILL.md +0 -0
  158. package/skills/builtin/pi-agent-harness/SKILL.md +0 -0
  159. package/skills/builtin/pi-agent-harness/agents/openai.yaml +0 -0
  160. package/skills/builtin/pibo-docker-system/SKILL.md +0 -0
  161. package/skills/builtin/pibo-spec-writing/SKILL.md +0 -0
  162. package/skills/builtin/prd/SKILL.md +0 -0
  163. package/skills/builtin/ralph-loop/SKILL.md +0 -0
  164. package/skills/builtin/ralph-prd-json/SKILL.md +0 -0
  165. package/skills/builtin/skill-creator/LICENSE.txt +0 -0
  166. package/skills/builtin/skill-creator/SKILL.md +0 -0
  167. package/skills/builtin/skill-creator/agents/analyzer.md +0 -0
  168. package/skills/builtin/skill-creator/agents/comparator.md +0 -0
  169. package/skills/builtin/skill-creator/agents/grader.md +0 -0
  170. package/skills/builtin/skill-creator/assets/eval_review.html +0 -0
  171. package/skills/builtin/skill-creator/eval-viewer/generate_review.py +0 -0
  172. package/skills/builtin/skill-creator/eval-viewer/viewer.html +0 -0
  173. package/skills/builtin/skill-creator/references/schemas.md +0 -0
  174. package/skills/builtin/skill-creator/scripts/__init__.py +0 -0
  175. package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +0 -0
  176. package/skills/builtin/skill-creator/scripts/generate_report.py +0 -0
  177. package/skills/builtin/skill-creator/scripts/improve_description.py +0 -0
  178. package/skills/builtin/skill-creator/scripts/package_skill.py +0 -0
  179. package/skills/builtin/skill-creator/scripts/quick_validate.py +0 -0
  180. package/skills/builtin/skill-creator/scripts/run_eval.py +0 -0
  181. package/skills/builtin/skill-creator/scripts/run_loop.py +0 -0
  182. package/skills/builtin/skill-creator/scripts/utils.py +0 -0
  183. package/skills/builtin/web-annotations/SKILL.md +0 -0
  184. package/src/mcp/LICENSE.mcp-cli +0 -0
  185. package/dist/apps/chat-ui/assets/index-Dz6asKNQ.css +0 -1
  186. package/dist/apps/chat-vscode-web/assets/index-BHL2ZJCu.js +0 -41
  187. package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.7.3.vsix +0 -0
package/README.md CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -94,6 +94,20 @@ export function workflowDraftActionResource(pathname) {
94
94
  throw new PiboWebHttpError("Invalid workflow draft action", 400);
95
95
  }
96
96
  }
97
+ export function workflowDraftManualTriggerRunResource(pathname) {
98
+ const prefix = `${CHAT_WEB_API_PREFIX}/workflows/drafts/`;
99
+ if (!pathname.startsWith(prefix))
100
+ return undefined;
101
+ const parts = pathname.slice(prefix.length).split("/");
102
+ if (parts.length !== 2 || !parts[0] || parts[1] !== "manual-trigger-runs")
103
+ return undefined;
104
+ try {
105
+ return { draftId: decodeURIComponent(parts[0]) };
106
+ }
107
+ catch {
108
+ throw new PiboWebHttpError("Invalid workflow draft manual trigger route", 400);
109
+ }
110
+ }
97
111
  export function workflowDuplicateResourceId(pathname) {
98
112
  const prefix = `${CHAT_WEB_API_PREFIX}/workflows/`;
99
113
  const suffix = "/duplicate";
@@ -1,5 +1,6 @@
1
1
  import { chatRoomIdFromMetadata } from "../types/rooms.js";
2
2
  import { sessionFromRow, statusFromOutputEvent } from "./chat-data-mappers.js";
3
+ import { rootSessionId } from "../../../data/session-store.js";
3
4
  export class ChatSessionQueryService {
4
5
  store;
5
6
  constructor(store) {
@@ -11,9 +12,17 @@ export class ChatSessionQueryService {
11
12
  this.upsertNavigation(session, roomId, status, session.updatedAt);
12
13
  }
13
14
  upsertSessionsIfChanged(sessions) {
14
- for (const session of sessions)
15
+ let written = 0;
16
+ let skipped = 0;
17
+ for (const session of sessions) {
18
+ if (this.sessionIndexMatches(session)) {
19
+ skipped++;
20
+ continue;
21
+ }
15
22
  this.upsertSession(session);
16
- return { checked: sessions.length, written: sessions.length, skipped: 0 };
23
+ written++;
24
+ }
25
+ return { checked: sessions.length, written, skipped };
17
26
  }
18
27
  recordEvent(event, session) {
19
28
  if (session)
@@ -44,11 +53,65 @@ export class ChatSessionQueryService {
44
53
  return Number(result.changes ?? 0);
45
54
  }
46
55
  close() { }
56
+ sessionIndexMatches(session, status = "idle") {
57
+ const roomId = chatRoomIdFromMetadata(session.metadata) ?? "room_default";
58
+ const title = session.title || "Untitled Session";
59
+ const metadataJson = JSON.stringify(session.metadata ?? {});
60
+ const activeModelJson = session.activeModel ? JSON.stringify(session.activeModel) : null;
61
+ const row = this.store.db.prepare(`
62
+ SELECT
63
+ s.pi_session_id,
64
+ s.room_id,
65
+ s.root_session_id,
66
+ s.parent_id,
67
+ s.origin_id,
68
+ s.channel,
69
+ s.kind,
70
+ s.profile,
71
+ s.active_model_json,
72
+ s.workspace,
73
+ s.title,
74
+ s.status,
75
+ s.metadata_json,
76
+ s.created_at,
77
+ s.updated_at,
78
+ s.last_activity_at,
79
+ n.status AS navigation_status,
80
+ n.title AS navigation_title,
81
+ n.sort_key AS navigation_sort_key,
82
+ n.updated_at AS navigation_updated_at
83
+ FROM sessions s
84
+ LEFT JOIN session_navigation n ON n.session_id = s.id
85
+ WHERE s.id = ? AND s.deleted_at IS NULL
86
+ `).get(session.id);
87
+ if (!row)
88
+ return false;
89
+ return row.pi_session_id === session.piSessionId
90
+ && row.room_id === roomId
91
+ && row.root_session_id === rootSessionId(session)
92
+ && row.parent_id === (session.parentId ?? null)
93
+ && row.origin_id === (session.originId ?? null)
94
+ && row.channel === session.channel
95
+ && row.kind === session.kind
96
+ && row.profile === session.profile
97
+ && row.active_model_json === activeModelJson
98
+ && row.workspace === (session.workspace ?? null)
99
+ && row.title === title
100
+ && row.status === status
101
+ && row.metadata_json === metadataJson
102
+ && row.created_at === session.createdAt
103
+ && row.updated_at === session.updatedAt
104
+ && row.last_activity_at === session.updatedAt
105
+ && row.navigation_status === status
106
+ && row.navigation_title === title
107
+ && row.navigation_sort_key === session.updatedAt
108
+ && row.navigation_updated_at === session.updatedAt;
109
+ }
47
110
  upsertNavigation(session, roomId, status, now) {
48
111
  this.store.navigation.upsertSession({
49
112
  roomId,
50
113
  sessionId: session.id,
51
- rootSessionId: session.parentId ? (typeof session.metadata?.rootSessionId === "string" ? session.metadata.rootSessionId : session.parentId) : session.id,
114
+ rootSessionId: rootSessionId(session),
52
115
  parentId: session.parentId,
53
116
  originId: session.originId,
54
117
  title: session.title || "Untitled Session",
@@ -75,8 +75,14 @@ export class ChatTimelineQueryService {
75
75
  return rows.map((row) => ({ eventType: row.type, count: Number(row.count) }));
76
76
  }
77
77
  getLatestEventSequence(piboSessionId) {
78
- const row = this.store.db.prepare("SELECT COALESCE(MAX(session_sequence), 0) AS latest_sequence FROM event_log WHERE session_id = ?").get(piboSessionId);
79
- return row.latest_sequence;
78
+ const row = this.store.db.prepare(`
79
+ SELECT session_sequence AS latest_sequence
80
+ FROM event_log
81
+ WHERE session_id = ?
82
+ ORDER BY session_sequence DESC, stream_id DESC
83
+ LIMIT 1
84
+ `).get(piboSessionId);
85
+ return row?.latest_sequence ?? 0;
80
86
  }
81
87
  getLatestStreamId(input = {}) {
82
88
  const clauses = [];
@@ -14,6 +14,11 @@ export async function loadPiSessionMetadata(session, cwd = process.cwd()) {
14
14
  const piSession = await findPiSession(session, cwd);
15
15
  return metadataFromPiSession(piSession);
16
16
  }
17
+ export async function loadPiSessionFastMetadata(session, cwd = process.cwd()) {
18
+ const piSession = findPiSessionDirectFast(session.piSessionId, cwd)
19
+ ?? findPiSessionDirect(session.piSessionId, cwd, { fast: true });
20
+ return metadataFromPiSession(piSession);
21
+ }
17
22
  function metadataFromPiSession(piSession) {
18
23
  if (!piSession)
19
24
  return {};
@@ -196,7 +201,10 @@ export function createTraceViewVersion(input) {
196
201
  .digest("hex");
197
202
  }
198
203
  const PI_SESSION_LIST_CACHE_TTL_MS = 5_000;
204
+ const PI_SESSION_DIRECT_CACHE_TTL_MS = 5_000;
205
+ const PI_SESSION_FAST_HEAD_BYTES = 64 * 1024;
199
206
  const piSessionListCache = new Map();
207
+ const piSessionDirectCache = new Map();
200
208
  export async function listPiSessions(cwd = process.cwd()) {
201
209
  const now = Date.now();
202
210
  const cached = piSessionListCache.get(cwd);
@@ -234,7 +242,31 @@ async function findPiSession(piboSession, cwd) {
234
242
  return (findPiSessionDirect(piboSession.piSessionId, cwd) ??
235
243
  (await listPiSessions(cwd)).find((session) => session.id === piboSession.piSessionId));
236
244
  }
237
- function findPiSessionDirect(piSessionId, cwd) {
245
+ function findPiSessionDirectFast(piSessionId, cwd) {
246
+ const cacheKey = `${cwd}\0${piSessionId}`;
247
+ const cached = piSessionDirectCache.get(cacheKey);
248
+ if (!cached || cached.expiresAt <= Date.now())
249
+ return undefined;
250
+ try {
251
+ const stats = statSync(cached.path);
252
+ if (stats.size === cached.size && stats.mtimeMs === cached.mtimeMs)
253
+ return cached.item;
254
+ }
255
+ catch {
256
+ piSessionDirectCache.delete(cacheKey);
257
+ }
258
+ return undefined;
259
+ }
260
+ function setPiSessionDirectFastCache(piSessionId, cwd, item, stats) {
261
+ piSessionDirectCache.set(`${cwd}\0${piSessionId}`, {
262
+ expiresAt: Date.now() + PI_SESSION_DIRECT_CACHE_TTL_MS,
263
+ path: item.path,
264
+ size: stats.size,
265
+ mtimeMs: stats.mtimeMs,
266
+ item,
267
+ });
268
+ }
269
+ function findPiSessionDirect(piSessionId, cwd, options = {}) {
238
270
  const sessionDir = defaultPiSessionDir(cwd);
239
271
  if (!existsSync(sessionDir))
240
272
  return undefined;
@@ -244,7 +276,9 @@ function findPiSessionDirect(piSessionId, cwd) {
244
276
  return undefined;
245
277
  const sessionPath = join(sessionDir, file);
246
278
  const stats = statSync(sessionPath);
247
- const entries = parseSessionEntries(readFileSync(sessionPath, "utf8"));
279
+ const entries = options.fast
280
+ ? readHeadEntries(sessionPath, stats.size, PI_SESSION_FAST_HEAD_BYTES)
281
+ : parseSessionEntries(readFileSync(sessionPath, "utf8"));
248
282
  const header = entries.find((entry) => entry.type === "session");
249
283
  if (header?.id !== piSessionId)
250
284
  return undefined;
@@ -261,17 +295,22 @@ function findPiSessionDirect(piSessionId, cwd) {
261
295
  continue;
262
296
  firstMessage = extractMessageText(messageContent(entry));
263
297
  }
264
- return {
298
+ const item = {
265
299
  path: sessionPath,
266
300
  id: piSessionId,
267
301
  cwd: stringValue(header.cwd) ?? cwd,
268
302
  name,
269
303
  parentSessionPath: stringValue(header.parentSession),
270
304
  created: stringValue(header.timestamp) ?? stats.birthtime.toISOString(),
271
- modified: sessionModifiedIso(entries.filter((entry) => entry.type !== "session"), stringValue(header.timestamp), stats.mtime),
305
+ modified: options.fast
306
+ ? stats.mtime.toISOString()
307
+ : sessionModifiedIso(entries.filter((entry) => entry.type !== "session"), stringValue(header.timestamp), stats.mtime),
272
308
  messageCount,
273
309
  firstMessage: firstMessage || "(no messages)",
274
310
  };
311
+ if (options.fast)
312
+ setPiSessionDirectFastCache(piSessionId, cwd, item, stats);
313
+ return item;
275
314
  }
276
315
  catch {
277
316
  return undefined;
@@ -307,6 +346,26 @@ function readEntries(path) {
307
346
  const content = readFileSync(path, "utf8");
308
347
  return parseSessionEntries(content).filter((entry) => entry.type !== "session");
309
348
  }
349
+ function readHeadEntries(path, fileSize, maxBytes) {
350
+ const length = Math.max(1, Math.min(maxBytes, fileSize));
351
+ const buffer = Buffer.alloc(length);
352
+ const fd = openSync(path, "r");
353
+ try {
354
+ const bytesRead = readSync(fd, buffer, 0, length, 0);
355
+ let content = buffer.subarray(0, bytesRead).toString("utf8");
356
+ if (bytesRead < fileSize && !content.endsWith("\n")) {
357
+ const lastNewline = content.lastIndexOf("\n");
358
+ if (lastNewline >= 0)
359
+ content = content.slice(0, lastNewline + 1);
360
+ }
361
+ if (!content.trim())
362
+ return [];
363
+ return parseSessionEntries(content.endsWith("\n") ? content : `${content}\n`);
364
+ }
365
+ finally {
366
+ closeSync(fd);
367
+ }
368
+ }
310
369
  export function readTailEntries(path, maxBytes = TRACE_TRANSCRIPT_TAIL_MAX_BYTES) {
311
370
  if (!existsSync(path))
312
371
  return [];
@@ -6,7 +6,7 @@ import { OutputCompactor } from "./output-compactor.js";
6
6
  import { isLiveOnlyOutputEvent, isPersistableOutputEvent } from "./output-event-policy.js";
7
7
  import { chatRoomIdFromMetadata, isDefaultPiboRoom, isPiboRoomArchived, roomWorkspaceFromMetadata, withChatRoomId, withPiboRoomWorkspace, } from "./types/rooms.js";
8
8
  import { chatStreamFramesFromOutputEvent, createChatStreamState, nextTransientChatStreamFrameId } from "./stream.js";
9
- import { buildSessionNodes, buildTraceView, createTraceViewVersion, loadPiSessionMetadata, readTailEntries, readTranscriptHistoryPage } from "./trace.js";
9
+ import { buildSessionNodes, buildTraceView, createTraceViewVersion, loadPiSessionFastMetadata, loadPiSessionMetadata, readTailEntries, readTranscriptHistoryPage } from "./trace.js";
10
10
  import { DEFAULT_TRACE_EVENTS_PAGE_SIZE, annotateTracePage, etagForVersion, estimateTraceViewBytes, traceCacheEstimatedBytes, liveSnapshotVersion, requestMatchesVersion, setTraceCache, traceCacheKey, withLiveSnapshots, withRawTraceTail, } from "./chat-trace-helpers.js";
11
11
  import { TRACE_V2_DEFAULT_TIMELINE_LIMIT, TRACE_V2_MAX_TIMELINE_LIMIT, TRACE_V2_PAYLOAD_DEFAULT_LIMIT_BYTES, TRACE_V2_PAYLOAD_MAX_LIMIT_BYTES, TRACE_V2_RAW_EVENTS_DEFAULT_LIMIT, TRACE_V2_RAW_EVENTS_MAX_LIMIT, TRACE_V2_TIMELINE_HARD_BYTES, parseTracePayloadRef, readTracePayloadChunk, traceRawEventsPageFromEvents, traceTimelinePageFromView, } from "./trace-v2.js";
12
12
  import { isChatWebSessionArchived } from "./session-metadata.js";
@@ -43,7 +43,7 @@ import { prepareChatFileAttachments, resolveDownloadPath, responseChatFileDownlo
43
43
  import { chatSettingsRoute, chatSettingsRouteInvalidatesBootstrapCatalog, chatSettingsRouteRequiresSameOrigin, handleChatSettingsRoute, } from "./chat-settings-routes.js";
44
44
  import { chatCapabilityRoute, chatCapabilityRouteRequiresSameOrigin, handleChatCapabilityRoute, } from "./chat-capability-routes.js";
45
45
  import { chatUserSkillRoute, chatUserSkillRouteRequiresSameOrigin, handleChatUserSkillRoute, syncChatUserSkills, } from "./chat-user-skill-routes.js";
46
- import { CHAT_WEB_API_PREFIX, agentResourceId, projectResourcePath, projectSessionResourceId, projectWorkflowHumanActionsResource, projectWorkflowSessionStartResource, roomResourcePath, sessionActionResource, sessionResourceId, signalResource, workflowArchiveResourceId, workflowCatalogResourceId, workflowDraftActionResource, workflowDraftResourceId, workflowDuplicateResourceId, workflowNextDraftResourceId, workflowPickerKind, workflowPromptAssetResourceId, workflowVersionResource, } from "./chat-api-routes.js";
46
+ import { CHAT_WEB_API_PREFIX, agentResourceId, projectResourcePath, projectSessionResourceId, projectWorkflowHumanActionsResource, projectWorkflowSessionStartResource, roomResourcePath, sessionActionResource, sessionResourceId, signalResource, workflowArchiveResourceId, workflowCatalogResourceId, workflowDraftActionResource, workflowDraftManualTriggerRunResource, workflowDraftResourceId, workflowDuplicateResourceId, workflowNextDraftResourceId, workflowPickerKind, workflowPromptAssetResourceId, workflowVersionResource, } from "./chat-api-routes.js";
47
47
  import { assertProjectSessionPatchFields, buildStreamingFixtureSchedule, createAgentInput, createAgentUpdate, createRoomUpdate, createSessionUpdate, normalizeAgentArchived, normalizeClientTxnId, normalizeMessageText, normalizeParentRoomId, normalizeProjectArchived, normalizeProjectDescription, normalizeProjectPath, normalizeProjectSessionArchived, normalizeRoomDeleteConfirmation, normalizeRoomName, normalizeRoomTopic, normalizeRoomType, normalizeRoomWorkspace, normalizeSessionDeleteConfirmation, normalizeSessionTitle, normalizeStreamingFixtureCadenceMs, normalizeStreamingFixtureDeltas, normalizeStreamingFixtureMix, normalizeStreamingFixturePreludeMessages, normalizeStreamingFixturePreludeOnly, normalizeStreamingFixtureProfile, normalizeStreamingFixtureSuppressLiveDeltas, normalizeStreamingFixtureTraceSnapshots, resolveCreateSessionProfile, } from "./chat-request-normalizers.js";
48
48
  import { ChatWorkflowArchiveStore, ChatWorkflowDraftStore, ChatWorkflowLifecycleEventStore, ChatWorkflowPromptAssetStore, ChatWorkflowPublishedVersionStore, ChatWorkflowTombstoneStore, hashWorkflowDefinitionJson, normalizeWorkflowPromptAssetLabel, sanitizeWorkflowDiagnostics, } from "./workflow-persistence.js";
49
49
  import { normalizeProjectWorkflowHumanActionBody, projectWorkflowHumanActionDiagnosticResponse, projectWorkflowHumanActionLifecyclePayload, projectWorkflowHumanActionRuntimeDiagnostic, projectWorkflowHumanActionSubmittedLifecyclePayload, projectWorkflowPendingHumanActionFromToken, validateProjectWorkflowHumanActionRequest, } from "./project-workflow-human-actions.js";
@@ -51,6 +51,7 @@ import { createProjectWorkflowRunCurrent, createProjectWorkflowSessionSnapshot,
51
51
  import { STATIC_WORKFLOW_VERSION_CATALOG, buildProjectWorkflowVersionCatalog, buildProjectWorkflowVersionOptions, buildWorkflowCatalogInspect as buildWorkflowCatalogInspectWithServices, buildWorkflowCatalogList as buildWorkflowCatalogListWithServices, buildWorkflowVersionHistory, buildWorkflowVersionInspect as buildWorkflowVersionInspectWithServices, buildWorkflowVersionList as buildWorkflowVersionListWithServices, buildWorkflowVersionPicker, createPublishedWorkflowDefinition, selectWorkflowCatalogDisplayVersion, workflowDefinitionTags, workflowVersionPickerOptionFromCatalogRecord, } from "./workflow-catalog.js";
52
52
  import { cloneJsonObject, isWorkflowValidationPipelineDiagnostic, normalizeWorkflowValidationTrigger, normalizeWorkflowVersionIntent, parseWorkflowDraftDefinitionFromPatch, summarizeWorkflowDiagnostics, withoutRawWorkflowIrParseDiagnostic, } from "./workflow-validation-helpers.js";
53
53
  import { validateWorkflowEdgeAdapterOutputCompatibilityLike, validateWorkflowEdgeDirectCompatibilityLike, } from "./workflow-edge-compatibility.js";
54
+ import { runWorkflowManualTextTrigger, } from "./workflow-manual-trigger-runtime.js";
54
55
  import { validateJsonSchemaObjectLike } from "./workflow-json-schema-validation.js";
55
56
  import { WORKFLOW_ADAPTER_REF_OPTIONS, WORKFLOW_GUARD_REF_OPTIONS, WORKFLOW_HUMAN_ACTION_REF_OPTIONS, buildWorkflowPromptAssetPicker, buildWorkflowRegisteredRefPicker, getWorkflowPromptAssetDocument, isWorkflowPromptAssetRegistered, } from "./workflow-registered-ref-pickers.js";
56
57
  import { validateRegisteredAdapterRefLike, validateWorkflowGuardRefLike, validateWorkflowHumanActionRefsLike, validateWorkflowPromptAssetRefLike, } from "./workflow-registered-ref-validation.js";
@@ -1536,6 +1537,31 @@ function runWorkflowDraftValidation(state, context, webSession, record, trigger)
1536
1537
  });
1537
1538
  return { validation, diagnostics };
1538
1539
  }
1540
+ function normalizeWorkflowDraftManualTriggerRunBody(body) {
1541
+ const triggerNodeId = typeof body.triggerNodeId === "string" ? body.triggerNodeId.trim() : "";
1542
+ if (!triggerNodeId)
1543
+ throw new PiboWebHttpError("Manual trigger node id is required", 400);
1544
+ if (typeof body.input !== "string")
1545
+ throw new PiboWebHttpError("Manual trigger input must be text", 400);
1546
+ return { triggerNodeId, input: body.input };
1547
+ }
1548
+ function resolveWorkflowRuntimeProfile(input) {
1549
+ const profile = input.context.channelContext.getProfiles?.().find((candidate) => candidate.name === input.requestedId || candidate.aliases.includes(input.requestedId));
1550
+ return profile?.name;
1551
+ }
1552
+ function workflowManualTriggerRunResponse(result, validation, draft) {
1553
+ return {
1554
+ ok: result.ok,
1555
+ draft: serializeWorkflowDraft(draft),
1556
+ validation: validation.validation,
1557
+ diagnostics: sanitizeWorkflowDiagnostics([...validation.diagnostics, ...result.diagnostics]),
1558
+ ...(result.run ? { run: result.run } : {}),
1559
+ nodeAttempts: result.nodeAttempts,
1560
+ edgeTransfers: result.edgeTransfers,
1561
+ ...(result.output !== undefined ? { output: result.output } : {}),
1562
+ ...(result.error ? { error: result.error } : {}),
1563
+ };
1564
+ }
1539
1565
  function validatePublishedWorkflowBoundary(input) {
1540
1566
  const diagnostics = sanitizeWorkflowDiagnostics(validateWorkflowDefinitionForV2(input.definition, input));
1541
1567
  return {
@@ -1656,15 +1682,62 @@ function validateWorkflowNodeLike(nodeId, value, input, diagnostics) {
1656
1682
  validateWorkflowHumanNodeLike(nodeId, value, diagnostics);
1657
1683
  return;
1658
1684
  }
1685
+ if (kind === "trigger") {
1686
+ validateWorkflowTriggerNodeLike(nodeId, value, diagnostics);
1687
+ return;
1688
+ }
1659
1689
  diagnostics.push({
1660
1690
  code: "WorkflowValidationError.unknownNodeKind",
1661
- message: `Workflow node '${nodeId}' must use kind agent, code, workflow, adapter, or human.`,
1691
+ message: `Workflow node '${nodeId}' must use kind trigger, agent, code, workflow, adapter, or human.`,
1662
1692
  severity: "error",
1663
1693
  path: `${path}.kind`,
1664
1694
  nodeId,
1665
1695
  hint: "Use one of the registered V2 editable node kinds.",
1666
1696
  });
1667
1697
  }
1698
+ function validateWorkflowTriggerNodeLike(nodeId, node, diagnostics) {
1699
+ const path = `$.nodes.${nodeId}`;
1700
+ const trigger = isJsonObject(node.trigger) ? node.trigger : undefined;
1701
+ if (!trigger) {
1702
+ diagnostics.push({
1703
+ code: "WorkflowValidationError.missingTriggerConfig",
1704
+ message: `Trigger node '${nodeId}' must include a trigger configuration object.`,
1705
+ severity: "error",
1706
+ path: `${path}.trigger`,
1707
+ nodeId,
1708
+ });
1709
+ return;
1710
+ }
1711
+ if (trigger.kind !== "manual") {
1712
+ diagnostics.push({
1713
+ code: "WorkflowValidationError.unsupportedTriggerKind",
1714
+ message: `Trigger node '${nodeId}' must use manual trigger kind in this Workflow V1 slice.`,
1715
+ severity: "error",
1716
+ path: `${path}.trigger.kind`,
1717
+ nodeId,
1718
+ hint: "Webhook, cron, and other trigger providers are planned but not implemented yet.",
1719
+ });
1720
+ }
1721
+ if (trigger.mode !== undefined && trigger.mode !== "editor" && trigger.mode !== "api") {
1722
+ diagnostics.push({
1723
+ code: "WorkflowValidationError.unsupportedTriggerMode",
1724
+ message: `Trigger node '${nodeId}' has unsupported manual trigger mode.`,
1725
+ severity: "error",
1726
+ path: `${path}.trigger.mode`,
1727
+ nodeId,
1728
+ });
1729
+ }
1730
+ if (!node.output) {
1731
+ diagnostics.push({
1732
+ code: "WorkflowValidationError.missingTriggerOutput",
1733
+ message: `Trigger node '${nodeId}' must declare an output port.`,
1734
+ severity: "error",
1735
+ path: `${path}.output`,
1736
+ nodeId,
1737
+ hint: "Use a text output port for the first manual trigger implementation.",
1738
+ });
1739
+ }
1740
+ }
1668
1741
  function validateWorkflowAgentNodeLike(nodeId, node, input, diagnostics) {
1669
1742
  const path = `$.nodes.${nodeId}`;
1670
1743
  if (node.runtime !== "pibo") {
@@ -3522,6 +3595,56 @@ export function createChatWebApp(options = {}) {
3522
3595
  const body = await readJsonBody(request);
3523
3596
  return responseJson({ asset: saveWorkflowPromptAssetRevision(state, webSession, body) }, { status: 201 });
3524
3597
  }
3598
+ const workflowDraftManualTriggerRun = workflowDraftManualTriggerRunResource(url.pathname);
3599
+ if (workflowDraftManualTriggerRun && request.method === "POST") {
3600
+ requireSameOriginJsonRequest(request);
3601
+ const webSession = await requireSession(request, context);
3602
+ const body = normalizeWorkflowDraftManualTriggerRunBody(await readJsonBody(request));
3603
+ const record = requireMutableWorkflowDraft(state, webSession, workflowDraftManualTriggerRun.draftId);
3604
+ const validation = runWorkflowDraftValidation(state, context, webSession, record, "before_workflow_start");
3605
+ if (!validation.validation.ok) {
3606
+ recordWorkflowLifecycleEvent(state, webSession, {
3607
+ type: "workflow.editor_test_run.blocked",
3608
+ workflowId: record.workflowId,
3609
+ workflowVersion: typeof record.definition.version === "string" ? record.definition.version : undefined,
3610
+ draftId: record.draftId,
3611
+ status: "blocked",
3612
+ validation: validation.validation,
3613
+ diagnostics: validation.diagnostics,
3614
+ payload: { triggerNodeId: body.triggerNodeId },
3615
+ });
3616
+ return workflowValidationBlockedResponse("Workflow draft has validation errors and cannot be test-run", validation, { draft: serializeWorkflowDraft(record) });
3617
+ }
3618
+ const result = await runWorkflowManualTextTrigger({
3619
+ definition: record.definition,
3620
+ triggerNodeId: body.triggerNodeId,
3621
+ input: body.input,
3622
+ actorId: auditActorIdFor(webSession),
3623
+ draftId: record.draftId,
3624
+ channelContext: context.channelContext,
3625
+ channel: CHAT_WEB_CHANNEL,
3626
+ defaultWorkspace: getDefaultPiboWorkspace(),
3627
+ onSessionCreated: (session) => state.sessionQuery.upsertSession(session),
3628
+ resolveProfile: (profileId) => resolveWorkflowRuntimeProfile({ context, requestedId: profileId }),
3629
+ });
3630
+ const diagnostics = result.ok ? validation.diagnostics : sanitizeWorkflowDiagnostics([...validation.diagnostics, ...result.diagnostics]);
3631
+ recordWorkflowLifecycleEvent(state, webSession, {
3632
+ type: result.ok ? "workflow.editor_test_run.completed" : "workflow.editor_test_run.failed",
3633
+ workflowId: record.workflowId,
3634
+ workflowVersion: typeof record.definition.version === "string" ? record.definition.version : undefined,
3635
+ draftId: record.draftId,
3636
+ workflowRunId: result.run?.id,
3637
+ status: result.ok ? "accepted" : "blocked",
3638
+ validation: validation.validation,
3639
+ diagnostics,
3640
+ payload: {
3641
+ triggerNodeId: body.triggerNodeId,
3642
+ ...(result.run?.status ? { status: result.run.status } : {}),
3643
+ ...(result.ok && result.output !== undefined ? { output: result.output } : {}),
3644
+ },
3645
+ });
3646
+ return responseJson(workflowManualTriggerRunResponse(result, { validation: validation.validation, diagnostics }, record), { status: result.ok ? 202 : 400 });
3647
+ }
3525
3648
  const workflowDraftAction = workflowDraftActionResource(url.pathname);
3526
3649
  if (workflowDraftAction && request.method === "POST") {
3527
3650
  requireSameOriginJsonRequest(request);
@@ -4024,7 +4147,7 @@ export function createChatWebApp(options = {}) {
4024
4147
  state.sessionQuery.upsertSession(selectedSession);
4025
4148
  const indexedSession = state.sessionQuery.getSession(selectedSession.id);
4026
4149
  const metadataStartedAt = performance.now();
4027
- const metadata = await loadPiSessionMetadata(selectedSession, selectedSession.workspace ?? process.cwd());
4150
+ const metadata = await loadPiSessionFastMetadata(selectedSession, selectedSession.workspace ?? process.cwd());
4028
4151
  const metadataMs = performance.now() - metadataStartedAt;
4029
4152
  const lastEventSequence = state.timelineQuery.getLatestEventSequence(selectedSession.id);
4030
4153
  const latestStreamId = state.timelineQuery.getLatestStreamId({ piboSessionId: selectedSession.id });
@@ -4075,9 +4198,11 @@ export function createChatWebApp(options = {}) {
4075
4198
  const lastEventSequence = state.timelineQuery.getLatestEventSequence(selectedSession.id);
4076
4199
  const latestStreamId = state.timelineQuery.getLatestStreamId({ piboSessionId: selectedSession.id });
4077
4200
  const liveSnapshots = timelineCursor.kind === "tail" ? state.outputCompactor.snapshotsForSession(selectedSession.id) : [];
4201
+ const metadataStartedAt = performance.now();
4078
4202
  const transcriptMetadata = timelineCursor.kind === "tail" || timelineCursor.kind === "transcript"
4079
- ? await loadPiSessionMetadata(selectedSession, selectedSession.workspace ?? process.cwd())
4203
+ ? await loadPiSessionFastMetadata(selectedSession, selectedSession.workspace ?? process.cwd())
4080
4204
  : undefined;
4205
+ metadataMs += performance.now() - metadataStartedAt;
4081
4206
  const baseVersion = createFastTraceV2Version({
4082
4207
  session: selectedSession,
4083
4208
  sessions: ownedSessions,