@cortexkit/pi-anthropic-auth 1.23.0 → 2.0.1
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/README.md +50 -58
- package/dist/commands.d.ts +23 -3
- package/dist/commands.js +58 -252
- package/dist/convert.d.ts +4 -0
- package/dist/convert.js +36 -19
- package/dist/custody.d.ts +2 -6
- package/dist/custody.js +5 -38
- package/dist/index.d.ts +2 -3
- package/dist/index.js +124 -68
- package/dist/native-commands.d.ts +2 -0
- package/dist/native-commands.js +334 -0
- package/dist/native.d.ts +72 -0
- package/dist/native.js +308 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +6 -0
- package/dist/stream.d.ts +17 -3
- package/dist/stream.js +544 -427
- package/dist/transcript.d.ts +19 -0
- package/dist/transcript.js +122 -0
- package/dist/transport.d.ts +5 -0
- package/dist/transport.js +30 -0
- package/package.json +2 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Context, Message, Tool } from '@earendil-works/pi-ai';
|
|
2
|
+
/**
|
|
3
|
+
* A transcript whose prompt and tool set are carried by its leading system
|
|
4
|
+
* message, which is the shape Pi 0.86 hands to providers.
|
|
5
|
+
*/
|
|
6
|
+
export type Transcript = {
|
|
7
|
+
messages: Message[];
|
|
8
|
+
};
|
|
9
|
+
/** Fold `Context.systemPrompt` and `Context.tools` into a leading system message. */
|
|
10
|
+
export declare function normalizeContext(context: Context): Transcript;
|
|
11
|
+
/** Resolve the tools available after applying every transcript delta in order. */
|
|
12
|
+
export declare function getCurrentTools(messages: readonly Message[]): Tool[];
|
|
13
|
+
/** Render the current system prompt text after replaying every system message. */
|
|
14
|
+
export declare function getCurrentSystemPrompt(messages: readonly Message[]): string;
|
|
15
|
+
/**
|
|
16
|
+
* Rebuild the transcript for APIs without mid-conversation system messages: the
|
|
17
|
+
* replayed system message leads, and every later system message is dropped.
|
|
18
|
+
*/
|
|
19
|
+
export declare function collapseSystemMessages(transcript: Transcript): Transcript;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replay a transcript's system messages into one leading prompt and tool set.
|
|
3
|
+
*
|
|
4
|
+
* Ported from pi-ai's `utils/transcript.ts`. Pi 0.86 exports these helpers from
|
|
5
|
+
* its package root; Oh My Pi serves every legacy pi-scope import — including
|
|
6
|
+
* this package's `@earendil-works/pi-ai` — from its own bundled
|
|
7
|
+
* `@oh-my-pi/pi-ai` fork, which has no system-message replay at all. Importing
|
|
8
|
+
* them there threw `Export named 'collapseSystemMessages' not found in module
|
|
9
|
+
* 'omp-legacy-pi-bundled:@oh-my-pi/pi-ai'` while the extension loaded, so no
|
|
10
|
+
* request was ever built. Host types are used for build-time shape only: nothing
|
|
11
|
+
* here imports the host at runtime (see scripts/check-pi-dist-imports.ts).
|
|
12
|
+
*
|
|
13
|
+
* Only `system` messages are read, so a host whose transcript has none — an
|
|
14
|
+
* OMP transcript puts the prompt in `Context.systemPrompt` and has no system
|
|
15
|
+
* role — still resolves to the message built from that prompt and
|
|
16
|
+
* `Context.tools`, which is what that host's own providers send.
|
|
17
|
+
*/
|
|
18
|
+
function contentText(content) {
|
|
19
|
+
if (typeof content === 'string')
|
|
20
|
+
return content;
|
|
21
|
+
return content
|
|
22
|
+
.filter((block) => block.type === 'text')
|
|
23
|
+
.map((block) => block.text)
|
|
24
|
+
.join('\n');
|
|
25
|
+
}
|
|
26
|
+
/** Render a system message as a complete prompt: its content followed by its sections. */
|
|
27
|
+
function systemMessageText(message) {
|
|
28
|
+
const parts = [contentText(message.content)];
|
|
29
|
+
for (const text of Object.values(message.sections ?? {})) {
|
|
30
|
+
if (text !== null)
|
|
31
|
+
parts.push(text);
|
|
32
|
+
}
|
|
33
|
+
return parts.filter((part) => part.length > 0).join('\n\n');
|
|
34
|
+
}
|
|
35
|
+
function isSystemMessage(message) {
|
|
36
|
+
return message.role === 'system';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the leading system message for a prompt and tool set. Returns undefined when
|
|
40
|
+
* both are empty, so an empty transcript stays empty.
|
|
41
|
+
*/
|
|
42
|
+
function createInitialSystemMessage(systemPrompt, tools) {
|
|
43
|
+
const hasSystemPrompt = systemPrompt !== undefined && systemPrompt.length > 0;
|
|
44
|
+
const hasTools = tools !== undefined && tools.length > 0;
|
|
45
|
+
if (!hasSystemPrompt && !hasTools)
|
|
46
|
+
return undefined;
|
|
47
|
+
return {
|
|
48
|
+
role: 'system',
|
|
49
|
+
content: systemPrompt ?? '',
|
|
50
|
+
...(hasTools ? { toolsAdded: tools } : {}),
|
|
51
|
+
timestamp: 0,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Fold `Context.systemPrompt` and `Context.tools` into a leading system message. */
|
|
55
|
+
export function normalizeContext(context) {
|
|
56
|
+
const initialMessage = createInitialSystemMessage(context.systemPrompt, context.tools);
|
|
57
|
+
const messages = initialMessage
|
|
58
|
+
? [initialMessage, ...context.messages]
|
|
59
|
+
: context.messages;
|
|
60
|
+
return { messages };
|
|
61
|
+
}
|
|
62
|
+
/** Resolve the tools available after applying every transcript delta in order. */
|
|
63
|
+
export function getCurrentTools(messages) {
|
|
64
|
+
const tools = new Map();
|
|
65
|
+
for (const message of messages) {
|
|
66
|
+
if (!isSystemMessage(message))
|
|
67
|
+
continue;
|
|
68
|
+
for (const tool of message.toolsRemoved ?? [])
|
|
69
|
+
tools.delete(tool.name);
|
|
70
|
+
for (const tool of message.toolsAdded ?? [])
|
|
71
|
+
tools.set(tool.name, tool);
|
|
72
|
+
}
|
|
73
|
+
return [...tools.values()];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Replay every system message into one leading system message holding the current
|
|
77
|
+
* prompt and tools. Later `content` is appended to the base prompt, `sections` are
|
|
78
|
+
* patched by name, and tools are resolved with {@link getCurrentTools}.
|
|
79
|
+
*/
|
|
80
|
+
function getCurrentSystemMessage(messages) {
|
|
81
|
+
const content = [];
|
|
82
|
+
const sections = new Map();
|
|
83
|
+
let timestamp;
|
|
84
|
+
for (const message of messages) {
|
|
85
|
+
if (!isSystemMessage(message))
|
|
86
|
+
continue;
|
|
87
|
+
timestamp ??= message.timestamp;
|
|
88
|
+
const text = contentText(message.content);
|
|
89
|
+
if (text.length > 0)
|
|
90
|
+
content.push(text);
|
|
91
|
+
for (const [name, value] of Object.entries(message.sections ?? {})) {
|
|
92
|
+
if (value === null)
|
|
93
|
+
sections.delete(name);
|
|
94
|
+
else
|
|
95
|
+
sections.set(name, value);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const tools = getCurrentTools(messages);
|
|
99
|
+
if (timestamp === undefined && tools.length === 0)
|
|
100
|
+
return undefined;
|
|
101
|
+
return {
|
|
102
|
+
role: 'system',
|
|
103
|
+
content: content.join('\n\n'),
|
|
104
|
+
...(sections.size > 0 ? { sections: Object.fromEntries(sections) } : {}),
|
|
105
|
+
...(tools.length > 0 ? { toolsAdded: tools } : {}),
|
|
106
|
+
timestamp: timestamp ?? 0,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Render the current system prompt text after replaying every system message. */
|
|
110
|
+
export function getCurrentSystemPrompt(messages) {
|
|
111
|
+
const message = getCurrentSystemMessage(messages);
|
|
112
|
+
return message ? systemMessageText(message) : '';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Rebuild the transcript for APIs without mid-conversation system messages: the
|
|
116
|
+
* replayed system message leads, and every later system message is dropped.
|
|
117
|
+
*/
|
|
118
|
+
export function collapseSystemMessages(transcript) {
|
|
119
|
+
const head = getCurrentSystemMessage(transcript.messages);
|
|
120
|
+
const messages = transcript.messages.filter((message) => message.role !== 'system');
|
|
121
|
+
return { messages: head ? [head, ...messages] : messages };
|
|
122
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Model base URLs and remembered cache-warm URLs must send OAuth tokens only to Anthropic’s HTTPS server. */
|
|
2
|
+
export declare function requirePiOAuthOrigin(value: string): URL;
|
|
3
|
+
export declare function buildPiOAuthMessagesUrl(baseUrl: string): URL;
|
|
4
|
+
/** Reject redirects rather than letting an approved OAuth destination forward the request. */
|
|
5
|
+
export declare const fetchPiOAuth: typeof fetch;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const ANTHROPIC_ORIGIN = 'https://api.anthropic.com';
|
|
2
|
+
/** Model base URLs and remembered cache-warm URLs must send OAuth tokens only to Anthropic’s HTTPS server. */
|
|
3
|
+
export function requirePiOAuthOrigin(value) {
|
|
4
|
+
let url;
|
|
5
|
+
try {
|
|
6
|
+
url = new URL(value);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
throw new Error('Native OAuth requires the official Anthropic HTTPS origin');
|
|
10
|
+
}
|
|
11
|
+
if (url.protocol !== 'https:' ||
|
|
12
|
+
url.origin !== ANTHROPIC_ORIGIN ||
|
|
13
|
+
url.username ||
|
|
14
|
+
url.password)
|
|
15
|
+
throw new Error('Native OAuth requires the official Anthropic HTTPS origin without URL userinfo');
|
|
16
|
+
return url;
|
|
17
|
+
}
|
|
18
|
+
export function buildPiOAuthMessagesUrl(baseUrl) {
|
|
19
|
+
return new URL('/v1/messages?beta=true', requirePiOAuthOrigin(baseUrl));
|
|
20
|
+
}
|
|
21
|
+
/** Reject redirects rather than letting an approved OAuth destination forward the request. */
|
|
22
|
+
export const fetchPiOAuth = Object.assign(async (input, init) => {
|
|
23
|
+
requirePiOAuthOrigin(input instanceof Request ? input.url : String(input));
|
|
24
|
+
return fetch(input, { ...init, redirect: 'error' });
|
|
25
|
+
}, {
|
|
26
|
+
preconnect: (...args) => {
|
|
27
|
+
requirePiOAuthOrigin(String(args[0]));
|
|
28
|
+
return fetch.preconnect(...args);
|
|
29
|
+
},
|
|
30
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/pi-anthropic-auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepublishOnly": "bun run build"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cortexkit/anthropic-auth-core": "
|
|
39
|
+
"@cortexkit/anthropic-auth-core": "2.0.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@earendil-works/pi-ai": ">=0.86.1",
|