@qilin-agent/llm 0.0.0-stage → 3.1.3

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.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Centralize the non-secret product identity every provider request sends as `User-Agent`, keeping
3
+ * adapters from drifting. See
4
+ * `.agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md`.
5
+ *
6
+ * App-attribution vocabulary for provider requests.
7
+ * @module @qilin-agent/llm/attribution
8
+ */
9
+ import { createRequire } from 'node:module';
10
+ // The package's own manifest is the single source of the version so the
11
+ // User-Agent cannot drift from what is published (`./package.json` is an
12
+ // export of this package; the relative path resolves from both `src/` and
13
+ // the bundled `lib/`).
14
+ const { version } = createRequire(import.meta.url)('../package.json');
15
+ /**
16
+ * The harness's own identity: the default every adapter sends. Deployments
17
+ * that need a white-label identity pass their own {@link AppIdentity} to
18
+ * {@link attributionHeaders} — omission falls back to this default; nothing
19
+ * can suppress attribution entirely.
20
+ */
21
+ export const APP_IDENTITY = {
22
+ product: 'qilin',
23
+ version,
24
+ url: 'https://github.com/kkutysllb/QiLin',
25
+ };
26
+ /**
27
+ * The standard `User-Agent` value: `product/version (+url)`. The
28
+ * parenthesized `+url` comment is the conventional self-identification form
29
+ * (RFC 9110 §10.1.5 product + comment syntax).
30
+ * @param identity - the identity to render; defaults to {@link APP_IDENTITY}.
31
+ * @returns the ready-to-send header value.
32
+ */
33
+ export function userAgent(identity = APP_IDENTITY) {
34
+ return `${identity.product}/${identity.version} (+${identity.url})`;
35
+ }
36
+ /**
37
+ * Build the attribution headers an adapter must send on every provider
38
+ * request. Header names are lowercase (HTTP field names are case-insensitive
39
+ * on the wire).
40
+ * @param identity - the identity to send; defaults to {@link APP_IDENTITY} — omission cannot suppress attribution.
41
+ * @returns headers to merge into the provider request (currently just `user-agent`).
42
+ */
43
+ export function attributionHeaders(identity = APP_IDENTITY) {
44
+ return { 'user-agent': userAgent(identity) };
45
+ }
46
+ //# sourceMappingURL=attribution.js.map
@@ -0,0 +1,56 @@
1
+ /**
2
+ * qilin-llm's owned branded ids: tool-call correlation and provider request
3
+ * diagnostics.
4
+ *
5
+ * The `Branded<B>` primitive and stateless constructor live in
6
+ * `@qilin-agent/brand` so every owner of a cross-boundary id can brand it
7
+ * without depending on qilin-llm; see that package's README for the
8
+ * nominal-typing policy.
9
+ *
10
+ * @module @qilin-agent/llm/brand
11
+ */
12
+ import { type Branded } from '@qilin-agent/brand';
13
+ /** Stable identity carried by one message across inbox, log, and model-request boundaries. */
14
+ export type MessageId = Branded<'MessageId'>;
15
+ /**
16
+ * Brand a message identifier.
17
+ * @param id - the opaque message identifier.
18
+ * @returns the same string with the message-id brand.
19
+ */
20
+ export declare function MessageId(id: string): MessageId;
21
+ /**
22
+ * Correlates a model-issued tool call with its result. Provider-issued for
23
+ * real adapters; synthesized by mocks/assembler fallbacks.
24
+ */
25
+ export type ToolCallId = Branded<'ToolCallId'>;
26
+ /**
27
+ * Brand a string as a {@link ToolCallId}.
28
+ * @param id - the provider-issued or synthesized call id.
29
+ * @returns the same string with the tool-call-id brand.
30
+ */
31
+ export declare function ToolCallId(id: string): ToolCallId;
32
+ /** Provider-issued request identifier retained for diagnostics across package boundaries. */
33
+ export type ProviderRequestId = Branded<'ProviderRequestId'>;
34
+ /**
35
+ * Brand a provider-issued request identifier.
36
+ * @param id - the opaque provider-issued string.
37
+ * @returns the same string, branded; no validation is performed.
38
+ */
39
+ export declare function ProviderRequestId(id: string): ProviderRequestId;
40
+ /** Identity of one model streaming attempt, unique within one Agent lifecycle. */
41
+ export type LlmAttemptId = Branded<'LlmAttemptId'>;
42
+ /**
43
+ * Brand one loop-owned streaming attempt identifier.
44
+ * @param id - the opaque Agent-lifecycle-local identifier.
45
+ * @returns the same string with the attempt-id brand.
46
+ */
47
+ export declare function LlmAttemptId(id: string): LlmAttemptId;
48
+ /** Adapter-owned identifier for one model's selectable reasoning effort. */
49
+ export type ReasoningEffortId = Branded<'ReasoningEffortId'>;
50
+ /**
51
+ * Brand an adapter-owned reasoning-effort identifier.
52
+ * @param id - the opaque identifier exposed by one model capability.
53
+ * @returns the same string, branded; no validation is performed.
54
+ */
55
+ export declare function ReasoningEffortId(id: string): ReasoningEffortId;
56
+ //# sourceMappingURL=brand.d.ts.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * qilin-llm's owned branded ids: tool-call correlation and provider request
3
+ * diagnostics.
4
+ *
5
+ * The `Branded<B>` primitive and stateless constructor live in
6
+ * `@qilin-agent/brand` so every owner of a cross-boundary id can brand it
7
+ * without depending on qilin-llm; see that package's README for the
8
+ * nominal-typing policy.
9
+ *
10
+ * @module @qilin-agent/llm/brand
11
+ */
12
+ import { brandString } from '@qilin-agent/brand';
13
+ /**
14
+ * Brand a message identifier.
15
+ * @param id - the opaque message identifier.
16
+ * @returns the same string with the message-id brand.
17
+ */
18
+ export function MessageId(id) {
19
+ return brandString(id);
20
+ }
21
+ /**
22
+ * Brand a string as a {@link ToolCallId}.
23
+ * @param id - the provider-issued or synthesized call id.
24
+ * @returns the same string with the tool-call-id brand.
25
+ */
26
+ export function ToolCallId(id) {
27
+ return brandString(id);
28
+ }
29
+ /**
30
+ * Brand a provider-issued request identifier.
31
+ * @param id - the opaque provider-issued string.
32
+ * @returns the same string, branded; no validation is performed.
33
+ */
34
+ export function ProviderRequestId(id) {
35
+ return brandString(id);
36
+ }
37
+ /**
38
+ * Brand one loop-owned streaming attempt identifier.
39
+ * @param id - the opaque Agent-lifecycle-local identifier.
40
+ * @returns the same string with the attempt-id brand.
41
+ */
42
+ export function LlmAttemptId(id) {
43
+ return brandString(id);
44
+ }
45
+ /**
46
+ * Brand an adapter-owned reasoning-effort identifier.
47
+ * @param id - the opaque identifier exposed by one model capability.
48
+ * @returns the same string, branded; no validation is performed.
49
+ */
50
+ export function ReasoningEffortId(id) {
51
+ return brandString(id);
52
+ }
53
+ //# sourceMappingURL=brand.js.map
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Conversation call configuration and freeze utilities. Provider routing,
3
+ * model, reasoning effort, and sampling values are request-header state that
4
+ * can affect cache reuse; request waterfalls replace them and the loop logs
5
+ * changed snapshots instead of allowing silent per-call drift.
6
+ * @module qilin-llm/call-config
7
+ */
8
+ import type { GenerateOptions } from './types.ts';
9
+ import type { ReasoningEffortId } from './brand.ts';
10
+ /**
11
+ * Provider, model, reasoning effort, and sampling scalars of one conversation's
12
+ * requests. Every field maps 1:1 onto the same-named `GenerateOptions` field;
13
+ * the loop builds requests from the logged header rather than accepting these
14
+ * per call.
15
+ */
16
+ export interface LlmCallConfig {
17
+ provider: string;
18
+ model: string;
19
+ reasoningEffort?: ReasoningEffortId;
20
+ temperature?: number;
21
+ maxTokens?: number;
22
+ stop?: string[];
23
+ }
24
+ /**
25
+ * Effective config fields supplied by exact-model adapter resolution rather
26
+ * than by the caller's request proposal.
27
+ */
28
+ export interface LlmCallConfigAdapterDefaults {
29
+ reasoningEffort?: true;
30
+ maxTokens?: true;
31
+ }
32
+ /**
33
+ * Field-wise equality over {@link LlmCallConfig} — the comparison a caller
34
+ * runs to decide whether a proposed configuration is a real change (worth a
35
+ * logged header snapshot) or the held one restated.
36
+ * @param a - one configuration.
37
+ * @param b - the other.
38
+ * @returns whether every field (including the `stop` list, element-wise) matches.
39
+ */
40
+ export declare function callConfigEquals(a: LlmCallConfig, b: LlmCallConfig): boolean;
41
+ /**
42
+ * Mark one exact request object as assembled by qilin-agent-loop.
43
+ * @param request - loop-owned request envelope before LLM dispatch.
44
+ * @returns the same request object marked as created by the process-local agent loop.
45
+ */
46
+ export declare function markAgentLoopRequest<T extends GenerateOptions>(request: T): T;
47
+ /**
48
+ * Test whether the exact request object was assembled by qilin-agent-loop.
49
+ * @param request - request envelope observed at the LLM waterfall.
50
+ * @returns whether {@link markAgentLoopRequest} recorded this object.
51
+ */
52
+ export declare function isAgentLoopRequest(request: GenerateOptions): boolean;
53
+ //# sourceMappingURL=call-config.d.ts.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Conversation call configuration and freeze utilities. Provider routing,
3
+ * model, reasoning effort, and sampling values are request-header state that
4
+ * can affect cache reuse; request waterfalls replace them and the loop logs
5
+ * changed snapshots instead of allowing silent per-call drift.
6
+ * @module qilin-llm/call-config
7
+ */
8
+ /** Process-local identities of request objects assembled by qilin-agent-loop. */
9
+ const AGENT_LOOP_REQUESTS = new WeakSet();
10
+ /**
11
+ * Field-wise equality over {@link LlmCallConfig} — the comparison a caller
12
+ * runs to decide whether a proposed configuration is a real change (worth a
13
+ * logged header snapshot) or the held one restated.
14
+ * @param a - one configuration.
15
+ * @param b - the other.
16
+ * @returns whether every field (including the `stop` list, element-wise) matches.
17
+ */
18
+ export function callConfigEquals(a, b) {
19
+ if (a.provider !== b.provider
20
+ || a.model !== b.model
21
+ || a.reasoningEffort !== b.reasoningEffort
22
+ || a.temperature !== b.temperature
23
+ || a.maxTokens !== b.maxTokens)
24
+ return false;
25
+ if (a.stop === undefined || b.stop === undefined)
26
+ return a.stop === b.stop;
27
+ return a.stop.length === b.stop.length && a.stop.every((s, i) => s === b.stop?.[i]);
28
+ }
29
+ /**
30
+ * Mark one exact request object as assembled by qilin-agent-loop.
31
+ * @param request - loop-owned request envelope before LLM dispatch.
32
+ * @returns the same request object marked as created by the process-local agent loop.
33
+ */
34
+ export function markAgentLoopRequest(request) {
35
+ AGENT_LOOP_REQUESTS.add(request);
36
+ return request;
37
+ }
38
+ /**
39
+ * Test whether the exact request object was assembled by qilin-agent-loop.
40
+ * @param request - request envelope observed at the LLM waterfall.
41
+ * @returns whether {@link markAgentLoopRequest} recorded this object.
42
+ */
43
+ export function isAgentLoopRequest(request) {
44
+ return AGENT_LOOP_REQUESTS.has(request);
45
+ }
46
+ //# sourceMappingURL=call-config.js.map
@@ -0,0 +1,149 @@
1
+ /** Content-block structure helpers. @module @qilin-agent/llm/content */
2
+ import type { ContentBlock, ImageBlock, LlmImageRequestBudget, ToolSchema, ToolUpdate, ToolHistory } from './types.ts';
3
+ import type { RequestMessage } from './types.ts';
4
+ import type { Message } from './message.ts';
5
+ import type { AttachmentStore, FileAttachmentRef, ImageAttachmentRef, RequestImageAttachment } from '@qilin-agent/attachment';
6
+ /** Execution-world path that model tools can use to read one normalized attachment. */
7
+ export interface ImageAttachmentAccess {
8
+ /** Absolute path to immutable normalized bytes; callers must treat it as read-only. */
9
+ readonlyPath: string;
10
+ }
11
+ /**
12
+ * Resolve current execution-world access for one durable image reference.
13
+ * @param ref - durable normalized attachment reference.
14
+ * @returns a read-only execution-world path, or undefined when unavailable.
15
+ */
16
+ export type ImageAttachmentAccessResolver = (ref: ImageAttachmentRef) => ImageAttachmentAccess | undefined;
17
+ /**
18
+ * Bridge one attachment provider's host object location into the mounted
19
+ * tool execution world. The consumer supplies the current filesystem
20
+ * provider's mapping without making attachment or LLM definitions depend on it.
21
+ * @param attachments - provider that owns the normalized attachment object.
22
+ * @param mapHostPath - map one absolute host path into the current tool execution world.
23
+ * @param ref - durable normalized attachment reference.
24
+ * @returns a read-only execution-world path, or undefined when either provider exposes no mapping.
25
+ * @throws an attachment error when the durable reference is invalid.
26
+ */
27
+ export declare function resolveImageAttachmentAccess(attachments: AttachmentStore, mapHostPath: (hostPath: string) => string | undefined, ref: ImageAttachmentRef): ImageAttachmentAccess | undefined;
28
+ /**
29
+ * Stable text shown to a model that cannot accept one durable image reference.
30
+ * @param ref - durable normalized attachment omitted from the request.
31
+ * @returns deterministic text-only placeholder.
32
+ */
33
+ export declare function textOnlyImageText(ref: ImageAttachmentRef): string;
34
+ /**
35
+ * Stable model-facing handle for one exact request image. Identity comes from
36
+ * the occurrence's own durable reference: request versions are prepared per
37
+ * attachment id, so one shared version may serve occurrences whose display
38
+ * names differ.
39
+ * @param ref - the occurrence's durable normalized attachment.
40
+ * @param version - exact request-image dimensions shown beside the text.
41
+ * @param access - optional path resolved for the current tool execution world.
42
+ * @returns attachment handle and request-image dimensions.
43
+ */
44
+ export declare function requestImageHandleText(ref: ImageAttachmentRef, version: Pick<RequestImageAttachment, 'width' | 'height'>, access?: ImageAttachmentAccess): string;
45
+ /**
46
+ * Stable per-image placeholder for a request-limit omission.
47
+ * @param ref - durable normalized attachment omitted from this request.
48
+ * @param access - optional provider-resolved path for model tools.
49
+ * @returns identity, normalized metadata, and the available recovery path.
50
+ */
51
+ export declare function offloadedImageText(ref: ImageAttachmentRef, access?: ImageAttachmentAccess): string;
52
+ /**
53
+ * True when typed model content contains an image block. This is the one image
54
+ * walk shared by every image policy (capability gating, text-only
55
+ * serialization, compaction survey), so a consumer cannot silently diverge.
56
+ * @param content - typed model content blocks.
57
+ * @returns whether any block is an image.
58
+ */
59
+ export declare function contentHasImage(content: readonly ContentBlock[]): boolean;
60
+ /**
61
+ * True when typed model content contains a file block.
62
+ * Reads current content on every call without retaining scan results.
63
+ * @param content - typed model content blocks.
64
+ * @returns whether any block is a file.
65
+ */
66
+ export declare function contentHasFile(content: readonly ContentBlock[]): boolean;
67
+ /**
68
+ * Stable model-facing handle for one durable file reference: the address of
69
+ * the verbatim stored copy and the instruction to read it on demand. This is
70
+ * the only representation a provider ever receives for a file.
71
+ * @param ref - durable verbatim file reference.
72
+ * @param readonlyPath - execution-world path of the stored copy, when resolvable.
73
+ * @returns deterministic handle text naming the file, its size, and its address.
74
+ */
75
+ export declare function fileHandleText(ref: FileAttachmentRef, readonlyPath: string | undefined): string;
76
+ /**
77
+ * Project request file content into deterministic handle text for every model
78
+ * route. Unlike images, no provider receives file blocks natively, so this
79
+ * projection is unconditional in request assembly.
80
+ * @param messages - complete request history.
81
+ * @param resolvePath - resolve one reference's current execution-world read path.
82
+ * @returns the original list without files, otherwise shallow message copies with handle text.
83
+ */
84
+ export declare function projectFilesToText(messages: readonly Message[], resolvePath: (ref: FileAttachmentRef) => string | undefined): readonly Message[];
85
+ /**
86
+ * Project file content in mixed durable and request-only inputs.
87
+ * @param messages - complete request inputs.
88
+ * @param resolvePath - resolve a reference's execution-world read path.
89
+ * @returns original inputs without files, otherwise copies with handle text.
90
+ */
91
+ export declare function projectFilesToText(messages: readonly RequestMessage[], resolvePath: (ref: FileAttachmentRef) => string | undefined): readonly RequestMessage[];
92
+ /**
93
+ * Project the surface's offloaded occurrences into deterministic text for one
94
+ * request. The offloaded set is a durable surface fact, so every route sends
95
+ * the same set; only the placeholder text is route-owned.
96
+ * @param messages - derived request history.
97
+ * @param placeholder - build the model-visible replacement for one offloaded attachment.
98
+ * @returns the original list when nothing is offloaded, otherwise shallow message copies with placeholders.
99
+ */
100
+ export declare function projectOffloadedImages(messages: readonly Message[], placeholder: (ref: ImageAttachmentRef) => string): readonly Message[];
101
+ /**
102
+ * Project offloaded images in mixed durable and request-only inputs.
103
+ * @param messages - complete request inputs.
104
+ * @param placeholder - replacement text for an offloaded attachment.
105
+ * @returns original messages or shallow copies with placeholders.
106
+ */
107
+ export declare function projectOffloadedImages(messages: readonly RequestMessage[], placeholder: (ref: ImageAttachmentRef) => string): readonly RequestMessage[];
108
+ /**
109
+ * Number of oldest retained occurrences a route must still offload before a
110
+ * derived request fits its budget at the exact byte length the route sends;
111
+ * zero when the request fits. A route fails with `IMAGE_OFFLOAD_REQUIRED`
112
+ * carrying this count instead of offloading on its own.
113
+ * @param messages - derived request history carrying the surface's `offloaded` marks.
114
+ * @param budget - route representation, budgets, and removal quanta.
115
+ * @param versionBytes - exact request-version byte length of one retained occurrence.
116
+ * @returns how many more leading retained occurrences to offload.
117
+ */
118
+ export declare function requiredImageOffload(messages: readonly RequestMessage[], budget: Pick<LlmImageRequestBudget, 'representation' | 'maxBytes' | 'maxImages' | 'byteQuantum' | 'countQuantum'>, versionBytes: (block: ImageBlock) => number): number;
119
+ /**
120
+ * Project request image content into deterministic text for an exact text-only model.
121
+ * @param messages - complete request history.
122
+ * @returns the original list without images, otherwise shallow message copies with stable placeholders.
123
+ */
124
+ export declare function projectImagesForTextModel(messages: readonly Message[]): readonly Message[];
125
+ /**
126
+ * Project image content in mixed durable and request-only inputs for a text-only model.
127
+ * @param messages - complete request inputs.
128
+ * @returns original inputs without images, otherwise copies with stable placeholders.
129
+ */
130
+ export declare function projectImagesForTextModel(messages: readonly RequestMessage[]): readonly RequestMessage[];
131
+ /** Request messages and tools after one route's tool update projection. */
132
+ export interface ProjectedToolUpdates {
133
+ /** History with only the developer updates supported by this route and declaration series. */
134
+ readonly messages: readonly RequestMessage[];
135
+ /** Provider declarations, including deferred and retained definitions when supported. */
136
+ readonly tools: readonly ToolSchema[] | undefined;
137
+ }
138
+ /**
139
+ * Construct provider declarations from session-folded history without changing logged active tools.
140
+ * Unsupported routes and incomplete history use current declarations without developer updates.
141
+ * Explicitly deferred baseline tools become available only after their first retained addition.
142
+ * @param messages - complete request inputs, or the prefix selected for an auxiliary call.
143
+ * @param tools - currently active tool schemas.
144
+ * @param toolUpdate - the resolved route's update mode.
145
+ * @param history - immutable state folded from committed headers and developer messages.
146
+ * @returns provider declarations and the corresponding filtered history.
147
+ */
148
+ export declare function projectToolUpdates(messages: readonly RequestMessage[], tools: readonly ToolSchema[] | undefined, toolUpdate: ToolUpdate | undefined, history?: ToolHistory): ProjectedToolUpdates;
149
+ //# sourceMappingURL=content.d.ts.map