@intelligo-dev/chat 1.0.0-beta.13
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 +201 -0
- package/NOTICE +6 -0
- package/README.md +116 -0
- package/dist/artifact-writer.d.ts +45 -0
- package/dist/artifact-writer.d.ts.map +1 -0
- package/dist/artifact-writer.js +77 -0
- package/dist/artifact-writer.js.map +1 -0
- package/dist/attachments.d.ts +56 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +204 -0
- package/dist/attachments.js.map +1 -0
- package/dist/body.d.ts +72 -0
- package/dist/body.d.ts.map +1 -0
- package/dist/body.js +174 -0
- package/dist/body.js.map +1 -0
- package/dist/client.d.ts +65 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +61 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +322 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/feedback.d.ts +22 -0
- package/dist/feedback.d.ts.map +1 -0
- package/dist/feedback.js +46 -0
- package/dist/feedback.js.map +1 -0
- package/dist/generation.d.ts +104 -0
- package/dist/generation.d.ts.map +1 -0
- package/dist/generation.js +85 -0
- package/dist/generation.js.map +1 -0
- package/dist/handler.d.ts +30 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +913 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/messages.d.ts +19 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +34 -0
- package/dist/messages.js.map +1 -0
- package/dist/parts.d.ts +117 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +13 -0
- package/dist/parts.js.map +1 -0
- package/dist/quota.d.ts +32 -0
- package/dist/quota.d.ts.map +1 -0
- package/dist/quota.js +81 -0
- package/dist/quota.js.map +1 -0
- package/dist/share.d.ts +24 -0
- package/dist/share.d.ts.map +1 -0
- package/dist/share.js +78 -0
- package/dist/share.js.map +1 -0
- package/dist/testing.d.ts +36 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +82 -0
- package/dist/testing.js.map +1 -0
- package/dist/title.d.ts +7 -0
- package/dist/title.d.ts.map +1 -0
- package/dist/title.js +15 -0
- package/dist/title.js.map +1 -0
- package/dist/usage.d.ts +21 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +35 -0
- package/dist/usage.js.map +1 -0
- package/dist/windowing.d.ts +38 -0
- package/dist/windowing.d.ts.map +1 -0
- package/dist/windowing.js +82 -0
- package/dist/windowing.js.map +1 -0
- package/package.json +78 -0
- package/src/artifact-writer.ts +114 -0
- package/src/attachments.ts +262 -0
- package/src/body.ts +236 -0
- package/src/client.ts +133 -0
- package/src/config.ts +376 -0
- package/src/errors.ts +80 -0
- package/src/feedback.ts +62 -0
- package/src/generation.ts +150 -0
- package/src/handler.ts +1164 -0
- package/src/index.ts +93 -0
- package/src/messages.ts +39 -0
- package/src/parts.ts +143 -0
- package/src/quota.ts +105 -0
- package/src/share.ts +103 -0
- package/src/testing.ts +150 -0
- package/src/title.ts +15 -0
- package/src/usage.ts +46 -0
- package/src/windowing.ts +110 -0
package/src/windowing.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation windowing: what the model is shown of a long history.
|
|
3
|
+
*
|
|
4
|
+
* Works on `UIMessage`s, the AI SDK's transcript, not stored rows.
|
|
5
|
+
* The default `prepareMessages` applies it; an application that wants
|
|
6
|
+
* to summarise what was pruned does so in its own `prepareMessages`,
|
|
7
|
+
* with its own model, and hands the summary back as `system`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { UIMessage } from "ai";
|
|
11
|
+
|
|
12
|
+
type TextPart = { type: "text"; text: string };
|
|
13
|
+
|
|
14
|
+
function isTextPart(part: unknown): part is TextPart {
|
|
15
|
+
return (
|
|
16
|
+
typeof part === "object" &&
|
|
17
|
+
part !== null &&
|
|
18
|
+
(part as { type?: unknown }).type === "text" &&
|
|
19
|
+
typeof (part as { text?: unknown }).text === "string"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The text parts of a message, joined. Tool and file parts contribute nothing. */
|
|
24
|
+
export function extractText(parts: ReadonlyArray<unknown>): string {
|
|
25
|
+
return parts
|
|
26
|
+
.filter(isTextPart)
|
|
27
|
+
.map((part) => part.text)
|
|
28
|
+
.join(" ");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A cheap token estimate that does not need a tokenizer.
|
|
33
|
+
*
|
|
34
|
+
* Latin text runs about four characters per token; Cyrillic — and
|
|
35
|
+
* most non-Latin scripts — closer to two, because their byte-pair
|
|
36
|
+
* vocabularies are smaller. A single divisor would under-count a
|
|
37
|
+
* Cyrillic transcript by half and window it far too late.
|
|
38
|
+
*/
|
|
39
|
+
export function estimateTokenCount(text: string): number {
|
|
40
|
+
// Stryker disable next-line ConditionalExpression: equivalent — the loop below counts nothing in an empty string and returns 0 either way.
|
|
41
|
+
if (!text) return 0;
|
|
42
|
+
let nonLatin = 0;
|
|
43
|
+
for (const char of text) {
|
|
44
|
+
const code = char.codePointAt(0) ?? 0;
|
|
45
|
+
if (code > 0x024f) nonLatin++;
|
|
46
|
+
}
|
|
47
|
+
const latin = text.length - nonLatin;
|
|
48
|
+
return Math.ceil(latin / 4 + nonLatin / 2);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function estimateConversationTokens(
|
|
52
|
+
messages: ReadonlyArray<UIMessage>
|
|
53
|
+
): number {
|
|
54
|
+
let total = 0;
|
|
55
|
+
for (const message of messages) {
|
|
56
|
+
// Tool payloads are not text but still cost tokens; count their
|
|
57
|
+
// serialised size at the Latin rate.
|
|
58
|
+
for (const part of message.parts) {
|
|
59
|
+
total += isTextPart(part)
|
|
60
|
+
? estimateTokenCount(part.text)
|
|
61
|
+
: Math.ceil(JSON.stringify(part).length / 4);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return total;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type ConversationWindowOptions = {
|
|
68
|
+
/** Keep at most this many non-system messages. */
|
|
69
|
+
maxMessages: number;
|
|
70
|
+
/** Also drop from the front until the estimate fits, when set. */
|
|
71
|
+
maxTokens?: number;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type ConversationWindow = {
|
|
75
|
+
windowed: UIMessage[];
|
|
76
|
+
pruned: UIMessage[];
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Keep the most recent messages, always starting the window on a user
|
|
81
|
+
* turn so the model never sees an assistant reply without the message
|
|
82
|
+
* it answered. System messages are never pruned.
|
|
83
|
+
*/
|
|
84
|
+
export function applyConversationWindow(
|
|
85
|
+
messages: ReadonlyArray<UIMessage>,
|
|
86
|
+
options: ConversationWindowOptions
|
|
87
|
+
): ConversationWindow {
|
|
88
|
+
const system = messages.filter((message) => message.role === "system");
|
|
89
|
+
const turns = messages.filter((message) => message.role !== "system");
|
|
90
|
+
|
|
91
|
+
let start = Math.max(0, turns.length - options.maxMessages);
|
|
92
|
+
// Stryker disable next-line ConditionalExpression: equivalent — with no budget the comparison against undefined is false, so the loop exits on its first test.
|
|
93
|
+
if (options.maxTokens !== undefined) {
|
|
94
|
+
while (
|
|
95
|
+
start < turns.length - 1 &&
|
|
96
|
+
estimateConversationTokens(turns.slice(start)) > options.maxTokens
|
|
97
|
+
) {
|
|
98
|
+
start++;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Open on a user message. If none follows, keep the last turn: a
|
|
102
|
+
// window of nothing is worse than one that opens mid-exchange.
|
|
103
|
+
// Stryker disable next-line OptionalChaining: equivalent — the condition to its left has already proved the index is in range.
|
|
104
|
+
while (start < turns.length - 1 && turns[start]?.role !== "user") start++;
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
windowed: [...system, ...turns.slice(start)],
|
|
108
|
+
pruned: turns.slice(0, start),
|
|
109
|
+
};
|
|
110
|
+
}
|