@caupulican/pi-adaptative 0.80.55 → 0.80.58
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/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +5 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +70 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +181 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +4 -0
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +2 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +23 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/memory/memory-manager.d.ts +22 -0
- package/dist/core/memory/memory-manager.d.ts.map +1 -0
- package/dist/core/memory/memory-manager.js +212 -0
- package/dist/core/memory/memory-manager.js.map +1 -0
- package/dist/core/memory/memory-provider.d.ts +25 -0
- package/dist/core/memory/memory-provider.d.ts.map +1 -0
- package/dist/core/memory/memory-provider.js +2 -0
- package/dist/core/memory/memory-provider.js.map +1 -0
- package/dist/core/memory/providers/file-store.d.ts +23 -0
- package/dist/core/memory/providers/file-store.d.ts.map +1 -0
- package/dist/core/memory/providers/file-store.js +212 -0
- package/dist/core/memory/providers/file-store.js.map +1 -0
- package/dist/core/sdk.d.ts +2 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +11 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/print-mode.d.ts +13 -0
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +18 -1
- package/dist/modes/print-mode.js.map +1 -1
- 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
|
@@ -31,6 +31,8 @@ import { createCoreDiagnosticsToolDefinitions } from "./extensions/builtin.js";
|
|
|
31
31
|
import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
|
|
32
32
|
import { disposeExtensionEventSubscriptions } from "./extensions/loader.js";
|
|
33
33
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
34
|
+
import { MemoryManager } from "./memory/memory-manager.js";
|
|
35
|
+
import { FileStoreProvider } from "./memory/providers/file-store.js";
|
|
34
36
|
import { compactToolResultDetailsForRetention } from "./message-retention.js";
|
|
35
37
|
import { resolveProfileModelSettings } from "./model-resolver.js";
|
|
36
38
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
@@ -57,6 +59,8 @@ export function parseSkillBlock(text) {
|
|
|
57
59
|
userMessage: match[4]?.trim() || undefined,
|
|
58
60
|
};
|
|
59
61
|
}
|
|
62
|
+
/** customType for spawned-usage roll-up entries (Cost Aggregation, Model A). */
|
|
63
|
+
export const SPAWNED_USAGE_CUSTOM_TYPE = "spawned_usage";
|
|
60
64
|
// ============================================================================
|
|
61
65
|
// Constants
|
|
62
66
|
// ============================================================================
|
|
@@ -112,6 +116,11 @@ export class AgentSession {
|
|
|
112
116
|
_toolProfileFilter;
|
|
113
117
|
_isExplicitModel;
|
|
114
118
|
_isExplicitThinking;
|
|
119
|
+
/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */
|
|
120
|
+
_memoryManager = new MemoryManager();
|
|
121
|
+
_isChildSession;
|
|
122
|
+
/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */
|
|
123
|
+
_pendingMemoryProviders = [];
|
|
115
124
|
_baseToolsOverride;
|
|
116
125
|
_sessionStartEvent;
|
|
117
126
|
_extensionUIContext;
|
|
@@ -150,6 +159,7 @@ export class AgentSession {
|
|
|
150
159
|
: undefined;
|
|
151
160
|
this._isExplicitModel = config.isExplicitModel ?? false;
|
|
152
161
|
this._isExplicitThinking = config.isExplicitThinking ?? false;
|
|
162
|
+
this._isChildSession = config.isChildSession ?? process.env.PI_CHILD_SESSION === "1";
|
|
153
163
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
154
164
|
this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
|
|
155
165
|
// Always subscribe to agent events for internal handling
|
|
@@ -651,6 +661,9 @@ export class AgentSession {
|
|
|
651
661
|
this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().");
|
|
652
662
|
this._disconnectFromAgent();
|
|
653
663
|
this._eventListeners = [];
|
|
664
|
+
// Best-effort memory cleanup (release locks/handles). Write-side onSessionEnd is wired on a
|
|
665
|
+
// true session-end hook (P3); file-store shutdown is a no-op.
|
|
666
|
+
void this._memoryManager.shutdownAll().catch(() => { });
|
|
654
667
|
cleanupSessionResources(this.sessionId);
|
|
655
668
|
}
|
|
656
669
|
// =========================================================================
|
|
@@ -867,6 +880,8 @@ export class AgentSession {
|
|
|
867
880
|
const appendSystemPromptParts = [
|
|
868
881
|
this._buildSelfModificationPrompt(),
|
|
869
882
|
this._buildAutonomyPrompt(),
|
|
883
|
+
// Memory subsystem: static, frozen-per-session block (e.g. file-store MEMORY.md/USER.md).
|
|
884
|
+
this._memoryManager.buildSystemPromptBlock() || undefined,
|
|
870
885
|
...loaderAppendSystemPrompt,
|
|
871
886
|
].filter((part) => Boolean(part));
|
|
872
887
|
const appendSystemPrompt = appendSystemPromptParts.length > 0 ? appendSystemPromptParts.join("\n\n") : undefined;
|
|
@@ -1938,6 +1953,8 @@ export class AgentSession {
|
|
|
1938
1953
|
this._applyExtensionBindings(this._extensionRunner);
|
|
1939
1954
|
await this._extensionRunner.emit(this._sessionStartEvent);
|
|
1940
1955
|
await this.extendResourcesFromExtensions(this._sessionStartEvent.reason === "reload" ? "reload" : "startup");
|
|
1956
|
+
// Initialize the memory subsystem after extensions have had a chance to register providers.
|
|
1957
|
+
await this._initializeMemory();
|
|
1941
1958
|
}
|
|
1942
1959
|
async extendResourcesFromExtensions(reason) {
|
|
1943
1960
|
if (!this._extensionRunner.hasHandlers("resources_discover")) {
|
|
@@ -2066,6 +2083,10 @@ export class AgentSession {
|
|
|
2066
2083
|
getThinkingLevel: () => this.thinkingLevel,
|
|
2067
2084
|
setThinkingLevel: (level) => this.setThinkingLevel(level),
|
|
2068
2085
|
getExternalResourceRoots: () => this.settingsManager.getEffectiveExternalResourceRoots(),
|
|
2086
|
+
registerMemoryProvider: (provider) => this.registerMemoryProvider(provider),
|
|
2087
|
+
reportSpawnedUsage: (usage, opts) => {
|
|
2088
|
+
this.addSpawnedUsage(usage, opts);
|
|
2089
|
+
},
|
|
2069
2090
|
}, {
|
|
2070
2091
|
getModel: () => this.model,
|
|
2071
2092
|
isIdle: () => !this.isStreaming,
|
|
@@ -2163,6 +2184,47 @@ export class AgentSession {
|
|
|
2163
2184
|
this.setThinkingLevel(profileSettings.thinkingLevel);
|
|
2164
2185
|
}
|
|
2165
2186
|
}
|
|
2187
|
+
/**
|
|
2188
|
+
* (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled
|
|
2189
|
+
* file-store + any extension-contributed providers, initialize, then surface the memory tools and
|
|
2190
|
+
* the frozen system-prompt block. Best-effort: never throws into the session lifecycle.
|
|
2191
|
+
*/
|
|
2192
|
+
async _initializeMemory() {
|
|
2193
|
+
try {
|
|
2194
|
+
// Release the previous generation's providers (locks/handles) before recreating, so a
|
|
2195
|
+
// reload does not orphan the old MemoryManager. No-op on first init / for file-store.
|
|
2196
|
+
await this._memoryManager.shutdownAll().catch(() => { });
|
|
2197
|
+
const manager = new MemoryManager();
|
|
2198
|
+
manager.registerProvider(new FileStoreProvider());
|
|
2199
|
+
for (const provider of this._pendingMemoryProviders) {
|
|
2200
|
+
try {
|
|
2201
|
+
manager.registerProvider(provider);
|
|
2202
|
+
}
|
|
2203
|
+
catch {
|
|
2204
|
+
// Duplicate name or reserved-tool collision — skip this provider, keep the rest.
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
this._memoryManager = manager;
|
|
2208
|
+
await manager.initializeAll(this.sessionManager.getSessionId(), {
|
|
2209
|
+
agentDir: this._agentDir,
|
|
2210
|
+
cwd: this._cwd,
|
|
2211
|
+
isChildSession: this._isChildSession,
|
|
2212
|
+
});
|
|
2213
|
+
// Surface memory tools + the frozen memory block now that providers are initialized.
|
|
2214
|
+
// _refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the
|
|
2215
|
+
// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.
|
|
2216
|
+
this._refreshToolRegistry();
|
|
2217
|
+
}
|
|
2218
|
+
catch (error) {
|
|
2219
|
+
console.error("Memory subsystem init failed:", error instanceof Error ? error.message : String(error));
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */
|
|
2223
|
+
registerMemoryProvider(provider) {
|
|
2224
|
+
if (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {
|
|
2225
|
+
this._pendingMemoryProviders.push(provider);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2166
2228
|
_refreshToolRegistry(options) {
|
|
2167
2229
|
const previousRegistryNames = new Set(this._toolRegistry.keys());
|
|
2168
2230
|
const previousActiveToolNames = this.getActiveToolNames();
|
|
@@ -2190,6 +2252,11 @@ export class AgentSession {
|
|
|
2190
2252
|
definition,
|
|
2191
2253
|
sourceInfo: createSyntheticSourceInfo(`<sdk:${definition.name}>`, { source: "sdk" }),
|
|
2192
2254
|
})),
|
|
2255
|
+
// Memory subsystem provider tools (e.g. file-store's `memory` tool).
|
|
2256
|
+
...this._memoryManager.getToolDefinitions().map((definition) => ({
|
|
2257
|
+
definition,
|
|
2258
|
+
sourceInfo: createSyntheticSourceInfo(`<memory:${definition.name}>`, { source: "sdk" }),
|
|
2259
|
+
})),
|
|
2193
2260
|
].filter((tool) => isAllowedTool(tool.definition.name));
|
|
2194
2261
|
const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
|
|
2195
2262
|
.filter(([name]) => isAllowedTool(name))
|
|
@@ -2381,6 +2448,8 @@ export class AgentSession {
|
|
|
2381
2448
|
});
|
|
2382
2449
|
try {
|
|
2383
2450
|
this._doctorReloadRuntime();
|
|
2451
|
+
// Reload starts memory providers fresh; loaded extensions re-register below.
|
|
2452
|
+
this._pendingMemoryProviders = [];
|
|
2384
2453
|
const hasBindings = this._extensionUIContext ||
|
|
2385
2454
|
this._extensionCommandContextActions ||
|
|
2386
2455
|
this._extensionShutdownHandler ||
|
|
@@ -2400,6 +2469,8 @@ export class AgentSession {
|
|
|
2400
2469
|
await emitSessionShutdownEvent(previousRunner, { type: "session_shutdown", reason: "reload" });
|
|
2401
2470
|
previousRunner.invalidate();
|
|
2402
2471
|
this._resourceLoader.commitReload?.();
|
|
2472
|
+
// Re-derive the memory subsystem from the reloaded settings/providers.
|
|
2473
|
+
await this._initializeMemory();
|
|
2403
2474
|
}
|
|
2404
2475
|
catch (error) {
|
|
2405
2476
|
if (newRunner && newRunner !== previousRunner) {
|
|
@@ -3023,6 +3094,116 @@ export class AgentSession {
|
|
|
3023
3094
|
contextUsage: this.getContextUsage(),
|
|
3024
3095
|
};
|
|
3025
3096
|
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Cumulative usage (full breakdown) for this session's entire spawn subtree: its own
|
|
3099
|
+
* assistant messages PLUS every `spawned_usage` report it has rolled up. Single source of
|
|
3100
|
+
* truth for "how much did this session and everything it spawned spend" — used by print-mode
|
|
3101
|
+
* to emit a child's total so a spawner can roll it up via {@link addSpawnedUsage}.
|
|
3102
|
+
*
|
|
3103
|
+
* Including the `spawned_usage` reports is what keeps the single-hop invariant intact: a child
|
|
3104
|
+
* that itself spawned grandchildren must report own + sub-usage in one number, or the parent
|
|
3105
|
+
* silently under-counts the grandchildren.
|
|
3106
|
+
*/
|
|
3107
|
+
getCumulativeUsage() {
|
|
3108
|
+
let input = 0;
|
|
3109
|
+
let output = 0;
|
|
3110
|
+
let cacheRead = 0;
|
|
3111
|
+
let cacheWrite = 0;
|
|
3112
|
+
let totalTokens = 0;
|
|
3113
|
+
let costInput = 0;
|
|
3114
|
+
let costOutput = 0;
|
|
3115
|
+
let costCacheRead = 0;
|
|
3116
|
+
let costCacheWrite = 0;
|
|
3117
|
+
let costTotal = 0;
|
|
3118
|
+
const add = (usage) => {
|
|
3119
|
+
input += usage.input;
|
|
3120
|
+
output += usage.output;
|
|
3121
|
+
cacheRead += usage.cacheRead;
|
|
3122
|
+
cacheWrite += usage.cacheWrite;
|
|
3123
|
+
totalTokens += usage.totalTokens;
|
|
3124
|
+
costInput += usage.cost.input;
|
|
3125
|
+
costOutput += usage.cost.output;
|
|
3126
|
+
costCacheRead += usage.cost.cacheRead;
|
|
3127
|
+
costCacheWrite += usage.cost.cacheWrite;
|
|
3128
|
+
costTotal += usage.cost.total;
|
|
3129
|
+
};
|
|
3130
|
+
for (const message of this.state.messages) {
|
|
3131
|
+
if (message.role !== "assistant")
|
|
3132
|
+
continue;
|
|
3133
|
+
const usage = message.usage;
|
|
3134
|
+
if (!usage)
|
|
3135
|
+
continue;
|
|
3136
|
+
add(usage);
|
|
3137
|
+
}
|
|
3138
|
+
// Roll up usage this session attributed to its own spawned children (single-hop).
|
|
3139
|
+
for (const entry of this.sessionManager.getEntries()) {
|
|
3140
|
+
if (entry.type !== "custom" || entry.customType !== SPAWNED_USAGE_CUSTOM_TYPE)
|
|
3141
|
+
continue;
|
|
3142
|
+
const data = entry.data;
|
|
3143
|
+
if (data?.usage)
|
|
3144
|
+
add(data.usage);
|
|
3145
|
+
}
|
|
3146
|
+
return {
|
|
3147
|
+
input,
|
|
3148
|
+
output,
|
|
3149
|
+
cacheRead,
|
|
3150
|
+
cacheWrite,
|
|
3151
|
+
totalTokens,
|
|
3152
|
+
cost: {
|
|
3153
|
+
input: costInput,
|
|
3154
|
+
output: costOutput,
|
|
3155
|
+
cacheRead: costCacheRead,
|
|
3156
|
+
cacheWrite: costCacheWrite,
|
|
3157
|
+
total: costTotal,
|
|
3158
|
+
},
|
|
3159
|
+
};
|
|
3160
|
+
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Record usage spent by a spawned/subagent session so the footer can roll it into the
|
|
3163
|
+
* displayed cost. Persisted as a `CustomEntry` (`customType: "spawned_usage"`, Model A) so
|
|
3164
|
+
* it survives reload and is reconstructed exactly like main usage; a new/forked session
|
|
3165
|
+
* starts fresh because it owns a new log file.
|
|
3166
|
+
*
|
|
3167
|
+
* Idempotent on `opts.reportId`: a re-report (retry, duplicate `agent_end`) with a
|
|
3168
|
+
* previously-seen id is ignored, so cost cannot be double-counted. Honors the single-hop
|
|
3169
|
+
* invariant documented on {@link SpawnedUsageReport}.
|
|
3170
|
+
*
|
|
3171
|
+
* @returns the id of the appended entry, or `undefined` if the report was a duplicate.
|
|
3172
|
+
*/
|
|
3173
|
+
addSpawnedUsage(usage, opts) {
|
|
3174
|
+
const reportId = opts?.reportId;
|
|
3175
|
+
if (reportId) {
|
|
3176
|
+
for (const entry of this.sessionManager.getEntries()) {
|
|
3177
|
+
if (entry.type === "custom" &&
|
|
3178
|
+
entry.customType === SPAWNED_USAGE_CUSTOM_TYPE &&
|
|
3179
|
+
entry.data?.reportId === reportId) {
|
|
3180
|
+
return undefined;
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
const report = {
|
|
3185
|
+
usage,
|
|
3186
|
+
label: opts?.label,
|
|
3187
|
+
sourceSessionId: opts?.sourceSessionId,
|
|
3188
|
+
reportId,
|
|
3189
|
+
};
|
|
3190
|
+
return this.sessionManager.appendCustomEntry(SPAWNED_USAGE_CUSTOM_TYPE, report);
|
|
3191
|
+
}
|
|
3192
|
+
/** Aggregate all recorded spawned-usage reports (see {@link addSpawnedUsage}). */
|
|
3193
|
+
getSpawnedUsage() {
|
|
3194
|
+
let cost = 0;
|
|
3195
|
+
let reports = 0;
|
|
3196
|
+
for (const entry of this.sessionManager.getEntries()) {
|
|
3197
|
+
if (entry.type !== "custom" || entry.customType !== SPAWNED_USAGE_CUSTOM_TYPE)
|
|
3198
|
+
continue;
|
|
3199
|
+
const data = entry.data;
|
|
3200
|
+
if (!data?.usage)
|
|
3201
|
+
continue;
|
|
3202
|
+
cost += data.usage.cost.total;
|
|
3203
|
+
reports += 1;
|
|
3204
|
+
}
|
|
3205
|
+
return { cost, reports };
|
|
3206
|
+
}
|
|
3026
3207
|
getContextUsage() {
|
|
3027
3208
|
const model = this.model;
|
|
3028
3209
|
if (!model)
|