@cognipeer/agent-sdk 0.10.2 → 0.10.3

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/index.cjs CHANGED
@@ -6156,6 +6156,9 @@ function isSyntheticSummaryMessage(message) {
6156
6156
  }
6157
6157
  return false;
6158
6158
  }
6159
+ function isCompactedToolContent(content) {
6160
+ return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
6161
+ }
6159
6162
 
6160
6163
  // src/structuredOutput/manager.ts
6161
6164
  var StructuredOutputManager = class {
@@ -8072,6 +8075,10 @@ function collectRecentTurns(messages, lastTurnsToKeep) {
8072
8075
  function renderStructuredSummary(summary) {
8073
8076
  if (!summary) return "";
8074
8077
  const lines = ["Context summary:"];
8078
+ if (summary.user_directives && summary.user_directives.length > 0) {
8079
+ lines.push("User directives (still in force \u2014 follow them):");
8080
+ lines.push(...summary.user_directives.map((directive) => `- ${directive}`));
8081
+ }
8075
8082
  if (summary.stable_facts.length > 0) {
8076
8083
  lines.push("Stable facts:");
8077
8084
  lines.push(...summary.stable_facts.map((fact) => `- ${fact.key}: ${fact.value}`));
@@ -8147,17 +8154,46 @@ function clampToBudget(messages, maxContextTokens) {
8147
8154
  }
8148
8155
  return working;
8149
8156
  }
8157
+ function collectSummaryOnlyBody(body, hasSummary, lastTurnsToKeep) {
8158
+ if (!hasSummary) {
8159
+ return collectRecentTurns(body, Math.max(1, lastTurnsToKeep));
8160
+ }
8161
+ let boundary = -1;
8162
+ for (let index = body.length - 1; index >= 0; index -= 1) {
8163
+ if (isSyntheticSummaryMessage(body[index])) {
8164
+ boundary = index;
8165
+ break;
8166
+ }
8167
+ }
8168
+ let lastUserIndex = -1;
8169
+ for (let index = body.length - 1; index >= 0; index -= 1) {
8170
+ if (body[index].role === "user") {
8171
+ lastUserIndex = index;
8172
+ break;
8173
+ }
8174
+ }
8175
+ const keep = /* @__PURE__ */ new Set();
8176
+ const firstUserIndex = body.findIndex((message) => message.role === "user");
8177
+ if (firstUserIndex >= 0) keep.add(firstUserIndex);
8178
+ const verbatimFrom = Math.min(lastUserIndex >= 0 ? lastUserIndex : body.length, boundary + 1);
8179
+ for (let index = Math.max(0, verbatimFrom); index < body.length; index += 1) {
8180
+ if (!isSyntheticSummaryMessage(body[index])) keep.add(index);
8181
+ }
8182
+ return body.filter((_, index) => keep.has(index));
8183
+ }
8150
8184
  function buildModelMessages(state, config) {
8151
8185
  const rawMessages = state.messages || [];
8152
8186
  if (config.context.policy === "raw") {
8153
8187
  return clampToBudget(rawMessages, config.limits.maxContextTokens);
8154
8188
  }
8155
- const recentMessages = collectRecentTurns(rawMessages, config.context.lastTurnsToKeep);
8156
8189
  const latestSummary = state.summaryRecords?.[state.summaryRecords.length - 1];
8157
8190
  const summaryText = renderStructuredSummary(latestSummary);
8158
8191
  const memoryText = renderMemoryBlock(state.memoryFacts);
8159
- const systemMessage2 = recentMessages[0]?.role === "system" ? recentMessages[0] : void 0;
8160
- const body = systemMessage2 ? recentMessages.slice(1) : recentMessages;
8192
+ const systemMessage2 = rawMessages[0]?.role === "system" ? rawMessages[0] : void 0;
8193
+ const body = config.context.policy === "summary_only" ? collectSummaryOnlyBody(systemMessage2 ? rawMessages.slice(1) : rawMessages, Boolean(summaryText), config.context.lastTurnsToKeep) : (() => {
8194
+ const recentMessages = collectRecentTurns(rawMessages, config.context.lastTurnsToKeep);
8195
+ return recentMessages[0]?.role === "system" ? recentMessages.slice(1) : recentMessages;
8196
+ })();
8161
8197
  const syntheticContextMessages = [];
8162
8198
  if (summaryText) {
8163
8199
  syntheticContextMessages.push({ role: "system", name: "context_summary", content: summaryText });
@@ -8168,7 +8204,7 @@ function buildModelMessages(state, config) {
8168
8204
  const assembled = [
8169
8205
  ...systemMessage2 ? [systemMessage2] : [],
8170
8206
  ...syntheticContextMessages,
8171
- ...config.context.policy === "summary_only" ? body.filter((message) => message.role === "user" || message.role === "assistant").slice(-2) : body
8207
+ ...body
8172
8208
  ];
8173
8209
  return clampToBudget(assembled, config.limits.maxContextTokens);
8174
8210
  }
@@ -8213,6 +8249,7 @@ function extractJsonObject(text) {
8213
8249
  }
8214
8250
  function normalizeStructuredSummary(input, fallbackText) {
8215
8251
  const summary = {
8252
+ user_directives: Array.isArray(input?.user_directives) ? input.user_directives.map((directive) => String(directive ?? "").trim()).filter(Boolean) : [],
8216
8253
  stable_facts: Array.isArray(input?.stable_facts) ? input.stable_facts.filter((fact) => fact && typeof fact === "object").map((fact) => ({
8217
8254
  key: String(fact.key || "unknown"),
8218
8255
  value: String(fact.value || ""),
@@ -8273,7 +8310,7 @@ function extractCanonicalFacts(messages) {
8273
8310
  return [...facts.values()];
8274
8311
  }
8275
8312
  function isSummarizedToolPlaceholder(content) {
8276
- return typeof content === "string" && (content === "SUMMARIZED" || content.startsWith("SUMMARIZED_TOOL_RESPONSE") || content.startsWith("ARCHIVED_TOOL_RESPONSE") || content.startsWith("STRUCTURED_TOOL_RESPONSE") || content.startsWith("DROPPED_TOOL_RESPONSE"));
8313
+ return isCompactedToolContent(content);
8277
8314
  }
8278
8315
  function collectLatestTurnToolCallIds(messages) {
8279
8316
  const ids = /* @__PURE__ */ new Set();
@@ -8332,11 +8369,16 @@ function runIntegrityCheck(previous, current) {
8332
8369
  const previousKeys = new Set((previous?.stable_facts || []).map((fact) => fact.key));
8333
8370
  const currentKeys = new Set(current.stable_facts.map((fact) => fact.key));
8334
8371
  const obsoleteKeys = new Set(current.discarded_obsolete);
8335
- const criticalFactLoss = [...previousKeys].some((key) => !obsoleteKeys.has(key) && !currentKeys.has(key));
8372
+ const currentDirectives = new Set(current.user_directives || []);
8373
+ const lostDirectives = (previous?.user_directives || []).filter((directive) => !currentDirectives.has(directive) && !obsoleteKeys.has(directive));
8374
+ const criticalFactLoss = [...previousKeys].some((key) => !obsoleteKeys.has(key) && !currentKeys.has(key)) || lostDirectives.length > 0;
8336
8375
  const obsoleteFactRevived = current.stable_facts.some((fact) => obsoleteKeys.has(fact.key));
8337
8376
  if (criticalFactLoss) {
8338
8377
  notes.push("Missing previously retained facts; merged forward during integrity repair.");
8339
8378
  }
8379
+ if (lostDirectives.length > 0) {
8380
+ notes.push(`Dropped ${lostDirectives.length} user directive(s); merged forward during integrity repair.`);
8381
+ }
8340
8382
  if (obsoleteFactRevived) {
8341
8383
  notes.push("Obsolete facts reappeared; removed during integrity repair.");
8342
8384
  }
@@ -8359,7 +8401,13 @@ function repairStructuredSummary(previous, current, integrity) {
8359
8401
  }
8360
8402
  }
8361
8403
  const filteredFacts = integrity.obsoleteFactRevived ? nextFacts.filter((fact) => !current.discarded_obsolete.includes(fact.key)) : nextFacts;
8362
- return { ...current, stable_facts: filteredFacts };
8404
+ const directives = [...current.user_directives || []];
8405
+ for (const directive of previous.user_directives || []) {
8406
+ if (!directives.includes(directive) && !current.discarded_obsolete.includes(directive)) {
8407
+ directives.push(directive);
8408
+ }
8409
+ }
8410
+ return { ...current, user_directives: directives, stable_facts: filteredFacts };
8363
8411
  }
8364
8412
  function createContextSummarizeNode(opts) {
8365
8413
  return async (state) => {
@@ -8433,6 +8481,7 @@ function createContextSummarizeNode(opts) {
8433
8481
 
8434
8482
  Return exactly one JSON object with this schema:
8435
8483
  {
8484
+ "user_directives": [string],
8436
8485
  "stable_facts": [{ "key": string, "value": string, "confidence": number }],
8437
8486
  "active_goals": [string],
8438
8487
  "open_questions": [string],
@@ -8441,6 +8490,7 @@ Return exactly one JSON object with this schema:
8441
8490
  }
8442
8491
 
8443
8492
  Rules:
8493
+ - user_directives: standing instructions the user gave about HOW to work or answer for the rest of the conversation (language, format, tone, scope, things to always or never do) that still apply. NOT the tasks or questions themselves \u2014 "read the logs" is a task (an active goal), "always answer in Turkish" is a directive. Copy each directive close to verbatim; never merge, soften or drop one. Carry forward every directive from the previous structured summary unless the user explicitly revoked it \u2014 then put its exact text in discarded_obsolete.
8444
8494
  - Keep stable_facts only for facts that future turns must remember.
8445
8495
  - Put invalidated or superseded fact keys in discarded_obsolete.
8446
8496
  - Preserve active_goals still relevant to the user.
@@ -8508,6 +8558,7 @@ ${canonicalFacts.length > 0 ? canonicalFacts.map((fact) => `- ${fact.key}: ${fac
8508
8558
  durationMs = Date.now() - startTime;
8509
8559
  structuredSummary = normalizeStructuredSummary(void 0, previousSummary || conversationText.slice(0, 800));
8510
8560
  structuredSummary = mergeStableFacts(structuredSummary, canonicalFacts);
8561
+ structuredSummary.user_directives = [...previousStructuredSummary?.user_directives || []];
8511
8562
  integrity = { passed: true, criticalFactLoss: false, obsoleteFactRevived: false, notes: ["Fallback summary generated locally."] };
8512
8563
  summaryText = renderStructuredSummary(structuredSummary);
8513
8564
  const errorEvent = {