@oh-my-pi/pi-agent-core 18.8.0 → 18.8.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/index.d.ts +1 -0
- package/dist/types/speculative-execution.d.ts +1 -1
- package/dist/types/tool-arguments.d.ts +19 -0
- package/package.json +8 -8
- package/src/agent-loop.ts +2 -8
- package/src/index.ts +2 -0
- package/src/speculative-execution.ts +5 -9
- package/src/tool-arguments.ts +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.8.1] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added the public `validateAgentToolArguments()` API for consistent, lenient-aware validation of agent tool arguments across agent and coding-agent workflows.
|
|
10
|
+
|
|
5
11
|
## [18.8.0] - 2026-10-07
|
|
6
12
|
|
|
7
13
|
### Changed
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
2
2
|
import type { AgentContext, AgentLoopConfig, AgentTool, AgentToolCall, AgentToolResult, SpeculativeAuthorization, SpeculativeChildDefinition, SpeculativeChildHandle, SpeculativeLaunchContext, SpeculativeToolExecutionConfig, ToolSpeculationEffect, ToolSpeculationStreamSession } from "./types.js";
|
|
3
3
|
export type SpeculativeRawOutcome = {
|
|
4
4
|
result: AgentToolResult<unknown>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ToolCall } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { AgentTool } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Where a call's `__parseError`/`__rawJson` keys came from.
|
|
5
|
+
* - `"parsed"`: a provider stream parsed the arguments, so `__parseError` is a
|
|
6
|
+
* genuine parse-failure sentinel and is never handed to a tool.
|
|
7
|
+
* - `"payload"`: the arguments are a payload the model wrote (eval tool bridge,
|
|
8
|
+
* `xd://` device content), so those keys are forged and only stripped.
|
|
9
|
+
*/
|
|
10
|
+
export type ToolArgumentSource = "parsed" | "payload";
|
|
11
|
+
/**
|
|
12
|
+
* Validate a call's arguments against `tool`'s schema, honoring
|
|
13
|
+
* {@link AgentTool.lenientArgValidation}: on a schema mismatch a lenient tool
|
|
14
|
+
* receives its raw arguments minus the internal `__parseError`/`__rawJson`
|
|
15
|
+
* sentinels. Malformed JSON from a provider stream is never lenient.
|
|
16
|
+
*
|
|
17
|
+
* @throws the validation error when the tool is strict or the arguments failed to parse.
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateAgentToolArguments(tool: AgentTool, toolCall: ToolCall, source?: ToolArgumentSource): ToolCall["arguments"];
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-agent-core",
|
|
4
|
-
"version": "18.8.
|
|
4
|
+
"version": "18.8.2",
|
|
5
5
|
"description": "General-purpose agent with transport abstraction, state management, and attachment support",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": {
|
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@oh-my-pi/pi-ai": "18.8.
|
|
42
|
-
"@oh-my-pi/pi-catalog": "18.8.
|
|
43
|
-
"@oh-my-pi/pi-natives": "18.8.
|
|
44
|
-
"@oh-my-pi/pi-utils": "18.8.
|
|
45
|
-
"@oh-my-pi/pi-wire": "18.8.
|
|
46
|
-
"@oh-my-pi/snapcompact": "18.8.
|
|
41
|
+
"@oh-my-pi/pi-ai": "18.8.2",
|
|
42
|
+
"@oh-my-pi/pi-catalog": "18.8.2",
|
|
43
|
+
"@oh-my-pi/pi-natives": "18.8.2",
|
|
44
|
+
"@oh-my-pi/pi-utils": "18.8.2",
|
|
45
|
+
"@oh-my-pi/pi-wire": "18.8.2",
|
|
46
|
+
"@oh-my-pi/snapcompact": "18.8.2",
|
|
47
47
|
"@opentelemetry/api": "^1.9.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@oh-my-pi/omptype": "18.8.
|
|
50
|
+
"@oh-my-pi/omptype": "18.8.2",
|
|
51
51
|
"@opentelemetry/context-async-hooks": "^2.9.0",
|
|
52
52
|
"@opentelemetry/sdk-trace-base": "^2.9.0",
|
|
53
53
|
"@types/bun": "^1.3.14"
|
package/src/agent-loop.ts
CHANGED
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
type TSchema,
|
|
24
24
|
toolWireSchema,
|
|
25
25
|
type UserMessage,
|
|
26
|
-
validateToolArguments,
|
|
27
26
|
} from "@oh-my-pi/pi-ai";
|
|
28
27
|
import {
|
|
29
28
|
type Dialect,
|
|
@@ -76,6 +75,7 @@ import {
|
|
|
76
75
|
startExecuteToolSpan,
|
|
77
76
|
startInvokeAgentSpan,
|
|
78
77
|
} from "./telemetry";
|
|
78
|
+
import { validateAgentToolArguments } from "./tool-arguments";
|
|
79
79
|
import { createAdditionalContextMessage, isNonBlankContext, joinAdditionalContext } from "./tool-context";
|
|
80
80
|
import dsmlToolCallLeakPrompt from "./prompts/dsml-tool-call-leak.md" with { type: "text" };
|
|
81
81
|
import type {
|
|
@@ -3062,15 +3062,9 @@ async function prepareToolCallDispatch(
|
|
|
3062
3062
|
if (!tool) {
|
|
3063
3063
|
throw new Error(formatToolNotFoundMessage(toolCall.name, context.tools, suggestFallbackToolNames?.()));
|
|
3064
3064
|
}
|
|
3065
|
-
return
|
|
3065
|
+
return validateAgentToolArguments(tool, { ...toolCall, arguments: args });
|
|
3066
3066
|
} catch (validationError) {
|
|
3067
|
-
// Lenience covers schema mismatches; a parse failure has no args to hand over.
|
|
3068
3067
|
const parseFailed = "__parseError" in args;
|
|
3069
|
-
if (tool?.lenientArgValidation && !parseFailed) {
|
|
3070
|
-
const fallback = { ...args };
|
|
3071
|
-
delete fallback.__rawJson;
|
|
3072
|
-
return fallback;
|
|
3073
|
-
}
|
|
3074
3068
|
entry.args = parseFailed ? { __parseError: args.__parseError } : args;
|
|
3075
3069
|
entry.validationErrorMessage =
|
|
3076
3070
|
validationError instanceof Error ? validationError.message : String(validationError);
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,8 @@ export * from "./thinking";
|
|
|
28
28
|
export * from "./tool-context";
|
|
29
29
|
// Tokenizer choice
|
|
30
30
|
export * from "./tokenizer";
|
|
31
|
+
// Lenient-aware tool argument validation
|
|
32
|
+
export * from "./tool-arguments";
|
|
31
33
|
// Types
|
|
32
34
|
export * from "./types";
|
|
33
35
|
// Yield utilities for Bun event-loop busy-wait prevention
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import type { AssistantMessage } from "@oh-my-pi/pi-ai";
|
|
3
|
+
import { validateAgentToolArguments } from "./tool-arguments";
|
|
3
4
|
import type {
|
|
4
5
|
AgentContext,
|
|
5
6
|
AgentLoopConfig,
|
|
@@ -712,15 +713,10 @@ export class SpeculativeOperationCoordinator {
|
|
|
712
713
|
}
|
|
713
714
|
let validatedArgs: Record<string, unknown>;
|
|
714
715
|
try {
|
|
715
|
-
validatedArgs =
|
|
716
|
+
validatedArgs = validateAgentToolArguments(tool, toolCall);
|
|
716
717
|
} catch {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
this.ineligible(toolCall, "tool arguments are not valid", source, parentToolCallId);
|
|
720
|
-
return undefined;
|
|
721
|
-
}
|
|
722
|
-
validatedArgs = { ...toolCall.arguments };
|
|
723
|
-
delete validatedArgs.__rawJson;
|
|
718
|
+
this.ineligible(toolCall, "tool arguments are not valid", source, parentToolCallId);
|
|
719
|
+
return undefined;
|
|
724
720
|
}
|
|
725
721
|
let executionArgs: Record<string, unknown>;
|
|
726
722
|
try {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ToolCall, validateToolArguments } from "@oh-my-pi/pi-ai";
|
|
2
|
+
import type { AgentTool } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where a call's `__parseError`/`__rawJson` keys came from.
|
|
6
|
+
* - `"parsed"`: a provider stream parsed the arguments, so `__parseError` is a
|
|
7
|
+
* genuine parse-failure sentinel and is never handed to a tool.
|
|
8
|
+
* - `"payload"`: the arguments are a payload the model wrote (eval tool bridge,
|
|
9
|
+
* `xd://` device content), so those keys are forged and only stripped.
|
|
10
|
+
*/
|
|
11
|
+
export type ToolArgumentSource = "parsed" | "payload";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validate a call's arguments against `tool`'s schema, honoring
|
|
15
|
+
* {@link AgentTool.lenientArgValidation}: on a schema mismatch a lenient tool
|
|
16
|
+
* receives its raw arguments minus the internal `__parseError`/`__rawJson`
|
|
17
|
+
* sentinels. Malformed JSON from a provider stream is never lenient.
|
|
18
|
+
*
|
|
19
|
+
* @throws the validation error when the tool is strict or the arguments failed to parse.
|
|
20
|
+
*/
|
|
21
|
+
export function validateAgentToolArguments(
|
|
22
|
+
tool: AgentTool,
|
|
23
|
+
toolCall: ToolCall,
|
|
24
|
+
source: ToolArgumentSource = "parsed",
|
|
25
|
+
): ToolCall["arguments"] {
|
|
26
|
+
try {
|
|
27
|
+
return validateToolArguments(tool, toolCall);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
const args: unknown = toolCall.arguments;
|
|
30
|
+
if (!tool.lenientArgValidation) throw error;
|
|
31
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return args as ToolCall["arguments"];
|
|
32
|
+
if (source === "parsed" && "__parseError" in args) throw error;
|
|
33
|
+
const fallback = { ...(args as Record<string, unknown>) };
|
|
34
|
+
delete fallback.__parseError;
|
|
35
|
+
delete fallback.__rawJson;
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
}
|