@linxiraos/pi-agent-core 1.4.0 → 1.4.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 +10 -2
- package/dist/types/compaction/anthropic.d.ts +9 -3
- package/dist/types/tool-arguments.d.ts +4 -3
- package/dist/types/types.d.ts +7 -1
- package/package.json +8 -8
- package/src/compaction/anthropic.ts +30 -6
- package/src/compaction/compaction.ts +10 -5
- package/src/tool-arguments.ts +16 -4
- package/src/types.ts +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [1.4.
|
|
3
|
+
## [1.4.2] - 2026-10-24
|
|
4
4
|
|
|
5
|
-
- Version
|
|
5
|
+
- Version alignment with the 1.4.2 release line (no behavioral changes).
|
|
6
6
|
|
|
7
7
|
## [9.2.2] - 2026-01-31
|
|
8
8
|
|
|
@@ -134,6 +134,14 @@
|
|
|
134
134
|
|
|
135
135
|
Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mono](https://github.com/badlogic/pi-mono).
|
|
136
136
|
|
|
137
|
+
## [1.4.1] - 2026-10-23
|
|
138
|
+
|
|
139
|
+
- Version alignment with the 1.4.1 release line (no behavioral changes).
|
|
140
|
+
|
|
141
|
+
## [1.4.0] - 2026-10-21
|
|
142
|
+
|
|
143
|
+
- Version line moves to 1.4.0 with the rest of the suite; no user-visible change in this package.
|
|
144
|
+
|
|
137
145
|
## [1.3.2] - 2026-10-19
|
|
138
146
|
|
|
139
147
|
- Version line moves to 1.3.2 with the rest of the suite; no user-visible change in this package.
|
|
@@ -14,6 +14,8 @@ export declare const ANTHROPIC_COMPACTION_PRESERVE_KEY = "anthropicCompaction";
|
|
|
14
14
|
export interface AnthropicCompactionPreserveData {
|
|
15
15
|
provider: string;
|
|
16
16
|
content: string;
|
|
17
|
+
/** Opaque signed tool-change records; replayed without normalization. */
|
|
18
|
+
toolChanges?: Record<string, unknown>[];
|
|
17
19
|
/** Signature attached to an on-demand block; replayed verbatim. */
|
|
18
20
|
signature?: string;
|
|
19
21
|
/** Legacy threshold block state; replay-only. */
|
|
@@ -35,9 +37,11 @@ export interface AnthropicCompactionPreserveData {
|
|
|
35
37
|
* lineage the beta documents); endpoint eligibility is resolved the way the
|
|
36
38
|
* provider routes requests, so a Foundry or `ANTHROPIC_BASE_URL` reroute of a
|
|
37
39
|
* first-party model is excluded unless the route opted in with
|
|
38
|
-
* `remoteCompaction.enabled`.
|
|
40
|
+
* `remoteCompaction.enabled`. Bedrock Converse models compact through a
|
|
41
|
+
* Bedrock Runtime side request; their ordinary turns stay on Converse.
|
|
39
42
|
*/
|
|
40
|
-
export declare function shouldUseAnthropicNativeCompaction(model: Model): model is Model<"anthropic-messages">;
|
|
43
|
+
export declare function shouldUseAnthropicNativeCompaction(model: Model): model is Model<"anthropic-messages" | "bedrock-converse-stream">;
|
|
44
|
+
type AnthropicNativeCompactionModel = Model<"anthropic-messages" | "bedrock-converse-stream">;
|
|
41
45
|
export declare function getPreservedAnthropicCompactionData(preserveData: Record<string, unknown> | undefined): AnthropicCompactionPreserveData | undefined;
|
|
42
46
|
/** Set or strip the Anthropic compaction slot; a new compaction never inherits a stale summary. */
|
|
43
47
|
export declare function withAnthropicCompactionPreserveData(preserveData: Record<string, unknown> | undefined, compaction: AnthropicCompactionPreserveData | undefined): Record<string, unknown> | undefined;
|
|
@@ -67,6 +71,7 @@ export interface AnthropicNativeCompactionRequest {
|
|
|
67
71
|
export interface AnthropicNativeCompactionResponse {
|
|
68
72
|
content: string;
|
|
69
73
|
signature: string;
|
|
74
|
+
toolChanges?: Record<string, unknown>[];
|
|
70
75
|
usage: Usage;
|
|
71
76
|
model: string;
|
|
72
77
|
}
|
|
@@ -81,4 +86,5 @@ export interface AnthropicNativeCompactionOptions extends Pick<SimpleStreamOptio
|
|
|
81
86
|
* without a summary is a native failure, including tool use, refusals and
|
|
82
87
|
* output limits; the configured method order can then choose a fallback.
|
|
83
88
|
*/
|
|
84
|
-
export declare function requestAnthropicNativeCompaction(model:
|
|
89
|
+
export declare function requestAnthropicNativeCompaction(model: AnthropicNativeCompactionModel, apiKey: ApiKey, request: AnthropicNativeCompactionRequest, signal: AbortSignal | undefined, options: AnthropicNativeCompactionOptions): Promise<AnthropicNativeCompactionResponse>;
|
|
90
|
+
export {};
|
|
@@ -10,9 +10,10 @@ import type { AgentTool } from "./types.js";
|
|
|
10
10
|
export type ToolArgumentSource = "parsed" | "payload";
|
|
11
11
|
/**
|
|
12
12
|
* Validate a call's arguments against `tool`'s schema, honoring
|
|
13
|
-
* {@link AgentTool.lenientArgValidation}:
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* {@link AgentTool.lenientArgValidation}: a lenient tool keeps unknown root
|
|
14
|
+
* keys its closed schema would heal away, and on a schema mismatch receives its
|
|
15
|
+
* raw arguments minus the internal `__parseError`/`__rawJson` sentinels.
|
|
16
|
+
* Malformed JSON from a provider stream is never lenient.
|
|
16
17
|
*
|
|
17
18
|
* @throws the validation error when the tool is strict or the arguments failed to parse.
|
|
18
19
|
*/
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1034,7 +1034,7 @@ export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any
|
|
|
1034
1034
|
* before ordinary dispatch commits its result.
|
|
1035
1035
|
*/
|
|
1036
1036
|
speculation?: ToolSpeculationPolicy;
|
|
1037
|
-
/** If true, schema validation errors are non-fatal: raw args are passed to execute() instead of returning an error to the LLM. Malformed argument JSON still returns the parse error. */
|
|
1037
|
+
/** If true, schema validation errors are non-fatal: raw args are passed to execute() instead of returning an error to the LLM, and unknown root keys a closed schema would drop stay on the args. Malformed argument JSON still returns the parse error. */
|
|
1038
1038
|
lenientArgValidation?: boolean;
|
|
1039
1039
|
/**
|
|
1040
1040
|
* Whether the agent loop may abort this tool mid-execution — or skip it
|
|
@@ -1090,6 +1090,12 @@ export interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any
|
|
|
1090
1090
|
approval?: ToolApproval;
|
|
1091
1091
|
/** Lines appended after the standard approval prompt header. */
|
|
1092
1092
|
formatApprovalDetails?: (args: unknown) => string | string[] | undefined;
|
|
1093
|
+
/**
|
|
1094
|
+
* Remembered-approval keys for `tools.approvalMode: always-ask-cached`: the files (or URL
|
|
1095
|
+
* targets) this call touches. When every key is already granted the call skips its prompt;
|
|
1096
|
+
* approving the call can record them. Omit it (or return `undefined`) and the call prompts by tier.
|
|
1097
|
+
*/
|
|
1098
|
+
approvalCacheTargets?: (args: unknown) => readonly string[] | undefined;
|
|
1093
1099
|
/** The main execution callback for this tool. */
|
|
1094
1100
|
execute: AgentToolExecFn<TParameters, TDetails, TTheme>;
|
|
1095
1101
|
/** Optional custom rendering for tool call display (returns UI component) */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@linxiraos/pi-agent-core",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.2",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://linxira-os.github.io/zeta/",
|
|
7
7
|
"author": "Linxira-OS",
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@linxiraos/pi-ai": "1.4.
|
|
39
|
-
"@linxiraos/pi-catalog": "1.4.
|
|
40
|
-
"@linxiraos/pi-natives": "1.4.
|
|
41
|
-
"@linxiraos/pi-utils": "1.4.
|
|
42
|
-
"@linxiraos/pi-wire": "1.4.
|
|
43
|
-
"@linxiraos/pi-snapcompact": "1.4.
|
|
38
|
+
"@linxiraos/pi-ai": "1.4.2",
|
|
39
|
+
"@linxiraos/pi-catalog": "1.4.2",
|
|
40
|
+
"@linxiraos/pi-natives": "1.4.2",
|
|
41
|
+
"@linxiraos/pi-utils": "1.4.2",
|
|
42
|
+
"@linxiraos/pi-wire": "1.4.2",
|
|
43
|
+
"@linxiraos/pi-snapcompact": "1.4.2",
|
|
44
44
|
"@opentelemetry/api": "^1.9.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@linxiraos/pi-omptype": "1.4.
|
|
47
|
+
"@linxiraos/pi-omptype": "1.4.2",
|
|
48
48
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
49
49
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
50
50
|
"@types/bun": "1.4.3"
|
|
@@ -19,7 +19,10 @@ import type {
|
|
|
19
19
|
} from "@linxiraos/pi-ai";
|
|
20
20
|
import * as AIError from "@linxiraos/pi-ai/error";
|
|
21
21
|
import { resolveAnthropicCompactionEffort } from "@linxiraos/pi-ai/providers/anthropic";
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
supportsAnthropicCompaction,
|
|
24
|
+
supportsBedrockConverseCompaction,
|
|
25
|
+
} from "@linxiraos/pi-ai/providers/anthropic-compaction";
|
|
23
26
|
import { isRecord, prompt } from "@linxiraos/pi-utils";
|
|
24
27
|
import { type InstrumentedChatSpanOptions, instrumentedCompleteSimple } from "../telemetry";
|
|
25
28
|
import type { AgentMessage } from "../types";
|
|
@@ -31,6 +34,8 @@ export const ANTHROPIC_COMPACTION_PRESERVE_KEY = "anthropicCompaction";
|
|
|
31
34
|
export interface AnthropicCompactionPreserveData {
|
|
32
35
|
provider: string;
|
|
33
36
|
content: string;
|
|
37
|
+
/** Opaque signed tool-change records; replayed without normalization. */
|
|
38
|
+
toolChanges?: Record<string, unknown>[];
|
|
34
39
|
/** Signature attached to an on-demand block; replayed verbatim. */
|
|
35
40
|
signature?: string;
|
|
36
41
|
/** Legacy threshold block state; replay-only. */
|
|
@@ -51,18 +56,28 @@ function isAnthropicMessagesModel(model: Model): model is Model<"anthropic-messa
|
|
|
51
56
|
return model.api === "anthropic-messages";
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
function isBedrockConverseModel(model: Model): model is Model<"bedrock-converse-stream"> {
|
|
60
|
+
return model.api === "bedrock-converse-stream";
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
/**
|
|
55
64
|
* Whether a model compacts through the Anthropic compaction beta. Model
|
|
56
65
|
* eligibility is catalog policy (`compat.supportsServerCompaction`, the
|
|
57
66
|
* lineage the beta documents); endpoint eligibility is resolved the way the
|
|
58
67
|
* provider routes requests, so a Foundry or `ANTHROPIC_BASE_URL` reroute of a
|
|
59
68
|
* first-party model is excluded unless the route opted in with
|
|
60
|
-
* `remoteCompaction.enabled`.
|
|
69
|
+
* `remoteCompaction.enabled`. Bedrock Converse models compact through a
|
|
70
|
+
* Bedrock Runtime side request; their ordinary turns stay on Converse.
|
|
61
71
|
*/
|
|
62
|
-
export function shouldUseAnthropicNativeCompaction(
|
|
63
|
-
|
|
72
|
+
export function shouldUseAnthropicNativeCompaction(
|
|
73
|
+
model: Model,
|
|
74
|
+
): model is Model<"anthropic-messages" | "bedrock-converse-stream"> {
|
|
75
|
+
if (isAnthropicMessagesModel(model)) return supportsAnthropicCompaction(model);
|
|
76
|
+
return isBedrockConverseModel(model) && supportsBedrockConverseCompaction(model);
|
|
64
77
|
}
|
|
65
78
|
|
|
79
|
+
type AnthropicNativeCompactionModel = Model<"anthropic-messages" | "bedrock-converse-stream">;
|
|
80
|
+
|
|
66
81
|
export function getPreservedAnthropicCompactionData(
|
|
67
82
|
preserveData: Record<string, unknown> | undefined,
|
|
68
83
|
): AnthropicCompactionPreserveData | undefined {
|
|
@@ -70,6 +85,9 @@ export function getPreservedAnthropicCompactionData(
|
|
|
70
85
|
if (!isRecord(candidate)) return undefined;
|
|
71
86
|
if (typeof candidate.provider !== "string" || candidate.provider.length === 0) return undefined;
|
|
72
87
|
if (typeof candidate.content !== "string" || candidate.content.length === 0) return undefined;
|
|
88
|
+
const toolChanges = candidate.toolChanges;
|
|
89
|
+
// The signature covers `tool_changes`: a block missing or mangling them cannot replay.
|
|
90
|
+
if (toolChanges !== undefined && (!Array.isArray(toolChanges) || !toolChanges.every(isRecord))) return undefined;
|
|
73
91
|
return {
|
|
74
92
|
provider: candidate.provider,
|
|
75
93
|
content: candidate.content,
|
|
@@ -90,6 +108,7 @@ export function getPreservedAnthropicCompactionData(
|
|
|
90
108
|
),
|
|
91
109
|
}
|
|
92
110
|
: {}),
|
|
111
|
+
...(toolChanges !== undefined ? { toolChanges } : {}),
|
|
93
112
|
...(candidate.exactTail === true ? { exactTail: true as const } : {}),
|
|
94
113
|
...(typeof candidate.model === "string" ? { model: candidate.model } : {}),
|
|
95
114
|
...(typeof candidate.usedTokens === "number" ? { usedTokens: candidate.usedTokens } : {}),
|
|
@@ -124,6 +143,7 @@ export function getAnthropicCompactionPayload(
|
|
|
124
143
|
...(preserved.signature ? { signature: preserved.signature } : {}),
|
|
125
144
|
...(preserved.encryptedContent ? { encryptedContent: preserved.encryptedContent } : {}),
|
|
126
145
|
...(preserved.filesText ? { filesText: preserved.filesText } : {}),
|
|
146
|
+
...(preserved.toolChanges ? { toolChanges: preserved.toolChanges } : {}),
|
|
127
147
|
...(preserved.retainedFiles?.length ? { retainedFiles: preserved.retainedFiles } : {}),
|
|
128
148
|
...(preserved.exactTail ? { exactTail: true as const } : {}),
|
|
129
149
|
};
|
|
@@ -196,6 +216,7 @@ export interface AnthropicNativeCompactionRequest {
|
|
|
196
216
|
export interface AnthropicNativeCompactionResponse {
|
|
197
217
|
content: string;
|
|
198
218
|
signature: string;
|
|
219
|
+
toolChanges?: Record<string, unknown>[];
|
|
199
220
|
usage: Usage;
|
|
200
221
|
model: string;
|
|
201
222
|
}
|
|
@@ -224,7 +245,7 @@ export interface AnthropicNativeCompactionOptions
|
|
|
224
245
|
* output limits; the configured method order can then choose a fallback.
|
|
225
246
|
*/
|
|
226
247
|
export async function requestAnthropicNativeCompaction(
|
|
227
|
-
model:
|
|
248
|
+
model: AnthropicNativeCompactionModel,
|
|
228
249
|
apiKey: ApiKey,
|
|
229
250
|
request: AnthropicNativeCompactionRequest,
|
|
230
251
|
signal: AbortSignal | undefined,
|
|
@@ -237,7 +258,9 @@ export async function requestAnthropicNativeCompaction(
|
|
|
237
258
|
apiKey,
|
|
238
259
|
signal,
|
|
239
260
|
maxTokens: request.maxTokens,
|
|
240
|
-
reasoning:
|
|
261
|
+
reasoning: isAnthropicMessagesModel(model)
|
|
262
|
+
? resolveAnthropicCompactionEffort(model, request.context.messages, request.reasoning)
|
|
263
|
+
: request.reasoning,
|
|
241
264
|
initiatorOverride: options.initiatorOverride,
|
|
242
265
|
metadata: options.metadata,
|
|
243
266
|
fetch: options.fetch,
|
|
@@ -279,6 +302,7 @@ export async function requestAnthropicNativeCompaction(
|
|
|
279
302
|
return {
|
|
280
303
|
content: payload.content,
|
|
281
304
|
signature: payload.signature,
|
|
305
|
+
...(payload.toolChanges ? { toolChanges: payload.toolChanges } : {}),
|
|
282
306
|
usage: response.usage,
|
|
283
307
|
model: response.model,
|
|
284
308
|
};
|
|
@@ -2024,6 +2024,7 @@ export async function compact(
|
|
|
2024
2024
|
let nativeFirstKeptEntryId = firstKeptEntryId;
|
|
2025
2025
|
let nativeUsedTokens: number | undefined;
|
|
2026
2026
|
let nativeRetainedFiles: AnthropicCompactionFiles[] | undefined;
|
|
2027
|
+
let nativeToolChanges: Record<string, unknown>[] | undefined;
|
|
2027
2028
|
if (!usedRemoteCompaction && settings.remoteEnabled !== false && shouldUseAnthropicNativeCompaction(model)) {
|
|
2028
2029
|
const previousNative = getPreservedAnthropicCompactionData(previousPreserveData);
|
|
2029
2030
|
// Lead with the previous summary as the live context renders it:
|
|
@@ -2052,6 +2053,7 @@ export async function compact(
|
|
|
2052
2053
|
: {}),
|
|
2053
2054
|
...(previousNative.filesText ? { filesText: previousNative.filesText } : {}),
|
|
2054
2055
|
...(previousNative.retainedFiles ? { retainedFiles: previousNative.retainedFiles } : {}),
|
|
2056
|
+
...(previousNative.toolChanges ? { toolChanges: previousNative.toolChanges } : {}),
|
|
2055
2057
|
...(previousNative.exactTail ? { exactTail: true as const } : {}),
|
|
2056
2058
|
}
|
|
2057
2059
|
: undefined,
|
|
@@ -2148,6 +2150,7 @@ export async function compact(
|
|
|
2148
2150
|
);
|
|
2149
2151
|
nativeSummary = remote.content;
|
|
2150
2152
|
nativeSignature = remote.signature;
|
|
2153
|
+
nativeToolChanges = remote.toolChanges;
|
|
2151
2154
|
nativeUsedTokens = calculatePromptTokens(remote.usage);
|
|
2152
2155
|
usedRemoteCompaction = true;
|
|
2153
2156
|
} catch (err) {
|
|
@@ -2235,16 +2238,18 @@ export async function compact(
|
|
|
2235
2238
|
const { readFiles, modifiedFiles } = computeFileLists(fileOps);
|
|
2236
2239
|
summary = upsertFileOperations(summary, readFiles, modifiedFiles, fileOps.read);
|
|
2237
2240
|
if (nativeSummary !== undefined) {
|
|
2238
|
-
// The replayed block
|
|
2239
|
-
// matches its signature. The
|
|
2240
|
-
// separately: the converter replaces the
|
|
2241
|
-
// block and skips its text, so they would
|
|
2242
|
-
// this provider. Every other provider keeps
|
|
2241
|
+
// The replayed block (summary and any `tool_changes`) stays
|
|
2242
|
+
// byte-identical to the API's output so it matches its signature. The
|
|
2243
|
+
// harness file lists above travel separately: the converter replaces the
|
|
2244
|
+
// summary message with the block and skips its text, so they would
|
|
2245
|
+
// otherwise be invisible to this provider. Every other provider keeps
|
|
2246
|
+
// reading the entry text.
|
|
2243
2247
|
const filesText = upsertFileOperations("", readFiles, modifiedFiles, fileOps.read) || undefined;
|
|
2244
2248
|
preserveData = withAnthropicCompactionPreserveData(preserveData, {
|
|
2245
2249
|
provider: model.provider,
|
|
2246
2250
|
content: nativeSummary,
|
|
2247
2251
|
...(nativeSignature ? { signature: nativeSignature } : {}),
|
|
2252
|
+
...(nativeToolChanges ? { toolChanges: nativeToolChanges } : {}),
|
|
2248
2253
|
...(filesText ? { filesText } : {}),
|
|
2249
2254
|
...(nativeRetainedFiles ? { retainedFiles: nativeRetainedFiles } : {}),
|
|
2250
2255
|
exactTail: true,
|
package/src/tool-arguments.ts
CHANGED
|
@@ -12,9 +12,10 @@ export type ToolArgumentSource = "parsed" | "payload";
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Validate a call's arguments against `tool`'s schema, honoring
|
|
15
|
-
* {@link AgentTool.lenientArgValidation}:
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* {@link AgentTool.lenientArgValidation}: a lenient tool keeps unknown root
|
|
16
|
+
* keys its closed schema would heal away, and on a schema mismatch receives its
|
|
17
|
+
* raw arguments minus the internal `__parseError`/`__rawJson` sentinels.
|
|
18
|
+
* Malformed JSON from a provider stream is never lenient.
|
|
18
19
|
*
|
|
19
20
|
* @throws the validation error when the tool is strict or the arguments failed to parse.
|
|
20
21
|
*/
|
|
@@ -24,7 +25,9 @@ export function validateAgentToolArguments(
|
|
|
24
25
|
source: ToolArgumentSource = "parsed",
|
|
25
26
|
): ToolCall["arguments"] {
|
|
26
27
|
try {
|
|
27
|
-
|
|
28
|
+
const validated = validateToolArguments(tool, toolCall, { keepUnknownRootKeys: tool.lenientArgValidation });
|
|
29
|
+
// Kept unknown root keys must not smuggle the internal sentinels past validation.
|
|
30
|
+
return tool.lenientArgValidation ? withoutSentinels(validated) : validated;
|
|
28
31
|
} catch (error) {
|
|
29
32
|
const args: unknown = toolCall.arguments;
|
|
30
33
|
if (!tool.lenientArgValidation) throw error;
|
|
@@ -36,3 +39,12 @@ export function validateAgentToolArguments(
|
|
|
36
39
|
return fallback;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
42
|
+
|
|
43
|
+
function withoutSentinels(args: ToolCall["arguments"]): ToolCall["arguments"] {
|
|
44
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return args;
|
|
45
|
+
if (!Object.hasOwn(args, "__parseError") && !Object.hasOwn(args, "__rawJson")) return args;
|
|
46
|
+
const stripped = { ...(args as Record<string, unknown>) };
|
|
47
|
+
delete stripped.__parseError;
|
|
48
|
+
delete stripped.__rawJson;
|
|
49
|
+
return stripped;
|
|
50
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1170,7 +1170,7 @@ export interface AgentTool<
|
|
|
1170
1170
|
* before ordinary dispatch commits its result.
|
|
1171
1171
|
*/
|
|
1172
1172
|
speculation?: ToolSpeculationPolicy;
|
|
1173
|
-
/** If true, schema validation errors are non-fatal: raw args are passed to execute() instead of returning an error to the LLM. Malformed argument JSON still returns the parse error. */
|
|
1173
|
+
/** If true, schema validation errors are non-fatal: raw args are passed to execute() instead of returning an error to the LLM, and unknown root keys a closed schema would drop stay on the args. Malformed argument JSON still returns the parse error. */
|
|
1174
1174
|
lenientArgValidation?: boolean;
|
|
1175
1175
|
/**
|
|
1176
1176
|
* Whether the agent loop may abort this tool mid-execution — or skip it
|
|
@@ -1229,6 +1229,13 @@ export interface AgentTool<
|
|
|
1229
1229
|
/** Lines appended after the standard approval prompt header. */
|
|
1230
1230
|
formatApprovalDetails?: (args: unknown) => string | string[] | undefined;
|
|
1231
1231
|
|
|
1232
|
+
/**
|
|
1233
|
+
* Remembered-approval keys for `tools.approvalMode: always-ask-cached`: the files (or URL
|
|
1234
|
+
* targets) this call touches. When every key is already granted the call skips its prompt;
|
|
1235
|
+
* approving the call can record them. Omit it (or return `undefined`) and the call prompts by tier.
|
|
1236
|
+
*/
|
|
1237
|
+
approvalCacheTargets?: (args: unknown) => readonly string[] | undefined;
|
|
1238
|
+
|
|
1232
1239
|
/** The main execution callback for this tool. */
|
|
1233
1240
|
execute: AgentToolExecFn<TParameters, TDetails, TTheme>;
|
|
1234
1241
|
|