@oh-my-pi/pi-agent-core 16.5.0 → 16.5.1

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 CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.5.1] - 2026-07-14
6
+
7
+ ### Fixed
8
+
9
+ - Fixed compatibility with Copilot gpt-5.6 models by correcting token escaping in compaction summaries.
10
+
5
11
  ## [16.5.0] - 2026-07-13
6
12
 
7
13
  ### Added
@@ -50,8 +50,11 @@ export declare function upsertFileOperations(summary: string, readFiles: string[
50
50
  */
51
51
  export declare function truncateToolResultForSummary(text: string): string;
52
52
  /**
53
- * Serialize LLM messages to text for summarization.
54
- * This prevents the model from treating it as a conversation to continue.
53
+ * Serialize LLM messages as plain summary input without provider control tokens.
54
+ */
55
+ export declare function serializeConversationForSummary(messages: Message[], dialect?: Dialect): string;
56
+ /**
57
+ * Serialize LLM messages to transcript text.
55
58
  * Call convertToLlm() first to handle custom message types.
56
59
  */
57
60
  export declare function serializeConversation(messages: Message[], dialect?: Dialect): string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-agent-core",
4
- "version": "16.5.0",
4
+ "version": "16.5.1",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -35,12 +35,12 @@
35
35
  "fmt": "biome format --write ."
36
36
  },
37
37
  "dependencies": {
38
- "@oh-my-pi/pi-ai": "16.5.0",
39
- "@oh-my-pi/pi-catalog": "16.5.0",
40
- "@oh-my-pi/pi-natives": "16.5.0",
41
- "@oh-my-pi/pi-utils": "16.5.0",
42
- "@oh-my-pi/pi-wire": "16.5.0",
43
- "@oh-my-pi/snapcompact": "16.5.0",
38
+ "@oh-my-pi/pi-ai": "16.5.1",
39
+ "@oh-my-pi/pi-catalog": "16.5.1",
40
+ "@oh-my-pi/pi-natives": "16.5.1",
41
+ "@oh-my-pi/pi-utils": "16.5.1",
42
+ "@oh-my-pi/pi-wire": "16.5.1",
43
+ "@oh-my-pi/snapcompact": "16.5.1",
44
44
  "@opentelemetry/api": "^1.9.1"
45
45
  },
46
46
  "devDependencies": {
@@ -27,7 +27,7 @@ import {
27
27
  extractFileOpsFromMessage,
28
28
  type FileOperations,
29
29
  SUMMARIZATION_SYSTEM_PROMPT,
30
- serializeConversation,
30
+ serializeConversationForSummary,
31
31
  stripReadSelector,
32
32
  truncateToolResultForSummary,
33
33
  upsertFileOperations,
@@ -320,7 +320,7 @@ export async function generateBranchSummary(
320
320
  // Transform to LLM-compatible messages, then serialize to text
321
321
  // Serialization prevents the model from treating it as a conversation to continue
322
322
  const llmMessages = (options.convertToLlm ?? defaultConvertToLlm)(messages);
323
- const conversationText = serializeConversation(llmMessages, preferredDialect(model.id));
323
+ const conversationText = serializeConversationForSummary(llmMessages, preferredDialect(model.id));
324
324
 
325
325
  // Build prompt
326
326
  const instructions = customInstructions || BRANCH_SUMMARY_PROMPT;
@@ -66,7 +66,7 @@ import {
66
66
  extractFileOpsFromMessage,
67
67
  type FileOperations,
68
68
  SUMMARIZATION_SYSTEM_PROMPT,
69
- serializeConversation,
69
+ serializeConversationForSummary,
70
70
  stripReadSelector,
71
71
  upsertFileOperations,
72
72
  } from "./utils";
@@ -816,7 +816,7 @@ export async function generateSummary(
816
816
  // Serialize conversation to text so model doesn't try to continue it
817
817
  // Convert to LLM messages first (handles custom app messages when caller provides a transformer).
818
818
  const llmMessages = (options?.convertToLlm ?? defaultConvertToLlm)(currentMessages);
819
- const conversationText = serializeConversation(llmMessages, preferredDialect(model.id));
819
+ const conversationText = serializeConversationForSummary(llmMessages, preferredDialect(model.id));
820
820
 
821
821
  // Build the prompt with conversation wrapped in tags
822
822
  let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`;
@@ -1030,7 +1030,7 @@ async function generateShortSummary(
1030
1030
  ): Promise<string> {
1031
1031
  const maxTokens = Math.min(512, Math.floor(0.2 * reserveTokens));
1032
1032
  const llmMessages = (options?.convertToLlm ?? defaultConvertToLlm)(recentMessages);
1033
- const conversationText = serializeConversation(llmMessages, preferredDialect(model.id));
1033
+ const conversationText = serializeConversationForSummary(llmMessages, preferredDialect(model.id));
1034
1034
 
1035
1035
  let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`;
1036
1036
  if (historySummary) {
@@ -1578,7 +1578,7 @@ async function generateTurnPrefixSummary(
1578
1578
  const maxTokens = Math.floor(0.5 * reserveTokens); // Smaller budget for turn prefix
1579
1579
 
1580
1580
  const llmMessages = (options?.convertToLlm ?? defaultConvertToLlm)(messages);
1581
- const conversationText = serializeConversation(llmMessages, preferredDialect(model.id));
1581
+ const conversationText = serializeConversationForSummary(llmMessages, preferredDialect(model.id));
1582
1582
  const promptText = `<conversation>\n${conversationText}\n</conversation>\n\n${TURN_PREFIX_SUMMARIZATION_PROMPT}`;
1583
1583
  const summarizationMessages = [
1584
1584
  {
@@ -207,9 +207,19 @@ export function truncateToolResultForSummary(text: string): string {
207
207
  return `${text.slice(0, TOOL_RESULT_MAX_CHARS)}\n\n[... ${truncatedChars} more characters truncated]`;
208
208
  }
209
209
 
210
+ const HARMONY_CONTROL_TOKEN_RE = /<\|(start|end|message|channel|constrain|return|call)\|>/g;
211
+
212
+ /**
213
+ * Serialize LLM messages as plain summary input without provider control tokens.
214
+ */
215
+ export function serializeConversationForSummary(messages: Message[], dialect?: Dialect): string {
216
+ const conversation = serializeConversation(messages, dialect);
217
+ if (dialect !== "harmony") return conversation;
218
+ return conversation.replace(HARMONY_CONTROL_TOKEN_RE, "<\\|$1\\|>");
219
+ }
220
+
210
221
  /**
211
- * Serialize LLM messages to text for summarization.
212
- * This prevents the model from treating it as a conversation to continue.
222
+ * Serialize LLM messages to transcript text.
213
223
  * Call convertToLlm() first to handle custom message types.
214
224
  */
215
225
  export function serializeConversation(messages: Message[], dialect?: Dialect): string {