@caupulican/pi-adaptative 0.96.3 → 0.96.5

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +8 -0
  3. package/dist/config.d.ts +2 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +3 -1
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/agent-session-contracts.d.ts +1 -1
  8. package/dist/core/agent-session-contracts.d.ts.map +1 -1
  9. package/dist/core/agent-session-contracts.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +2 -0
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +29 -14
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
  15. package/dist/core/goals/goal-lifecycle.js +5 -1
  16. package/dist/core/goals/goal-lifecycle.js.map +1 -1
  17. package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
  18. package/dist/core/goals/goal-session-controller.js +3 -1
  19. package/dist/core/goals/goal-session-controller.js.map +1 -1
  20. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  21. package/dist/core/goals/goal-tool-core.js +32 -7
  22. package/dist/core/goals/goal-tool-core.js.map +1 -1
  23. package/dist/core/learning/durable-learning-state.d.ts +76 -0
  24. package/dist/core/learning/durable-learning-state.d.ts.map +1 -0
  25. package/dist/core/learning/durable-learning-state.js +493 -0
  26. package/dist/core/learning/durable-learning-state.js.map +1 -0
  27. package/dist/core/reflection-controller.d.ts +37 -7
  28. package/dist/core/reflection-controller.d.ts.map +1 -1
  29. package/dist/core/reflection-controller.js +278 -49
  30. package/dist/core/reflection-controller.js.map +1 -1
  31. package/dist/core/settings-manager.js.map +1 -1
  32. package/dist/core/tools/goal.d.ts.map +1 -1
  33. package/dist/core/tools/goal.js +6 -3
  34. package/dist/core/tools/goal.js.map +1 -1
  35. package/dist/modes/interactive/components/settings-selector.js +1 -1
  36. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  37. package/docs/durable-learning-state-design.md +217 -0
  38. package/docs/settings.md +5 -3
  39. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  40. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  41. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  42. package/examples/extensions/sandbox/package-lock.json +2 -2
  43. package/examples/extensions/sandbox/package.json +1 -1
  44. package/examples/extensions/with-deps/package-lock.json +2 -2
  45. package/examples/extensions/with-deps/package.json +1 -1
  46. package/npm-shrinkwrap.json +12 -12
  47. package/package.json +4 -4
@@ -8,7 +8,7 @@ import { NATIVE_TOOL_PROTOCOL_RESIDUE_ERROR } from "@caupulican/pi-agent-core/to
8
8
  import { modelsAreEqual } from "@caupulican/pi-ai/models";
9
9
  import { cleanupSessionResources } from "@caupulican/pi-ai/session-resources";
10
10
  import { streamSimple } from "@caupulican/pi-ai/stream";
11
- import { getAgentDir } from "../config.js";
11
+ import { getAgentDir, VERSION, VERSION_SOURCE_AVAILABLE } from "../config.js";
12
12
  import { resourceDir, stateFile } from "./agent-paths.js";
13
13
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
14
14
  import { buildForegroundEnvelope, formatForegroundEnvelopeObservation } from "./autonomy/foreground-envelope.js";
@@ -35,6 +35,7 @@ import { hasGoalContinuationControl } from "./goals/goal-tool-names.js";
35
35
  import { parseExplicitGoalStartAuthority } from "./goals/natural-language-goal.js";
36
36
  import { constrainStreamIdleToHttpTimeout } from "./http-dispatcher.js";
37
37
  import { HumanInputController } from "./human-input-controller.js";
38
+ import { DURABLE_LEARNING_MEMORY_POLICY_VERSION, DurableLearningState } from "./learning/durable-learning-state.js";
38
39
  import { appendLearningDecisionSnapshot, getLearningDecisionSnapshots } from "./learning/session-learning-decision.js";
39
40
  import { SkillCurator } from "./learning/skill-curator.js";
40
41
  import { isWarmableLocalModel, LocalPrefixWarmController } from "./local-prefix-warm-controller.js";
@@ -228,14 +229,19 @@ export class AgentSession {
228
229
  this._foregroundRecovery.observeAssistant(assistantMsg);
229
230
  }
230
231
  }
231
- if (event.type === "agent_end" && !this._willRetryAfterAgentEnd(event)) {
232
- const reflectionTurn = this._reflection.analyzeCompletedTurn(event.messages);
233
- // The shared projection excludes raw tool-result payloads and bounds both roles before any
234
- // deterministic memory sync. No reflection provider request is scheduled at this boundary.
235
- this._memory.scheduleTurnSync(reflectionTurn.userText, reflectionTurn.assistantText);
236
- if (reflectionTurn.trigger !== "none")
237
- this._reflection.queueCurrentTurnCue(reflectionTurn.trigger);
238
- this._goals.endQueuedOwnerChatGoalExecution();
232
+ if (event.type === "agent_end") {
233
+ const willRetry = this._willRetryAfterAgentEnd(event);
234
+ // Settle the exact cue-bearing run before completed-turn analysis can queue a later cue.
235
+ this._reflection.finishCurrentTurnCue(event.messages, { willRetry });
236
+ if (!willRetry) {
237
+ const reflectionTurn = this._reflection.analyzeCompletedTurn(event.messages);
238
+ // The shared projection excludes raw tool-result payloads and bounds both roles before any
239
+ // deterministic memory sync. No reflection provider request is scheduled at this boundary.
240
+ this._memory.scheduleTurnSync(reflectionTurn.userText, reflectionTurn.assistantText);
241
+ if (reflectionTurn.trigger !== "none")
242
+ this._reflection.queueCurrentTurnCue(reflectionTurn.trigger);
243
+ this._goals.endQueuedOwnerChatGoalExecution();
244
+ }
239
245
  }
240
246
  // Error/abort turns bypass the normal steering boundary, and a completion can arrive after the
241
247
  // final normal poll. agent_end is the fallback before foreground recovery decides whether queued
@@ -315,6 +321,8 @@ export class AgentSession {
315
321
  this._customTools = config.customTools ?? [];
316
322
  this._cwd = config.cwd;
317
323
  this._agentDir = agentDir;
324
+ this._isChildSession = (config.isChildSession ?? process.env.PI_CHILD_SESSION === "1") || isWorkerSession();
325
+ this._durableLearningState = this._isChildSession ? undefined : DurableLearningState.forAgentDir(agentDir);
318
326
  this._skillVault = new SkillVaultController({
319
327
  getSkills: () => this._resourceLoader.getActiveSkills(),
320
328
  getMaxBodyBytes: () => resolveActiveSkillBodyByteLimit(this.model?.contextWindow),
@@ -668,6 +676,10 @@ export class AgentSession {
668
676
  getSettingsManager: () => this.settingsManager,
669
677
  getSessionManager: () => this.sessionManager,
670
678
  getAgentDir: () => this._agentDir,
679
+ getDurableLearningState: () => this._durableLearningState,
680
+ getRuntimeVersion: () => (VERSION_SOURCE_AVAILABLE ? VERSION : undefined),
681
+ getMemoryPolicyVersion: () => DURABLE_LEARNING_MEMORY_POLICY_VERSION,
682
+ warn: (message) => this._emit({ type: "warning", message }),
671
683
  getCwd: () => this._cwd,
672
684
  getSkillsForAudit: () => this._resourceLoader.getActiveSkills(),
673
685
  isChildSession: () => this._isChildSession,
@@ -700,7 +712,6 @@ export class AgentSession {
700
712
  : undefined;
701
713
  this._isExplicitModel = config.isExplicitModel ?? false;
702
714
  this._isExplicitThinking = config.isExplicitThinking ?? false;
703
- this._isChildSession = (config.isChildSession ?? process.env.PI_CHILD_SESSION === "1") || isWorkerSession();
704
715
  this._baseToolsOverride = config.baseToolsOverride;
705
716
  this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
706
717
  this._runtimeBuilder = new RuntimeBuilder({
@@ -1388,14 +1399,18 @@ export class AgentSession {
1388
1399
  if (goalRecovered) {
1389
1400
  void this.sendCustomMessage({
1390
1401
  customType: "runaway-recovery",
1391
- content: "A bounded harness guard ended the previous agent loop, but the durable goal remains active and must continue automatically. Do not repeat the same failed operation unchanged. Inspect the recorded failure, change tool or approach, and keep working unless evidence proves a true owner/approval boundary.",
1402
+ content: info.reason === "stagnant_tool_cycle"
1403
+ ? "A bounded harness guard ended an unchanged tool-result cycle, but the durable goal remains active and must continue automatically. Reuse the latest returned state; do not call the same status/read cycle again. Execute an available state-changing or finalization action, wait once on the true dependency, or record a concrete blocker."
1404
+ : "A bounded harness guard ended the previous agent loop, but the durable goal remains active and must continue automatically. Do not repeat the same failed operation unchanged. Inspect the recorded failure, change tool or approach, and keep working unless evidence proves a true owner/approval boundary.",
1392
1405
  display: false,
1393
1406
  details: info,
1394
1407
  }, { deliverAs: "nextTurn" });
1395
1408
  }
1396
1409
  const cause = info.reason === "provider_turn_limit"
1397
1410
  ? `the configured provider-turn limit of ${info.repeats} requests was reached`
1398
- : `the model repeated the same tool call ${info.repeats} times in a row without making progress`;
1411
+ : info.reason === "stagnant_tool_cycle"
1412
+ ? `the same tool-call cycle returned identical results ${info.repeats} times`
1413
+ : `the model repeated the same tool call ${info.repeats} times in a row without making progress`;
1399
1414
  this._emit({
1400
1415
  type: "warning",
1401
1416
  message: `Bounded guard ended this run: ${cause}.${goalRecovered ? " The active goal remains scheduled; the next pass must use a different approach." : ""}`,
@@ -2217,7 +2232,7 @@ export class AgentSession {
2217
2232
  // Queue one durable logical cue. ProviderRequestContextController owns its transient preview
2218
2233
  // and accepted-plan commit, so it never enters or needs cleanup from agent history.
2219
2234
  if (!options?.internalContextType)
2220
- this._reflection.queueCurrentTurnCue("root-turn");
2235
+ this._reflection.queueExternalRootTurnCue();
2221
2236
  // Add user message (built earlier, before the router judge, so it could be painted
2222
2237
  // immediately — see the early message_start emit above).
2223
2238
  messages.push(promptMessage);
@@ -2874,7 +2889,7 @@ export class AgentSession {
2874
2889
  // =========================================================================
2875
2890
  async navigateTree(targetId, options = {}) {
2876
2891
  const result = await this._treeNavigator.navigateTree(targetId, options);
2877
- this._reflection.invalidateCurrentTurnCueStateCache();
2892
+ this._reflection.invalidateCurrentTurnCueStateCache({ releaseActiveClaim: !result.cancelled });
2878
2893
  return result;
2879
2894
  }
2880
2895
  getUserMessagesForForking() {