@oh-my-pi/pi-ai 17.4.0 → 17.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 +30 -0
- package/LICENSE +23 -0
- package/THIRD-PARTY-NOTICES.txt +22909 -0
- package/dist/types/auth-retry.d.ts +8 -3
- package/dist/types/auth-storage.d.ts +9 -0
- package/dist/types/dialect/qwen-xml.d.ts +6 -0
- package/dist/types/error/auth-classify.d.ts +8 -8
- package/dist/types/error/oauth.d.ts +2 -1
- package/dist/types/providers/cursor/exec-modern.d.ts +1 -1
- package/dist/types/providers/cursor-pi-args.d.ts +21 -0
- package/dist/types/providers/cursor.d.ts +23 -3
- package/dist/types/providers/google-types.d.ts +6 -0
- package/dist/types/providers/mock.d.ts +3 -1
- package/dist/types/providers/openai-shared.d.ts +6 -1
- package/dist/types/registry/oauth/google-antigravity.d.ts +2 -6
- package/dist/types/registry/oauth/index.d.ts +2 -3
- package/dist/types/registry/oauth/types.d.ts +2 -1
- package/dist/types/registry/oauth/xai-oauth.d.ts +2 -2
- package/dist/types/registry/registry.d.ts +1 -1
- package/dist/types/registry/types.d.ts +2 -1
- package/dist/types/registry/xai-oauth.d.ts +1 -1
- package/dist/types/types.d.ts +21 -0
- package/dist/types/utils/stream-markup-healing.d.ts +1 -1
- package/package.json +8 -6
- package/src/auth-retry.ts +41 -3
- package/src/auth-storage.ts +229 -75
- package/src/dialect/qwen-xml.ts +82 -0
- package/src/error/auth-classify.ts +10 -8
- package/src/error/oauth.ts +2 -1
- package/src/providers/amazon-bedrock.ts +12 -19
- package/src/providers/anthropic.ts +29 -35
- package/src/providers/cursor/exec-modern.ts +2 -0
- package/src/providers/cursor-pi-args.ts +38 -2
- package/src/providers/cursor.ts +357 -32
- package/src/providers/google-shared.ts +11 -12
- package/src/providers/google-types.ts +7 -0
- package/src/providers/mock.ts +4 -1
- package/src/providers/openai-codex-responses.ts +34 -8
- package/src/providers/openai-completions.ts +2 -2
- package/src/providers/openai-shared.ts +72 -14
- package/src/registry/oauth/google-antigravity.ts +247 -162
- package/src/registry/oauth/index.ts +3 -3
- package/src/registry/oauth/types.ts +2 -1
- package/src/registry/oauth/xai-oauth.ts +14 -7
- package/src/registry/types.ts +2 -1
- package/src/registry/xai-oauth.ts +2 -2
- package/src/stream.ts +8 -4
- package/src/types.ts +22 -0
- package/src/utils/schema/CONSTRAINTS.md +1 -0
- package/src/utils/schema/fields.ts +20 -4
- package/src/utils/stream-markup-healing.ts +9 -2
|
@@ -914,7 +914,15 @@ async function resizeAnthropicManyImageContent(
|
|
|
914
914
|
let changed = false;
|
|
915
915
|
const next = await Promise.all(
|
|
916
916
|
content.map(async block => {
|
|
917
|
-
|
|
917
|
+
// Remotely referenced blocks never put base64 on the wire, so their size
|
|
918
|
+
// cannot violate the many-image request budget — and resizing would
|
|
919
|
+
// desync fallback bytes from the advertised remote image.
|
|
920
|
+
if (
|
|
921
|
+
block.type !== "image" ||
|
|
922
|
+
block.url ||
|
|
923
|
+
(block.providerFile?.provider === "anthropic" && block.providerFile.id)
|
|
924
|
+
)
|
|
925
|
+
return block;
|
|
918
926
|
let resized = anthropicManyImageResizeCache.get(block);
|
|
919
927
|
if (resized === undefined) {
|
|
920
928
|
resized = await limit(() => resizeAnthropicManyImageBlock(block));
|
|
@@ -971,19 +979,14 @@ async function prepareAnthropicManyImageContext(context: Context, supportsImages
|
|
|
971
979
|
return { ...context, messages };
|
|
972
980
|
}
|
|
973
981
|
|
|
982
|
+
type AnthropicImageSource =
|
|
983
|
+
| { type: "base64"; media_type: AnthropicImageMediaType; data: string }
|
|
984
|
+
| { type: "url"; url: string }
|
|
985
|
+
| { type: "file"; file_id: string };
|
|
986
|
+
|
|
974
987
|
type AnthropicToolResultContent =
|
|
975
988
|
| string
|
|
976
|
-
| Array<
|
|
977
|
-
| { type: "text"; text: string }
|
|
978
|
-
| {
|
|
979
|
-
type: "image";
|
|
980
|
-
source: {
|
|
981
|
-
type: "base64";
|
|
982
|
-
media_type: AnthropicImageMediaType;
|
|
983
|
-
data: string;
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
>;
|
|
989
|
+
| Array<{ type: "text"; text: string } | { type: "image"; source: AnthropicImageSource }>;
|
|
987
990
|
|
|
988
991
|
/**
|
|
989
992
|
* Convert content blocks to Anthropic API format
|
|
@@ -992,17 +995,7 @@ function convertContentBlocks(
|
|
|
992
995
|
content: (TextContent | ImageContent)[],
|
|
993
996
|
supportsImages = true,
|
|
994
997
|
): AnthropicToolResultContent {
|
|
995
|
-
const blocks: Array<
|
|
996
|
-
| { type: "text"; text: string }
|
|
997
|
-
| {
|
|
998
|
-
type: "image";
|
|
999
|
-
source: {
|
|
1000
|
-
type: "base64";
|
|
1001
|
-
media_type: AnthropicImageMediaType;
|
|
1002
|
-
data: string;
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
> = [];
|
|
998
|
+
const blocks: Array<{ type: "text"; text: string } | { type: "image"; source: AnthropicImageSource }> = [];
|
|
1006
999
|
let sawText = false;
|
|
1007
1000
|
let sawImage = false;
|
|
1008
1001
|
|
|
@@ -1020,21 +1013,22 @@ function convertContentBlocks(
|
|
|
1020
1013
|
continue;
|
|
1021
1014
|
}
|
|
1022
1015
|
|
|
1023
|
-
|
|
1024
|
-
if (
|
|
1025
|
-
|
|
1026
|
-
|
|
1016
|
+
let source: AnthropicImageSource;
|
|
1017
|
+
if (block.providerFile?.provider === "anthropic" && block.providerFile.id) {
|
|
1018
|
+
source = { type: "file", file_id: block.providerFile.id };
|
|
1019
|
+
} else if (block.url) {
|
|
1020
|
+
source = { type: "url", url: block.url };
|
|
1021
|
+
} else {
|
|
1022
|
+
const mediaType = normalizeAnthropicImageMediaType(block.mimeType);
|
|
1023
|
+
if (!mediaType) {
|
|
1024
|
+
blocks.push({ type: "text", text: `[unsupported image: ${block.mimeType}]` });
|
|
1025
|
+
continue;
|
|
1026
|
+
}
|
|
1027
|
+
source = { type: "base64", media_type: mediaType, data: block.data };
|
|
1027
1028
|
}
|
|
1028
1029
|
|
|
1029
1030
|
sawImage = true;
|
|
1030
|
-
blocks.push({
|
|
1031
|
-
type: "image",
|
|
1032
|
-
source: {
|
|
1033
|
-
type: "base64",
|
|
1034
|
-
media_type: mediaType,
|
|
1035
|
-
data: block.data,
|
|
1036
|
-
},
|
|
1037
|
-
});
|
|
1031
|
+
blocks.push({ type: "image", source });
|
|
1038
1032
|
}
|
|
1039
1033
|
|
|
1040
1034
|
if (!supportsImages) {
|
|
@@ -43,8 +43,9 @@ export function piReadPath(readPath: string, offset?: number, limit?: number): s
|
|
|
43
43
|
const start = offset !== undefined ? Math.max(1, Math.floor(offset)) : undefined;
|
|
44
44
|
const count = limit !== undefined ? Math.floor(limit) : undefined;
|
|
45
45
|
if (start === undefined && count === undefined) return readPath;
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
const base = readPath.split(":").some(chunk => chunk.toLowerCase() === "raw") ? readPath : `${readPath}:raw`;
|
|
47
|
+
if (start === undefined) return `${base}:1+${count}`;
|
|
48
|
+
return count === undefined ? `${base}:${start}-` : `${base}:${start}+${count}`;
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
const READ_RANGE_CHUNK_RE = /^L?(\d+)(?:(\.\.|[-+])L?(\d+)?)?$/i;
|
|
@@ -77,6 +78,41 @@ export function piReadPathHasRange(readPath: string): boolean {
|
|
|
77
78
|
return preceding !== undefined && isReadRangeList(preceding);
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Force a Cursor exec read onto `read`'s verbatim `:raw` selector.
|
|
83
|
+
*
|
|
84
|
+
* Native `editToolCall` (StrReplace) materializes via `readArgs` then
|
|
85
|
+
* `writeArgs`. The server treats the read result as file bytes and writes
|
|
86
|
+
* them back. A hashline-formatted native read (`[path#TAG]` + `LINE:`
|
|
87
|
+
* prefixes) poisons that cycle: the write would persist the markup.
|
|
88
|
+
* `:raw` is the existing selector that drops both. A path that already
|
|
89
|
+
* carries `raw` is left alone; a range-only selector gets `raw` inserted
|
|
90
|
+
* so the range still applies without the gutter.
|
|
91
|
+
*/
|
|
92
|
+
export function cursorRawReadPath(readPath: string): string {
|
|
93
|
+
const chunks = readPath.split(":");
|
|
94
|
+
if (chunks.some(chunk => chunk.toLowerCase() === "raw")) return readPath;
|
|
95
|
+
if (piReadPathHasRange(readPath)) {
|
|
96
|
+
const last = chunks.pop()!;
|
|
97
|
+
return `${chunks.join(":")}:raw:${last}`;
|
|
98
|
+
}
|
|
99
|
+
return `${readPath}:raw`;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Path the edit-owned materialization read should execute.
|
|
104
|
+
*
|
|
105
|
+
* Range is composed first (`piReadPath` already uses `:raw` for a range),
|
|
106
|
+
* then a whole-file path is forced onto `:raw`. The caller must drop
|
|
107
|
+
* `offset`/`limit` after this so the bridge's `piReadPath` cannot append a
|
|
108
|
+
* second `:raw` onto the already-composed selector.
|
|
109
|
+
*/
|
|
110
|
+
export function cursorEditOwnedReadPath(readPath: string, offset?: number, limit?: number): string | null {
|
|
111
|
+
const ranged = piReadPath(readPath, offset, limit);
|
|
112
|
+
if (ranged === null) return null;
|
|
113
|
+
return cursorRawReadPath(ranged);
|
|
114
|
+
}
|
|
115
|
+
|
|
80
116
|
/**
|
|
81
117
|
* The same range as {@link piReadPath}, rendered for a transcript block rather
|
|
82
118
|
* than for execution.
|