@gajae-code/agent-core 0.11.0 → 0.11.2
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 +8 -0
- package/dist/types/agent-loop.d.ts +44 -0
- package/dist/types/agent.d.ts +8 -0
- package/dist/types/compaction/compaction.d.ts +21 -2
- package/dist/types/compaction/pruning.d.ts +6 -2
- package/dist/types/proxy.d.ts +11 -0
- package/dist/types/types.d.ts +8 -2
- package/package.json +4 -4
- package/src/agent-loop.ts +564 -60
- package/src/agent.ts +36 -3
- package/src/compaction/compaction.ts +79 -92
- package/src/compaction/openai.ts +8 -25
- package/src/compaction/pruning.ts +112 -4
- package/src/proxy.ts +82 -2
- package/src/types.ts +4 -1
package/src/proxy.ts
CHANGED
|
@@ -30,6 +30,33 @@ class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, Assista
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
interface ReasoningBuffers {
|
|
34
|
+
summary: string;
|
|
35
|
+
raw: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const reasoningBuffers = new WeakMap<object, ReasoningBuffers>();
|
|
39
|
+
|
|
40
|
+
function materializeReasoningProvenance(
|
|
41
|
+
content: Extract<AssistantMessage["content"][number], { type: "thinking" }>,
|
|
42
|
+
): void {
|
|
43
|
+
const buffers = reasoningBuffers.get(content);
|
|
44
|
+
if (!buffers) return;
|
|
45
|
+
const mutable = content as { provenance?: "summary" | "raw" | "mixed"; summaryText?: string; rawText?: string };
|
|
46
|
+
if (mutable.provenance === undefined) {
|
|
47
|
+
if (mutable.summaryText === undefined && buffers.summary) mutable.summaryText = buffers.summary;
|
|
48
|
+
if (mutable.rawText === undefined && buffers.raw) mutable.rawText = buffers.raw;
|
|
49
|
+
mutable.provenance =
|
|
50
|
+
buffers.summary && buffers.raw ? "mixed" : buffers.summary ? "summary" : buffers.raw ? "raw" : undefined;
|
|
51
|
+
}
|
|
52
|
+
// Finalized display string must exclude raw CoT when a summary exists (parity with
|
|
53
|
+
// the Responses/Codex decoders): summary/mixed -> summary only; raw-only -> raw. The
|
|
54
|
+
// raw text stays available separately via rawText for explicit consumers.
|
|
55
|
+
const effSummary = mutable.summaryText ?? buffers.summary;
|
|
56
|
+
const effRaw = mutable.rawText ?? buffers.raw;
|
|
57
|
+
content.thinking = mutable.provenance === "raw" ? effRaw : effSummary || effRaw;
|
|
58
|
+
}
|
|
59
|
+
|
|
33
60
|
/**
|
|
34
61
|
* Proxy event types - server sends these with partial field stripped to reduce bandwidth.
|
|
35
62
|
*/
|
|
@@ -41,6 +68,9 @@ export type ProxyAssistantMessageEvent =
|
|
|
41
68
|
| { type: "thinking_start"; contentIndex: number }
|
|
42
69
|
| { type: "thinking_delta"; contentIndex: number; delta: string }
|
|
43
70
|
| { type: "thinking_end"; contentIndex: number; contentSignature?: string }
|
|
71
|
+
| { type: "reasoning_summary_start"; contentIndex: number }
|
|
72
|
+
| { type: "reasoning_summary_delta"; contentIndex: number; delta: string }
|
|
73
|
+
| { type: "reasoning_summary_end"; contentIndex: number; content?: string }
|
|
44
74
|
| { type: "toolcall_start"; contentIndex: number; id: string; toolName: string }
|
|
45
75
|
| { type: "toolcall_delta"; contentIndex: number; delta: string }
|
|
46
76
|
| { type: "toolcall_end"; contentIndex: number }
|
|
@@ -238,14 +268,22 @@ function processProxyEvent(
|
|
|
238
268
|
throw new Error("Received text_end for non-text content");
|
|
239
269
|
}
|
|
240
270
|
|
|
241
|
-
case "thinking_start":
|
|
242
|
-
|
|
271
|
+
case "thinking_start": {
|
|
272
|
+
const content = { type: "thinking", thinking: "" } as Extract<
|
|
273
|
+
AssistantMessage["content"][number],
|
|
274
|
+
{ type: "thinking" }
|
|
275
|
+
>;
|
|
276
|
+
partial.content[proxyEvent.contentIndex] = content;
|
|
277
|
+
reasoningBuffers.set(content, { summary: "", raw: "" });
|
|
243
278
|
return { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
279
|
+
}
|
|
244
280
|
|
|
245
281
|
case "thinking_delta": {
|
|
246
282
|
const content = partial.content[proxyEvent.contentIndex];
|
|
247
283
|
if (content?.type === "thinking") {
|
|
248
284
|
content.thinking += proxyEvent.delta;
|
|
285
|
+
const buffers = reasoningBuffers.get(content);
|
|
286
|
+
if (buffers) buffers.raw += proxyEvent.delta;
|
|
249
287
|
return {
|
|
250
288
|
type: "thinking_delta",
|
|
251
289
|
contentIndex: proxyEvent.contentIndex,
|
|
@@ -256,10 +294,52 @@ function processProxyEvent(
|
|
|
256
294
|
throw new Error("Received thinking_delta for non-thinking content");
|
|
257
295
|
}
|
|
258
296
|
|
|
297
|
+
case "reasoning_summary_start":
|
|
298
|
+
return { type: "reasoning_summary_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
299
|
+
|
|
300
|
+
case "reasoning_summary_delta": {
|
|
301
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
302
|
+
if (content?.type === "thinking") {
|
|
303
|
+
content.thinking += proxyEvent.delta;
|
|
304
|
+
const buffers = reasoningBuffers.get(content);
|
|
305
|
+
if (buffers) buffers.summary += proxyEvent.delta;
|
|
306
|
+
return {
|
|
307
|
+
type: "reasoning_summary_delta",
|
|
308
|
+
contentIndex: proxyEvent.contentIndex,
|
|
309
|
+
delta: proxyEvent.delta,
|
|
310
|
+
partial,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
throw new Error("Received reasoning_summary_delta for non-thinking content");
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
case "reasoning_summary_end": {
|
|
317
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
318
|
+
if (content?.type === "thinking") {
|
|
319
|
+
const buffers = reasoningBuffers.get(content);
|
|
320
|
+
// Final-only summaries arrive with the text on the end event and no summary
|
|
321
|
+
// deltas, so the accumulated buffer is empty. Prefer the end event's content
|
|
322
|
+
// so the summary survives the proxy and materializes as provenance "summary".
|
|
323
|
+
if (buffers && !buffers.summary.trim() && proxyEvent.content) {
|
|
324
|
+
buffers.summary = proxyEvent.content;
|
|
325
|
+
if (!content.thinking.trim()) content.thinking = proxyEvent.content;
|
|
326
|
+
}
|
|
327
|
+
materializeReasoningProvenance(content);
|
|
328
|
+
return {
|
|
329
|
+
type: "reasoning_summary_end",
|
|
330
|
+
contentIndex: proxyEvent.contentIndex,
|
|
331
|
+
content: buffers?.summary || proxyEvent.content || "",
|
|
332
|
+
partial,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
throw new Error("Received reasoning_summary_end for non-thinking content");
|
|
336
|
+
}
|
|
337
|
+
|
|
259
338
|
case "thinking_end": {
|
|
260
339
|
const content = partial.content[proxyEvent.contentIndex];
|
|
261
340
|
if (content?.type === "thinking") {
|
|
262
341
|
content.thinkingSignature = proxyEvent.contentSignature;
|
|
342
|
+
materializeReasoningProvenance(content);
|
|
263
343
|
return {
|
|
264
344
|
type: "thinking_end",
|
|
265
345
|
contentIndex: proxyEvent.contentIndex,
|
package/src/types.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type {
|
|
|
13
13
|
Tool,
|
|
14
14
|
ToolChoice,
|
|
15
15
|
ToolResultMessage,
|
|
16
|
+
TransportFailureFacts,
|
|
16
17
|
TSchema,
|
|
17
18
|
} from "@gajae-code/ai";
|
|
18
19
|
import type { AppendOnlyContextManager } from "./append-only-context";
|
|
@@ -58,6 +59,7 @@ export type ManagedAttemptContinuation = (ownership: ManagedAttemptContinuationO
|
|
|
58
59
|
/** Decision returned by managed fallback policy for one provisional attempt. */
|
|
59
60
|
export type ManagedAttemptDecision =
|
|
60
61
|
| { type: "retry"; continuation: ManagedAttemptContinuation }
|
|
62
|
+
| { type: "maintenance"; continuation: ManagedAttemptContinuation }
|
|
61
63
|
| { type: "terminal"; terminal: RunTerminalRequest };
|
|
62
64
|
|
|
63
65
|
/** Structured result for one managed upstream invocation. */
|
|
@@ -67,9 +69,10 @@ export type ManagedAttemptOutcome =
|
|
|
67
69
|
failure: {
|
|
68
70
|
message: AssistantMessage;
|
|
69
71
|
/** Exact provider transport facts, including retry headers, for fallback policy. */
|
|
70
|
-
transportFailure?:
|
|
72
|
+
transportFailure?: TransportFailureFacts;
|
|
71
73
|
};
|
|
72
74
|
}
|
|
75
|
+
| { type: "context_overflow_discarded"; message: AssistantMessage }
|
|
73
76
|
| { type: "run_terminal"; reason: "cancelled" | "error" | "exhausted" };
|
|
74
77
|
|
|
75
78
|
export type ManagedAttemptOutcomeHandler = (
|