@aexol/spectral 0.9.106 → 0.9.108
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 +9 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +55 -4
- package/dist/memory/tool-output-compressor.d.ts +16 -0
- package/dist/memory/tool-output-compressor.d.ts.map +1 -1
- package/dist/memory/tool-output-compressor.js +24 -0
- package/dist/memory/tools/compact-context.d.ts +14 -0
- package/dist/memory/tools/compact-context.d.ts.map +1 -1
- package/dist/memory/tools/compact-context.js +40 -0
- package/dist/sdk/ai/providers/faux.d.ts +1 -0
- package/dist/sdk/ai/providers/faux.d.ts.map +1 -1
- package/dist/sdk/ai/providers/faux.js +9 -0
- package/package.json +1 -1
package/dist/agent/index.d.ts
CHANGED
|
@@ -24,11 +24,19 @@
|
|
|
24
24
|
* - Signal propagation (abort passthrough)
|
|
25
25
|
* - Access to observational memory via the recall tool
|
|
26
26
|
*/
|
|
27
|
-
import {
|
|
27
|
+
import type { AgentTool } from "../sdk/agent-core/index.js";
|
|
28
|
+
import { type ExtensionAPI, type ExtensionContext } from "../sdk/coding-agent/index.js";
|
|
28
29
|
import { type AgentConfig } from "./agents.js";
|
|
29
30
|
import type { ServerEvent } from "../server/wire.ts";
|
|
31
|
+
import type { ExtensionContext as RichExtensionContext } from "../sdk/coding-agent/core/extensions/types.js";
|
|
30
32
|
export declare function stripInjectedPrimaryAgentPrompt(systemPrompt: string | undefined): string | undefined;
|
|
31
33
|
export declare function buildSubagentSystemPrompt(baseSystemPrompt: string | undefined, agent: Pick<AgentConfig, "name" | "systemPrompt">): string;
|
|
34
|
+
/**
|
|
35
|
+
* Give subagents a point-in-time branch view without exposing the live parent
|
|
36
|
+
* SessionManager. Each getBranch call returns fresh clones of the snapshot.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createSubagentSessionManagerSnapshot(sessionManager: ExtensionContext["sessionManager"]): Pick<RichExtensionContext["sessionManager"], "getBranch">;
|
|
39
|
+
export declare function resolveSubagentTools(toolNames: string[] | undefined, cwd: string, ext: ExtensionAPI, ctx: ExtensionContext): AgentTool[];
|
|
32
40
|
export default function subagentExtension(ext: ExtensionAPI, opts?: {
|
|
33
41
|
disabledAgents?: string[];
|
|
34
42
|
emitSubagentEvent?: (event: ServerEvent) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAIX,SAAS,EAET,MAAM,4BAA4B,CAAC;AAUpC,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EAAE,KAAK,WAAW,EAAmC,MAAM,aAAa,CAAC;AAEhF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOrD,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AAmF7G,wBAAgB,+BAA+B,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASpG;AAED,wBAAgB,yBAAyB,CACxC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,cAAc,CAAC,GAC/C,MAAM,CAKR;AAiHD;;;GAGG;AACH,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,GAChD,IAAI,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,EAAE,WAAW,CAAC,CAK3D;AAED,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,EAC/B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,gBAAgB,GACnB,SAAS,EAAE,CAqCb;AA0VD,MAAM,CAAC,OAAO,UAAU,iBAAiB,CACxC,GAAG,EAAE,YAAY,EACjB,IAAI,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;CAAE,GACpF,IAAI,CAgZN"}
|
package/dist/agent/index.js
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
* - Access to observational memory via the recall tool
|
|
26
26
|
*/
|
|
27
27
|
import { agentLoop } from "../sdk/agent-core/index.js";
|
|
28
|
+
import { buildIsolatedRequestTimePrunedMessages, createIsolatedDcpNudgePayloadHook, } from "../memory/tools/compact-context.js";
|
|
29
|
+
import { loadConfig } from "../memory/config.js";
|
|
28
30
|
import { StringEnum } from "../sdk/ai/index.js";
|
|
29
31
|
import { mutateSystemPrompt } from "../sdk/coding-agent/core/system-prompt-mutator.js";
|
|
30
32
|
import { Type } from "typebox";
|
|
@@ -35,6 +37,9 @@ import { loadAgentSettings } from "../server/handlers/agent-settings.js";
|
|
|
35
37
|
// ---------------------------------------------------------------------------
|
|
36
38
|
import { createTool, allToolNames } from "../sdk/coding-agent/core/tools/index.js";
|
|
37
39
|
import { wrapToolDefinition } from "../sdk/coding-agent/core/tools/tool-definition-wrapper.js";
|
|
40
|
+
import { READ_PROJECT_OBSERVATIONS_TOOL_NAME } from "../memory/tools/read-project-observations.js";
|
|
41
|
+
import { RECALL_OBSERVATION_TOOL_NAME } from "../memory/tools/recall-observation.js";
|
|
42
|
+
import { compressSubagentToolResult } from "../memory/tool-output-compressor.js";
|
|
38
43
|
// ---------------------------------------------------------------------------
|
|
39
44
|
// Constants
|
|
40
45
|
// ---------------------------------------------------------------------------
|
|
@@ -174,11 +179,29 @@ function resolveModelString(modelStr, modelRegistry) {
|
|
|
174
179
|
* `createTool()`. Extension-registered tools (e.g., recall) are resolved
|
|
175
180
|
* via the ExtensionAPI and wrapped.
|
|
176
181
|
*/
|
|
177
|
-
function
|
|
178
|
-
|
|
182
|
+
function cloneSessionEntry(entry) {
|
|
183
|
+
return structuredClone(entry);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Give subagents a point-in-time branch view without exposing the live parent
|
|
187
|
+
* SessionManager. Each getBranch call returns fresh clones of the snapshot.
|
|
188
|
+
*/
|
|
189
|
+
export function createSubagentSessionManagerSnapshot(sessionManager) {
|
|
190
|
+
const snapshot = sessionManager.getBranch().map(cloneSessionEntry);
|
|
191
|
+
return {
|
|
192
|
+
getBranch: () => snapshot.map(cloneSessionEntry),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export function resolveSubagentTools(toolNames, cwd, ext, ctx) {
|
|
196
|
+
const requestedNames = new Set(toolNames ?? []);
|
|
197
|
+
// Project observation search is read-only and can use a minimal, invocation-
|
|
198
|
+
// local context without exposing the parent session manager.
|
|
199
|
+
requestedNames.add(READ_PROJECT_OBSERVATIONS_TOOL_NAME);
|
|
200
|
+
requestedNames.add(RECALL_OBSERVATION_TOOL_NAME);
|
|
201
|
+
if (requestedNames.size === 0)
|
|
179
202
|
return [];
|
|
180
203
|
const tools = [];
|
|
181
|
-
for (const name of
|
|
204
|
+
for (const name of requestedNames) {
|
|
182
205
|
// Built-in tools
|
|
183
206
|
if (allToolNames.has(name)) {
|
|
184
207
|
try {
|
|
@@ -196,7 +219,11 @@ function resolveSubagentTools(toolNames, cwd, ext, ctx) {
|
|
|
196
219
|
const richApi = ext;
|
|
197
220
|
const toolDef = richApi.getToolDefinition(name);
|
|
198
221
|
if (toolDef) {
|
|
199
|
-
|
|
222
|
+
const isolatedContext = name === RECALL_OBSERVATION_TOOL_NAME
|
|
223
|
+
? { cwd, sessionManager: createSubagentSessionManagerSnapshot(ctx.sessionManager) }
|
|
224
|
+
: { cwd };
|
|
225
|
+
const isolatedContextWithNoParent = isolatedContext;
|
|
226
|
+
tools.push(wrapToolDefinition(toolDef, () => isolatedContextWithNoParent));
|
|
200
227
|
}
|
|
201
228
|
}
|
|
202
229
|
return tools;
|
|
@@ -322,12 +349,36 @@ async function runSingleAgent(defaultCwd, agents, agentName, task, cwd, step, si
|
|
|
322
349
|
}
|
|
323
350
|
};
|
|
324
351
|
try {
|
|
352
|
+
// Invocation-local hook state; never reuse the parent extension context/runtime.
|
|
325
353
|
const config = {
|
|
326
354
|
model,
|
|
327
355
|
apiKey: auth.apiKey,
|
|
356
|
+
onPayload: createIsolatedDcpNudgePayloadHook({
|
|
357
|
+
config: loadConfig(effectiveCwd),
|
|
358
|
+
policy: ctx.settingsManager?.getCompactionPolicy?.(),
|
|
359
|
+
}),
|
|
328
360
|
headers: auth.headers,
|
|
329
361
|
convertToLlm: (msgs) => msgs.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult"),
|
|
330
362
|
toolExecution: "parallel",
|
|
363
|
+
transformContext: async (messages) => {
|
|
364
|
+
// Pure request-time DCP adapter: policy-derived, invocation-local, and
|
|
365
|
+
// never connected to the parent Runtime or SessionManager.
|
|
366
|
+
try {
|
|
367
|
+
return buildIsolatedRequestTimePrunedMessages(messages);
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
return messages;
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
afterToolCall: async ({ toolCall, args, result, isError }) => {
|
|
374
|
+
try {
|
|
375
|
+
const content = compressSubagentToolResult(toolCall.name, args, result);
|
|
376
|
+
return content ? { content, details: result.details, isError, terminate: result.terminate } : undefined;
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
return undefined;
|
|
380
|
+
}
|
|
381
|
+
},
|
|
331
382
|
};
|
|
332
383
|
const stream = agentLoop([{ role: "user", content: [{ type: "text", text: task }], timestamp: Date.now() }], {
|
|
333
384
|
systemPrompt: effectivePrompt,
|
|
@@ -51,5 +51,21 @@ export interface ToolOutputCompressionTelemetry {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function getToolOutputCompressionTelemetry(runtime: Runtime): ToolOutputCompressionTelemetry;
|
|
53
53
|
export declare function resetToolOutputCompressionTelemetry(runtime: Runtime): void;
|
|
54
|
+
/** Compress a subagent tool result without using the parent Runtime or extension lifecycle. */
|
|
55
|
+
export declare function compressSubagentToolResult(toolName: string, input: unknown, result: {
|
|
56
|
+
content: Array<{
|
|
57
|
+
type: string;
|
|
58
|
+
text?: string;
|
|
59
|
+
data?: string;
|
|
60
|
+
mimeType?: string;
|
|
61
|
+
}>;
|
|
62
|
+
}): Array<{
|
|
63
|
+
type: "text";
|
|
64
|
+
text: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "image";
|
|
67
|
+
data: string;
|
|
68
|
+
mimeType: string;
|
|
69
|
+
}> | undefined;
|
|
54
70
|
export declare function registerToolOutputCompressor(ext: ExtensionAPI, runtime: Runtime): void;
|
|
55
71
|
//# sourceMappingURL=tool-output-compressor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-output-compressor.d.ts","sourceRoot":"","sources":["../../src/memory/tool-output-compressor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAWjE,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;AAqyBF,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,wBAAgB,4BAA4B,CAC3C,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACd,IAAI,CAqEN"}
|
|
1
|
+
{"version":3,"file":"tool-output-compressor.d.ts","sourceRoot":"","sources":["../../src/memory/tool-output-compressor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAWjE,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;AAqyBF,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,+FAA+F;AAC/F,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,GAC3F,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,CAevG;AAED,wBAAgB,4BAA4B,CAC3C,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,OAAO,GACd,IAAI,CAqEN"}
|
|
@@ -766,6 +766,30 @@ function compressedContentResult(runtime, event, toolName, original, compressed)
|
|
|
766
766
|
content: [...event.content.filter((c) => c.type !== "text"), { type: "text", text: replacementText }],
|
|
767
767
|
};
|
|
768
768
|
}
|
|
769
|
+
/** Compress a subagent tool result without using the parent Runtime or extension lifecycle. */
|
|
770
|
+
export function compressSubagentToolResult(toolName, input, result) {
|
|
771
|
+
const safeInput = input && typeof input === "object" && !Array.isArray(input) ? input : {};
|
|
772
|
+
const text = result.content.filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n");
|
|
773
|
+
if (!text || text.startsWith("[tool-output-compressor "))
|
|
774
|
+
return undefined;
|
|
775
|
+
const event = { content: result.content, input: safeInput, toolName };
|
|
776
|
+
let compressed;
|
|
777
|
+
const config = DEFAULT_COMPRESSOR_CONFIG;
|
|
778
|
+
if (toolName === "read")
|
|
779
|
+
compressed = compressReadOutput(event, config);
|
|
780
|
+
else if (toolName === "bash")
|
|
781
|
+
compressed = compressBashOutput(event, config);
|
|
782
|
+
else if (toolName === "ls")
|
|
783
|
+
compressed = compressLsOutput(event, config);
|
|
784
|
+
else if (toolName === "grep")
|
|
785
|
+
compressed = compressGrepOutput(event, config);
|
|
786
|
+
else if (toolName === "find")
|
|
787
|
+
compressed = compressFindOutput(event, config);
|
|
788
|
+
if (!compressed || compressed === text)
|
|
789
|
+
return undefined;
|
|
790
|
+
const compressedContent = result.content.map((part) => part.type === "text" ? { type: "text", text: part.text ?? "" } : part.type === "image" && part.data && part.mimeType ? { type: "image", data: part.data, mimeType: part.mimeType } : undefined).filter((part) => part !== undefined && part.type !== "text");
|
|
791
|
+
return [{ type: "text", text: `${formatCompressionHeader({ toolName, originalChars: text.length, compressedChars: compressed.length, savingsPercent: Math.round((1 - compressed.length / Math.max(1, text.length)) * 10_000) / 100 })}\n${compressed}` }, ...compressedContent];
|
|
792
|
+
}
|
|
769
793
|
export function registerToolOutputCompressor(ext, runtime) {
|
|
770
794
|
ext.on("tool_result", (_event, _ctx) => {
|
|
771
795
|
const config = resolveCompressorConfig(_ctx);
|
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
import type { AgentMessage } from "../../sdk/agent-core/index.js";
|
|
2
|
+
import { type CompactionPolicy } from "../../sdk/coding-agent/core/compaction/index.js";
|
|
1
3
|
import { type ExtensionAPI } from "../../sdk/coding-agent/index.js";
|
|
2
4
|
import type { Runtime } from "../runtime.js";
|
|
5
|
+
import { type Config } from "../config.js";
|
|
3
6
|
export declare const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
7
|
+
/**
|
|
8
|
+
* Creates an invocation-local provider payload hook for isolated agent loops.
|
|
9
|
+
* The values are snapshotted at invocation start; no Runtime, SessionManager, or
|
|
10
|
+
* extension state is retained by the returned hook.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createIsolatedDcpNudgePayloadHook(options?: {
|
|
13
|
+
config?: Pick<Config, "dcpInRunNudgeIterationThreshold" | "dcpInRunNudgeFrequency">;
|
|
14
|
+
policy?: CompactionPolicy;
|
|
15
|
+
}): NonNullable<import("../../sdk/ai/index.js").SimpleStreamOptions["onPayload"]>;
|
|
16
|
+
/** Request-time DCP adapter for isolated loops: it borrows only pure policy helpers. */
|
|
17
|
+
export declare function buildIsolatedRequestTimePrunedMessages(currentMessages: AgentMessage[], policy?: CompactionPolicy, keepRecentTokens?: number): AgentMessage[];
|
|
4
18
|
export declare function registerCompactContextTool(ext: ExtensionAPI, runtime: Runtime): void;
|
|
5
19
|
//# 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":"
|
|
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,EASN,KAAK,gBAAgB,EACrB,MAAM,iDAAiD,CAAC;AACzD,OAAO,EAAc,KAAK,YAAY,EAAyB,MAAM,iCAAiC,CAAC;AAKvG,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAErD,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAoO3D;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,GAAE;IAC1D,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,iCAAiC,GAAG,wBAAwB,CAAC,CAAC;IACpF,MAAM,CAAC,EAAE,gBAAgB,CAAC;CACrB,GAAG,WAAW,CAAC,OAAO,uBAAuB,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAiBrF;AA+MD,wFAAwF;AACxF,wBAAgB,sCAAsC,CACrD,eAAe,EAAE,YAAY,EAAE,EAC/B,MAAM,GAAE,gBAA4C,EACpD,gBAAgB,CAAC,EAAE,MAAM,GACvB,YAAY,EAAE,CAchB;AAsQD,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAkSpF"}
|
|
@@ -4,6 +4,7 @@ import { defineTool } from "../../sdk/coding-agent/index.js";
|
|
|
4
4
|
import { buildSessionContext } from "../../sdk/coding-agent/core/session-manager.js";
|
|
5
5
|
import { rawTokensSinceLastCompaction } from "../branch.js";
|
|
6
6
|
import { debugLog, withDebugLogContext } from "../debug-log.js";
|
|
7
|
+
import { DEFAULTS } from "../config.js";
|
|
7
8
|
export const COMPACT_CONTEXT_TOOL_NAME = "compact_context";
|
|
8
9
|
const DCP_NUDGE_HEADING = "## DCP-lite context hygiene";
|
|
9
10
|
const MAX_COMPACT_CONTEXT_TEXT_CHARS = 240;
|
|
@@ -194,6 +195,31 @@ function injectDcpNudgeIntoProviderPayload(payload, nudge) {
|
|
|
194
195
|
return undefined;
|
|
195
196
|
return injectDcpNudgeIntoAnthropicPayload(payload, nudge) ?? injectDcpNudgeIntoOpenAiPayload(payload, nudge);
|
|
196
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Creates an invocation-local provider payload hook for isolated agent loops.
|
|
200
|
+
* The values are snapshotted at invocation start; no Runtime, SessionManager, or
|
|
201
|
+
* extension state is retained by the returned hook.
|
|
202
|
+
*/
|
|
203
|
+
export function createIsolatedDcpNudgePayloadHook(options = {}) {
|
|
204
|
+
let providerRequestCount = 0;
|
|
205
|
+
let lastNudgeRequest = 0;
|
|
206
|
+
const config = options.config ?? DEFAULTS;
|
|
207
|
+
const policy = options.policy ?? DEFAULT_COMPACTION_POLICY;
|
|
208
|
+
return (payload) => {
|
|
209
|
+
providerRequestCount += 1;
|
|
210
|
+
const frequency = config.dcpInRunNudgeFrequency;
|
|
211
|
+
const hasSignal = providerRequestCount >= config.dcpInRunNudgeIterationThreshold;
|
|
212
|
+
const frequencyReady = lastNudgeRequest === 0 || providerRequestCount - lastNudgeRequest >= frequency;
|
|
213
|
+
if (!hasSignal || !frequencyReady || payloadContainsDcpNudge(payload))
|
|
214
|
+
return undefined;
|
|
215
|
+
const nudge = buildDcpNudge(0, undefined, undefined, policy, providerRequestCount);
|
|
216
|
+
const nextPayload = injectDcpNudgeIntoProviderPayload(payload, nudge);
|
|
217
|
+
if (nextPayload === undefined)
|
|
218
|
+
return undefined;
|
|
219
|
+
lastNudgeRequest = providerRequestCount;
|
|
220
|
+
return nextPayload;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
197
223
|
function rawTokensForContext(ctx) {
|
|
198
224
|
const entries = ctx.sessionManager.getBranch();
|
|
199
225
|
return rawTokensSinceLastCompaction(entries);
|
|
@@ -343,6 +369,20 @@ function createVirtualCompactionEntry(pathEntries, result) {
|
|
|
343
369
|
}
|
|
344
370
|
function buildRequestTimePrunedMessages(ctx, request, policy, currentMessages) {
|
|
345
371
|
const pathEntries = getBranchEntries(ctx);
|
|
372
|
+
return buildRequestTimePrunedMessagesFromEntries(pathEntries, request, policy, currentMessages);
|
|
373
|
+
}
|
|
374
|
+
/** Request-time DCP adapter for isolated loops: it borrows only pure policy helpers. */
|
|
375
|
+
export function buildIsolatedRequestTimePrunedMessages(currentMessages, policy = DEFAULT_COMPACTION_POLICY, keepRecentTokens) {
|
|
376
|
+
const syntheticEntries = currentMessages.map((message, index) => ({
|
|
377
|
+
type: "message",
|
|
378
|
+
id: `isolated-${index}`,
|
|
379
|
+
parentId: index > 0 ? `isolated-${index - 1}` : null,
|
|
380
|
+
timestamp: new Date(index).toISOString(),
|
|
381
|
+
message,
|
|
382
|
+
}));
|
|
383
|
+
return buildRequestTimePrunedMessagesFromEntries(syntheticEntries, { source: "auto", mode: "request_time", scope: "older_history", keepRecentTokens, phaseBoundary: false, minRawTokens: 0 }, policy, currentMessages)?.messages ?? currentMessages;
|
|
384
|
+
}
|
|
385
|
+
function buildRequestTimePrunedMessagesFromEntries(pathEntries, request, policy, currentMessages) {
|
|
346
386
|
const settings = getRequestTimeCompactionSettings(request, policy);
|
|
347
387
|
const preparation = prepareCompaction(pathEntries, settings, { phaseBoundary: request.phaseBoundary });
|
|
348
388
|
if (!preparation)
|
|
@@ -27,6 +27,7 @@ export declare function fauxAssistantMessage(content: string | FauxContentBlock
|
|
|
27
27
|
}): AssistantMessage;
|
|
28
28
|
export type FauxResponseFactory = (context: Context, options: StreamOptions | undefined, state: {
|
|
29
29
|
callCount: number;
|
|
30
|
+
lastPayload?: unknown;
|
|
30
31
|
}, model: Model<string>) => AssistantMessage | Promise<AssistantMessage>;
|
|
31
32
|
export type FauxResponseStep = AssistantMessage | FauxResponseFactory;
|
|
32
33
|
export interface RegisterFauxProviderOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"faux.d.ts","sourceRoot":"","sources":["../../../../src/sdk/ai/providers/faux.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,gBAAgB,EAEhB,OAAO,EAGP,KAAK,EAGL,aAAa,EACb,WAAW,EACX,eAAe,EACf,QAAQ,EAGR,MAAM,aAAa,CAAC;AAoBrB,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,eAAe,GAAG,QAAQ,CAAC;AAExE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAElD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAE9D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,QAAQ,CAOrH;AASD,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,gBAAgB,EAAE,EACvD,OAAO,GAAE;IACR,UAAU,CAAC,EAAE,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACd,GACJ,gBAAgB,CAalB;AAED,MAAM,MAAM,mBAAmB,GAAG,CACjC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"faux.d.ts","sourceRoot":"","sources":["../../../../src/sdk/ai/providers/faux.ts"],"names":[],"mappings":"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"}
|
|
@@ -317,6 +317,15 @@ export function registerFauxProvider(options = {}) {
|
|
|
317
317
|
state.callCount++;
|
|
318
318
|
queueMicrotask(async () => {
|
|
319
319
|
try {
|
|
320
|
+
const payload = {
|
|
321
|
+
system: context.systemPrompt,
|
|
322
|
+
messages: context.messages,
|
|
323
|
+
tools: context.tools,
|
|
324
|
+
};
|
|
325
|
+
// Faux is intentionally a low-level provider: exercise the same payload
|
|
326
|
+
// interception seam as HTTP providers so agent-loop continuations can be
|
|
327
|
+
// tested without network calls.
|
|
328
|
+
state.lastPayload = (await streamOptions?.onPayload?.(payload, requestModel)) ?? payload;
|
|
320
329
|
await streamOptions?.onResponse?.({ status: 200, headers: {} }, requestModel);
|
|
321
330
|
if (!step) {
|
|
322
331
|
let message = createErrorMessage(new Error("No more faux responses queued"), api, provider, requestModel.id);
|