pi-openai-toolkit 0.20.7 → 0.21.0
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/LICENSE +21 -21
- package/NOTICE +83 -83
- package/README.md +8 -26
- package/README.zh.md +8 -26
- package/config.schema.json +278 -366
- package/docs/configuration.md +294 -310
- package/docs/internals.md +166 -175
- package/package.json +3 -13
- package/src/compact-client.ts +412 -389
- package/src/compaction-errors.ts +96 -0
- package/src/compaction-projection.ts +35 -35
- package/src/config/legacy.ts +519 -717
- package/src/config/migration.ts +103 -100
- package/src/config/notifications.ts +36 -28
- package/src/config/policy.ts +10 -18
- package/src/config/v2.ts +1167 -1380
- package/src/config.ts +310 -319
- package/src/context-management/codex-provider.ts +270 -270
- package/src/context-management/history-notes.ts +357 -357
- package/src/context-management/manual-compact.ts +0 -11
- package/src/context-management/tools.ts +371 -371
- package/src/context-management/types.ts +168 -168
- package/src/context-management/window-manager.ts +801 -801
- package/src/debug.ts +238 -237
- package/src/deferred-tool-carryover.ts +282 -282
- package/src/details-store.ts +151 -151
- package/src/extension-runtime.ts +1662 -1623
- package/src/image-generation/extension.ts +189 -189
- package/src/image-generation/protocol.ts +579 -579
- package/src/image-generation/types.ts +300 -300
- package/src/native-fallback.ts +4 -132
- package/src/payload-rewrite.ts +515 -518
- package/src/pi-context-hook.ts +117 -117
- package/src/remote-v2-client.ts +811 -814
- package/src/request-context-cache.ts +155 -155
- package/src/responses-headers.ts +180 -180
- package/src/runtime.ts +865 -832
- package/src/serializer.ts +882 -882
- package/src/supported-environment.ts +27 -27
- package/src/types.ts +565 -648
- package/src/web-search/alpha-client.ts +876 -876
- package/src/web-search/extension.ts +530 -530
- package/src/web-search/payload.ts +299 -299
- package/src/web-search/prompt.ts +60 -60
- package/src/web-search/types.ts +166 -166
- package/tsconfig.check.json +50 -54
- package/src/auto-mode/classifier.ts +0 -161
- package/src/auto-mode/extension.ts +0 -691
- package/src/auto-mode/model-selection-guard.ts +0 -52
- package/src/auto-mode/policy.ts +0 -146
- package/src/auto-mode/prompt.ts +0 -279
- package/src/auto-mode/reviewer.ts +0 -325
- package/src/auto-mode/tool-review-tui.ts +0 -211
- package/src/auto-mode/transcript.ts +0 -135
- package/src/auto-mode/types.ts +0 -137
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/** Content-free diagnostics shared by the compaction HTTP/stream boundaries. */
|
|
2
|
+
export type CompactionErrorInfo = {
|
|
3
|
+
errorCode?: string;
|
|
4
|
+
errorType?: string;
|
|
5
|
+
errorParam?: string;
|
|
6
|
+
/** Controlled text, never a provider-authored message. */
|
|
7
|
+
errorMessage?: string;
|
|
8
|
+
errorCategory?: "auth" | "quota" | "protocol";
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const HINTS: Record<string, string> = {
|
|
12
|
+
subscription_sharing_unsupported_capability: "This OpenAI subscription-sharing grant does not authorize compaction. Use a separately authenticated supported API-key or native Codex route; credentials are not interchangeable.",
|
|
13
|
+
hardened_oauth_rule_missing: "This OAuth grant does not authorize this operation. Select a separately authenticated supported route; Toolkit will not switch credentials.",
|
|
14
|
+
rejected_by_hardened_oauth_boundary: "This OAuth grant does not authorize this operation. Select a separately authenticated supported route; Toolkit will not switch credentials.",
|
|
15
|
+
missing_scope: "The credential lacks the required Responses authorization scope. Authenticate the intended route separately.",
|
|
16
|
+
invalid_api_key: "The selected route rejected its credential. Check authentication for that route.",
|
|
17
|
+
insufficient_quota: "The selected route has insufficient quota. Check its billing and quota.",
|
|
18
|
+
rate_limit_exceeded: "The selected route is rate limited. Retry later.",
|
|
19
|
+
unsupported_capability: "The endpoint does not support the requested compaction protocol.",
|
|
20
|
+
unsupported_compaction: "The endpoint does not support the requested compaction protocol.",
|
|
21
|
+
unsupported_protocol: "The endpoint does not support the requested compaction protocol.",
|
|
22
|
+
unsupported_parameter: "The endpoint rejected a compaction request parameter.",
|
|
23
|
+
unknown_parameter: "The endpoint rejected a compaction request parameter.",
|
|
24
|
+
invalid_request_error: "The endpoint rejected the compaction request.",
|
|
25
|
+
};
|
|
26
|
+
const PROTOCOL_CODES = new Set(["unsupported_capability", "unsupported_compaction", "unsupported_protocol", "unsupported_parameter", "unknown_parameter"]);
|
|
27
|
+
const SAFE_TYPES = new Set(["invalid_request_error", "authentication_error", "permission_error", "rate_limit_error", "insufficient_quota", "server_error"]);
|
|
28
|
+
const SAFE_PARAMS = new Set(["input", "model", "compaction_trigger", "stream", "store", "tools", "instructions", "reasoning", "text"]);
|
|
29
|
+
|
|
30
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
31
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function decodeCompactionError(value: unknown): CompactionErrorInfo {
|
|
35
|
+
if (!isRecord(value)) return {};
|
|
36
|
+
const source = isRecord(value.error) ? value.error
|
|
37
|
+
: isRecord(value.response) && isRecord(value.response.error) ? value.response.error : value;
|
|
38
|
+
// Unknown identifiers may themselves contain secrets. Only public vocabulary
|
|
39
|
+
// is emitted; classification can conservatively exclude an unknown auth code.
|
|
40
|
+
const code = typeof source.code === "string" && source.code.length <= 128 ? source.code : undefined;
|
|
41
|
+
const type = typeof source.type === "string" && source.type.length <= 128 ? source.type : undefined;
|
|
42
|
+
const excluded = [code, type].filter((item): item is string => !!item).join(" ");
|
|
43
|
+
const missingScope = typeof source.message === "string" && source.message.length <= 4096 && /missing (?:required )?scopes?\b/i.test(source.message);
|
|
44
|
+
const errorCategory = missingScope || /auth|oauth|permission|subscription|scope|access_denied|forbidden|api_key|token|credential|invalid_grant/i.test(excluded) ? "auth"
|
|
45
|
+
: /quota|billing|rate_limit|too_many_requests/i.test(excluded) ? "quota"
|
|
46
|
+
: code && PROTOCOL_CODES.has(code) ? "protocol" : undefined;
|
|
47
|
+
const errorCode = code && Object.hasOwn(HINTS, code) ? code : undefined;
|
|
48
|
+
return {
|
|
49
|
+
...(errorCode ? { errorCode } : {}),
|
|
50
|
+
...(type && SAFE_TYPES.has(type) ? { errorType: type } : {}),
|
|
51
|
+
...(typeof source.param === "string" && SAFE_PARAMS.has(source.param) ? { errorParam: source.param } : {}),
|
|
52
|
+
...(missingScope ? { errorMessage: HINTS.missing_scope } : errorCode ? { errorMessage: HINTS[errorCode] } : {}),
|
|
53
|
+
...(errorCategory ? { errorCategory } : {}),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** One protocol probe, not a transport/auth retry. Unknown failures fail closed. */
|
|
58
|
+
export function qualifiesForStandaloneCompaction(failure: CompactionErrorInfo & { reason: string; status?: number }): boolean {
|
|
59
|
+
if (failure.errorCategory === "auth" || failure.errorCategory === "quota") return false;
|
|
60
|
+
if (failure.reason === "non-2xx") return [400, 404, 405, 422, 501].includes(failure.status ?? 0);
|
|
61
|
+
if (failure.reason === "error-event") return failure.errorCategory === "protocol";
|
|
62
|
+
return failure.status !== undefined && failure.status >= 200 && failure.status < 300 && [
|
|
63
|
+
"empty-body", "invalid-sse", "missing-completed-event", "incomplete-response",
|
|
64
|
+
"invalid-compaction-count", "malformed-compaction-item", "conflicting-compaction-item",
|
|
65
|
+
"invalid-compaction-metadata", "invalid-event-order", "duplicate-completed-event",
|
|
66
|
+
].includes(failure.reason);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Body collection must be cancellable even with a stalled mocked/custom transport. */
|
|
70
|
+
export async function readCompactionResponseText(response: Response, signal?: AbortSignal): Promise<string> {
|
|
71
|
+
if (signal?.aborted) throw new DOMException("Compaction aborted", "AbortError");
|
|
72
|
+
const reader = response.body?.getReader();
|
|
73
|
+
if (!reader) return "";
|
|
74
|
+
const decoder = new TextDecoder();
|
|
75
|
+
const parts: string[] = [];
|
|
76
|
+
let onAbort: (() => void) | undefined;
|
|
77
|
+
const aborted = new Promise<never>((_resolve, reject) => {
|
|
78
|
+
onAbort = () => reject(new DOMException("Compaction aborted", "AbortError"));
|
|
79
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
while (true) {
|
|
83
|
+
if (signal?.aborted) throw new DOMException("Compaction aborted", "AbortError");
|
|
84
|
+
const chunk = await Promise.race([reader.read(), aborted]);
|
|
85
|
+
if (signal?.aborted) throw new DOMException("Compaction aborted", "AbortError");
|
|
86
|
+
parts.push(chunk.done ? decoder.decode() : decoder.decode(chunk.value, { stream: true }));
|
|
87
|
+
if (chunk.done) return parts.join("");
|
|
88
|
+
}
|
|
89
|
+
} finally {
|
|
90
|
+
if (onAbort) signal?.removeEventListener("abort", onAbort);
|
|
91
|
+
// Abort/completion never waits for transport cleanup. Cancel the reader,
|
|
92
|
+
// not the locked body, and observe late rejection before releasing it.
|
|
93
|
+
try { void reader.cancel().catch(() => undefined); } catch { /* Custom transport cleanup. */ }
|
|
94
|
+
finally { try { reader.releaseLock(); } catch { /* Preserve the operation outcome. */ } }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
NativeCompactionDetails,
|
|
3
|
-
NativeCompactionInputProvenance,
|
|
4
|
-
} from "./types";
|
|
5
|
-
|
|
6
|
-
/** The configured Pi context-hook projector is unavailable or failed. */
|
|
7
|
-
export const COMPACTION_PROJECTION_UNAVAILABLE = "no-supported-projection-seam" as const;
|
|
8
|
-
/** The current session context could not be read before projection. */
|
|
9
|
-
export const COMPACTION_SESSION_CONTEXT_UNAVAILABLE = "session-context-unavailable" as const;
|
|
10
|
-
/** A projected recursive context did not contain the current compaction summary. */
|
|
11
|
-
export const COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE = "projected-compaction-context-unavailable" as const;
|
|
12
|
-
/** The latest opaque checkpoint was created with no or a different input marker. */
|
|
13
|
-
export const COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE = "unverified-compaction-checkpoint" as const;
|
|
14
|
-
|
|
15
|
-
/** Persisted edits changed input already sealed inside an opaque checkpoint. */
|
|
16
|
-
export const COMPACTION_CHECKPOINT_CONTEXT_EDITED = "checkpoint-context-edited" as const;
|
|
17
|
-
|
|
18
|
-
export type UnprojectedCompactionReason =
|
|
19
|
-
| typeof COMPACTION_CHECKPOINT_CONTEXT_EDITED
|
|
20
|
-
| typeof COMPACTION_PROJECTION_UNAVAILABLE
|
|
21
|
-
| typeof COMPACTION_SESSION_CONTEXT_UNAVAILABLE
|
|
22
|
-
| typeof COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE
|
|
23
|
-
| typeof COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* A Remote V2 checkpoint is safe for the current replay chain only when its
|
|
27
|
-
* marker matches the configured input source. Structural persistence validation
|
|
28
|
-
* intentionally remains more permissive for old session files.
|
|
29
|
-
*/
|
|
30
|
-
export function hasVerifiedCompactionInputProvenance(
|
|
31
|
-
details: Pick<NativeCompactionDetails, "inputProvenance"> | undefined,
|
|
32
|
-
expected: NativeCompactionInputProvenance,
|
|
33
|
-
): boolean {
|
|
34
|
-
return details?.inputProvenance === expected;
|
|
35
|
-
}
|
|
1
|
+
import type {
|
|
2
|
+
NativeCompactionDetails,
|
|
3
|
+
NativeCompactionInputProvenance,
|
|
4
|
+
} from "./types";
|
|
5
|
+
|
|
6
|
+
/** The configured Pi context-hook projector is unavailable or failed. */
|
|
7
|
+
export const COMPACTION_PROJECTION_UNAVAILABLE = "no-supported-projection-seam" as const;
|
|
8
|
+
/** The current session context could not be read before projection. */
|
|
9
|
+
export const COMPACTION_SESSION_CONTEXT_UNAVAILABLE = "session-context-unavailable" as const;
|
|
10
|
+
/** A projected recursive context did not contain the current compaction summary. */
|
|
11
|
+
export const COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE = "projected-compaction-context-unavailable" as const;
|
|
12
|
+
/** The latest opaque checkpoint was created with no or a different input marker. */
|
|
13
|
+
export const COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE = "unverified-compaction-checkpoint" as const;
|
|
14
|
+
|
|
15
|
+
/** Persisted edits changed input already sealed inside an opaque checkpoint. */
|
|
16
|
+
export const COMPACTION_CHECKPOINT_CONTEXT_EDITED = "checkpoint-context-edited" as const;
|
|
17
|
+
|
|
18
|
+
export type UnprojectedCompactionReason =
|
|
19
|
+
| typeof COMPACTION_CHECKPOINT_CONTEXT_EDITED
|
|
20
|
+
| typeof COMPACTION_PROJECTION_UNAVAILABLE
|
|
21
|
+
| typeof COMPACTION_SESSION_CONTEXT_UNAVAILABLE
|
|
22
|
+
| typeof COMPACTION_CHECKPOINT_PROVENANCE_UNAVAILABLE
|
|
23
|
+
| typeof COMPACTION_PROJECTED_CONTEXT_UNAVAILABLE;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A Remote V2 checkpoint is safe for the current replay chain only when its
|
|
27
|
+
* marker matches the configured input source. Structural persistence validation
|
|
28
|
+
* intentionally remains more permissive for old session files.
|
|
29
|
+
*/
|
|
30
|
+
export function hasVerifiedCompactionInputProvenance(
|
|
31
|
+
details: Pick<NativeCompactionDetails, "inputProvenance"> | undefined,
|
|
32
|
+
expected: NativeCompactionInputProvenance,
|
|
33
|
+
): boolean {
|
|
34
|
+
return details?.inputProvenance === expected;
|
|
35
|
+
}
|