pi-maestro-teammate 2.3.0 → 2.5.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.
package/agents/planner.md CHANGED
@@ -59,7 +59,8 @@ Return only Markdown for the Plan, with no preface, commentary, interview log, o
59
59
  Dependencies must form an executable DAG and identify safe parallel work. A task is a verifiable outcome, not a command or activity log.
60
60
  8. `## Validation`: specify exact commands or observable checks, expected results, requirement coverage, and relevant regression or integration boundaries.
61
61
  9. `## Risks and Recovery`: state concrete risks, mitigations, and rollback or recovery behavior.
62
- 10. `## Open Decisions`: list unresolved user-owned decisions. Write `None` only after evidence-based review; a Plan with unresolved decisions is not confirmation-ready.
62
+ 10. `## Knowledge Outcome`: require an end-of-execution assessment after implementation and verification. Name plausible candidate topics only when the work may produce a reusable non-obvious pitfall, failure lesson, trade-off, or prescriptive constraint; otherwise write `None expected` with a concrete reason. This section predicts what to assess—it must not fabricate knowledge in advance. Actual staging happens after approval in Act/Run mode, and the executor must explicitly report zero candidates when no result meets the project's knowledge quality bar.
63
+ 11. `## Open Decisions`: list unresolved user-owned decisions. Write `None` only after evidence-based review; a Plan with unresolved decisions is not confirmation-ready.
63
64
 
64
65
  Execution ownership: after the Plan is approved, implementation defaults to the project's `general-executor` agent (fallback: `general` when that role is not discovered). State this default in the Plan's Execution Plan section when it helps, and shape each task so a generic executor can consume it without rediscovery — concrete outcome, bounded scope, named files, acceptance criteria, and verification commands. Do not assume a workflow-task pipeline (`.task/TASK-*.json`) exists; the Plan must be executable by `general-executor` from the Plan text alone.
65
66
 
package/package.json CHANGED
@@ -1,221 +1,221 @@
1
- {
2
- "name": "pi-maestro-teammate",
3
- "version": "2.3.0",
4
- "description": "Pi extension — teammate agent dispatch with DAG task graphs, RPC messaging, and compact TUI",
5
- "type": "module",
6
- "engines": {
7
- "node": ">=22.19.0"
8
- },
9
- "bin": {
10
- "pi-teammate-broker": "./bin/pi-teammate-broker.mjs",
11
- "pi-teammate-models": "./bin/pi-teammate-models.mjs",
12
- "pi-teammate-outbox": "./bin/pi-teammate-outbox.mjs",
13
- "pi-teammate-remote": "./bin/pi-teammate-remote.mjs"
14
- },
15
- "keywords": [
16
- "pi-package",
17
- "pi-extension",
18
- "pi",
19
- "teammate",
20
- "agents"
21
- ],
22
- "scripts": {
23
- "test": "node --experimental-transform-types --import ./test/setup.ts --test --test-concurrency=2 \"test/*.test.ts\"",
24
- "typecheck": "tsc -p tsconfig.build.json",
25
- "build:declarations": "tsc -p tsconfig.declarations.json",
26
- "check:declarations": "node scripts/check-declarations.mjs",
27
- "prepack": "npm run build:declarations && node ../../scripts/bundle-settings-core.mjs",
28
- "postpack": "node ../../scripts/bundle-settings-core.mjs --clean",
29
- "test:e2e": "node --experimental-transform-types --import ./test/setup.ts --test --test-timeout=300000 test/backend-registry-dsh.e2e.test.ts",
30
- "refresh:acp-registry": "node scripts/refresh-acp-registry.mjs",
31
- "check:acp-registry": "node scripts/refresh-acp-registry.mjs --check"
32
- },
33
- "main": "./src/index.ts",
34
- "types": "./types/index.d.ts",
35
- "exports": {
36
- ".": {
37
- "types": "./types/index.d.ts",
38
- "default": "./src/index.ts"
39
- },
40
- "./v1": {
41
- "types": "./types/public/v1/index.d.ts",
42
- "default": "./src/public/v1/index.ts"
43
- },
44
- "./v1/acp-cli": {
45
- "types": "./types/backends/acp-cli.d.ts",
46
- "default": "./src/backends/acp-cli.ts"
47
- },
48
- "./v1/agents": {
49
- "types": "./types/public/v1/agents.d.ts",
50
- "default": "./src/public/v1/agents.ts"
51
- },
52
- "./v1/backends": {
53
- "types": "./types/public/v1/backends.d.ts",
54
- "default": "./src/public/v1/backends.ts"
55
- },
56
- "./v1/child-extensions": {
57
- "types": "./types/public/v1/child-extensions.d.ts",
58
- "default": "./src/public/v1/child-extensions.ts"
59
- },
60
- "./v1/events": {
61
- "types": "./types/public/v1/events.d.ts",
62
- "default": "./src/public/v1/events.ts"
63
- },
64
- "./v1/execution": {
65
- "types": "./types/public/v1/execution.d.ts",
66
- "default": "./src/public/v1/execution.ts"
67
- },
68
- "./v1/extension": {
69
- "types": "./types/public/v1/extension.d.ts",
70
- "default": "./src/public/v1/extension.ts"
71
- },
72
- "./v1/model-routing": {
73
- "types": "./types/public/v1/model-routing.d.ts",
74
- "default": "./src/public/v1/model-routing.ts"
75
- },
76
- "./v1/monitor-window-state": {
77
- "types": "./types/public/v1/monitor-window-state.d.ts",
78
- "default": "./src/public/v1/monitor-window-state.ts"
79
- },
80
- "./v1/cli-tools": {
81
- "types": "./types/public/v1/cli-tools.d.ts",
82
- "default": "./src/public/v1/cli-tools.ts"
83
- },
84
- "./v1/completion-durability": {
85
- "types": "./types/public/v1/completion-durability.d.ts",
86
- "default": "./src/public/v1/completion-durability.ts"
87
- },
88
- "./v1/mailbox": {
89
- "types": "./types/public/v1/mailbox.d.ts",
90
- "default": "./src/public/v1/mailbox.ts"
91
- },
92
- "./v1/observation": {
93
- "types": "./types/public/v1/observation.d.ts",
94
- "default": "./src/public/v1/observation.ts"
95
- },
96
- "./v1/progress-tree": {
97
- "types": "./types/public/v1/progress-tree.d.ts",
98
- "default": "./src/public/v1/progress-tree.ts"
99
- },
100
- "./v1/remote": {
101
- "types": "./types/public/v1/remote.d.ts",
102
- "default": "./src/public/v1/remote.ts"
103
- },
104
- "./v1/retry": {
105
- "types": "./types/public/v1/retry.d.ts",
106
- "default": "./src/public/v1/retry.ts"
107
- },
108
- "./v1/session-history": {
109
- "types": "./types/public/v1/session-history.d.ts",
110
- "default": "./src/public/v1/session-history.ts"
111
- },
112
- "./v1/scheduler": {
113
- "types": "./types/public/v1/scheduler.d.ts",
114
- "default": "./src/public/v1/scheduler.ts"
115
- },
116
- "./v1/sessions": {
117
- "types": "./types/public/v1/sessions.d.ts",
118
- "default": "./src/public/v1/sessions.ts"
119
- },
120
- "./v1/supervision": {
121
- "types": "./types/public/v1/supervision.d.ts",
122
- "default": "./src/public/v1/supervision.ts"
123
- },
124
- "./v1/ssh-hosts": {
125
- "types": "./types/public/v1/ssh-hosts.d.ts",
126
- "default": "./src/public/v1/ssh-hosts.ts"
127
- },
128
- "./v1/workspace-projections": {
129
- "types": "./types/public/v1/workspace-projections.d.ts",
130
- "default": "./src/public/v1/workspace-projections.ts"
131
- },
132
- "./v1/workspace-completion": {
133
- "types": "./types/public/v1/workspace-completion.d.ts",
134
- "default": "./src/public/v1/workspace-completion.ts"
135
- },
136
- "./v1/todo-context": {
137
- "types": "./types/public/v1/todo-context.d.ts",
138
- "default": "./src/public/v1/todo-context.ts"
139
- },
140
- "./v1/types": {
141
- "types": "./types/public/v1/types.d.ts",
142
- "default": "./src/public/v1/types.ts"
143
- },
144
- "./v2/runtime": {
145
- "types": "./types/public/v2/runtime.d.ts",
146
- "default": "./src/public/v2/runtime.ts"
147
- },
148
- "./v2/runtime-broker": {
149
- "types": "./types/public/v2/runtime-broker.d.ts",
150
- "default": "./src/public/v2/runtime-broker.ts"
151
- },
152
- "./src/*": "./src/*"
153
- },
154
- "deprecatedSubpaths": {
155
- "./src/*": "Compatibility only; use the versioned ./v1/* public API."
156
- },
157
- "files": [
158
- "bin/*.mjs",
159
- "src/**/*.{ts,json}",
160
- "types/**/*.d.ts",
161
- "agents/",
162
- "README.md"
163
- ],
164
- "pi": {
165
- "extensions": [
166
- "./src/extension/index.ts"
167
- ]
168
- },
169
- "peerDependencies": {
170
- "@earendil-works/pi-agent-core": "*",
171
- "@earendil-works/pi-ai": "*",
172
- "@earendil-works/pi-coding-agent": "*",
173
- "@earendil-works/pi-tui": "*",
174
- "typebox": "*"
175
- },
176
- "peerDependenciesMeta": {
177
- "@earendil-works/pi-agent-core": {
178
- "optional": true
179
- },
180
- "@earendil-works/pi-ai": {
181
- "optional": true
182
- },
183
- "@earendil-works/pi-coding-agent": {
184
- "optional": true
185
- },
186
- "@earendil-works/pi-tui": {
187
- "optional": true
188
- },
189
- "typebox": {
190
- "optional": true
191
- }
192
- },
193
- "dependencies": {
194
- "@agentclientprotocol/sdk": "1.3.0",
195
- "cross-spawn": "7.0.6",
196
- "jiti": "2.7.0",
197
- "pi-maestro-settings-core": "0.2.1",
198
- "pi-maestro-backend-core": "*",
199
- "pi-maestro-backends": "*",
200
- "proper-lockfile": "4.1.2",
201
- "ssh2": "1.17.0",
202
- "zod": "4.4.3"
203
- },
204
- "bundledDependencies": [
205
- "pi-maestro-settings-core"
206
- ],
207
- "devDependencies": {
208
- "@earendil-works/pi-agent-core": "0.84.4",
209
- "@types/cross-spawn": "6.0.6",
210
- "@earendil-works/pi-ai": "0.84.4",
211
- "@earendil-works/pi-coding-agent": "0.84.4",
212
- "@earendil-works/pi-tui": "0.84.4",
213
- "@types/ssh2": "1.15.5",
214
- "typebox": "1.3.7"
215
- },
216
- "directories": {
217
- "test": "test"
218
- },
219
- "author": "",
220
- "license": "ISC"
221
- }
1
+ {
2
+ "name": "pi-maestro-teammate",
3
+ "version": "2.5.0",
4
+ "description": "Pi extension — teammate agent dispatch with DAG task graphs, RPC messaging, and compact TUI",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=22.19.0"
8
+ },
9
+ "bin": {
10
+ "pi-teammate-broker": "./bin/pi-teammate-broker.mjs",
11
+ "pi-teammate-models": "./bin/pi-teammate-models.mjs",
12
+ "pi-teammate-outbox": "./bin/pi-teammate-outbox.mjs",
13
+ "pi-teammate-remote": "./bin/pi-teammate-remote.mjs"
14
+ },
15
+ "keywords": [
16
+ "pi-package",
17
+ "pi-extension",
18
+ "pi",
19
+ "teammate",
20
+ "agents"
21
+ ],
22
+ "scripts": {
23
+ "test": "node --experimental-transform-types --import ./test/setup.ts --test --test-concurrency=2 \"test/*.test.ts\"",
24
+ "typecheck": "tsc -p tsconfig.build.json",
25
+ "build:declarations": "tsc -p tsconfig.declarations.json",
26
+ "check:declarations": "node scripts/check-declarations.mjs",
27
+ "prepack": "npm run build:declarations && node ../../scripts/bundle-settings-core.mjs",
28
+ "postpack": "node ../../scripts/bundle-settings-core.mjs --clean",
29
+ "test:e2e": "node --experimental-transform-types --import ./test/setup.ts --test --test-timeout=300000 test/backend-registry-dsh.e2e.test.ts",
30
+ "refresh:acp-registry": "node scripts/refresh-acp-registry.mjs",
31
+ "check:acp-registry": "node scripts/refresh-acp-registry.mjs --check"
32
+ },
33
+ "main": "./src/index.ts",
34
+ "types": "./types/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./types/index.d.ts",
38
+ "default": "./src/index.ts"
39
+ },
40
+ "./v1": {
41
+ "types": "./types/public/v1/index.d.ts",
42
+ "default": "./src/public/v1/index.ts"
43
+ },
44
+ "./v1/acp-cli": {
45
+ "types": "./types/backends/acp-cli.d.ts",
46
+ "default": "./src/backends/acp-cli.ts"
47
+ },
48
+ "./v1/agents": {
49
+ "types": "./types/public/v1/agents.d.ts",
50
+ "default": "./src/public/v1/agents.ts"
51
+ },
52
+ "./v1/backends": {
53
+ "types": "./types/public/v1/backends.d.ts",
54
+ "default": "./src/public/v1/backends.ts"
55
+ },
56
+ "./v1/child-extensions": {
57
+ "types": "./types/public/v1/child-extensions.d.ts",
58
+ "default": "./src/public/v1/child-extensions.ts"
59
+ },
60
+ "./v1/events": {
61
+ "types": "./types/public/v1/events.d.ts",
62
+ "default": "./src/public/v1/events.ts"
63
+ },
64
+ "./v1/execution": {
65
+ "types": "./types/public/v1/execution.d.ts",
66
+ "default": "./src/public/v1/execution.ts"
67
+ },
68
+ "./v1/extension": {
69
+ "types": "./types/public/v1/extension.d.ts",
70
+ "default": "./src/public/v1/extension.ts"
71
+ },
72
+ "./v1/model-routing": {
73
+ "types": "./types/public/v1/model-routing.d.ts",
74
+ "default": "./src/public/v1/model-routing.ts"
75
+ },
76
+ "./v1/monitor-window-state": {
77
+ "types": "./types/public/v1/monitor-window-state.d.ts",
78
+ "default": "./src/public/v1/monitor-window-state.ts"
79
+ },
80
+ "./v1/cli-tools": {
81
+ "types": "./types/public/v1/cli-tools.d.ts",
82
+ "default": "./src/public/v1/cli-tools.ts"
83
+ },
84
+ "./v1/completion-durability": {
85
+ "types": "./types/public/v1/completion-durability.d.ts",
86
+ "default": "./src/public/v1/completion-durability.ts"
87
+ },
88
+ "./v1/mailbox": {
89
+ "types": "./types/public/v1/mailbox.d.ts",
90
+ "default": "./src/public/v1/mailbox.ts"
91
+ },
92
+ "./v1/observation": {
93
+ "types": "./types/public/v1/observation.d.ts",
94
+ "default": "./src/public/v1/observation.ts"
95
+ },
96
+ "./v1/progress-tree": {
97
+ "types": "./types/public/v1/progress-tree.d.ts",
98
+ "default": "./src/public/v1/progress-tree.ts"
99
+ },
100
+ "./v1/remote": {
101
+ "types": "./types/public/v1/remote.d.ts",
102
+ "default": "./src/public/v1/remote.ts"
103
+ },
104
+ "./v1/retry": {
105
+ "types": "./types/public/v1/retry.d.ts",
106
+ "default": "./src/public/v1/retry.ts"
107
+ },
108
+ "./v1/session-history": {
109
+ "types": "./types/public/v1/session-history.d.ts",
110
+ "default": "./src/public/v1/session-history.ts"
111
+ },
112
+ "./v1/scheduler": {
113
+ "types": "./types/public/v1/scheduler.d.ts",
114
+ "default": "./src/public/v1/scheduler.ts"
115
+ },
116
+ "./v1/sessions": {
117
+ "types": "./types/public/v1/sessions.d.ts",
118
+ "default": "./src/public/v1/sessions.ts"
119
+ },
120
+ "./v1/supervision": {
121
+ "types": "./types/public/v1/supervision.d.ts",
122
+ "default": "./src/public/v1/supervision.ts"
123
+ },
124
+ "./v1/ssh-hosts": {
125
+ "types": "./types/public/v1/ssh-hosts.d.ts",
126
+ "default": "./src/public/v1/ssh-hosts.ts"
127
+ },
128
+ "./v1/workspace-projections": {
129
+ "types": "./types/public/v1/workspace-projections.d.ts",
130
+ "default": "./src/public/v1/workspace-projections.ts"
131
+ },
132
+ "./v1/workspace-completion": {
133
+ "types": "./types/public/v1/workspace-completion.d.ts",
134
+ "default": "./src/public/v1/workspace-completion.ts"
135
+ },
136
+ "./v1/todo-context": {
137
+ "types": "./types/public/v1/todo-context.d.ts",
138
+ "default": "./src/public/v1/todo-context.ts"
139
+ },
140
+ "./v1/types": {
141
+ "types": "./types/public/v1/types.d.ts",
142
+ "default": "./src/public/v1/types.ts"
143
+ },
144
+ "./v2/runtime": {
145
+ "types": "./types/public/v2/runtime.d.ts",
146
+ "default": "./src/public/v2/runtime.ts"
147
+ },
148
+ "./v2/runtime-broker": {
149
+ "types": "./types/public/v2/runtime-broker.d.ts",
150
+ "default": "./src/public/v2/runtime-broker.ts"
151
+ },
152
+ "./src/*": "./src/*"
153
+ },
154
+ "deprecatedSubpaths": {
155
+ "./src/*": "Compatibility only; use the versioned ./v1/* public API."
156
+ },
157
+ "files": [
158
+ "bin/*.mjs",
159
+ "src/**/*.{ts,json}",
160
+ "types/**/*.d.ts",
161
+ "agents/",
162
+ "README.md"
163
+ ],
164
+ "pi": {
165
+ "extensions": [
166
+ "./src/extension/index.ts"
167
+ ]
168
+ },
169
+ "peerDependencies": {
170
+ "@earendil-works/pi-agent-core": "*",
171
+ "@earendil-works/pi-ai": "*",
172
+ "@earendil-works/pi-coding-agent": "*",
173
+ "@earendil-works/pi-tui": "*",
174
+ "typebox": "*"
175
+ },
176
+ "peerDependenciesMeta": {
177
+ "@earendil-works/pi-agent-core": {
178
+ "optional": true
179
+ },
180
+ "@earendil-works/pi-ai": {
181
+ "optional": true
182
+ },
183
+ "@earendil-works/pi-coding-agent": {
184
+ "optional": true
185
+ },
186
+ "@earendil-works/pi-tui": {
187
+ "optional": true
188
+ },
189
+ "typebox": {
190
+ "optional": true
191
+ }
192
+ },
193
+ "dependencies": {
194
+ "@agentclientprotocol/sdk": "1.3.0",
195
+ "cross-spawn": "7.0.6",
196
+ "jiti": "2.7.0",
197
+ "pi-maestro-settings-core": "0.2.1",
198
+ "pi-maestro-backend-core": "*",
199
+ "pi-maestro-backends": "*",
200
+ "proper-lockfile": "4.1.2",
201
+ "ssh2": "1.17.0",
202
+ "zod": "4.4.3"
203
+ },
204
+ "bundledDependencies": [
205
+ "pi-maestro-settings-core"
206
+ ],
207
+ "devDependencies": {
208
+ "@earendil-works/pi-agent-core": "0.84.4",
209
+ "@types/cross-spawn": "6.0.6",
210
+ "@earendil-works/pi-ai": "0.84.4",
211
+ "@earendil-works/pi-coding-agent": "0.84.4",
212
+ "@earendil-works/pi-tui": "0.84.4",
213
+ "@types/ssh2": "1.15.5",
214
+ "typebox": "1.3.7"
215
+ },
216
+ "directories": {
217
+ "test": "test"
218
+ },
219
+ "author": "",
220
+ "license": "ISC"
221
+ }
@@ -381,7 +381,7 @@ interface ChildCompactionStateEvent {
381
381
  type: "teammate_compaction_state";
382
382
  recoveryId: string;
383
383
  generation: number;
384
- phase: "pending" | "continuation" | "completed" | "failed";
384
+ phase: "pending" | "continuation" | "completed" | "failed" | "cancelled";
385
385
  reason?: string;
386
386
  }
387
387
 
@@ -392,7 +392,8 @@ function childCompactionStateEvent(message: Record<string, unknown>): ChildCompa
392
392
  || (message.phase !== "pending"
393
393
  && message.phase !== "continuation"
394
394
  && message.phase !== "completed"
395
- && message.phase !== "failed")) return undefined;
395
+ && message.phase !== "failed"
396
+ && message.phase !== "cancelled")) return undefined;
396
397
  return {
397
398
  type: "teammate_compaction_state",
398
399
  recoveryId: message.recoveryId,
@@ -1364,6 +1365,17 @@ export async function runSingleAttempt(
1364
1365
  const eventKey = compactionRecoveryKey(event);
1365
1366
  if (closedCompactionRecoveries.has(eventKey)) return;
1366
1367
  const active = state.compactionRecovery;
1368
+ if (event.phase === "cancelled") {
1369
+ if (active && (active.generation !== event.generation || active.recoveryId !== event.recoveryId)) return;
1370
+ closedCompactionRecoveries.add(eventKey);
1371
+ state.compactionRecovery = undefined;
1372
+ compactionSettlementSwallowed = false;
1373
+ if (timers.compactionRecovery) {
1374
+ clearTimeout(timers.compactionRecovery);
1375
+ timers.compactionRecovery = undefined;
1376
+ }
1377
+ return;
1378
+ }
1367
1379
  const phaseRank = { pending: 0, completed: 1, continuation: 2 } as const;
1368
1380
  let phaseAdvanced = false;
1369
1381
  if (active) {
@@ -1813,11 +1813,15 @@ async function withWorkspaceOwnerClaimMutex<T>(
1813
1813
 
1814
1814
  const current = await inspectBoundedJson(lockPath, OWNER_CLAIM_LOCK_FILE_MAX_BYTES);
1815
1815
  const record = validateWorkspaceOwnerClaimLockRecord(current?.value);
1816
+ // PIDs are recyclable, so acquiredAt is also a hard lease bound for valid locks.
1817
+ const recordStale = record !== undefined
1818
+ && (Math.abs(acquiredAt - record.acquiredAt) > OWNER_CLAIM_LOCK_STALE_MS
1819
+ || !processIsAlive(record.pid));
1816
1820
  const changedAt = current ? Math.max(current.mtimeMs, current.ctimeMs) : acquiredAt;
1817
1821
  const malformedStale = current !== undefined
1818
1822
  && record === undefined
1819
1823
  && Math.abs(acquiredAt - changedAt) > OWNER_CLAIM_LOCK_STALE_MS;
1820
- if (current && (record && !processIsAlive(record.pid) || malformedStale)) {
1824
+ if (current && (recordStale || malformedStale)) {
1821
1825
  await quarantinePrivateFileIfUnchanged(lockPath, current, OWNER_CLAIM_LOCK_FILE_MAX_BYTES).catch(() => false);
1822
1826
  continue;
1823
1827
  }
@@ -99,6 +99,7 @@ export interface SessionHistoryOptions {
99
99
  export type SessionHistoryListOptions = SessionHistoryOptions;
100
100
  export type SessionHistorySearchOptions = SessionHistoryOptions;
101
101
  export type SessionHistoryReadOptions = SessionHistoryOptions;
102
+ export type SessionHistoryCompactionOptions = Omit<SessionHistoryOptions, "include">;
102
103
 
103
104
  export interface SessionHistorySession {
104
105
  sessionId: string;
@@ -161,6 +162,12 @@ export interface SessionHistorySearchResult extends ScanMetrics {
161
162
  matches: readonly SessionHistorySearchMatch[];
162
163
  matchCount: number;
163
164
  }
165
+ export interface SessionHistoryCompactionResult extends ScanMetrics {
166
+ version: typeof SESSION_HISTORY_VERSION;
167
+ generation?: number;
168
+ checkpoints: readonly SessionHistoryEntry[];
169
+ checkpointCount: number;
170
+ }
164
171
  export interface SessionHistoryEntryRead {
165
172
  sessionId: string;
166
173
  entryId: string;
@@ -296,6 +303,26 @@ export class SessionHistoryService {
296
303
  return this.search(query, options);
297
304
  }
298
305
 
306
+ async compactions(options: SessionHistoryCompactionOptions = {}): Promise<SessionHistoryCompactionResult> {
307
+ const limit = boundedLimit(options.limit);
308
+ const scan = await this.#scan(new Set<SessionHistoryInclude>(["compaction"]), options.signal);
309
+ const all = scan.sessions
310
+ .flatMap((session) => session.entries)
311
+ .filter((entry) => entry.kind === "compaction")
312
+ .sort((left, right) => right.timestamp - left.timestamp || right.entryId.localeCompare(left.entryId));
313
+ const checkpoints = all.slice(0, limit);
314
+ return resultWithMetrics(scan, {
315
+ version: SESSION_HISTORY_VERSION,
316
+ ...(scan.generation === undefined ? {} : { generation: scan.generation }),
317
+ checkpoints: Object.freeze(checkpoints),
318
+ checkpointCount: all.length,
319
+ }, all.length - checkpoints.length);
320
+ }
321
+
322
+ async listCompactions(options: SessionHistoryCompactionOptions = {}): Promise<SessionHistoryCompactionResult> {
323
+ return this.compactions(options);
324
+ }
325
+
299
326
  async read(sessionId: string, options?: SessionHistoryReadOptions): Promise<SessionHistoryReadResult>;
300
327
  async read(request: SessionHistoryReadRequest): Promise<SessionHistoryReadResult>;
301
328
  async read(
@@ -418,6 +445,9 @@ export function listSessionHistory(source: SessionHistoryInventorySource | Sessi
418
445
  export function searchSessionHistory(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, query: string, options: SessionHistorySearchOptions = {}): Promise<SessionHistorySearchResult> {
419
446
  return createSessionHistoryService(source).search(query, options);
420
447
  }
448
+ export function listSessionCompactions(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, options: SessionHistoryCompactionOptions = {}): Promise<SessionHistoryCompactionResult> {
449
+ return createSessionHistoryService(source).compactions(options);
450
+ }
421
451
  export function readSessionHistory(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, request: SessionHistoryReadRequest): Promise<SessionHistoryReadResult> {
422
452
  return createSessionHistoryService(source).read(request);
423
453
  }
@@ -60,6 +60,7 @@ export interface SessionHistoryOptions {
60
60
  export type SessionHistoryListOptions = SessionHistoryOptions;
61
61
  export type SessionHistorySearchOptions = SessionHistoryOptions;
62
62
  export type SessionHistoryReadOptions = SessionHistoryOptions;
63
+ export type SessionHistoryCompactionOptions = Omit<SessionHistoryOptions, "include">;
63
64
  export interface SessionHistorySession {
64
65
  sessionId: string;
65
66
  resourceUri: string;
@@ -117,6 +118,12 @@ export interface SessionHistorySearchResult extends ScanMetrics {
117
118
  matches: readonly SessionHistorySearchMatch[];
118
119
  matchCount: number;
119
120
  }
121
+ export interface SessionHistoryCompactionResult extends ScanMetrics {
122
+ version: typeof SESSION_HISTORY_VERSION;
123
+ generation?: number;
124
+ checkpoints: readonly SessionHistoryEntry[];
125
+ checkpointCount: number;
126
+ }
120
127
  export interface SessionHistoryEntryRead {
121
128
  sessionId: string;
122
129
  entryId: string;
@@ -154,6 +161,8 @@ export declare class SessionHistoryService {
154
161
  listSessions(options?: SessionHistoryListOptions): Promise<SessionHistoryListResult>;
155
162
  search(query: string, options?: SessionHistorySearchOptions): Promise<SessionHistorySearchResult>;
156
163
  searchSessions(query: string, options?: SessionHistorySearchOptions): Promise<SessionHistorySearchResult>;
164
+ compactions(options?: SessionHistoryCompactionOptions): Promise<SessionHistoryCompactionResult>;
165
+ listCompactions(options?: SessionHistoryCompactionOptions): Promise<SessionHistoryCompactionResult>;
157
166
  read(sessionId: string, options?: SessionHistoryReadOptions): Promise<SessionHistoryReadResult>;
158
167
  read(request: SessionHistoryReadRequest): Promise<SessionHistoryReadResult>;
159
168
  readSession(sessionId: string, options?: SessionHistoryReadOptions): Promise<SessionHistoryReadResult>;
@@ -164,6 +173,7 @@ export declare class SessionHistoryService {
164
173
  export declare function createSessionHistoryService(source: SessionHistoryInventorySource | SessionHistoryServiceOptions): SessionHistoryService;
165
174
  export declare function listSessionHistory(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, options?: SessionHistoryListOptions): Promise<SessionHistoryListResult>;
166
175
  export declare function searchSessionHistory(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, query: string, options?: SessionHistorySearchOptions): Promise<SessionHistorySearchResult>;
176
+ export declare function listSessionCompactions(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, options?: SessionHistoryCompactionOptions): Promise<SessionHistoryCompactionResult>;
167
177
  export declare function readSessionHistory(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, request: SessionHistoryReadRequest): Promise<SessionHistoryReadResult>;
168
178
  export declare function readSessionHistoryEntry(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, sessionId: string, entryId: string, options?: SessionHistoryReadOptions): Promise<SessionHistoryEntryRead | undefined>;
169
179
  export declare function readSessionHistoryTurn(source: SessionHistoryInventorySource | SessionHistoryServiceOptions, sessionId: string, turn: number, options?: SessionHistoryReadOptions): Promise<SessionHistoryTurn | undefined>;