pi-advisor-flow 0.11.2-dev.1 → 0.11.2-dev.2
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/CHANGELOG.md +5 -0
- package/README.md +1 -1
- package/dist/index.js +33 -4
- package/package.json +1 -1
- package/src/conversation.ts +2 -2
- package/src/images.ts +4 -4
- package/src/scout-context.ts +2 -1
- package/src/session-context.ts +52 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,11 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
9
9
|
### Fixed
|
|
10
10
|
|
|
11
11
|
- Avoided a startup crash when a host omits `systemPromptOptions` from `before_agent_start`.
|
|
12
|
+
- Prevented OMP's legacy session-history fallback from disclosing entries or images before the latest reset boundary or outside the latest compaction's retained range.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Documented support for OMP session managers without Pi's `buildContextEntries()` projection.
|
|
12
17
|
|
|
13
18
|
## 0.11.1 - 2026-10-04
|
|
14
19
|
|
package/README.md
CHANGED
|
@@ -151,7 +151,7 @@ Advisor Scout is off by default. When enabled in `/advisor-settings` or via `"ad
|
|
|
151
151
|
|
|
152
152
|
Advisor requests can include user messages, tool calls, tool results, targeted questions, trusted project and global `AGENTS.md` rules, and repository information. `advisorAgentsMdContext` is on by default and can be disabled in `/advisor-settings`; rules are sent as origin-labelled, capped, redacted, untrusted review guidance only. Untrusted projects withhold both rule files and tell the Advisor that rules were withheld. Repository context is configurable from no access through changed-file summaries to a capped patch; when it is disabled, the Advisor is told so rather than shown an apparently clean tree. Images from disclosed conversation and full-policy tool results can be sent as pixels only to image-capable Advisor models; Scout sees markers, not pixels. Exact tracked and untracked image files can be attached using `includeTrackedFiles` and `includeUntracked` under their existing separate global consent rules. Images are limited to four and 8 MiB total, with a 4 MiB per-image cap; unsupported, missing, or oversized images are reported as withheld, not reviewed. Explicit tracked and untracked file contents require separate global opt-ins and are sent as untrusted data. Secret redaction is off by default; when enabled, credential-shaped values in targeted questions are redacted before the provider request. Tools without an explicit policy use full context. Settings are global, so a project cannot silently change them.
|
|
153
153
|
|
|
154
|
-
When Scout is enabled, the Executor model provider also receives bounded Advisor-eligible conversation history. Read [Privacy and data handling](https://github.com/philipbrembeck/pi-advisor/blob/main/docs/privacy.md) before using pi-advisor with sensitive work.
|
|
154
|
+
When Scout is enabled, the Executor model provider also receives bounded Advisor-eligible conversation history. Pi's `buildContextEntries()` projection is used when available. OMP-compatible session managers without that API are supported through the active branch, with the latest reset boundary and compaction's retained range applied before history or images are disclosed; cleared and compacted-out entries are not forwarded. Read [Privacy and data handling](https://github.com/philipbrembeck/pi-advisor/blob/main/docs/privacy.md) before using pi-advisor with sensitive work.
|
|
155
155
|
|
|
156
156
|
## Documentation
|
|
157
157
|
|
package/dist/index.js
CHANGED
|
@@ -2403,6 +2403,35 @@ var detectImageFormat = (bytes) => {
|
|
|
2403
2403
|
}
|
|
2404
2404
|
};
|
|
2405
2405
|
|
|
2406
|
+
// src/session-context.ts
|
|
2407
|
+
var projectBranch = (source) => {
|
|
2408
|
+
const resetBoundaryIndex = source.findLastIndex((entry) => Object.is(entry.type, "reset_boundary"));
|
|
2409
|
+
const branch = source.slice(resetBoundaryIndex + 1);
|
|
2410
|
+
const compactionIndex = branch.findLastIndex((entry) => entry.type === "compaction");
|
|
2411
|
+
if (compactionIndex === -1) {
|
|
2412
|
+
return branch;
|
|
2413
|
+
}
|
|
2414
|
+
const compaction = branch[compactionIndex];
|
|
2415
|
+
if (compaction.type !== "compaction") {
|
|
2416
|
+
return branch;
|
|
2417
|
+
}
|
|
2418
|
+
const firstKeptIndex = branch.findIndex((entry, index) => index < compactionIndex && entry.id === compaction.firstKeptEntryId);
|
|
2419
|
+
const projected = [compaction];
|
|
2420
|
+
if (firstKeptIndex !== -1) {
|
|
2421
|
+
for (let index = firstKeptIndex;index < compactionIndex; index += 1) {
|
|
2422
|
+
const entry = branch[index];
|
|
2423
|
+
if (entry.type !== "compaction" && !(entry.type === "message" && entry.message.role === "system")) {
|
|
2424
|
+
projected.push(entry);
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
return [...projected, ...branch.slice(compactionIndex + 1)];
|
|
2429
|
+
};
|
|
2430
|
+
var sessionContextEntries = (ctx) => {
|
|
2431
|
+
const sessionManager = ctx.sessionManager;
|
|
2432
|
+
return sessionManager.buildContextEntries ? sessionManager.buildContextEntries() : projectBranch(sessionManager.getBranch());
|
|
2433
|
+
};
|
|
2434
|
+
|
|
2406
2435
|
// src/images.ts
|
|
2407
2436
|
var ADVISOR_IMAGE_MAX_BYTES = 4 * 1024 * 1024;
|
|
2408
2437
|
var ADVISOR_IMAGES_TOTAL_MAX_BYTES = 8 * 1024 * 1024;
|
|
@@ -2465,12 +2494,12 @@ var selectedConversationImages = (ctx, conversation, policies, selectedEntryIds,
|
|
|
2465
2494
|
if (!conversation) {
|
|
2466
2495
|
return { imagePartsSeen: 0, selected: [] };
|
|
2467
2496
|
}
|
|
2468
|
-
const entries =
|
|
2497
|
+
const entries = sessionContextEntries(ctx);
|
|
2469
2498
|
const images = [];
|
|
2470
2499
|
const seen = new Set;
|
|
2471
2500
|
let imagePartsSeen = 0;
|
|
2472
2501
|
for (const [index, entry] of entries.entries()) {
|
|
2473
|
-
if (entry.type !== "message" || selectedEntryIds && !selectedEntryIds.has(entry.id ?? String(index))) {
|
|
2502
|
+
if (entry.type !== "message" || selectedEntryIds !== undefined && !selectedEntryIds.has(entry.id ?? String(index))) {
|
|
2474
2503
|
continue;
|
|
2475
2504
|
}
|
|
2476
2505
|
const { message } = entry;
|
|
@@ -2832,7 +2861,7 @@ var recentConversation = (ctx, maxChars = 15000, toolResultMaxLines = advisorToo
|
|
|
2832
2861
|
if (maxChars === 0) {
|
|
2833
2862
|
return "";
|
|
2834
2863
|
}
|
|
2835
|
-
const entries = ctx
|
|
2864
|
+
const entries = sessionContextEntries(ctx).map((entry) => conversationEntry(entry, toolResultMaxLines, toolResultMaxBytes, policies, redact, describeImages, imageNonce)).filter((entry) => entry !== undefined);
|
|
2836
2865
|
return selectRecentEntries(entries, maxChars);
|
|
2837
2866
|
};
|
|
2838
2867
|
|
|
@@ -3245,7 +3274,7 @@ var fitToBudget = (built, caps) => {
|
|
|
3245
3274
|
};
|
|
3246
3275
|
};
|
|
3247
3276
|
var buildScoutManifest = (ctx, options = {}) => {
|
|
3248
|
-
const entries = ctx
|
|
3277
|
+
const entries = sessionContextEntries(ctx);
|
|
3249
3278
|
const caps = resolveCaps(options);
|
|
3250
3279
|
const indexed = indexToolCalls(entries);
|
|
3251
3280
|
if (!indexed.ok) {
|
package/package.json
CHANGED
package/src/conversation.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { contentParts, isRecordOf, isString } from "./content-utils.ts";
|
|
|
11
11
|
import type { RecordValue } from "./content-utils.ts";
|
|
12
12
|
import { imageMarker } from "./images.ts";
|
|
13
13
|
import { redactSecrets } from "./redaction.ts";
|
|
14
|
+
import { sessionContextEntries } from "./session-context.ts";
|
|
14
15
|
import { capToolResult } from "./tool-result-cap.ts";
|
|
15
16
|
|
|
16
17
|
const textFromPart = <Part>(part: Part): string => {
|
|
@@ -204,8 +205,7 @@ export const recentConversation = (
|
|
|
204
205
|
if (maxChars === 0) {
|
|
205
206
|
return "";
|
|
206
207
|
}
|
|
207
|
-
const entries = ctx
|
|
208
|
-
.getBranch()
|
|
208
|
+
const entries = sessionContextEntries(ctx)
|
|
209
209
|
.map((entry) =>
|
|
210
210
|
conversationEntry(
|
|
211
211
|
entry,
|
package/src/images.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { AdvisorToolPolicies } from "./config/types.ts";
|
|
|
7
7
|
import { contentParts, isRecordOf, isString } from "./content-utils.ts";
|
|
8
8
|
import type { RecordValue } from "./content-utils.ts";
|
|
9
9
|
import { detectImageFormat } from "./image-validation.ts";
|
|
10
|
+
import { sessionContextEntries } from "./session-context.ts";
|
|
10
11
|
|
|
11
12
|
export const ADVISOR_IMAGE_MAX_BYTES = 4 * 1024 * 1024;
|
|
12
13
|
export const ADVISOR_IMAGES_TOTAL_MAX_BYTES = 8 * 1024 * 1024;
|
|
@@ -120,16 +121,15 @@ export const selectedConversationImages = (
|
|
|
120
121
|
if (!conversation) {
|
|
121
122
|
return { imagePartsSeen: 0, selected: [] };
|
|
122
123
|
}
|
|
123
|
-
const entries =
|
|
124
|
-
? ctx.sessionManager.buildContextEntries()
|
|
125
|
-
: ctx.sessionManager.getBranch();
|
|
124
|
+
const entries = sessionContextEntries(ctx);
|
|
126
125
|
const images: SelectedImage[] = [];
|
|
127
126
|
const seen = new Set<string>();
|
|
128
127
|
let imagePartsSeen = 0;
|
|
129
128
|
for (const [index, entry] of entries.entries()) {
|
|
130
129
|
if (
|
|
131
130
|
entry.type !== "message" ||
|
|
132
|
-
(selectedEntryIds
|
|
131
|
+
(selectedEntryIds !== undefined &&
|
|
132
|
+
!selectedEntryIds.has(entry.id ?? String(index)))
|
|
133
133
|
) {
|
|
134
134
|
continue;
|
|
135
135
|
}
|
package/src/scout-context.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
ScoutContextGroup,
|
|
20
20
|
ScoutManifestResult,
|
|
21
21
|
} from "./scout-types.ts";
|
|
22
|
+
import { sessionContextEntries } from "./session-context.ts";
|
|
22
23
|
|
|
23
24
|
// Re-exports preserve scout-context's historical public import surface.
|
|
24
25
|
export { reconstructScoutConversation } from "./scout-reconstruct.ts";
|
|
@@ -174,7 +175,7 @@ export const buildScoutManifest = (
|
|
|
174
175
|
ctx: ExtensionContext,
|
|
175
176
|
options: BuildScoutManifestOptions = {}
|
|
176
177
|
): ScoutManifestResult => {
|
|
177
|
-
const entries = ctx
|
|
178
|
+
const entries = sessionContextEntries(ctx);
|
|
178
179
|
const caps = resolveCaps(options);
|
|
179
180
|
const indexed = indexToolCalls(entries);
|
|
180
181
|
if (!indexed.ok) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ExtensionContext,
|
|
3
|
+
SessionEntry,
|
|
4
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5
|
+
|
|
6
|
+
type SessionManagerWithContextEntries = ExtensionContext["sessionManager"] & {
|
|
7
|
+
buildContextEntries?: () => SessionEntry[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const projectBranch = (source: SessionEntry[]): SessionEntry[] => {
|
|
11
|
+
const resetBoundaryIndex = source.findLastIndex((entry) =>
|
|
12
|
+
Object.is(entry.type, "reset_boundary")
|
|
13
|
+
);
|
|
14
|
+
const branch = source.slice(resetBoundaryIndex + 1);
|
|
15
|
+
const compactionIndex = branch.findLastIndex(
|
|
16
|
+
(entry) => entry.type === "compaction"
|
|
17
|
+
);
|
|
18
|
+
if (compactionIndex === -1) {
|
|
19
|
+
return branch;
|
|
20
|
+
}
|
|
21
|
+
const compaction = branch[compactionIndex];
|
|
22
|
+
if (compaction.type !== "compaction") {
|
|
23
|
+
return branch;
|
|
24
|
+
}
|
|
25
|
+
const firstKeptIndex = branch.findIndex(
|
|
26
|
+
(entry, index) =>
|
|
27
|
+
index < compactionIndex && entry.id === compaction.firstKeptEntryId
|
|
28
|
+
);
|
|
29
|
+
const projected: SessionEntry[] = [compaction];
|
|
30
|
+
if (firstKeptIndex !== -1) {
|
|
31
|
+
for (let index = firstKeptIndex; index < compactionIndex; index += 1) {
|
|
32
|
+
const entry = branch[index];
|
|
33
|
+
if (
|
|
34
|
+
entry.type !== "compaction" &&
|
|
35
|
+
!(entry.type === "message" && entry.message.role === "system")
|
|
36
|
+
) {
|
|
37
|
+
projected.push(entry);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return [...projected, ...branch.slice(compactionIndex + 1)];
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const sessionContextEntries = (
|
|
45
|
+
ctx: ExtensionContext
|
|
46
|
+
): SessionEntry[] => {
|
|
47
|
+
// SAFETY: older hosts lack projection; retain reset and compaction boundaries before disclosure.
|
|
48
|
+
const sessionManager = ctx.sessionManager as SessionManagerWithContextEntries;
|
|
49
|
+
return sessionManager.buildContextEntries
|
|
50
|
+
? sessionManager.buildContextEntries()
|
|
51
|
+
: projectBranch(sessionManager.getBranch());
|
|
52
|
+
};
|