pi-sessions 0.8.0 → 0.10.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.
Files changed (111) hide show
  1. package/README.md +74 -37
  2. package/dist/session-messaging/broker/process.js +234 -0
  3. package/dist/shared/session-broker/framing.js +58 -0
  4. package/dist/shared/session-broker/protocol.js +163 -0
  5. package/dist/shared/session-broker/socket-path.js +19 -0
  6. package/dist/shared/typebox.js +36 -0
  7. package/extensions/pi-sessions.ts +125 -0
  8. package/extensions/session-ask/agent.ts +34 -14
  9. package/extensions/{session-ask.ts → session-ask/install.ts} +73 -90
  10. package/extensions/session-ask/navigate.ts +3 -1
  11. package/extensions/session-ask/presenter.ts +23 -0
  12. package/extensions/session-ask/renderer.ts +63 -0
  13. package/extensions/session-ask/tool-contract.ts +27 -0
  14. package/extensions/session-ask/view-model.ts +18 -0
  15. package/extensions/session-auto-title/generate.ts +18 -18
  16. package/extensions/{session-auto-title.ts → session-auto-title/install.ts} +60 -53
  17. package/extensions/session-auto-title/model.ts +25 -17
  18. package/extensions/session-auto-title/retitle.ts +17 -18
  19. package/extensions/session-auto-title/wizard.ts +12 -11
  20. package/extensions/session-handoff/board-view-model.ts +179 -0
  21. package/extensions/session-handoff/board.ts +663 -0
  22. package/extensions/session-handoff/bootstrap.ts +172 -0
  23. package/extensions/session-handoff/extract.ts +129 -132
  24. package/extensions/session-handoff/install.ts +225 -0
  25. package/extensions/session-handoff/kickoff.ts +92 -0
  26. package/extensions/session-handoff/launch/backend.ts +16 -0
  27. package/extensions/session-handoff/launch/deferred.ts +20 -0
  28. package/extensions/session-handoff/launch/ghostty.ts +99 -0
  29. package/extensions/session-handoff/launch/resolution.ts +57 -0
  30. package/extensions/session-handoff/launch/shell.ts +7 -0
  31. package/extensions/session-handoff/launch/tmux.ts +31 -0
  32. package/extensions/session-handoff/launch-options.ts +61 -0
  33. package/extensions/session-handoff/launch-target.ts +91 -0
  34. package/extensions/session-handoff/metadata.ts +194 -56
  35. package/extensions/session-handoff/model.ts +58 -0
  36. package/extensions/session-handoff/query.ts +0 -1
  37. package/extensions/session-handoff/receipt.ts +96 -0
  38. package/extensions/session-handoff/review.ts +2 -28
  39. package/extensions/session-handoff/spawn.ts +76 -181
  40. package/extensions/session-handoff/strong-modal.ts +13 -0
  41. package/extensions/session-handoff/tool-contract.ts +12 -0
  42. package/extensions/session-handoff/tool-presenter.ts +35 -0
  43. package/extensions/session-handoff/tool-renderer.ts +66 -0
  44. package/extensions/session-handoff/tool-schema.ts +54 -0
  45. package/extensions/session-handoff/tool-view-model.ts +49 -0
  46. package/extensions/session-handoff/tool.ts +206 -0
  47. package/extensions/session-handoff/ui.ts +66 -0
  48. package/extensions/session-hooks/install.ts +75 -0
  49. package/extensions/{session-index.ts → session-index/install.ts} +9 -7
  50. package/extensions/session-messaging/broker/process.ts +21 -28
  51. package/extensions/session-messaging/broker/spawn.ts +12 -7
  52. package/extensions/session-messaging/install.ts +78 -0
  53. package/extensions/session-messaging/pi/cancel-session-presenter.ts +64 -0
  54. package/extensions/session-messaging/pi/incoming-message-presenter.ts +32 -0
  55. package/extensions/session-messaging/pi/incoming-message-view-model.ts +20 -0
  56. package/extensions/session-messaging/pi/incoming-runtime.ts +27 -23
  57. package/extensions/session-messaging/pi/message-contracts.ts +32 -0
  58. package/extensions/session-messaging/pi/renderer.ts +19 -12
  59. package/extensions/session-messaging/pi/send-message-presenter.ts +39 -0
  60. package/extensions/session-messaging/pi/send-message-view-model.ts +54 -0
  61. package/extensions/session-messaging/pi/service.ts +262 -81
  62. package/extensions/session-messaging/pi/tools.ts +184 -40
  63. package/extensions/session-search/extract.ts +60 -14
  64. package/extensions/session-search/hooks.ts +10 -13
  65. package/extensions/session-search/install.ts +373 -0
  66. package/extensions/session-search/renderer.ts +195 -0
  67. package/extensions/session-search/tool-contract.ts +51 -0
  68. package/extensions/shared/composition.ts +20 -0
  69. package/extensions/shared/errors.ts +3 -0
  70. package/extensions/shared/model-resolution.ts +73 -0
  71. package/extensions/shared/model-runtime.ts +33 -0
  72. package/extensions/shared/model.ts +7 -10
  73. package/extensions/shared/rendering/collapsible-text.ts +89 -0
  74. package/extensions/shared/rendering/expandable-content-layout.ts +84 -0
  75. package/extensions/shared/rendering/theme.ts +5 -0
  76. package/extensions/shared/session-broker/client.ts +30 -29
  77. package/extensions/shared/session-broker/protocol.ts +128 -10
  78. package/extensions/shared/session-index/common.ts +5 -5
  79. package/extensions/shared/session-index/lineage.ts +0 -3
  80. package/extensions/shared/session-index/schema.ts +0 -1
  81. package/extensions/shared/session-index/scoring.ts +1 -2
  82. package/extensions/shared/session-index/search.ts +11 -4
  83. package/extensions/shared/session-index/store.ts +4 -9
  84. package/extensions/shared/settings.ts +83 -40
  85. package/extensions/shared/text.ts +5 -0
  86. package/extensions/shared/thinking-levels.ts +22 -0
  87. package/extensions/shared/tmux.ts +205 -0
  88. package/extensions/subagents/cancel.ts +111 -0
  89. package/extensions/subagents/classify.ts +58 -0
  90. package/extensions/subagents/install.ts +229 -0
  91. package/extensions/subagents/launch-target.ts +75 -0
  92. package/extensions/subagents/ledger.ts +217 -0
  93. package/extensions/subagents/reconcile.ts +386 -0
  94. package/extensions/subagents/report-message-presenter.ts +36 -0
  95. package/extensions/subagents/report-message-renderer.ts +21 -0
  96. package/extensions/subagents/report-message-view-model.ts +29 -0
  97. package/extensions/subagents/report.ts +159 -0
  98. package/extensions/subagents/roster.ts +262 -0
  99. package/extensions/subagents/settle.ts +182 -0
  100. package/extensions/subagents/wake.ts +173 -0
  101. package/images/handoff-board-subagents.png +0 -0
  102. package/images/handoff-board-user-sessions.png +0 -0
  103. package/images/handoff-subagent-report.png +0 -0
  104. package/images/session-handoff-tool.png +0 -0
  105. package/package.json +16 -18
  106. package/extensions/session-handoff.ts +0 -741
  107. package/extensions/session-hooks.ts +0 -75
  108. package/extensions/session-messaging/pi/message-view.ts +0 -131
  109. package/extensions/session-messaging.ts +0 -30
  110. package/extensions/session-search.ts +0 -419
  111. package/extensions/shared/session-broker/active.ts +0 -26
@@ -0,0 +1,179 @@
1
+ import { tmuxSessionName } from "../shared/tmux.ts";
2
+ import { isRunningSubagentState, type SubagentState } from "../subagents/classify.ts";
3
+ import type { SubagentRosterEntry } from "../subagents/roster.ts";
4
+ import { shellQuote } from "./launch/shell.ts";
5
+ import type { HandoffLaunchReceipt } from "./receipt.ts";
6
+
7
+ export type HandoffBoardTab = "subagents" | "user-sessions";
8
+ export type UserSessionStatus = "live" | "ready" | "starting" | "closed" | "unknown";
9
+
10
+ export interface UserSessionRunEvidence {
11
+ transcriptAvailable: boolean;
12
+ hasStarted: boolean;
13
+ }
14
+
15
+ export interface UserSessionEntry {
16
+ sessionId: string;
17
+ timestamp: string;
18
+ receipt: HandoffLaunchReceipt;
19
+ runEvidence?: UserSessionRunEvidence | undefined;
20
+ }
21
+
22
+ export interface HandoffBoardSnapshot {
23
+ subagents: readonly SubagentRosterEntry[];
24
+ userSessions: readonly UserSessionEntry[];
25
+ liveSessionIds: ReadonlySet<string>;
26
+ hasLiveSessionEvidence: boolean;
27
+ }
28
+
29
+ export interface HandoffBoardDetail {
30
+ label: string;
31
+ value: string;
32
+ }
33
+
34
+ export interface HandoffBoardAction {
35
+ subagent?: SubagentRosterEntry | undefined;
36
+ canStop: boolean;
37
+ observeCommand?: string | undefined;
38
+ resumeCommand?: string | undefined;
39
+ }
40
+
41
+ export interface HandoffSubagentRow {
42
+ kind: "subagent";
43
+ title: string;
44
+ depth: number;
45
+ status: SubagentState;
46
+ timestamp: string;
47
+ }
48
+
49
+ export interface UserSessionRow {
50
+ kind: "user-session";
51
+ title: string;
52
+ status: UserSessionStatus;
53
+ timestamp: string;
54
+ }
55
+
56
+ export interface HandoffSubagentsView {
57
+ tab: "subagents";
58
+ rows: readonly HandoffSubagentRow[];
59
+ details: readonly HandoffBoardDetail[];
60
+ action?: HandoffBoardAction | undefined;
61
+ }
62
+
63
+ export interface UserSessionsView {
64
+ tab: "user-sessions";
65
+ rows: readonly UserSessionRow[];
66
+ details: readonly HandoffBoardDetail[];
67
+ action?: HandoffBoardAction | undefined;
68
+ }
69
+
70
+ export type HandoffBoardView = HandoffSubagentsView | UserSessionsView;
71
+
72
+ export function buildHandoffBoardView(
73
+ snapshot: HandoffBoardSnapshot,
74
+ tab: HandoffBoardTab,
75
+ selectedIndex: number,
76
+ options: { insideTmux: boolean },
77
+ ): HandoffBoardView {
78
+ if (tab === "subagents") {
79
+ const selected = snapshot.subagents[selectedIndex];
80
+ return {
81
+ tab,
82
+ rows: snapshot.subagents.map((subagent) => ({
83
+ kind: "subagent",
84
+ title: subagent.title,
85
+ depth: subagent.depth,
86
+ status: subagent.state,
87
+ timestamp: subagent.launchedAt,
88
+ })),
89
+ details: selected
90
+ ? [
91
+ { label: "Session", value: selected.sessionId },
92
+ { label: "Model", value: selected.model ?? "Default" },
93
+ {
94
+ label: "Owner",
95
+ value: selected.ownerIsCurrentSession ? "this session" : selected.ownerTitle,
96
+ },
97
+ { label: "Goal", value: selected.goal },
98
+ ]
99
+ : [],
100
+ ...(selected ? { action: buildSubagentAction(selected, options.insideTmux) } : {}),
101
+ };
102
+ }
103
+
104
+ const rows = snapshot.userSessions.map(
105
+ (entry): UserSessionRow => ({
106
+ kind: "user-session",
107
+ title: entry.receipt.title,
108
+ status: getUserSessionStatus(snapshot, entry),
109
+ timestamp: entry.timestamp,
110
+ }),
111
+ );
112
+ const selected = snapshot.userSessions[selectedIndex];
113
+ if (!selected) {
114
+ return { tab, rows, details: [] };
115
+ }
116
+
117
+ const details: HandoffBoardDetail[] = [
118
+ { label: "Session", value: selected.sessionId },
119
+ { label: "Model", value: selected.receipt.model },
120
+ { label: "Launch", value: selected.receipt.launch },
121
+ ];
122
+ if (selected.receipt.backend) {
123
+ details.push({ label: "Backend", value: selected.receipt.backend });
124
+ }
125
+ if (selected.receipt.cwd) {
126
+ details.push({ label: "Directory", value: selected.receipt.cwd });
127
+ }
128
+ const action = buildUserSessionAction(snapshot, selected);
129
+ return {
130
+ tab,
131
+ rows,
132
+ details,
133
+ ...(action ? { action } : {}),
134
+ };
135
+ }
136
+
137
+ function getUserSessionStatus(
138
+ snapshot: HandoffBoardSnapshot,
139
+ entry: UserSessionEntry,
140
+ ): UserSessionStatus {
141
+ if (snapshot.liveSessionIds.has(entry.sessionId)) {
142
+ return "live";
143
+ }
144
+ const evidence = entry.runEvidence;
145
+ if (!evidence?.transcriptAvailable) {
146
+ return "unknown";
147
+ }
148
+ if (evidence.hasStarted) {
149
+ return snapshot.hasLiveSessionEvidence ? "closed" : "unknown";
150
+ }
151
+ return entry.receipt.launch === "deferred" ? "ready" : "starting";
152
+ }
153
+
154
+ function buildUserSessionAction(
155
+ snapshot: HandoffBoardSnapshot,
156
+ entry: UserSessionEntry,
157
+ ): HandoffBoardAction | undefined {
158
+ if (!snapshot.hasLiveSessionEvidence || snapshot.liveSessionIds.has(entry.sessionId)) {
159
+ return undefined;
160
+ }
161
+ return {
162
+ canStop: false,
163
+ resumeCommand: entry.receipt.resumeCommand,
164
+ };
165
+ }
166
+
167
+ function buildSubagentAction(entry: SubagentRosterEntry, insideTmux: boolean): HandoffBoardAction {
168
+ return {
169
+ subagent: entry,
170
+ canStop: isRunningSubagentState(entry.state),
171
+ ...(entry.tmuxWindowId ? { observeCommand: buildObserveCommand(entry, insideTmux) } : {}),
172
+ ...(!entry.managedLive ? { resumeCommand: entry.resumeCommand } : {}),
173
+ };
174
+ }
175
+
176
+ function buildObserveCommand(entry: SubagentRosterEntry, insideTmux: boolean): string {
177
+ const target = shellQuote(`${tmuxSessionName(entry.ownerSessionId)}:${entry.tmuxWindowId}`);
178
+ return insideTmux ? `tmux switch-client -t ${target}` : `tmux attach-session -t ${target}`;
179
+ }