@gajae-code/agent-core 0.10.0 → 0.10.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 +6 -0
- package/dist/types/agent.d.ts +7 -1
- package/dist/types/types.d.ts +1 -1
- package/package.json +4 -4
- package/src/agent.ts +22 -1
- package/src/compaction/openai.ts +16 -5
- package/src/types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.10.2] - 2026-07-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Extended the gpt-5.6 `Request blocked (code=invalid_prompt)` fix to the compaction paths that bypass the streaming transport. Remote OpenAI compaction (`/responses/compact`, `compaction.remoteEnabled` default on — the "remote compact task" in openai/codex#32028) built its native `input` from reasoning signatures, verbatim history items, and message/tool text without neutralizing leaked Harmony control-token markers (e.g. `<|channel|>analysis`), so gpt-5.6 rejected the compaction request and, on retry, could escalate to account-level blocking. `requestOpenAiRemoteCompaction` now neutralizes reserved control tokens across the whole outgoing `input`, and the generic `requestRemoteCompaction` prompt/systemPrompt are neutralized too. Local summarization was already covered by the streaming-transport request-boundary fix.
|
|
10
|
+
|
|
5
11
|
## [0.10.0] - 2026-07-12
|
|
6
12
|
|
|
7
13
|
### Fixed
|
package/dist/types/agent.d.ts
CHANGED
|
@@ -298,6 +298,7 @@ export declare class Agent {
|
|
|
298
298
|
get streamMaxRetries(): number | undefined;
|
|
299
299
|
set streamMaxRetries(value: number | undefined);
|
|
300
300
|
get state(): AgentState;
|
|
301
|
+
get contextRevision(): number;
|
|
301
302
|
get appendOnlyContext(): AppendOnlyContextManager | undefined;
|
|
302
303
|
setAppendOnlyContext(manager?: AppendOnlyContextManager): void;
|
|
303
304
|
subscribe(fn: (e: AgentEvent) => void): () => void;
|
|
@@ -309,7 +310,7 @@ export declare class Agent {
|
|
|
309
310
|
emitExternalEvent(event: AgentEvent): void;
|
|
310
311
|
createExternalEventEmitterForCurrentRun(): ((event: AgentEvent) => void) | undefined;
|
|
311
312
|
setSystemPrompt(v: string[]): void;
|
|
312
|
-
setModel(m: Model): void;
|
|
313
|
+
setModel(m: Model | undefined): void;
|
|
313
314
|
setThinkingLevel(l: Effort | undefined): void;
|
|
314
315
|
setSteeringMode(mode: "all" | "one-at-a-time"): void;
|
|
315
316
|
getSteeringMode(): "all" | "one-at-a-time";
|
|
@@ -321,6 +322,11 @@ export declare class Agent {
|
|
|
321
322
|
replaceMessages(ms: AgentMessage[]): void;
|
|
322
323
|
appendMessage(m: AgentMessage): void;
|
|
323
324
|
popMessage(): AgentMessage | undefined;
|
|
325
|
+
/**
|
|
326
|
+
* For callers that mutate committed messages or the system prompt in place
|
|
327
|
+
* outside Agent-owned mutators.
|
|
328
|
+
*/
|
|
329
|
+
touchContext(): void;
|
|
324
330
|
/**
|
|
325
331
|
* Queue a steering message to interrupt the agent mid-run.
|
|
326
332
|
* Delivered after current tool execution, skips remaining tools.
|
package/dist/types/types.d.ts
CHANGED
|
@@ -308,7 +308,7 @@ export type AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessag
|
|
|
308
308
|
*/
|
|
309
309
|
export interface AgentState {
|
|
310
310
|
systemPrompt: string[];
|
|
311
|
-
model: Model;
|
|
311
|
+
model: Model | undefined;
|
|
312
312
|
thinkingLevel?: Effort;
|
|
313
313
|
tools: AgentTool<any>[];
|
|
314
314
|
messages: AgentMessage[];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/agent-core",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.2",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://gajae-code.com",
|
|
7
7
|
"author": "Yeachan-Heo and Gajae Code Contributors",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"fmt": "biome format --write ."
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@gajae-code/ai": "0.10.
|
|
36
|
-
"@gajae-code/natives": "0.10.
|
|
37
|
-
"@gajae-code/utils": "0.10.
|
|
35
|
+
"@gajae-code/ai": "0.10.2",
|
|
36
|
+
"@gajae-code/natives": "0.10.2",
|
|
37
|
+
"@gajae-code/utils": "0.10.2",
|
|
38
38
|
"@opentelemetry/api": "^1.9.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
package/src/agent.ts
CHANGED
|
@@ -296,6 +296,7 @@ export class Agent {
|
|
|
296
296
|
pendingToolCalls: new Set<string>(),
|
|
297
297
|
error: undefined,
|
|
298
298
|
};
|
|
299
|
+
#contextRevision = 0;
|
|
299
300
|
|
|
300
301
|
#listeners = new Set<(e: AgentEvent) => void>();
|
|
301
302
|
#abortController?: AbortController;
|
|
@@ -640,6 +641,10 @@ export class Agent {
|
|
|
640
641
|
return this.#state;
|
|
641
642
|
}
|
|
642
643
|
|
|
644
|
+
get contextRevision(): number {
|
|
645
|
+
return this.#contextRevision;
|
|
646
|
+
}
|
|
647
|
+
|
|
643
648
|
get appendOnlyContext(): AppendOnlyContextManager | undefined {
|
|
644
649
|
return this.#appendOnlyContext;
|
|
645
650
|
}
|
|
@@ -822,10 +827,12 @@ export class Agent {
|
|
|
822
827
|
// State mutators
|
|
823
828
|
setSystemPrompt(v: string[]) {
|
|
824
829
|
this.#state.systemPrompt = v;
|
|
830
|
+
this.#contextRevision++;
|
|
825
831
|
}
|
|
826
832
|
|
|
827
|
-
setModel(m: Model) {
|
|
833
|
+
setModel(m: Model | undefined) {
|
|
828
834
|
this.#state.model = m;
|
|
835
|
+
this.#contextRevision++;
|
|
829
836
|
}
|
|
830
837
|
|
|
831
838
|
setThinkingLevel(l: Effort | undefined) {
|
|
@@ -858,10 +865,12 @@ export class Agent {
|
|
|
858
865
|
|
|
859
866
|
setTools(t: AgentTool<any>[]) {
|
|
860
867
|
this.#state.tools = t;
|
|
868
|
+
this.#contextRevision++;
|
|
861
869
|
}
|
|
862
870
|
|
|
863
871
|
replaceMessages(ms: AgentMessage[]) {
|
|
864
872
|
this.#state.messages = ms.slice();
|
|
873
|
+
this.#contextRevision++;
|
|
865
874
|
}
|
|
866
875
|
|
|
867
876
|
appendMessage(m: AgentMessage) {
|
|
@@ -869,12 +878,14 @@ export class Agent {
|
|
|
869
878
|
// N is O(N+M), not O(M*N). Consumers read state.messages fresh; run() snapshots
|
|
870
879
|
// via slice() at the API boundary, so no caller relies on per-append array identity.
|
|
871
880
|
this.#state.messages.push(m);
|
|
881
|
+
this.#contextRevision++;
|
|
872
882
|
}
|
|
873
883
|
|
|
874
884
|
popMessage(): AgentMessage | undefined {
|
|
875
885
|
const messages = this.#state.messages.slice(0, -1);
|
|
876
886
|
const removed = this.#state.messages.at(-1);
|
|
877
887
|
this.#state.messages = messages;
|
|
888
|
+
this.#contextRevision++;
|
|
878
889
|
|
|
879
890
|
if (removed && this.#state.streamMessage === removed) {
|
|
880
891
|
this.#state.streamMessage = null;
|
|
@@ -883,6 +894,14 @@ export class Agent {
|
|
|
883
894
|
return removed;
|
|
884
895
|
}
|
|
885
896
|
|
|
897
|
+
/**
|
|
898
|
+
* For callers that mutate committed messages or the system prompt in place
|
|
899
|
+
* outside Agent-owned mutators.
|
|
900
|
+
*/
|
|
901
|
+
touchContext(): void {
|
|
902
|
+
this.#contextRevision++;
|
|
903
|
+
}
|
|
904
|
+
|
|
886
905
|
/**
|
|
887
906
|
* Queue a steering message to interrupt the agent mid-run.
|
|
888
907
|
* Delivered after current tool execution, skips remaining tools.
|
|
@@ -1056,6 +1075,7 @@ export class Agent {
|
|
|
1056
1075
|
|
|
1057
1076
|
clearMessages() {
|
|
1058
1077
|
this.#state.messages = [];
|
|
1078
|
+
this.#contextRevision++;
|
|
1059
1079
|
}
|
|
1060
1080
|
|
|
1061
1081
|
abort() {
|
|
@@ -1094,6 +1114,7 @@ export class Agent {
|
|
|
1094
1114
|
|
|
1095
1115
|
reset() {
|
|
1096
1116
|
this.#state.messages = [];
|
|
1117
|
+
this.#contextRevision++;
|
|
1097
1118
|
this.#state.isStreaming = false;
|
|
1098
1119
|
this.#state.streamMessage = null;
|
|
1099
1120
|
this.#state.pendingToolCalls = new Set<string>();
|
package/src/compaction/openai.ts
CHANGED
|
@@ -24,6 +24,8 @@ import type { AssistantMessage, Message, Model } from "@gajae-code/ai/types";
|
|
|
24
24
|
import {
|
|
25
25
|
getOpenAIResponsesHistoryItems,
|
|
26
26
|
getOpenAIResponsesHistoryPayload,
|
|
27
|
+
neutralizeReservedControlTokens,
|
|
28
|
+
neutralizeResponsesInputControlTokens,
|
|
27
29
|
normalizeResponsesToolCallId,
|
|
28
30
|
} from "@gajae-code/ai/utils";
|
|
29
31
|
import { $env, logger } from "@gajae-code/utils";
|
|
@@ -479,10 +481,12 @@ export async function requestOpenAiRemoteCompaction(
|
|
|
479
481
|
const endpoint = resolveOpenAiCompactEndpoint(model, options?.authCredentialType);
|
|
480
482
|
const request: OpenAiRemoteCompactionRequest = {
|
|
481
483
|
model: model.id,
|
|
482
|
-
input:
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
484
|
+
input: neutralizeResponsesInputControlTokens(
|
|
485
|
+
trimOpenAiCompactInput(
|
|
486
|
+
compactInput,
|
|
487
|
+
resolveOpenAiCompactInputBudget(model.contextWindow, model.maxTokens),
|
|
488
|
+
instructions,
|
|
489
|
+
),
|
|
486
490
|
),
|
|
487
491
|
instructions,
|
|
488
492
|
};
|
|
@@ -553,10 +557,17 @@ export async function requestRemoteCompaction(
|
|
|
553
557
|
request: RemoteCompactionRequest,
|
|
554
558
|
signal?: AbortSignal,
|
|
555
559
|
): Promise<RemoteCompactionResponse> {
|
|
560
|
+
// The prompt embeds the serialized transcript, which can carry leaked Harmony
|
|
561
|
+
// control-token markers (e.g. `<|channel|>analysis`) from model output; a
|
|
562
|
+
// gpt-5.6-backed summarization endpoint rejects those with `Request blocked`.
|
|
563
|
+
const sanitizedRequest: RemoteCompactionRequest = {
|
|
564
|
+
systemPrompt: neutralizeReservedControlTokens(request.systemPrompt),
|
|
565
|
+
prompt: neutralizeReservedControlTokens(request.prompt),
|
|
566
|
+
};
|
|
556
567
|
const response = await fetch(endpoint, {
|
|
557
568
|
method: "POST",
|
|
558
569
|
headers: { "content-type": "application/json" },
|
|
559
|
-
body: JSON.stringify(
|
|
570
|
+
body: JSON.stringify(sanitizedRequest),
|
|
560
571
|
signal,
|
|
561
572
|
});
|
|
562
573
|
|
package/src/types.ts
CHANGED
|
@@ -357,7 +357,7 @@ export type AgentMessage = Message | CustomAgentMessages[keyof CustomAgentMessag
|
|
|
357
357
|
*/
|
|
358
358
|
export interface AgentState {
|
|
359
359
|
systemPrompt: string[];
|
|
360
|
-
model: Model;
|
|
360
|
+
model: Model | undefined;
|
|
361
361
|
thinkingLevel?: Effort;
|
|
362
362
|
tools: AgentTool<any>[];
|
|
363
363
|
messages: AgentMessage[]; // Can include attachments + custom message types
|