pi-ui-extend 0.1.45 → 0.1.47
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/dist/app/session/tabs-controller.d.ts +1 -0
- package/dist/app/session/tabs-controller.js +15 -3
- package/external/pi-tools-suite/package.json +3 -3
- package/external/pi-tools-suite/src/dcp/index.ts +25 -9
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +73 -13
- package/package.json +4 -4
|
@@ -107,6 +107,7 @@ export declare class AppTabsController {
|
|
|
107
107
|
private observeRuntimeForTab;
|
|
108
108
|
private shouldSyncTabFromRuntimeEvent;
|
|
109
109
|
private shouldScheduleDelayedSyncForRuntimeEvent;
|
|
110
|
+
private shouldInvalidateCachedViewForRuntimeEvent;
|
|
110
111
|
private scheduleDelayedRuntimeSync;
|
|
111
112
|
private clearRuntimeRefreshTimers;
|
|
112
113
|
private clearHistoryReloadTimers;
|
|
@@ -641,8 +641,7 @@ export class AppTabsController {
|
|
|
641
641
|
void this.saveTabs();
|
|
642
642
|
this.scheduleTabPrewarm();
|
|
643
643
|
const cachedView = this.sessionViewsByTabId.get(target.id);
|
|
644
|
-
const cachedViewNeedsHistoryReload = this.tabIdsNeedingHistoryReload.has(target.id)
|
|
645
|
-
&& this.sessionActivity(targetRuntime.session) !== "running";
|
|
644
|
+
const cachedViewNeedsHistoryReload = this.tabIdsNeedingHistoryReload.has(target.id);
|
|
646
645
|
if (cachedView && this.host.restoreSessionView && !cachedViewNeedsHistoryReload) {
|
|
647
646
|
this.host.restoreSessionView(cachedView);
|
|
648
647
|
this.restoreDeferredUserMessages(target.id);
|
|
@@ -883,9 +882,11 @@ export class AppTabsController {
|
|
|
883
882
|
return;
|
|
884
883
|
existing?.unsubscribe();
|
|
885
884
|
const unsubscribe = runtime.session.subscribe((event) => {
|
|
885
|
+
if (this.shouldInvalidateCachedViewForRuntimeEvent(event)) {
|
|
886
|
+
this.tabIdsNeedingHistoryReload.add(tabId);
|
|
887
|
+
}
|
|
886
888
|
if (this.shouldScheduleDelayedSyncForRuntimeEvent(event)) {
|
|
887
889
|
this.scheduleDelayedRuntimeSync(tabId, runtime);
|
|
888
|
-
this.tabIdsNeedingHistoryReload.add(tabId);
|
|
889
890
|
}
|
|
890
891
|
if (!this.shouldSyncTabFromRuntimeEvent(event))
|
|
891
892
|
return;
|
|
@@ -905,6 +906,17 @@ export class AppTabsController {
|
|
|
905
906
|
|| event.type === "turn_end"
|
|
906
907
|
|| event.type === "compaction_end";
|
|
907
908
|
}
|
|
909
|
+
shouldInvalidateCachedViewForRuntimeEvent(event) {
|
|
910
|
+
return event.type === "message_start"
|
|
911
|
+
|| event.type === "message_update"
|
|
912
|
+
|| event.type === "message_end"
|
|
913
|
+
|| event.type === "tool_execution_start"
|
|
914
|
+
|| event.type === "tool_execution_update"
|
|
915
|
+
|| event.type === "tool_execution_end"
|
|
916
|
+
|| event.type === "agent_end"
|
|
917
|
+
|| event.type === "turn_end"
|
|
918
|
+
|| event.type === "compaction_end";
|
|
919
|
+
}
|
|
908
920
|
scheduleDelayedRuntimeSync(tabId, runtime) {
|
|
909
921
|
this.clearRuntimeRefreshTimers(tabId);
|
|
910
922
|
for (const delayMs of [0, 100, 500, 1500, 3000]) {
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"vscode-languageserver-protocol": "^3.17.5"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@earendil-works/pi-ai": "0.79.
|
|
42
|
-
"@earendil-works/pi-coding-agent": "0.79.
|
|
43
|
-
"@earendil-works/pi-tui": "0.79.
|
|
41
|
+
"@earendil-works/pi-ai": "0.79.10",
|
|
42
|
+
"@earendil-works/pi-coding-agent": "0.79.10",
|
|
43
|
+
"@earendil-works/pi-tui": "0.79.10",
|
|
44
44
|
"typebox": "*"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
@@ -123,12 +123,28 @@ function appendTextToContent(content: unknown, text: string): unknown {
|
|
|
123
123
|
|
|
124
124
|
function appendDcpControlToMessages(messages: unknown, text: string): unknown {
|
|
125
125
|
if (!Array.isArray(messages)) return messages
|
|
126
|
-
const existingIndex = messages.findIndex((message: any) =>
|
|
127
|
-
message?.role === "system" || message?.role === "developer"
|
|
128
|
-
)
|
|
129
126
|
const block = `${DCP_PROVIDER_CONTROL_HEADER}\n${text}`
|
|
130
|
-
|
|
131
|
-
|
|
127
|
+
|
|
128
|
+
// Keep DCP's volatile ID map at the tail of the provider context instead of
|
|
129
|
+
// mutating the stable system/developer prefix. Prefix cache reuse is much
|
|
130
|
+
// better when only the newest transcript item changes on each request.
|
|
131
|
+
let targetIndex = -1
|
|
132
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
133
|
+
const message = messages[index] as any
|
|
134
|
+
if (!message || typeof message !== "object") continue
|
|
135
|
+
if (message.role === "system" || message.role === "developer") continue
|
|
136
|
+
targetIndex = index
|
|
137
|
+
break
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (targetIndex < 0) {
|
|
141
|
+
targetIndex = messages.findIndex((message: any) =>
|
|
142
|
+
message?.role === "system" || message?.role === "developer"
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (targetIndex >= 0) {
|
|
147
|
+
return messages.map((message: any, index) => index === targetIndex
|
|
132
148
|
? { ...message, content: appendTextToContent(message.content, block) }
|
|
133
149
|
: message)
|
|
134
150
|
}
|
|
@@ -155,10 +171,6 @@ function appendDcpControlToProviderPayload(payload: unknown, text: string): unkn
|
|
|
155
171
|
if (!payload || typeof payload !== "object") return payload
|
|
156
172
|
const record = payload as Record<string, unknown>
|
|
157
173
|
|
|
158
|
-
if ("system" in record) {
|
|
159
|
-
return { ...record, system: appendDcpControlToAnthropicSystem(record.system, text) }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
174
|
if (Array.isArray(record.input)) {
|
|
163
175
|
return { ...record, input: appendDcpControlToMessages(record.input, text) }
|
|
164
176
|
}
|
|
@@ -167,6 +179,10 @@ function appendDcpControlToProviderPayload(payload: unknown, text: string): unkn
|
|
|
167
179
|
return { ...record, messages: appendDcpControlToMessages(record.messages, text) }
|
|
168
180
|
}
|
|
169
181
|
|
|
182
|
+
if ("system" in record) {
|
|
183
|
+
return { ...record, system: appendDcpControlToAnthropicSystem(record.system, text) }
|
|
184
|
+
}
|
|
185
|
+
|
|
170
186
|
if (record.config && typeof record.config === "object") {
|
|
171
187
|
const config = record.config as Record<string, unknown>
|
|
172
188
|
return {
|
|
@@ -46,27 +46,87 @@ function priorityForMessage(tokenEstimate: number, config: DcpConfig | undefined
|
|
|
46
46
|
return "low";
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function
|
|
50
|
-
const
|
|
51
|
-
if (!
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
function messageIdIndex(id: string): number | undefined {
|
|
50
|
+
const match = /^m(\d+)$/.exec(id);
|
|
51
|
+
if (!match) return undefined;
|
|
52
|
+
const index = Number.parseInt(match[1]!, 10);
|
|
53
|
+
return Number.isFinite(index) ? index : undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function summarizeMessageIds(ids: string[]): string {
|
|
57
|
+
if (ids.length === 0) return "none";
|
|
58
|
+
|
|
59
|
+
const ranges: string[] = [];
|
|
60
|
+
let start = ids[0]!;
|
|
61
|
+
let previous = ids[0]!;
|
|
62
|
+
let previousIndex = messageIdIndex(previous);
|
|
63
|
+
|
|
64
|
+
const flush = () => {
|
|
65
|
+
const startIndex = messageIdIndex(start);
|
|
66
|
+
const endIndex = messageIdIndex(previous);
|
|
67
|
+
if (
|
|
68
|
+
startIndex !== undefined &&
|
|
69
|
+
endIndex !== undefined &&
|
|
70
|
+
endIndex - startIndex >= 2
|
|
71
|
+
) {
|
|
72
|
+
ranges.push(`${start}..${previous}`);
|
|
73
|
+
} else if (start === previous) {
|
|
74
|
+
ranges.push(start);
|
|
75
|
+
} else {
|
|
76
|
+
ranges.push(start, previous);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
for (let i = 1; i < ids.length; i++) {
|
|
81
|
+
const id = ids[i]!;
|
|
82
|
+
const index = messageIdIndex(id);
|
|
83
|
+
if (previousIndex !== undefined && index === previousIndex + 1) {
|
|
84
|
+
previous = id;
|
|
85
|
+
previousIndex = index;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
flush();
|
|
90
|
+
start = id;
|
|
91
|
+
previous = id;
|
|
92
|
+
previousIndex = index;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
flush();
|
|
96
|
+
return ranges.join(", ");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function compactPriorityHint(ids: string[], state: DcpState): string | undefined {
|
|
100
|
+
const high: string[] = [];
|
|
101
|
+
const medium: string[] = [];
|
|
102
|
+
const blocks: string[] = [];
|
|
103
|
+
|
|
104
|
+
for (const id of ids) {
|
|
105
|
+
const meta = state.messageMetaSnapshot.get(id);
|
|
106
|
+
if (!meta) continue;
|
|
107
|
+
if (meta.priority === "high") high.push(id);
|
|
108
|
+
else if (meta.priority === "medium") medium.push(id);
|
|
109
|
+
if (meta.blockId !== undefined) blocks.push(`${id}=b${meta.blockId}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const parts: string[] = [];
|
|
113
|
+
if (high.length > 0) parts.push(`high=${summarizeMessageIds(high)}`);
|
|
114
|
+
if (medium.length > 0) parts.push(`medium=${summarizeMessageIds(medium)}`);
|
|
115
|
+
if (blocks.length > 0) parts.push(`blocks=${blocks.join(",")}`);
|
|
116
|
+
return parts.length > 0 ? `Hints: ${parts.join("; ")}` : undefined;
|
|
58
117
|
}
|
|
59
118
|
|
|
60
119
|
export function buildMessageIdControlText(state: DcpState): string | undefined {
|
|
61
120
|
const ids = [...state.messageIdSnapshot.keys()];
|
|
62
121
|
if (ids.length === 0) return undefined;
|
|
63
122
|
|
|
123
|
+
const hint = compactPriorityHint(ids, state);
|
|
124
|
+
|
|
64
125
|
return [
|
|
65
126
|
"<dcp-message-ids>",
|
|
66
|
-
"DCP metadata for the preceding conversation messages.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
...ids.map((id) => controlLineForMessageId(id, state)),
|
|
127
|
+
"DCP metadata for the preceding conversation messages. IDs follow current message order; use only these IDs with compress; do not quote/output.",
|
|
128
|
+
`Current raw message IDs: ${summarizeMessageIds(ids)}${ids.length > 2 ? ` (${ids.length} messages)` : ""}`,
|
|
129
|
+
...(hint ? [hint] : []),
|
|
70
130
|
"</dcp-message-ids>",
|
|
71
131
|
].join("\n");
|
|
72
132
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ui-extend",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.47",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"prepublishOnly": "npm run check && npm run build:pix && npm run generate-schemas"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@earendil-works/pi-ai": "0.79.
|
|
68
|
-
"@earendil-works/pi-coding-agent": "0.79.
|
|
69
|
-
"@earendil-works/pi-tui": "0.79.
|
|
67
|
+
"@earendil-works/pi-ai": "0.79.10",
|
|
68
|
+
"@earendil-works/pi-coding-agent": "0.79.10",
|
|
69
|
+
"@earendil-works/pi-tui": "0.79.10",
|
|
70
70
|
"@mariozechner/clipboard": "^0.3.9",
|
|
71
71
|
"jsonc-parser": "3.3.1",
|
|
72
72
|
"typebox": "1.1.38",
|