@aexol/spectral 0.9.184 → 0.9.186
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/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +8 -2
- package/dist/memory/branch.d.ts +13 -0
- package/dist/memory/branch.d.ts.map +1 -1
- package/dist/memory/branch.js +100 -0
- package/dist/memory/hooks/compaction-hook.d.ts.map +1 -1
- package/dist/memory/hooks/compaction-hook.js +43 -1
- package/dist/memory/hooks/observer-trigger.d.ts.map +1 -1
- package/dist/memory/hooks/observer-trigger.js +9 -3
- package/dist/memory/index.d.ts +13 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +17 -26
- package/dist/memory/project-observation-memory.d.ts +16 -0
- package/dist/memory/project-observation-memory.d.ts.map +1 -0
- package/dist/memory/project-observation-memory.js +27 -0
- package/dist/memory/project-observations-store.d.ts +8 -0
- package/dist/memory/project-observations-store.d.ts.map +1 -1
- package/dist/memory/project-observations-store.js +5 -0
- package/dist/memory/prompts.d.ts +2 -2
- package/dist/memory/prompts.d.ts.map +1 -1
- package/dist/memory/prompts.js +1 -1
- package/dist/memory/session-memory.d.ts +21 -0
- package/dist/memory/session-memory.d.ts.map +1 -0
- package/dist/memory/session-memory.js +33 -0
- package/dist/memory/tool-output-compressor.d.ts +0 -1
- package/dist/memory/tool-output-compressor.d.ts.map +1 -1
- package/dist/memory/tool-output-compressor.js +0 -1
- package/dist/memory/tools/compact-context.d.ts +31 -0
- package/dist/memory/tools/compact-context.d.ts.map +1 -1
- package/dist/memory/tools/compact-context.js +224 -23
- package/dist/memory/tools/read-project-observations.d.ts.map +1 -1
- package/dist/memory/tools/read-project-observations.js +6 -3
- package/dist/memory/tools/recall-observation.d.ts.map +1 -1
- package/dist/memory/tools/recall-observation.js +18 -4
- package/dist/memory/tools/receive-agent-observations.d.ts.map +1 -1
- package/dist/memory/tools/receive-agent-observations.js +4 -2
- package/dist/memory/tools/share-project-observation.d.ts.map +1 -1
- package/dist/memory/tools/share-project-observation.js +5 -3
- package/dist/memory/tools/write-project-observation.d.ts.map +1 -1
- package/dist/memory/tools/write-project-observation.js +16 -3
- package/dist/sdk/coding-agent/core/agent-session.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/agent-session.js +0 -1
- package/dist/sdk/coding-agent/core/compaction/compaction.d.ts +11 -0
- package/dist/sdk/coding-agent/core/compaction/compaction.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/compaction/compaction.js +15 -2
- package/dist/sdk/coding-agent/core/compaction/policy.d.ts +22 -4
- package/dist/sdk/coding-agent/core/compaction/policy.d.ts.map +1 -1
- package/dist/sdk/coding-agent/core/compaction/policy.js +39 -6
- package/dist/server/inter-agent-broker.d.ts +12 -7
- package/dist/server/inter-agent-broker.d.ts.map +1 -1
- package/dist/server/inter-agent-broker.js +12 -7
- package/dist/server/session-stream.d.ts.map +1 -1
- package/dist/server/session-stream.js +6 -4
- package/dist/server/sqlite-adapter.d.ts +11 -8
- package/dist/server/sqlite-adapter.d.ts.map +1 -1
- package/dist/server/sqlite-adapter.js +195 -44
- package/dist/server/storage.d.ts +22 -5
- package/dist/server/storage.d.ts.map +1 -1
- package/dist/server/storage.js +52 -6
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { registerStatusCommand } from "./commands/status.js";
|
|
2
|
+
import { registerViewCommand } from "./commands/view.js";
|
|
3
|
+
import { registerCompactionHook } from "./hooks/compaction-hook.js";
|
|
4
|
+
import { registerCompactionTrigger } from "./hooks/compaction-trigger.js";
|
|
5
|
+
import { registerObserverTrigger } from "./hooks/observer-trigger.js";
|
|
6
|
+
import { registerToolOutputCompressor } from "./tool-output-compressor.js";
|
|
7
|
+
import { registerCompactContextTool } from "./tools/compact-context.js";
|
|
8
|
+
/**
|
|
9
|
+
* Session/branch memory layer.
|
|
10
|
+
*
|
|
11
|
+
* This layer owns the branch-scoped observational-memory pipeline:
|
|
12
|
+
* - the observer (`observer.ts` via `observer-trigger.ts`) extracts
|
|
13
|
+
* observations from new conversation turns;
|
|
14
|
+
* - the deterministic pruner (`deterministic-pruner.ts` via
|
|
15
|
+
* `compaction-hook.ts`) drops low-value observations at compaction time;
|
|
16
|
+
* - the summary render path (`compaction.ts`) produces the compacted memory
|
|
17
|
+
* that is persisted into `session_memory_snapshots`;
|
|
18
|
+
* - the snapshot persistence hooks (`compaction-hook.ts`,
|
|
19
|
+
* `compaction-trigger.ts`, `observer-trigger.ts`) keep that session memory
|
|
20
|
+
* alive across compactions.
|
|
21
|
+
*
|
|
22
|
+
* It is intentionally separate from `project-observation-memory.ts`, which
|
|
23
|
+
* owns the per-machine + per-cwd, cross-session project observation store.
|
|
24
|
+
*/
|
|
25
|
+
export function registerSessionMemory(ext, runtime) {
|
|
26
|
+
registerObserverTrigger(ext, runtime);
|
|
27
|
+
registerCompactContextTool(ext, runtime);
|
|
28
|
+
registerCompactionTrigger(ext, runtime);
|
|
29
|
+
registerCompactionHook(ext, runtime);
|
|
30
|
+
registerToolOutputCompressor(ext, runtime);
|
|
31
|
+
registerStatusCommand(ext, runtime);
|
|
32
|
+
registerViewCommand(ext, runtime);
|
|
33
|
+
}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* This is complementary to the conversation-level compaction pipeline:
|
|
6
6
|
* - Compressor: compresses raw tool output (pre-context)
|
|
7
7
|
* - Compaction: summarizes + prunes conversation history (post-context)
|
|
8
|
-
* - Unified compaction: narrative summary + observation extraction (at compaction boundary)
|
|
9
8
|
*
|
|
10
9
|
* Strategies (mirroring RTK's four-pronged approach):
|
|
11
10
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-output-compressor.d.ts","sourceRoot":"","sources":["../../src/memory/tool-output-compressor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tool-output-compressor.d.ts","sourceRoot":"","sources":["../../src/memory/tool-output-compressor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAEX,gBAAgB,EAIhB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAGN,KAAK,0BAA0B,EAC/B,MAAM,+CAA+C,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAO5C,MAAM,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAE1D,eAAO,MAAM,yBAAyB,EAAE,gBAEvC,CAAC;AAgsBF,MAAM,WAAW,gBAAgB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,8BAA8B;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3F;AA8BD,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,OAAO,GAAG,8BAA8B,CAElG;AAED,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE1E;AAkDD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACzC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,EAC7F,GAAG,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,CAAC,GAC7C,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAYvG;AAED,wBAAgB,4BAA4B,CAC3C,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACd,IAAI,CAkCN"}
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* This is complementary to the conversation-level compaction pipeline:
|
|
6
6
|
* - Compressor: compresses raw tool output (pre-context)
|
|
7
7
|
* - Compaction: summarizes + prunes conversation history (post-context)
|
|
8
|
-
* - Unified compaction: narrative summary + observation extraction (at compaction boundary)
|
|
9
8
|
*
|
|
10
9
|
* Strategies (mirroring RTK's four-pronged approach):
|
|
11
10
|
*
|
|
@@ -3,7 +3,38 @@ import { type CompactionPolicy } from "../../sdk/coding-agent/core/compaction/in
|
|
|
3
3
|
import { type ExtensionAPI } from "../../sdk/coding-agent/index.js";
|
|
4
4
|
import type { Runtime } from "../runtime.js";
|
|
5
5
|
export declare const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
6
|
+
export interface AutoPruneFrozen {
|
|
7
|
+
/** Session identity used to invalidate the frozen cut after branch/session switches. */
|
|
8
|
+
sessionId: string;
|
|
9
|
+
/** Index into the provider message array for the first kept message. */
|
|
10
|
+
cutIndex: number;
|
|
11
|
+
/** Stable AgentMessage reference at `cutIndex`, used as an O(1) identity anchor. */
|
|
12
|
+
anchor: AgentMessage;
|
|
13
|
+
/** Deterministic DCP-lite summary generated at the original prune. */
|
|
14
|
+
summary: string;
|
|
15
|
+
/** Original tokensBefore for the frozen compaction summary message. */
|
|
16
|
+
tokensBefore: number;
|
|
17
|
+
/** Original compaction timestamp for the frozen compaction summary message. */
|
|
18
|
+
timestamp: string;
|
|
19
|
+
/** Keep-recent token budget that produced this cut (policy-change invalidation). */
|
|
20
|
+
keepRecentTokensUsed: number;
|
|
21
|
+
/** Token estimate of the kept tail at the moment the cut was frozen. */
|
|
22
|
+
tailTokensAtFreeze: number;
|
|
23
|
+
}
|
|
6
24
|
/** Request-time DCP adapter for isolated loops: it borrows only pure policy helpers. */
|
|
7
25
|
export declare function buildIsolatedRequestTimePrunedMessages(currentMessages: AgentMessage[], policy?: CompactionPolicy, keepRecentTokens?: number): AgentMessage[];
|
|
26
|
+
export interface IsolatedRequestTimePruneResult {
|
|
27
|
+
messages: AgentMessage[];
|
|
28
|
+
frozen: AutoPruneFrozen | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Stateful per-run variant of {@link buildIsolatedRequestTimePrunedMessages}.
|
|
32
|
+
*
|
|
33
|
+
* The subagent loop owns the returned `frozen` value across provider requests.
|
|
34
|
+
* On the first prune we freeze the deterministic summary + cut, then reuse that
|
|
35
|
+
* exact prefix until the kept-tail anchor reference changes or the tail grows
|
|
36
|
+
* past the window-relative hysteresis budget.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildIsolatedRequestTimePrunedMessagesResult(currentMessages: AgentMessage[], policy?: CompactionPolicy, keepRecentTokens?: number, frozen?: AutoPruneFrozen | null, contextWindow?: number | null): IsolatedRequestTimePruneResult;
|
|
8
39
|
export declare function registerCompactContextTool(ext: ExtensionAPI, runtime: Runtime): void;
|
|
9
40
|
//# sourceMappingURL=compact-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compact-context.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/compact-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"compact-context.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/compact-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAaN,KAAK,gBAAgB,EACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAc,KAAK,YAAY,EAAyB,MAAM,iCAAiC,CAAC;AAMvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AA+F3D,MAAM,WAAW,eAAe;IAC/B,wFAAwF;IACxF,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,MAAM,EAAE,YAAY,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,oBAAoB,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,kBAAkB,EAAE,MAAM,CAAC;CAC3B;AAgYD,wFAAwF;AACxF,wBAAgB,sCAAsC,CACrD,eAAe,EAAE,YAAY,EAAE,EAC/B,MAAM,GAAE,gBAA4C,EACpD,gBAAgB,CAAC,EAAE,MAAM,GACvB,YAAY,EAAE,CAMhB;AAED,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CAC/B;AAkBD;;;;;;;GAOG;AACH,wBAAgB,4CAA4C,CAC3D,eAAe,EAAE,YAAY,EAAE,EAC/B,MAAM,GAAE,gBAA4C,EACpD,gBAAgB,CAAC,EAAE,MAAM,EACzB,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,EAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC3B,8BAA8B,CA4DhC;AA0SD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAgTpF"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Type } from "../../sdk/ai/index.js";
|
|
2
|
-
import { compactDcpLite, DEFAULT_COMPACTION_POLICY, estimateTokens, getManualCompactionSettings, normalizeAgentDrivenOlderHistoryKeepRecentTokens, prepareCompaction, decideCompaction, } from "../../sdk/coding-agent/core/compaction/index.js";
|
|
2
|
+
import { compactDcpLite, CONTEXT_LIMIT_RATIO, DEFAULT_COMPACTION_POLICY, estimateTokens, getManualCompactionSettings, normalizeAgentDrivenOlderHistoryKeepRecentTokens, prepareCompaction, decideCompaction, getAutoOlderHistoryHysteresisTokens, getAutoOlderHistoryKeepRecentTokens, } from "../../sdk/coding-agent/core/compaction/index.js";
|
|
3
3
|
import { defineTool } from "../../sdk/coding-agent/index.js";
|
|
4
4
|
import { buildSessionContext } from "../../sdk/coding-agent/core/session-manager.js";
|
|
5
|
+
import { createCompactionSummaryMessage } from "../../sdk/coding-agent/core/messages.js";
|
|
5
6
|
import { rawTokensSinceLastCompaction } from "../branch.js";
|
|
6
7
|
import { debugLog, withDebugLogContext } from "../debug-log.js";
|
|
7
8
|
export const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
@@ -61,6 +62,7 @@ function getState(runtime) {
|
|
|
61
62
|
request: null,
|
|
62
63
|
turnCount: 0,
|
|
63
64
|
lastAgentDrivenRequestTurn: null,
|
|
65
|
+
autoPruneFrozen: null,
|
|
64
66
|
};
|
|
65
67
|
stateByRuntime.set(runtime, state);
|
|
66
68
|
}
|
|
@@ -176,12 +178,32 @@ function getAutoOlderHistoryRequestSettings(policy) {
|
|
|
176
178
|
pinLatestUserMessage: true,
|
|
177
179
|
};
|
|
178
180
|
}
|
|
181
|
+
function getContextWindow(ctx) {
|
|
182
|
+
try {
|
|
183
|
+
const usage = ctx.getContextUsage();
|
|
184
|
+
if (usage && typeof usage.contextWindow === "number" && usage.contextWindow > 0) {
|
|
185
|
+
return usage.contextWindow;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// getContextUsage is optional in some headless harnesses.
|
|
190
|
+
}
|
|
191
|
+
const modelWindow = ctx.model?.contextWindow;
|
|
192
|
+
return typeof modelWindow === "number" && modelWindow > 0 ? modelWindow : undefined;
|
|
193
|
+
}
|
|
194
|
+
function getAutoRequestTimeRequestSettings(policy, contextWindow) {
|
|
195
|
+
const keepRecentTokens = getAutoOlderHistoryKeepRecentTokens(policy, contextWindow) ?? policy.agentDriven.olderHistoryKeepRecentTokens;
|
|
196
|
+
return {
|
|
197
|
+
phaseBoundary: false,
|
|
198
|
+
scope: "older_history",
|
|
199
|
+
keepRecentTokens,
|
|
200
|
+
minRawTokens: keepRecentTokens + policy.agentDriven.olderHistoryMinCompactableTokens,
|
|
201
|
+
pinLatestUserMessage: true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
179
204
|
function isContextAtOrAboveRatio(percent, ratio) {
|
|
180
205
|
return typeof percent === "number" && Number.isFinite(percent) && percent >= ratio * 100;
|
|
181
206
|
}
|
|
182
|
-
function isContextAtOrAboveTokenLimit(contextTokens, tokenLimit) {
|
|
183
|
-
return typeof contextTokens === "number" && Number.isFinite(contextTokens) && contextTokens >= tokenLimit;
|
|
184
|
-
}
|
|
185
207
|
function hasPendingModelRequest(ctx) {
|
|
186
208
|
try {
|
|
187
209
|
if (!ctx.isIdle())
|
|
@@ -196,8 +218,11 @@ function hasPendingModelRequest(ctx) {
|
|
|
196
218
|
return false;
|
|
197
219
|
}
|
|
198
220
|
}
|
|
199
|
-
function decideAutoCompaction(ctx, runtime, state, policy, rawTokens,
|
|
200
|
-
const
|
|
221
|
+
function decideAutoCompaction(ctx, runtime, state, policy, rawTokens, percent, iterationSignal = false, isMidRun = hasPendingModelRequest(ctx)) {
|
|
222
|
+
const contextWindow = getContextWindow(ctx);
|
|
223
|
+
const requestSettings = isMidRun
|
|
224
|
+
? getAutoRequestTimeRequestSettings(policy, contextWindow)
|
|
225
|
+
: getAutoOlderHistoryRequestSettings(policy);
|
|
201
226
|
return decideCompaction({
|
|
202
227
|
source: "automatic",
|
|
203
228
|
isMidRun,
|
|
@@ -206,17 +231,17 @@ function decideAutoCompaction(ctx, runtime, state, policy, rawTokens, contextTok
|
|
|
206
231
|
pending: state.request !== null,
|
|
207
232
|
cooldownActive: remainingCooldownTurns(state, policy) > 0,
|
|
208
233
|
hasSufficientMaterial: rawTokens >= requestSettings.minRawTokens,
|
|
209
|
-
contextRatioReached: isContextAtOrAboveRatio(percent,
|
|
210
|
-
absoluteThresholdReached: isContextAtOrAboveTokenLimit(contextTokens, runtime.config.autoCompactionContextTokens),
|
|
211
|
-
rawThresholdReached: rawTokens >= runtime.config.compactionThresholdTokens,
|
|
234
|
+
contextRatioReached: isContextAtOrAboveRatio(percent, CONTEXT_LIMIT_RATIO),
|
|
212
235
|
iterationReached: iterationSignal,
|
|
213
236
|
});
|
|
214
237
|
}
|
|
215
|
-
function maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, rawTokens,
|
|
216
|
-
const decision = decideAutoCompaction(ctx, runtime, state, policy, rawTokens,
|
|
238
|
+
function maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, rawTokens, percent, iterationSignal = false) {
|
|
239
|
+
const decision = decideAutoCompaction(ctx, runtime, state, policy, rawTokens, percent, iterationSignal);
|
|
217
240
|
if (decision.mode === "none")
|
|
218
241
|
return false;
|
|
219
|
-
const requestSettings =
|
|
242
|
+
const requestSettings = decision.mode === "request_time"
|
|
243
|
+
? getAutoRequestTimeRequestSettings(policy, getContextWindow(ctx))
|
|
244
|
+
: getAutoOlderHistoryRequestSettings(policy);
|
|
220
245
|
state.lastAgentDrivenRequestTurn = state.turnCount;
|
|
221
246
|
state.request = { source: "auto", mode: decision.mode, ...requestSettings };
|
|
222
247
|
if (decision.mode === "request_time")
|
|
@@ -241,12 +266,27 @@ function getRequestTimeCompactionSettings(request, policy) {
|
|
|
241
266
|
function getBranchEntries(ctx) {
|
|
242
267
|
return ctx.sessionManager.getBranch();
|
|
243
268
|
}
|
|
244
|
-
function
|
|
269
|
+
function getAutoPruneSessionId(ctx) {
|
|
270
|
+
try {
|
|
271
|
+
return ctx.sessionManager.getSessionId();
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
return "unknown-session";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function autoPruneFrozenIdentityMatches(frozen, sessionId, currentMessages) {
|
|
278
|
+
if (frozen.sessionId !== sessionId)
|
|
279
|
+
return false;
|
|
280
|
+
return currentMessages.length > frozen.cutIndex &&
|
|
281
|
+
frozen.cutIndex >= 0 &&
|
|
282
|
+
currentMessages[frozen.cutIndex] === frozen.anchor;
|
|
283
|
+
}
|
|
284
|
+
function createVirtualCompactionEntry(pathEntries, result, timestamp) {
|
|
245
285
|
return {
|
|
246
286
|
type: "compaction",
|
|
247
287
|
id: REQUEST_TIME_VIRTUAL_COMPACTION_ID,
|
|
248
288
|
parentId: pathEntries[pathEntries.length - 1]?.id ?? null,
|
|
249
|
-
timestamp: pathEntries[pathEntries.length - 1]?.timestamp ?? new Date().toISOString(),
|
|
289
|
+
timestamp: timestamp ?? pathEntries[pathEntries.length - 1]?.timestamp ?? new Date().toISOString(),
|
|
250
290
|
summary: result.summary,
|
|
251
291
|
firstKeptEntryId: result.firstKeptEntryId,
|
|
252
292
|
tokensBefore: result.tokensBefore,
|
|
@@ -270,12 +310,55 @@ function buildRequestTimePrunedMessages(ctx, request, policy, currentMessages, o
|
|
|
270
310
|
message,
|
|
271
311
|
}));
|
|
272
312
|
const fromCurrentMessages = buildRequestTimePrunedMessagesFromEntries(currentEntries, request, policy, currentMessages, onFailure);
|
|
273
|
-
if (fromCurrentMessages)
|
|
313
|
+
if (fromCurrentMessages) {
|
|
314
|
+
if (typeof fromCurrentMessages.cutIndex === "number") {
|
|
315
|
+
fromCurrentMessages.anchorMessage = currentMessages[fromCurrentMessages.cutIndex];
|
|
316
|
+
}
|
|
274
317
|
return fromCurrentMessages;
|
|
318
|
+
}
|
|
275
319
|
return buildRequestTimePrunedMessagesFromEntries(getBranchEntries(ctx), request, policy, currentMessages, onFailure);
|
|
276
320
|
}
|
|
321
|
+
function buildFrozenRequestTimePrunedMessages(frozen, currentMessages) {
|
|
322
|
+
if (frozen.cutIndex < 0 ||
|
|
323
|
+
currentMessages.length <= frozen.cutIndex ||
|
|
324
|
+
currentMessages[frozen.cutIndex] !== frozen.anchor) {
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
const messages = [
|
|
328
|
+
createCompactionSummaryMessage(frozen.summary, frozen.tokensBefore, frozen.timestamp),
|
|
329
|
+
...currentMessages.slice(frozen.cutIndex),
|
|
330
|
+
];
|
|
331
|
+
const originalTokens = rawTokensForCurrentMessages(currentMessages);
|
|
332
|
+
const prunedTokens = rawTokensForCurrentMessages(messages);
|
|
333
|
+
if (prunedTokens >= originalTokens)
|
|
334
|
+
return undefined;
|
|
335
|
+
return {
|
|
336
|
+
messages,
|
|
337
|
+
tokensRemoved: Math.max(0, originalTokens - prunedTokens),
|
|
338
|
+
originalTokens,
|
|
339
|
+
prunedTokens,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
277
342
|
/** Request-time DCP adapter for isolated loops: it borrows only pure policy helpers. */
|
|
278
343
|
export function buildIsolatedRequestTimePrunedMessages(currentMessages, policy = DEFAULT_COMPACTION_POLICY, keepRecentTokens) {
|
|
344
|
+
return buildIsolatedRequestTimePrunedMessagesResult(currentMessages, policy, keepRecentTokens).messages;
|
|
345
|
+
}
|
|
346
|
+
function autoPruneHysteresisExceeded(frozen, currentMessages, policy, contextWindow) {
|
|
347
|
+
if (frozen.cutIndex < 0 || frozen.cutIndex >= currentMessages.length)
|
|
348
|
+
return true;
|
|
349
|
+
const tailTokens = rawTokensForCurrentMessages(currentMessages.slice(frozen.cutIndex));
|
|
350
|
+
const hysteresisTokens = getAutoOlderHistoryHysteresisTokens(policy, contextWindow, frozen.keepRecentTokensUsed);
|
|
351
|
+
return tailTokens - frozen.tailTokensAtFreeze > hysteresisTokens;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Stateful per-run variant of {@link buildIsolatedRequestTimePrunedMessages}.
|
|
355
|
+
*
|
|
356
|
+
* The subagent loop owns the returned `frozen` value across provider requests.
|
|
357
|
+
* On the first prune we freeze the deterministic summary + cut, then reuse that
|
|
358
|
+
* exact prefix until the kept-tail anchor reference changes or the tail grows
|
|
359
|
+
* past the window-relative hysteresis budget.
|
|
360
|
+
*/
|
|
361
|
+
export function buildIsolatedRequestTimePrunedMessagesResult(currentMessages, policy = DEFAULT_COMPACTION_POLICY, keepRecentTokens, frozen, contextWindow) {
|
|
279
362
|
const syntheticEntries = currentMessages.map((message, index) => ({
|
|
280
363
|
type: "message",
|
|
281
364
|
id: `isolated-${index}`,
|
|
@@ -283,18 +366,69 @@ export function buildIsolatedRequestTimePrunedMessages(currentMessages, policy =
|
|
|
283
366
|
timestamp: new Date(index).toISOString(),
|
|
284
367
|
message,
|
|
285
368
|
}));
|
|
286
|
-
|
|
369
|
+
const resolvedKeepRecentTokens = getAutoOlderHistoryKeepRecentTokens(policy, contextWindow, keepRecentTokens);
|
|
370
|
+
const request = {
|
|
371
|
+
source: "auto",
|
|
372
|
+
mode: "request_time",
|
|
373
|
+
scope: "older_history",
|
|
374
|
+
keepRecentTokens: resolvedKeepRecentTokens,
|
|
375
|
+
phaseBoundary: false,
|
|
376
|
+
minRawTokens: 0,
|
|
377
|
+
pinLatestUserMessage: true,
|
|
378
|
+
};
|
|
379
|
+
const sessionId = "isolated-subagent-run";
|
|
380
|
+
if (frozen &&
|
|
381
|
+
frozen.keepRecentTokensUsed === resolvedKeepRecentTokens &&
|
|
382
|
+
autoPruneFrozenIdentityMatches(frozen, sessionId, currentMessages) &&
|
|
383
|
+
!autoPruneHysteresisExceeded(frozen, currentMessages, policy, contextWindow)) {
|
|
384
|
+
const reused = buildFrozenRequestTimePrunedMessages(frozen, currentMessages);
|
|
385
|
+
if (reused)
|
|
386
|
+
return { messages: reused.messages, frozen };
|
|
387
|
+
}
|
|
388
|
+
const pruned = buildRequestTimePrunedMessagesFromEntries(syntheticEntries, request, policy, currentMessages);
|
|
389
|
+
const cutIndex = pruned?.cutIndex;
|
|
390
|
+
const anchorMessage = typeof cutIndex === "number" ? currentMessages[cutIndex] : undefined;
|
|
391
|
+
if (!pruned ||
|
|
392
|
+
typeof cutIndex !== "number" ||
|
|
393
|
+
anchorMessage === undefined ||
|
|
394
|
+
typeof pruned.summary !== "string") {
|
|
395
|
+
return { messages: currentMessages, frozen: null };
|
|
396
|
+
}
|
|
397
|
+
const nextFrozen = {
|
|
398
|
+
sessionId,
|
|
399
|
+
cutIndex,
|
|
400
|
+
anchor: anchorMessage,
|
|
401
|
+
summary: pruned.summary,
|
|
402
|
+
tokensBefore: pruned.tokensBefore ?? 0,
|
|
403
|
+
timestamp: pruned.timestamp ?? new Date().toISOString(),
|
|
404
|
+
keepRecentTokensUsed: resolvedKeepRecentTokens ?? 0,
|
|
405
|
+
tailTokensAtFreeze: rawTokensForCurrentMessages(currentMessages.slice(cutIndex)),
|
|
406
|
+
};
|
|
407
|
+
return { messages: pruned.messages, frozen: nextFrozen };
|
|
287
408
|
}
|
|
288
409
|
function buildRequestTimePrunedMessagesFromEntries(pathEntries, request, policy, currentMessages, onFailure) {
|
|
289
410
|
const settings = getRequestTimeCompactionSettings(request, policy);
|
|
290
|
-
const preparation = prepareCompaction(pathEntries, settings, {
|
|
411
|
+
const preparation = prepareCompaction(pathEntries, settings, {
|
|
412
|
+
phaseBoundary: request.phaseBoundary,
|
|
413
|
+
pinLatestUserMessage: request.pinLatestUserMessage,
|
|
414
|
+
});
|
|
291
415
|
if (!preparation) {
|
|
292
416
|
onFailure?.("prepare_compaction_returned_undefined");
|
|
293
417
|
return undefined;
|
|
294
418
|
}
|
|
295
419
|
const result = compactDcpLite(preparation);
|
|
420
|
+
const summary = result.summary;
|
|
421
|
+
const firstKeptEntryId = result.firstKeptEntryId;
|
|
422
|
+
const tokensBefore = result.tokensBefore;
|
|
423
|
+
const details = result.details;
|
|
296
424
|
const tokensRemoved = Math.max(0, result.tokensRemoved ?? 0);
|
|
297
|
-
const
|
|
425
|
+
const virtualTimestamp = pathEntries[pathEntries.length - 1]?.timestamp ?? new Date().toISOString();
|
|
426
|
+
const virtualCompaction = createVirtualCompactionEntry(pathEntries, {
|
|
427
|
+
summary,
|
|
428
|
+
firstKeptEntryId,
|
|
429
|
+
tokensBefore,
|
|
430
|
+
details,
|
|
431
|
+
}, virtualTimestamp);
|
|
298
432
|
const virtualContext = buildSessionContext([...pathEntries, virtualCompaction]);
|
|
299
433
|
if (virtualContext.messages.length === 0) {
|
|
300
434
|
onFailure?.("virtual_context_has_no_messages");
|
|
@@ -311,7 +445,17 @@ function buildRequestTimePrunedMessagesFromEntries(pathEntries, request, policy,
|
|
|
311
445
|
: `pruned_context_not_smaller:${originalTokens}->${prunedTokens}`);
|
|
312
446
|
return undefined;
|
|
313
447
|
}
|
|
314
|
-
|
|
448
|
+
const cutIndex = pathEntries.findIndex((entry) => entry.id === firstKeptEntryId);
|
|
449
|
+
return {
|
|
450
|
+
messages: virtualContext.messages,
|
|
451
|
+
tokensRemoved,
|
|
452
|
+
originalTokens,
|
|
453
|
+
prunedTokens,
|
|
454
|
+
cutIndex: cutIndex >= 0 ? cutIndex : undefined,
|
|
455
|
+
summary,
|
|
456
|
+
tokensBefore,
|
|
457
|
+
timestamp: virtualTimestamp,
|
|
458
|
+
};
|
|
315
459
|
}
|
|
316
460
|
function notifyDcp(ctx, message, level, telemetry) {
|
|
317
461
|
const notify = ctx.ui?.notify;
|
|
@@ -499,9 +643,8 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
499
643
|
rawTokens = 0;
|
|
500
644
|
}
|
|
501
645
|
const usage = ctx.getContextUsage();
|
|
502
|
-
const contextTokens = usage?.tokens;
|
|
503
646
|
const percent = usage?.percent;
|
|
504
|
-
maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, rawTokens,
|
|
647
|
+
maybeScheduleAutoOlderHistoryCompaction(ctx, runtime, state, policy, rawTokens, percent);
|
|
505
648
|
}));
|
|
506
649
|
ext.on("context", withDebug((_event, ctx) => {
|
|
507
650
|
runtime.ensureConfig(ctx.cwd);
|
|
@@ -566,12 +709,53 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
566
709
|
// The context hook is the last zero-lag seam before conversion/provider send.
|
|
567
710
|
// Treat an explicit provider-preparation event as in-run even if the session
|
|
568
711
|
// state has not flipped to streaming/pending yet.
|
|
569
|
-
const
|
|
712
|
+
const autoContextWindow = getContextWindow(ctx);
|
|
713
|
+
const autoSettings = getAutoRequestTimeRequestSettings(policy, autoContextWindow);
|
|
570
714
|
const autoRawTokens = Math.max(safeRawTokensForContext(ctx), rawTokensForCurrentMessages(_event.messages));
|
|
571
715
|
const autoUsage = ctx.getContextUsage();
|
|
572
716
|
const autoContextTokens = autoUsage?.tokens;
|
|
573
717
|
const autoPercent = autoUsage?.percent;
|
|
574
|
-
const
|
|
718
|
+
const autoSessionId = getAutoPruneSessionId(ctx);
|
|
719
|
+
// 2a. Frozen cut reuse. Once the auto path has pruned, keep reusing the
|
|
720
|
+
// exact summary + anchor so the provider prompt prefix stays byte
|
|
721
|
+
// stable across requests. Only invalidate on identity mismatch or
|
|
722
|
+
// when the kept tail grows past the window-relative hysteresis budget.
|
|
723
|
+
let frozen = state.autoPruneFrozen ?? null;
|
|
724
|
+
if (frozen && isMidRun) {
|
|
725
|
+
const identityMatches = autoPruneFrozenIdentityMatches(frozen, autoSessionId, _event.messages);
|
|
726
|
+
const keepRecentMatches = frozen.keepRecentTokensUsed === (autoSettings.keepRecentTokens ?? 0);
|
|
727
|
+
const hysteresisExceeded = autoPruneHysteresisExceeded(frozen, _event.messages, policy, autoContextWindow);
|
|
728
|
+
if (!identityMatches || !keepRecentMatches || hysteresisExceeded) {
|
|
729
|
+
state.autoPruneFrozen = null;
|
|
730
|
+
frozen = null;
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
const frozenPruned = buildFrozenRequestTimePrunedMessages(frozen, _event.messages);
|
|
734
|
+
if (frozenPruned) {
|
|
735
|
+
debugLog("compact_context.request_time.auto_frozen_reuse", {
|
|
736
|
+
rawTokens: autoRawTokens,
|
|
737
|
+
contextTokens: autoContextTokens ?? null,
|
|
738
|
+
percent: autoPercent ?? null,
|
|
739
|
+
originalTokens: frozenPruned.originalTokens,
|
|
740
|
+
prunedTokens: frozenPruned.prunedTokens,
|
|
741
|
+
tokensRemoved: frozenPruned.tokensRemoved,
|
|
742
|
+
cutIndex: frozen.cutIndex,
|
|
743
|
+
});
|
|
744
|
+
notifyRequestTimeApplied(ctx, frozenPruned, { source: "auto", mode: "request_time", ...autoSettings });
|
|
745
|
+
return { messages: frozenPruned.messages };
|
|
746
|
+
}
|
|
747
|
+
debugLog("compact_context.request_time.auto_frozen_invalid", {
|
|
748
|
+
rawTokens: autoRawTokens,
|
|
749
|
+
contextTokens: autoContextTokens ?? null,
|
|
750
|
+
percent: autoPercent ?? null,
|
|
751
|
+
reason: "frozen_identity_or_payload_invalid",
|
|
752
|
+
cutIndex: frozen.cutIndex,
|
|
753
|
+
});
|
|
754
|
+
state.autoPruneFrozen = null;
|
|
755
|
+
frozen = null;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
const autoDecision = decideAutoCompaction(ctx, runtime, state, policy, autoRawTokens, autoPercent, false, isMidRun);
|
|
575
759
|
if (autoDecision.mode !== "request_time")
|
|
576
760
|
return;
|
|
577
761
|
const autoRequest = { source: "auto", mode: autoDecision.mode, ...autoSettings };
|
|
@@ -597,7 +781,24 @@ export function registerCompactContextTool(ext, runtime) {
|
|
|
597
781
|
originalTokens: autoPruned.originalTokens,
|
|
598
782
|
prunedTokens: autoPruned.prunedTokens,
|
|
599
783
|
tokensRemoved: autoPruned.tokensRemoved,
|
|
784
|
+
frozen: false,
|
|
600
785
|
});
|
|
786
|
+
const autoCutIndex = autoPruned.cutIndex;
|
|
787
|
+
const autoAnchorMessage = autoPruned.anchorMessage;
|
|
788
|
+
if (typeof autoCutIndex === "number" &&
|
|
789
|
+
autoAnchorMessage !== undefined &&
|
|
790
|
+
typeof autoPruned.summary === "string") {
|
|
791
|
+
state.autoPruneFrozen = {
|
|
792
|
+
sessionId: autoSessionId,
|
|
793
|
+
cutIndex: autoCutIndex,
|
|
794
|
+
anchor: autoAnchorMessage,
|
|
795
|
+
summary: autoPruned.summary,
|
|
796
|
+
tokensBefore: autoPruned.tokensBefore ?? 0,
|
|
797
|
+
timestamp: autoPruned.timestamp ?? new Date().toISOString(),
|
|
798
|
+
keepRecentTokensUsed: autoSettings.keepRecentTokens ?? 0,
|
|
799
|
+
tailTokensAtFreeze: rawTokensForCurrentMessages(_event.messages.slice(autoCutIndex)),
|
|
800
|
+
};
|
|
801
|
+
}
|
|
601
802
|
notifyRequestTimeApplied(ctx, autoPruned, autoRequest);
|
|
602
803
|
return { messages: autoPruned.messages };
|
|
603
804
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-project-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/read-project-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;
|
|
1
|
+
{"version":3,"file":"read-project-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/read-project-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAGhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;iFAwFtC,CAAC;AAEH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE3E"}
|
|
@@ -5,13 +5,16 @@ export const READ_PROJECT_OBSERVATIONS_TOOL_NAME = "read_project_observations";
|
|
|
5
5
|
export const readProjectObservationsTool = defineTool({
|
|
6
6
|
name: READ_PROJECT_OBSERVATIONS_TOOL_NAME,
|
|
7
7
|
label: "Search project observations",
|
|
8
|
-
description: "Search
|
|
8
|
+
description: "Search past observations across sessions in this project, stored per-machine " +
|
|
9
|
+
"and per-working-directory (cwd). " +
|
|
9
10
|
"Use this when you need to recall project conventions, past decisions, " +
|
|
10
11
|
"file locations, or user preferences before editing or creating files. " +
|
|
11
12
|
"Uses simple substring matching — be specific with your query terms. " +
|
|
12
|
-
"Returns up to 20 most recent matching observations with relevance tags."
|
|
13
|
-
|
|
13
|
+
"Returns up to 20 most recent matching observations with relevance tags. " +
|
|
14
|
+
"Results are local to this machine and cwd; they are NOT synced across machines or teams.",
|
|
15
|
+
promptSnippet: "Use read_project_observations(<query>) to search past observations across sessions in this local project working directory.",
|
|
14
16
|
promptGuidelines: [
|
|
17
|
+
"Results are per-machine + per-cwd and cross-session; they are NOT shared across machines or teams.",
|
|
15
18
|
"Use read_project_observations before creating new files to find conventions for that file kind.",
|
|
16
19
|
"Use read_project_observations before editing a file to find past context about that file or its directory.",
|
|
17
20
|
"Be specific: search for file paths, technology names, or pattern keywords.",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recall-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/recall-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAGN,KAAK,uBAAuB,EAE5B,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"recall-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/recall-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAGN,KAAK,uBAAuB,EAE5B,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvE,eAAO,MAAM,4BAA4B,WAAW,CAAC;AAIrD,KAAK,2BAA2B,GAC7B,IAAI,GACJ,SAAS,GACT,YAAY,GACZ,WAAW,GACX,WAAW,GACX,oBAAoB,GACpB,eAAe,CAAC;AAEnB,KAAK,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC,CAAC;AAChG,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,SAAS,GAAG,0BAA0B,GAAG,QAAQ,CAAC,GAAG;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC;AAExI,MAAM,MAAM,wBAAwB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,6BAA6B,GAAG;IACpC,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAC;IAC3C,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,KAAK,6CAA6C,GAAG;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,KAAK,4CAA4C,GAAG;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,QAAQ,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IAC1C,MAAM,EAAE,2BAA2B,CAAC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,wBAAwB,EAAE,6BAA6B,EAAE,CAAC;IAC1D,YAAY,EAAE,6BAA6B,EAAE,CAAC;IAC9C,OAAO,EAAE,6BAA6B,EAAE,CAAC;IACzC,aAAa,EAAE,wBAAwB,EAAE,CAAC;IAC1C,iCAAiC,EAAE,6CAA6C,EAAE,CAAC;IACnF,+BAA+B,EAAE,4CAA4C,EAAE,CAAC;IAChF,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAuUF,eAAO,MAAM,qBAAqB;;iFAqDhC,CAAC;AAEH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE1D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Type } from "../../sdk/ai/index.js";
|
|
2
2
|
import { defineTool } from "../../sdk/coding-agent/index.js";
|
|
3
3
|
import { recallMemorySources, } from "../branch.js";
|
|
4
|
+
import { getProjectObsStore } from "../project-observations-store.js";
|
|
4
5
|
import { renderRecallSourceEntries, renderRecallSourceEntry } from "../serialize.js";
|
|
5
6
|
import { estimateEntryTokens } from "../tokens.js";
|
|
6
7
|
export const RECALL_OBSERVATION_TOOL_NAME = "recall";
|
|
@@ -315,7 +316,8 @@ function renderFoundResult(result) {
|
|
|
315
316
|
export const recallObservationTool = defineTool({
|
|
316
317
|
name: RECALL_OBSERVATION_TOOL_NAME,
|
|
317
318
|
label: "Recall memory evidence",
|
|
318
|
-
description: "Recover exact evidence and source context behind a compacted observational-memory observation or reflection id
|
|
319
|
+
description: "Recover exact evidence and source context behind a compacted observational-memory observation or reflection id " +
|
|
320
|
+
"from the current branch or an earlier session in the same working directory. " +
|
|
319
321
|
"Use when compressed memory is important and original source context is needed before acting.",
|
|
320
322
|
promptSnippet: "Use recall(<id>) to recover exact source context behind compacted memory observations/reflections when precision matters.",
|
|
321
323
|
promptGuidelines: [
|
|
@@ -340,10 +342,22 @@ export const recallObservationTool = defineTool({
|
|
|
340
342
|
return textResult(message, emptyDetails("invalid_id", memoryId, message));
|
|
341
343
|
}
|
|
342
344
|
const branchEntries = ctx.sessionManager.getBranch();
|
|
343
|
-
|
|
345
|
+
let result = recallMemorySources(branchEntries, memoryId);
|
|
344
346
|
if (result.status === "not_found") {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
+
const store = getProjectObsStore();
|
|
348
|
+
const projectId = store?.getProjectByCwd(ctx.cwd);
|
|
349
|
+
const archiveEntries = projectId ? store?.getProjectRecallSource?.(projectId, memoryId) : null;
|
|
350
|
+
if (archiveEntries && archiveEntries.length > 0) {
|
|
351
|
+
const archivedResult = recallMemorySources(archiveEntries, memoryId);
|
|
352
|
+
if (archivedResult.status === "found") {
|
|
353
|
+
result = archivedResult;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (result.status === "not_found") {
|
|
357
|
+
const message = `No observation or reflection with id ${memoryId} was found on the current branch ` +
|
|
358
|
+
`or in this project's cross-session memory.`;
|
|
359
|
+
return textResult(message, emptyDetails("not_found", memoryId, message));
|
|
360
|
+
}
|
|
347
361
|
}
|
|
348
362
|
return renderFoundResult(result);
|
|
349
363
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"receive-agent-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/receive-agent-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,oCAAoC,+BAA+B,CAAC;AAEjF,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,aAAa,GAAG,YAAY,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,4BAA4B;;;
|
|
1
|
+
{"version":3,"file":"receive-agent-observations.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/receive-agent-observations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,oCAAoC,+BAA+B,CAAC;AAEjF,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,aAAa,GAAG,YAAY,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,4BAA4B;;;iFAqEvC,CAAC;AAEH,wBAAgB,oCAAoC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE5E"}
|
|
@@ -6,10 +6,12 @@ export const RECEIVE_AGENT_OBSERVATIONS_TOOL_NAME = "receive_agent_observations"
|
|
|
6
6
|
export const receiveAgentObservationsTool = defineTool({
|
|
7
7
|
name: RECEIVE_AGENT_OBSERVATIONS_TOOL_NAME,
|
|
8
8
|
label: "Receive observations from other agents",
|
|
9
|
-
description: "Poll for observations shared by other active sessions on this
|
|
9
|
+
description: "Poll for observations shared by other active sessions on this machine working in the " +
|
|
10
|
+
"same directory (same-machine, same-cwd; no cross-machine or team relay). " +
|
|
10
11
|
"Call this before starting work or when you suspect another agent has shared context.",
|
|
11
|
-
promptSnippet: "Use receive_agent_observations() to pull shared observations from other active sessions.",
|
|
12
|
+
promptSnippet: "Use receive_agent_observations() to pull shared observations from other active sessions on this machine.",
|
|
12
13
|
promptGuidelines: [
|
|
14
|
+
"Messages are same-machine + same-cwd only; there is no cross-machine or team fan-out.",
|
|
13
15
|
"Call at the start of a session or task to pick up context shared by collaborators.",
|
|
14
16
|
"Deduplicate results by memory_id against observations already in your context.",
|
|
15
17
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/share-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAOhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AA6C/E,eAAO,MAAM,2BAA2B;;
|
|
1
|
+
{"version":3,"file":"share-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/share-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAOhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AA6C/E,eAAO,MAAM,2BAA2B;;iFAuEtC,CAAC;AAEH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE3E"}
|
|
@@ -40,12 +40,14 @@ function findObservationInStore(store, projectId, memoryId) {
|
|
|
40
40
|
export const shareProjectObservationTool = defineTool({
|
|
41
41
|
name: SHARE_PROJECT_OBSERVATION_TOOL_NAME,
|
|
42
42
|
label: "Share observation with other agents",
|
|
43
|
-
description: "
|
|
43
|
+
description: "Share a project observation or reflection with other active sessions on this machine " +
|
|
44
|
+
"working in the same directory (same-machine, same-cwd broadcast — no cross-machine or team relay). " +
|
|
44
45
|
"Use this when you discover a fact another agent should know immediately, " +
|
|
45
46
|
"rather than waiting for them to search project memory.",
|
|
46
|
-
promptSnippet: "Use share_project_observation(memory_id) to push a known observation to other active sessions.",
|
|
47
|
+
promptSnippet: "Use share_project_observation(memory_id) to push a known observation to other active sessions on this machine.",
|
|
47
48
|
promptGuidelines: [
|
|
48
|
-
"
|
|
49
|
+
"Delivery is same-machine + same-cwd only; there is no cross-machine or team fan-out.",
|
|
50
|
+
"Only share observations that are relevant to collaborators in the same local project directory.",
|
|
49
51
|
"Prefer sharing high/critical relevance facts — avoid noise.",
|
|
50
52
|
"The memory_id must be a 12-character lowercase hex id from the current branch or project memory.",
|
|
51
53
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/write-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;;
|
|
1
|
+
{"version":3,"file":"write-project-observation.d.ts","sourceRoot":"","sources":["../../../src/memory/tools/write-project-observation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAIhF,eAAO,MAAM,mCAAmC,8BAA8B,CAAC;AAE/E,eAAO,MAAM,2BAA2B;;;iFA2EtC,CAAC;AAEH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAE3E"}
|