pi-codebuddy-sdk 0.1.12 → 0.1.13
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/package.json +1 -1
- package/src/provider.ts +59 -9
package/package.json
CHANGED
package/src/provider.ts
CHANGED
|
@@ -83,20 +83,70 @@ function extractLatestUserText(context: Context): string {
|
|
|
83
83
|
const messages = context.messages;
|
|
84
84
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
85
85
|
if (messages[i].role === "user") {
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
.join("\n");
|
|
93
|
-
if (texts) return texts;
|
|
94
|
-
}
|
|
86
|
+
let raw = extractRawContent((messages[i] as any).content);
|
|
87
|
+
if (!raw) continue;
|
|
88
|
+
// Strip context-mode session state injection prepended to user messages.
|
|
89
|
+
// Pi's context-mode adds its hierarchy/state before the actual user input.
|
|
90
|
+
raw = stripContextModeInjection(raw);
|
|
91
|
+
if (raw) return raw;
|
|
95
92
|
}
|
|
96
93
|
}
|
|
97
94
|
return "Continue.";
|
|
98
95
|
}
|
|
99
96
|
|
|
97
|
+
function extractRawContent(content: unknown): string {
|
|
98
|
+
if (typeof content === "string") return content;
|
|
99
|
+
if (!Array.isArray(content)) return "";
|
|
100
|
+
return content
|
|
101
|
+
.filter((c: any) => c?.type === "text")
|
|
102
|
+
.map((c: any) => c.text)
|
|
103
|
+
.join("\n");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Pi context-mode prepends its session state to user messages.
|
|
108
|
+
* Strip it to keep CodeBuddy from treating it as conversation content.
|
|
109
|
+
*
|
|
110
|
+
* Injected format:
|
|
111
|
+
* context-mode active. Hierarchy: ...
|
|
112
|
+
* <session_state source="compaction">
|
|
113
|
+
* <session_mode>investigate</session_mode>
|
|
114
|
+
* </session_state>
|
|
115
|
+
* [actual user message]
|
|
116
|
+
*/
|
|
117
|
+
function stripContextModeInjection(text: string): string {
|
|
118
|
+
// Find the end of context-mode injection
|
|
119
|
+
// Pattern: </session_state> followed by newlines then actual message
|
|
120
|
+
const sessionEnd = text.lastIndexOf("</session_state>");
|
|
121
|
+
if (sessionEnd >= 0) {
|
|
122
|
+
const after = text.slice(sessionEnd + "</session_state>".length).trimStart();
|
|
123
|
+
if (after) return after;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Fallback: look for "context-mode active" header and take everything after it + session_state
|
|
127
|
+
const cmStart = text.indexOf("context-mode active.");
|
|
128
|
+
if (cmStart >= 0) {
|
|
129
|
+
// Find first blank line after </session_state> or end of XML
|
|
130
|
+
const afterSession = afterSessionState(text);
|
|
131
|
+
if (afterSession) return afterSession;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return text;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function afterSessionState(text: string): string | null {
|
|
138
|
+
// Try to find the actual user message after context-mode XML injection
|
|
139
|
+
const patterns = [
|
|
140
|
+
/context-mode active\.[\s\S]*?<\/session_state>\s*\n+([\s\S]+)$/,
|
|
141
|
+
/<session_state[\s\S]*?<\/session_state>\s*\n+([\s\S]+)$/,
|
|
142
|
+
];
|
|
143
|
+
for (const re of patterns) {
|
|
144
|
+
const m = text.match(re);
|
|
145
|
+
if (m?.[1]?.trim()) return m[1].trim();
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
|
|
100
150
|
// ── thinking config mapping ──
|
|
101
151
|
|
|
102
152
|
const DEFAULT_THINKING_BUDGETS: Record<string, number> = {
|