@oh-my-pi/pi-ai 18.12.1 → 18.12.3
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 +28 -23
- package/dist/types/dialect/deepseek.d.ts +13 -0
- package/dist/types/judgment/native.d.ts +13 -2
- package/dist/types/judgment/types.d.ts +32 -5
- package/dist/types/judgment/wire.d.ts +2 -0
- package/dist/types/providers/google-shared.d.ts +17 -0
- package/dist/types/providers/ollama.d.ts +6 -1
- package/dist/types/providers/transform-messages.d.ts +2 -0
- package/dist/types/usage/muse-code.d.ts +1 -1
- package/dist/types/utils/dsml-leak.d.ts +13 -11
- package/dist/types/utils/http-inspector.d.ts +2 -0
- package/dist/types/utils/validation.d.ts +11 -1
- package/package.json +6 -6
- package/src/dialect/deepseek.ts +344 -81
- package/src/error/flags.ts +2 -2
- package/src/judgment/native.ts +63 -7
- package/src/judgment/openai-decisions.ts +3 -0
- package/src/judgment/systemone.ts +27 -6
- package/src/judgment/text.ts +6 -0
- package/src/judgment/types.ts +41 -5
- package/src/judgment/wire.ts +2 -0
- package/src/providers/factory-droid/gemini.ts +13 -5
- package/src/providers/google-shared.ts +61 -6
- package/src/providers/ollama.ts +12 -4
- package/src/providers/transform-messages.ts +9 -4
- package/src/usage/muse-code.ts +114 -28
- package/src/utils/dsml-leak.ts +58 -19
- package/src/utils/http-inspector.ts +3 -2
- package/src/utils/leaked-thinking-stream.ts +16 -4
- package/src/utils/request-debug.ts +3 -2
- package/src/utils/schema/CONSTRAINTS.md +12 -5
- package/src/utils/schema/allowlist.ts +144 -18
- package/src/utils/validation.ts +47 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [18.12.3] - 2026-10-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `validateToolArguments(tool, call, { keepUnknownRootKeys: true })` to keep unknown root keys that a closed schema would otherwise drop during argument repair ([#16317](https://github.com/can1357/oh-my-pi/issues/16317))
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed Claude streams that a gateway cut off before `message_delta` failing the turn instead of being retried ([#16341](https://github.com/can1357/oh-my-pi/pull/16341) by [@lz-lunzi](https://github.com/lz-lunzi))
|
|
14
|
+
- Fixed Gemini pairing parallel same-name tool results with the wrong call when history stores them out of call order (sessions from before 18.4.2, SDK-built contexts) ([#16259](https://github.com/can1357/oh-my-pi/pull/16259) by [@will-bogusz](https://github.com/will-bogusz))
|
|
15
|
+
- Fixed Factory Droid Gemini dropping calls to tools with names over 64 characters (most MCP tools) and their results from later requests, so the model called the tool again; such names now shorten to 64 characters ([#16283](https://github.com/can1357/oh-my-pi/pull/16283) by [@will-bogusz](https://github.com/will-bogusz))
|
|
16
|
+
- Fixed Factory Droid Gemini requests failing with 400 "For schema with items, schema type should be ARRAY" when a tool parameter accepts a string or a list, as the default `task` tool's `model` field does ([#16249](https://github.com/can1357/oh-my-pi/pull/16249) by [@will-bogusz](https://github.com/will-bogusz))
|
|
17
|
+
- Fixed `PI_REQ_DEBUG=1` request dumps writing your API key, bearer token and response cookies to disk in plain text: credential headers now read `[redacted]`, as in rejected-request dumps ([#16293](https://github.com/can1357/oh-my-pi/pull/16293) by [@will-bogusz](https://github.com/will-bogusz))
|
|
18
|
+
- Fixed finalized signed reasoning disappearing from displayed thinking when no deltas streamed ([#16227](https://github.com/can1357/oh-my-pi/issues/16227))
|
|
19
|
+
|
|
20
|
+
## [18.12.2] - 2026-10-18
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Added `nativeJudgmentImageBounds()`: the image bounds a native judge enforces, its wire's transport limits tightened by the catalog's model bounds
|
|
25
|
+
- Added Box judgment questions (`BoxQuestion`/`BoxAnswer`, TypeSafe Jev 1.14+ direct or through OpenRouter): each names the request image it searches by `image` index, and comes back as that image's edges as 0–1 fractions; text, OpenAI Decisions, and Workers AI judges reject them
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Fixed Muse Code usage going stale whenever its 5-hour window sits idle: the idle window now reports as unused, and weekly usage carries over from the last active window until its reset ([#16193](https://github.com/can1357/oh-my-pi/pull/16193) by [@eggpeat](https://github.com/eggpeat))
|
|
30
|
+
- Fixed DeepSeek tool calls never running when the model writes them as chat-template tokens with `_` in place of `▁`, a missing `|`, or no per-call close (e.g. `<|tool_calls_begin|>…<|tool_calls_end|>`): they now run as tool calls, and any that still cannot be parsed are removed from history and reported to the model as a failed call ([#16216](https://github.com/can1357/oh-my-pi/pull/16216) by [@H4vC](https://github.com/H4vC))
|
|
31
|
+
|
|
5
32
|
## [18.12.1] - 2026-10-17
|
|
6
33
|
|
|
7
34
|
### Fixed
|
|
@@ -2320,26 +2347,4 @@
|
|
|
2320
2347
|
- Fixed OpenAI Responses native history replay leaking image generation provider-only fields into the next request, which made OpenAI-compatible proxies reject `pi` tool-calling sessions with `Unknown parameter: input[1].action`. ([#3201](https://github.com/can1357/oh-my-pi/issues/3201))
|
|
2321
2348
|
- Fixed a stream thought-leakage issue for `gemini-3.5-flash` where the model's internal reasoning JSON could leak into the visible text stream. The stream parser now uses a brace-balanced counting algorithm to accurately slice and discard the leading thought JSON block, with a robust fallback for unescaped double quotes, dynamic tool-name derivation, and preservation of subsequent text deltas without triggering empty-response retries.
|
|
2322
2349
|
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
### Changed
|
|
2326
|
-
|
|
2327
|
-
- Improved JSON robustness by replacing external dependency with a custom, high-performance parser
|
|
2328
|
-
- Strengthened streaming JSON parsing to prevent non-finite numbers from surfacing as `undefined/NaN`
|
|
2329
|
-
- Configured JSON parser to reject JS-specific `NaN` and `Infinity` values for tool arguments
|
|
2330
|
-
- Replaced the JSON repair/parse helpers (`parseJsonWithRepair`, `parseStreamingJson`) with a single from-scratch tolerant parser (`RelaxedJson`) that accepts single-quoted strings, unquoted object keys, trailing/stray commas, `//` and `/* */` comments, Python `True`/`False`/`None`, raw control characters, invalid escapes, and unescaped apostrophes (`'it's'`). Final parsing still throws on truncated/garbage input (so a malformed tool call is skipped rather than executed with half-formed args) and rejects JS-only `NaN`/`Infinity`; streaming parsing stays non-throwing and rolls back incomplete trailing tokens instead of surfacing `undefined`/`NaN`. The Cursor provider's ad-hoc regex + JSON5 tool-argument parser now routes through the shared parser.
|
|
2331
|
-
|
|
2332
|
-
### Fixed
|
|
2333
|
-
|
|
2334
|
-
- Fixed tool call ID normalization for Anthropic-compatible models
|
|
2335
|
-
- Fixed Anthropic Messages replay sanitizing malformed tool-call IDs, including aborted native tool calls with empty IDs, so retries no longer send invalid `tool_use.id` / `tool_result.tool_use_id` pairs.
|
|
2336
|
-
- Fixed the Codex Responses WebSocket transport attributing a prior turn's output to the current one on a reused connection: a trailing/duplicate frame from a cleanly-completed previous response that slipped past the queue drain could be consumed as this request's terminal (ending the turn with empty output) or as a stale tool call. Frames are now keyed by `response.id` — a frame carrying the previous response's id is dropped, and one carrying a third id (or a regressed `sequence_number`) fails closed so the turn retries instead of mixing two responses' streams. Idless frames (deltas, the rate-limit/metadata preamble, `response.created`-less streams) still pass through, matching upstream codex-rs.
|
|
2337
|
-
- Fixed `transformMessages` pulling an earlier, orphaned tool result onto a later tool call that reused the same id (left behind when compaction folded the originating `tool_use` into a summary). The pending-call flush now pairs each call with a result positioned _after_ its assistant turn, so a reused id surfaces its own output rather than a prior turn's.
|
|
2338
|
-
- Fixed DashScope 429 rate-limit messages that mention authorization being classified as credential failures, preventing valid API keys from being invalidated after throttling. ([#3172](https://github.com/can1357/oh-my-pi/issues/3172))
|
|
2339
|
-
- Fixed OpenCode Go `401 Insufficient balance` quota errors being treated as unknown failures instead of usage-limit errors, restoring credential rotation and fallback chains. ([#3169](https://github.com/can1357/oh-my-pi/issues/3169))
|
|
2340
|
-
|
|
2341
|
-
### Removed
|
|
2342
|
-
|
|
2343
|
-
- Removed the `partial-json` dependency; streaming JSON parsing now uses the in-house `RelaxedJson` parser.
|
|
2344
|
-
|
|
2345
|
-
Older entries are archived in [packages/ai/CHANGELOG.md@bb602d67c9b6](https://github.com/can1357/oh-my-pi/blob/bb602d67c9b685535bbf8ef1a1cc9de3c944ede4/packages/ai/CHANGELOG.md).
|
|
2350
|
+
Older entries are archived in [packages/ai/CHANGELOG.md@5eb78e90fa4e](https://github.com/can1357/oh-my-pi/blob/5eb78e90fa4ec4318b9520302f1977fa58c48745/packages/ai/CHANGELOG.md).
|
|
@@ -4,6 +4,19 @@ export declare const DEEPSEEK_TOOL_CALLS_END = "<\uFF5Ctool\u2581calls\u2581end\
|
|
|
4
4
|
export declare const DEEPSEEK_TOOL_CALL_BEGIN = "<\uFF5Ctool\u2581call\u2581begin\uFF5C>";
|
|
5
5
|
export declare const DEEPSEEK_TOOL_CALL_END = "<\uFF5Ctool\u2581call\u2581end\uFF5C>";
|
|
6
6
|
export declare const DEEPSEEK_TOOL_SEPARATOR = "<\uFF5Ctool\u2581sep\uFF5C>";
|
|
7
|
+
/** DeepSeek template tokens that structure a tool call. */
|
|
8
|
+
export declare const DEEPSEEK_TOOL_CALL_TOKENS: Readonly<Record<string, true>>;
|
|
9
|
+
/** A token found in text: its canonical spelling and the text actually written. */
|
|
10
|
+
export interface DeepSeekTokenMatch {
|
|
11
|
+
readonly token: string;
|
|
12
|
+
readonly raw: string;
|
|
13
|
+
readonly index: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Find the earliest of `tokens` in `text` at or after `from`, in its canonical
|
|
17
|
+
* spelling or any re-spelling described at {@link TEMPLATE_TOKEN_SPELLING}.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findDeepSeekTemplateToken(text: string, tokens: Readonly<Record<string, true>>, from?: number): DeepSeekTokenMatch | undefined;
|
|
7
20
|
export declare class DeepSeekInbandScanner implements InbandScanner {
|
|
8
21
|
#private;
|
|
9
22
|
constructor(options?: InbandScannerOptions);
|
|
@@ -41,10 +41,15 @@ export type JudgmentApi = keyof typeof JUDGMENT_WIRES;
|
|
|
41
41
|
export declare function isJudgmentApi(api: Api): api is JudgmentApi;
|
|
42
42
|
/** Whether both the native protocol and catalog model support image input. */
|
|
43
43
|
export declare function nativeJudgmentSupportsImages(model: Model): boolean;
|
|
44
|
+
/** Whether `model`'s native judgment takes images and its wire forwards box questions. The model itself may still refuse them (Box needs Jev 1.14+). */
|
|
45
|
+
export declare function nativeJudgmentSupportsBoxes(model: Model): boolean;
|
|
44
46
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
+
* Every image bound `model`'s native judgment enforces: its wire's transport limits tightened by the
|
|
48
|
+
* catalog's model bounds. `undefined` when it takes no images. Native APIs reject images outside these
|
|
49
|
+
* rather than resizing them, so callers size images to them first.
|
|
47
50
|
*/
|
|
51
|
+
export declare function nativeJudgmentImageBounds(model: Model): JudgmentImageInput | undefined;
|
|
52
|
+
/** Whether `model`'s native judgment API takes these exact images: image support within every {@link nativeJudgmentImageBounds}. */
|
|
48
53
|
export declare function nativeJudgmentAcceptsImages(model: Model, images: readonly ImageContent[]): boolean;
|
|
49
54
|
/**
|
|
50
55
|
* Reject images that `model`'s native judgment API cannot take — no image support, an unsupported or
|
|
@@ -52,6 +57,12 @@ export declare function nativeJudgmentAcceptsImages(model: Model, images: readon
|
|
|
52
57
|
* @throws {AIError.ValidationError} naming the reason.
|
|
53
58
|
*/
|
|
54
59
|
export declare function checkNativeJudgmentImages(model: Model, request: JudgmentRequest, imageAssets?: JudgmentImageAssets): void;
|
|
60
|
+
/**
|
|
61
|
+
* Reject box questions whose `image` is not an index into `request.images`: nothing would say which
|
|
62
|
+
* image their edges measure.
|
|
63
|
+
* @throws {AIError.ValidationError} naming the question.
|
|
64
|
+
*/
|
|
65
|
+
export declare function checkBoxQuestions(request: JudgmentRequest): void;
|
|
55
66
|
/** `TYPESAFE_BASE_URL` when set, else the public API root; trailing slashes stripped. */
|
|
56
67
|
export declare function typesafeBaseUrl(): string;
|
|
57
68
|
/** `TYPESAFE_DEFAULT_MODEL` when set, else {@link TYPESAFE_DEFAULT_MODEL}. */
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* A {@link Judge} answers a map of named questions — {@link ChoiceQuestion}
|
|
5
5
|
* (one option from a fixed set), {@link NoulQuestion} (probability that a
|
|
6
|
-
* yes/no condition holds), {@link ScoreQuestion} (position on ordered levels)
|
|
7
|
-
*
|
|
6
|
+
* yes/no condition holds), {@link ScoreQuestion} (position on ordered levels),
|
|
7
|
+
* {@link BoxQuestion} (where a target is in one of the request's images, native
|
|
8
|
+
* judges only) — about one {@link JudgmentState}. Every question in a request sees the same
|
|
8
9
|
* state and is answered independently, so callers batch independent questions
|
|
9
10
|
* into one call. The shape mirrors TypeSafe's System One API so the native
|
|
10
11
|
* backend ({@link NativeJudge}) forwards requests verbatim, while the text
|
|
@@ -41,7 +42,19 @@ export interface ScoreQuestion {
|
|
|
41
42
|
instructions: string;
|
|
42
43
|
criteria: readonly [string, string, ...string[]];
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Where one target is in an image (TypeSafe Box, Jev 1.14+): https://docs.typesafe.ai/primitives/box.
|
|
47
|
+
* Only native judges answer it. `instructions` must name the target and, among several images, which
|
|
48
|
+
* one to search; `image` stays local and says which entry of {@link JudgmentRequest.images} the
|
|
49
|
+
* answer's edges measure, so a judge that resizes or pads that image can map them back.
|
|
50
|
+
*/
|
|
51
|
+
export interface BoxQuestion {
|
|
52
|
+
type: "box";
|
|
53
|
+
instructions: string;
|
|
54
|
+
/** Index into the request's `images` of the image searched. */
|
|
55
|
+
image: number;
|
|
56
|
+
}
|
|
57
|
+
export type Question = ChoiceQuestion | NoulQuestion | ScoreQuestion | BoxQuestion;
|
|
45
58
|
/** Questions keyed by caller-chosen ids; answers come back under the same ids. */
|
|
46
59
|
export type Questions = Record<string, Question>;
|
|
47
60
|
export interface ChoiceAnswer<L extends string = string> {
|
|
@@ -67,9 +80,23 @@ export interface ScoreAnswer {
|
|
|
67
80
|
/** Concentration of the distribution, 0–1. */
|
|
68
81
|
confidence: number;
|
|
69
82
|
}
|
|
70
|
-
|
|
83
|
+
/** A rectangle's edges as 0–1 fractions of an image's width (`left` < `right`) and height (`top` < `bottom`), from its top-left corner. */
|
|
84
|
+
export interface BoxEdges {
|
|
85
|
+
top: number;
|
|
86
|
+
bottom: number;
|
|
87
|
+
left: number;
|
|
88
|
+
right: number;
|
|
89
|
+
}
|
|
90
|
+
export interface BoxAnswer {
|
|
91
|
+
type: "box";
|
|
92
|
+
/** Smallest rectangle containing the target, on the image the question's `image` names. Always present: absence is a separate yes/no question. */
|
|
93
|
+
box: BoxEdges;
|
|
94
|
+
/** How sure the model is of the box, 0–1. */
|
|
95
|
+
confidence: number;
|
|
96
|
+
}
|
|
97
|
+
export type Answer = ChoiceAnswer | NoulAnswer | ScoreAnswer | BoxAnswer;
|
|
71
98
|
/** The answer type for a question, preserving choice labels. */
|
|
72
|
-
export type AnswerFor<Q extends Question> = Q extends ChoiceQuestion<infer L> ? ChoiceAnswer<L> : Q extends NoulQuestion ? NoulAnswer : ScoreAnswer;
|
|
99
|
+
export type AnswerFor<Q extends Question> = Q extends ChoiceQuestion<infer L> ? ChoiceAnswer<L> : Q extends NoulQuestion ? NoulAnswer : Q extends BoxQuestion ? BoxAnswer : ScoreAnswer;
|
|
73
100
|
export interface JudgmentRequest<Q extends Questions = Questions> {
|
|
74
101
|
state: JudgmentState;
|
|
75
102
|
questions: Q;
|
|
@@ -42,6 +42,8 @@ export interface JudgmentWire {
|
|
|
42
42
|
imagesRequireOptIn?: boolean;
|
|
43
43
|
/** Whether this wire drops per-image detail metadata. */
|
|
44
44
|
ignoresImageDetail?: boolean;
|
|
45
|
+
/** Whether this dialect forwards `box` questions; others reject them before sending. */
|
|
46
|
+
boxes?: boolean;
|
|
45
47
|
/** The response's answers and usage; `undefined` when the payload is not this API's response shape. */
|
|
46
48
|
decode(payload: unknown): DecodedJudgment | undefined;
|
|
47
49
|
}
|
|
@@ -76,6 +76,23 @@ export declare function isThinkingPart(part: Pick<Part, "thought" | "thoughtSign
|
|
|
76
76
|
*/
|
|
77
77
|
export declare function retainThoughtSignature(existing: string | undefined, incoming: string | undefined): string | undefined;
|
|
78
78
|
export declare const SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
|
|
79
|
+
/**
|
|
80
|
+
* Gemini pairs id-less function responses with calls by position. The agent loop stores
|
|
81
|
+
* parallel results in call order, but histories can still arrive out of call order (sessions
|
|
82
|
+
* saved by older versions, contexts built through the SDK), so the converters guard the wire:
|
|
83
|
+
* record each call as it is emitted and each response with its call, then {@link apply} sorts
|
|
84
|
+
* every turn's matched responses back into call order within the slots they already occupy.
|
|
85
|
+
*/
|
|
86
|
+
export declare class FunctionCallOrder {
|
|
87
|
+
#private;
|
|
88
|
+
call(id: string): void;
|
|
89
|
+
/** The call ordinal of `id`, if that call was recorded. */
|
|
90
|
+
ordinal(id: string): number | undefined;
|
|
91
|
+
response(part: Part, callId: string): void;
|
|
92
|
+
apply(contents: readonly {
|
|
93
|
+
parts?: Part[];
|
|
94
|
+
}[]): void;
|
|
95
|
+
}
|
|
79
96
|
/**
|
|
80
97
|
* Convert internal messages to Gemini Content[] format.
|
|
81
98
|
*/
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import type { StreamFunction, StreamOptions, ToolChoice } from "../types.js";
|
|
1
|
+
import type { Model, StreamFunction, StreamOptions, ToolChoice } from "../types.js";
|
|
2
2
|
export interface OllamaChatOptions extends StreamOptions {
|
|
3
3
|
reasoning?: "minimal" | "low" | "medium" | "high" | "xhigh" | "max";
|
|
4
4
|
disableReasoning?: boolean;
|
|
5
5
|
toolChoice?: ToolChoice;
|
|
6
6
|
}
|
|
7
|
+
/** Whether Ollama chat removes assistant thinking from replayed history. */
|
|
8
|
+
export declare function ollamaChatDropsOwnThinking(model: {
|
|
9
|
+
api?: string;
|
|
10
|
+
compat?: Model["compat"];
|
|
11
|
+
} | null | undefined): boolean;
|
|
7
12
|
/** Retry EOS-only Ollama completions before the agent loop sees an empty stop. */
|
|
8
13
|
export declare const streamOllama: StreamFunction<"ollama-chat">;
|
|
@@ -52,6 +52,8 @@ export declare function shouldDropTruncatedThinkingOnlyAssistant(msg: AssistantM
|
|
|
52
52
|
*/
|
|
53
53
|
export declare function isSurvivingAssistant(msg: AssistantMessage, model?: Model): boolean;
|
|
54
54
|
export declare function isAnthropicMessagesModel(model: Model): model is Model<"anthropic-messages">;
|
|
55
|
+
/** Whether `turn` came from `model` itself: its own turns replay their native reasoning unchanged. */
|
|
56
|
+
export declare function isSameModelTurn(turn: Pick<AssistantMessage, "provider" | "api" | "model">, model: Pick<Model, "provider" | "api" | "id">): boolean;
|
|
55
57
|
/**
|
|
56
58
|
* Normalize tool call ID for cross-provider compatibility.
|
|
57
59
|
* OpenAI Responses API generates IDs that are 450+ chars with special characters like `|`.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type UsageProvider } from "../usage.js";
|
|
2
2
|
export declare const museCodeUsageProvider: UsageProvider;
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Removal of DeepSeek
|
|
2
|
+
* Removal of DeepSeek tool-call markup left in visible assistant text.
|
|
3
3
|
*
|
|
4
4
|
* DeepSeek models on OpenAI-compatible hosts sometimes emit their tool calls as
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* runs no healer at all). That markup must not stay
|
|
9
|
-
* teaches the model to keep writing tool calls as text
|
|
10
|
-
* strip it before the message is committed and tell the
|
|
5
|
+
* text in `content`: the V4 `<|DSML|…>` envelope or the V3 chat-template
|
|
6
|
+
* tokens (`<|tool▁calls▁begin|>` …). A well-formed call is healed into a
|
|
7
|
+
* structured call by `StreamMarkupHealing`, but a degraded model can drop
|
|
8
|
+
* required tags (or the host runs no healer at all). That markup must not stay
|
|
9
|
+
* in history: replaying it teaches the model to keep writing tool calls as text
|
|
10
|
+
* (issue #10556). Callers strip it before the message is committed and tell the
|
|
11
|
+
* model its call failed.
|
|
11
12
|
*/
|
|
12
13
|
import type { AssistantMessage, Model } from "../types.js";
|
|
13
14
|
/**
|
|
14
15
|
* Whether DSML leak recovery applies to `model`: a DeepSeek-class model, or one
|
|
15
16
|
* explicitly configured with the `dsml` stream healer (e.g. a `models.yml` entry
|
|
16
|
-
* whose id the classifier cannot place). Other models never write
|
|
17
|
-
* calls, so
|
|
17
|
+
* whose id the classifier cannot place). Other models never write DeepSeek tool
|
|
18
|
+
* calls, so such markup from them is prose and is left alone.
|
|
18
19
|
*/
|
|
19
20
|
export declare function isDsmlLeakRecoveryTarget(model: Model): boolean;
|
|
20
21
|
/**
|
|
21
|
-
* Strip leaked
|
|
22
|
-
* Returns `undefined` when `text` carries
|
|
22
|
+
* Strip leaked DeepSeek tool-call markup (DSML or chat-template tokens) from
|
|
23
|
+
* `text`, leaving quoted code intact. Returns `undefined` when `text` carries
|
|
24
|
+
* no such markup.
|
|
23
25
|
*/
|
|
24
26
|
export declare function stripDsmlToolMarkup(text: string): string | undefined;
|
|
25
27
|
/**
|
|
@@ -85,3 +85,5 @@ export declare function rewriteCopilotError(errorMessage: string, error: unknown
|
|
|
85
85
|
* credential rotation (sibling keys fail identically).
|
|
86
86
|
*/
|
|
87
87
|
export declare function rewriteClinePassError(errorMessage: string, provider: string): string;
|
|
88
|
+
/** Copy of `headers` with every credential value replaced by `[redacted]`; shared by every persisted dump. */
|
|
89
|
+
export declare function redactHeaders<T>(headers: Record<string, T> | undefined): Record<string, T | string> | undefined;
|
|
@@ -19,10 +19,20 @@ import type { Tool, ToolCall } from "../types.js";
|
|
|
19
19
|
* @throws Error if tool is not found or validation fails
|
|
20
20
|
*/
|
|
21
21
|
export declare function validateToolCall(tools: Tool[], toolCall: ToolCall): ToolCall["arguments"];
|
|
22
|
+
/** Options for {@link validateToolArguments}. */
|
|
23
|
+
export interface ValidateToolArgumentsOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Keep unknown root keys on the validated value instead of letting the
|
|
26
|
+
* unrecognized-key repair delete them from a closed schema. Set for tools
|
|
27
|
+
* that own their refusal (`lenientArgValidation`), so execute() can reject
|
|
28
|
+
* fields the model sent rather than run without them.
|
|
29
|
+
*/
|
|
30
|
+
keepUnknownRootKeys?: boolean;
|
|
31
|
+
}
|
|
22
32
|
/**
|
|
23
33
|
* Validates tool call arguments against an ArkType or plain JSON Schema schema.
|
|
24
34
|
* Applies conservative LLM-quirk normalization before declaring failure.
|
|
25
35
|
*
|
|
26
36
|
* @throws Error with a formatted message when validation cannot be reconciled.
|
|
27
37
|
*/
|
|
28
|
-
export declare function validateToolArguments(tool: Tool, toolCall: ToolCall): ToolCall["arguments"];
|
|
38
|
+
export declare function validateToolArguments(tool: Tool, toolCall: ToolCall, options?: ValidateToolArgumentsOptions): ToolCall["arguments"];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-ai",
|
|
3
|
-
"version": "18.12.
|
|
3
|
+
"version": "18.12.3",
|
|
4
4
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -155,11 +155,11 @@
|
|
|
155
155
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
156
156
|
},
|
|
157
157
|
"dependencies": {
|
|
158
|
-
"@oh-my-pi/omptype": "18.12.
|
|
159
|
-
"@oh-my-pi/pi-catalog": "18.12.
|
|
160
|
-
"@oh-my-pi/pi-natives": "18.12.
|
|
161
|
-
"@oh-my-pi/pi-utils": "18.12.
|
|
162
|
-
"@oh-my-pi/pi-wire": "18.12.
|
|
158
|
+
"@oh-my-pi/omptype": "18.12.3",
|
|
159
|
+
"@oh-my-pi/pi-catalog": "18.12.3",
|
|
160
|
+
"@oh-my-pi/pi-natives": "18.12.3",
|
|
161
|
+
"@oh-my-pi/pi-utils": "18.12.3",
|
|
162
|
+
"@oh-my-pi/pi-wire": "18.12.3"
|
|
163
163
|
},
|
|
164
164
|
"devDependencies": {
|
|
165
165
|
"@types/bun": "^1.3.14"
|