@caupulican/pi-adaptative 0.80.60 → 0.80.62
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 +12 -0
- package/dist/core/agent-session.d.ts +8 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +58 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/memory/effectiveness-tracker.d.ts +31 -0
- package/dist/core/memory/effectiveness-tracker.d.ts.map +1 -0
- package/dist/core/memory/effectiveness-tracker.js +54 -0
- package/dist/core/memory/effectiveness-tracker.js.map +1 -0
- package/dist/core/memory/providers/transcript-recall.d.ts +27 -0
- package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -0
- package/dist/core/memory/providers/transcript-recall.js +154 -0
- package/dist/core/memory/providers/transcript-recall.js.map +1 -0
- package/dist/core/memory/transcript-index.d.ts +22 -0
- package/dist/core/memory/transcript-index.d.ts.map +1 -0
- package/dist/core/memory/transcript-index.js +85 -0
- package/dist/core/memory/transcript-index.js.map +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -32,8 +32,10 @@ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
|
32
32
|
import { disposeExtensionEventSubscriptions } from "./extensions/loader.js";
|
|
33
33
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
34
34
|
import { decideDemand, ReflectionEngine, } from "./learning/reflection-engine.js";
|
|
35
|
+
import { EffectivenessTracker } from "./memory/effectiveness-tracker.js";
|
|
35
36
|
import { MemoryManager } from "./memory/memory-manager.js";
|
|
36
37
|
import { FileStoreProvider } from "./memory/providers/file-store.js";
|
|
38
|
+
import { TranscriptRecallProvider } from "./memory/providers/transcript-recall.js";
|
|
37
39
|
import { compactToolResultDetailsForRetention } from "./message-retention.js";
|
|
38
40
|
import { resolveProfileModelSettings } from "./model-resolver.js";
|
|
39
41
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
@@ -119,6 +121,8 @@ export class AgentSession {
|
|
|
119
121
|
_isExplicitThinking;
|
|
120
122
|
/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */
|
|
121
123
|
_memoryManager = new MemoryManager();
|
|
124
|
+
/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */
|
|
125
|
+
_effectivenessTracker = new EffectivenessTracker();
|
|
122
126
|
_isChildSession;
|
|
123
127
|
/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */
|
|
124
128
|
_pendingMemoryProviders = [];
|
|
@@ -960,11 +964,31 @@ export class AgentSession {
|
|
|
960
964
|
}
|
|
961
965
|
return this._promptUnserialized(text, options);
|
|
962
966
|
}
|
|
967
|
+
/**
|
|
968
|
+
* Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so
|
|
969
|
+
* recall only runs when it could plausibly help. The provider's similarity cutoff is the real
|
|
970
|
+
* filter — this just avoids the index query on turns that obviously don't warrant it.
|
|
971
|
+
*/
|
|
972
|
+
_shouldAttemptRecall(text) {
|
|
973
|
+
const t = text.trim();
|
|
974
|
+
if (t.length < 12 || t.startsWith("/"))
|
|
975
|
+
return false;
|
|
976
|
+
const words = t.split(/\s+/).filter((w) => w.length >= 3);
|
|
977
|
+
// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),
|
|
978
|
+
// raise the bar so we only recall on clearly substantial turns — and relax it again once recall
|
|
979
|
+
// starts paying off. Never fully disabled, so the loop can recover.
|
|
980
|
+
const recallRarelyUseful = this._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;
|
|
981
|
+
return words.length >= (recallRarelyUseful ? 6 : 3);
|
|
982
|
+
}
|
|
963
983
|
async _promptUnserialized(text, options) {
|
|
964
984
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
|
965
985
|
const processSlashCommands = options?.processSlashCommands ?? expandPromptTemplates;
|
|
966
986
|
const preflightResult = options?.preflightResult;
|
|
967
987
|
let messages;
|
|
988
|
+
// R4 effectiveness feedback: remember the recall page + the query so we can score, after the
|
|
989
|
+
// response, whether the agent actually used the recalled context.
|
|
990
|
+
let injectedRecall = "";
|
|
991
|
+
let recallQuery = "";
|
|
968
992
|
try {
|
|
969
993
|
// Handle extension commands first. Programmatic extension messages may opt
|
|
970
994
|
// into command handling; if the agent is currently streaming, queue the
|
|
@@ -1043,8 +1067,25 @@ export class AgentSession {
|
|
|
1043
1067
|
if (lastAssistant) {
|
|
1044
1068
|
await this._checkCompaction(lastAssistant, false);
|
|
1045
1069
|
}
|
|
1046
|
-
// Build messages array (custom message if any, then user message)
|
|
1070
|
+
// Build messages array (recall page, then custom message if any, then user message)
|
|
1047
1071
|
messages = [];
|
|
1072
|
+
// R3: cross-session similarity recall. For a substantive turn, ask the memory providers to
|
|
1073
|
+
// prefetch a relevant <memory_context> page from past sessions and prepend it as data ahead of
|
|
1074
|
+
// the user message. Best-effort and gated: trivial turns are skipped, and providers return ""
|
|
1075
|
+
// (no page) when nothing is relevant — so it stays net-negative and the GC packs stale pages.
|
|
1076
|
+
if (this._shouldAttemptRecall(expandedText)) {
|
|
1077
|
+
try {
|
|
1078
|
+
const recall = await this._memoryManager.prefetch(expandedText);
|
|
1079
|
+
if (recall) {
|
|
1080
|
+
injectedRecall = recall;
|
|
1081
|
+
recallQuery = expandedText;
|
|
1082
|
+
messages.push({ role: "user", content: [{ type: "text", text: recall }], timestamp: Date.now() });
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
catch {
|
|
1086
|
+
// recall must never break a turn
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1048
1089
|
// Add user message
|
|
1049
1090
|
const userContent = [{ type: "text", text: expandedText }];
|
|
1050
1091
|
if (currentImages) {
|
|
@@ -1093,6 +1134,19 @@ export class AgentSession {
|
|
|
1093
1134
|
}
|
|
1094
1135
|
preflightResult?.(true);
|
|
1095
1136
|
await this._runAgentPrompt(messages);
|
|
1137
|
+
// R4: score whether the agent actually used the recalled context, so the recall gate can adapt.
|
|
1138
|
+
if (injectedRecall) {
|
|
1139
|
+
const response = this._findLastAssistantMessage();
|
|
1140
|
+
const responseText = response
|
|
1141
|
+
? response.content
|
|
1142
|
+
.filter((c) => c.type === "text")
|
|
1143
|
+
.map((c) => c.text)
|
|
1144
|
+
.join(" ")
|
|
1145
|
+
: "";
|
|
1146
|
+
if (responseText) {
|
|
1147
|
+
this._effectivenessTracker.recordRecallOutcome(injectedRecall, recallQuery, responseText);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1096
1150
|
}
|
|
1097
1151
|
/**
|
|
1098
1152
|
* Try to execute an extension command. Returns true if command was found and executed.
|
|
@@ -2202,6 +2256,9 @@ export class AgentSession {
|
|
|
2202
2256
|
await this._memoryManager.shutdownAll().catch(() => { });
|
|
2203
2257
|
const manager = new MemoryManager();
|
|
2204
2258
|
manager.registerProvider(new FileStoreProvider());
|
|
2259
|
+
// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers
|
|
2260
|
+
// prefetch() with a <memory_context> page. Never writes.
|
|
2261
|
+
manager.registerProvider(new TranscriptRecallProvider());
|
|
2205
2262
|
for (const provider of this._pendingMemoryProviders) {
|
|
2206
2263
|
try {
|
|
2207
2264
|
manager.registerProvider(provider);
|