@zigai/pi-autoname-session 1.1.4
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 -0
- package/README.md +73 -0
- package/config.schema.json +163 -0
- package/package.json +95 -0
- package/src/index.ts +751 -0
- package/src/picker-request.ts +104 -0
- package/src/session-naming.ts +711 -0
- package/src/settings-input.ts +164 -0
- package/src/settings.prevalidated.ts +31 -0
- package/src/settings.ts +121 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
2
|
+
import { Type, type Static } from "typebox";
|
|
3
|
+
import { Value } from "typebox/value";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Request header that opts a Codex model into the Responses Lite wire
|
|
7
|
+
* contract. Requests carrying it are rejected unless reasoning context is
|
|
8
|
+
* set to "all_turns".
|
|
9
|
+
*/
|
|
10
|
+
const CODEX_RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
|
|
11
|
+
|
|
12
|
+
// Request bodies are in-memory values rather than serialized JSON: pi-ai
|
|
13
|
+
// assigns undefined to absent optional keys (for example prompt_cache_key
|
|
14
|
+
// when no session id is configured) and drops those keys during
|
|
15
|
+
// serialization. The schema mirrors that contract so validation sees the
|
|
16
|
+
// wire-equivalent value instead of discarding valid bodies.
|
|
17
|
+
const jsonValueSchema = Type.Cyclic(
|
|
18
|
+
{
|
|
19
|
+
JsonValue: Type.Union([
|
|
20
|
+
Type.Null(),
|
|
21
|
+
Type.Boolean(),
|
|
22
|
+
Type.Number(),
|
|
23
|
+
Type.String(),
|
|
24
|
+
Type.Undefined(),
|
|
25
|
+
Type.Array(Type.Ref("JsonValue")),
|
|
26
|
+
Type.Record(Type.String(), Type.Ref("JsonValue")),
|
|
27
|
+
]),
|
|
28
|
+
},
|
|
29
|
+
"JsonValue",
|
|
30
|
+
);
|
|
31
|
+
const jsonRecordSchema = Type.Record(Type.String(), jsonValueSchema);
|
|
32
|
+
const pickerPayloadSchema = Type.Refine(jsonRecordSchema, (payload) => {
|
|
33
|
+
try {
|
|
34
|
+
const prototype = Reflect.getPrototypeOf(payload);
|
|
35
|
+
return prototype === Object.prototype || prototype === null;
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const pickerPayloadParser = {
|
|
42
|
+
parse: (Value.Parse<typeof pickerPayloadSchema>).bind(undefined, pickerPayloadSchema),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
type PickerPayload = Static<typeof pickerPayloadSchema>;
|
|
46
|
+
|
|
47
|
+
type LitePickerPayload = PickerPayload & {
|
|
48
|
+
readonly parallel_tool_calls: false;
|
|
49
|
+
readonly reasoning: PickerPayload;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function hasResponsesLiteHeader(headers: Readonly<Record<string, string>> | undefined): boolean {
|
|
53
|
+
if (headers === undefined) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
58
|
+
if (name.trim().toLowerCase() === CODEX_RESPONSES_LITE_HEADER && value.trim() !== "") {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function requiresResponsesLitePayload(
|
|
67
|
+
model: Model<Api>,
|
|
68
|
+
requestHeaders: Readonly<Record<string, string>> | undefined,
|
|
69
|
+
): boolean {
|
|
70
|
+
if (model.provider !== "openai-codex" || model.api !== "openai-codex-responses") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return hasResponsesLiteHeader(requestHeaders) || model.id.toLowerCase().includes("luna");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Return a replacement payload when a picker model requires one, or undefined to keep it. */
|
|
78
|
+
export function preparePickerPayload(
|
|
79
|
+
model: Model<Api>,
|
|
80
|
+
payload: unknown,
|
|
81
|
+
requestHeaders?: Readonly<Record<string, string>>,
|
|
82
|
+
): LitePickerPayload | undefined {
|
|
83
|
+
try {
|
|
84
|
+
const parsedPayload = pickerPayloadParser.parse(payload);
|
|
85
|
+
|
|
86
|
+
if (!requiresResponsesLitePayload(model, requestHeaders)) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const reasoning = Value.Check(jsonRecordSchema, parsedPayload.reasoning)
|
|
91
|
+
? parsedPayload.reasoning
|
|
92
|
+
: {};
|
|
93
|
+
return {
|
|
94
|
+
...parsedPayload,
|
|
95
|
+
parallel_tool_calls: false,
|
|
96
|
+
reasoning: {
|
|
97
|
+
...reasoning,
|
|
98
|
+
context: "all_turns",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
} catch {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
}
|