@daihum/ai-model-contracts 0.1.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/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # @daihum/ai-model-contracts
2
+
3
+ Pure, serializable **model-operation payload contracts** for DAIHUM AI. The stable
4
+ vocabulary leaf: zero dependencies, no behavior, no environment assumptions.
5
+
6
+ Subpaths: `./chat`, `./embedding`, `./candidate-rank`, `./tools`, `./usage`,
7
+ `./embedding-compat`. Prefer subpath imports over the root barrel.
8
+
9
+ ## What this package is NOT
10
+
11
+ By rule (boundary gate R1/R7/R8) it carries **only** model I/O. It must never grow:
12
+
13
+ - `routePlan` or any routing/provider-selection structure — that lives in
14
+ `@daihum/ai-routing`, which lowers a route plan into resolved
15
+ `providerId`/`modelId`/`routeId` + a provider call context.
16
+ - execution/authority context (workspaceId, actorId, dataClass, …) — that travels
17
+ in the provider call context (`@daihum/ai-provider-contracts`), never in a payload.
18
+ - provider registries/interfaces/errors — `@daihum/ai-provider-contracts`.
19
+ - secrets, catalog, pricing, cost, audit, config, runtime code, fetch/fs, RAG hits.
20
+
21
+ Test: these types should be copy-pasteable into another repo as plain TypeScript
22
+ without bringing behavior, environment, provider knowledge, or product assumptions.
23
+
24
+ ## candidate-rank vs rerank
25
+
26
+ `candidate-rank` is the **model-level** ranking op (query + candidate texts → ids/
27
+ order/scores), a peer of chat/embedding. The word **rerank** is reserved for the
28
+ RAG pipeline stage in `@daihum/ai-rag`. Candidates are `{ candidateId, text }` only
29
+ (no metadata backdoor); result `score` is optional (`scoreKind` documents its origin).
@@ -0,0 +1,65 @@
1
+ import { t as DaihumAiUsage } from "./usage-Db6aaBEO.js";
2
+
3
+ //#region src/candidate-rank.d.ts
4
+
5
+ /**
6
+ * Model-level candidate ranking (renamed from the former "rerank" model op;
7
+ * "rerank" is reserved for the RAG pipeline stage in @daihum/ai-rag).
8
+ *
9
+ * Operation shape: query + candidate texts -> candidate ids / order / scores.
10
+ * This is a peer of chat and embedding, NOT an optimization of chat — some
11
+ * runtimes serve it natively (e.g. an OpenRouter /rerank endpoint), others via
12
+ * a candidate-rank-from-chat adapter (@daihum/ai-candidate-rank-adapters).
13
+ */
14
+ /**
15
+ * A candidate to rank. Model-visible payload ONLY: an opaque id + the text the
16
+ * model sees. Deliberately has NO `metadata?: unknown` — that would be a
17
+ * fat-envelope backdoor for hydrated hits / provenance / authority / secrets.
18
+ * Callers map their own source ids through *ephemeral* candidateIds.
19
+ */
20
+ interface DaihumAiCandidateRankCandidate {
21
+ readonly candidateId: string;
22
+ readonly text: string;
23
+ }
24
+ interface DaihumAiCandidateRankRequest {
25
+ readonly requestId?: string;
26
+ readonly providerId?: string;
27
+ readonly modelId?: string;
28
+ readonly routeId?: string;
29
+ readonly query: string;
30
+ readonly candidates: readonly DaihumAiCandidateRankCandidate[];
31
+ /** If set, the response MAY be partial (top-K). Omitted candidates are not errors. */
32
+ readonly topK?: number;
33
+ readonly signal?: AbortSignal;
34
+ readonly metadata?: Readonly<Record<string, unknown>>;
35
+ }
36
+ /** Where a result's score came from. A chat-prompted ranker can order reliably
37
+ * but cannot calibrate a score; in that case `score` is omitted (rank is
38
+ * authoritative) and the RAG blend stage derives a score from rank. */
39
+ type DaihumAiCandidateRankScoreKind = "provider" | "normalized" | "rank-derived";
40
+ interface DaihumAiCandidateRankResult {
41
+ readonly candidateId: string;
42
+ /** 1-based, unique within the response. Response order SHOULD match rank ascending. */
43
+ readonly rank: number;
44
+ /** Optional on purpose — see DaihumAiCandidateRankScoreKind. */
45
+ readonly score?: number;
46
+ readonly scoreKind?: DaihumAiCandidateRankScoreKind;
47
+ }
48
+ interface DaihumAiCandidateRankWarning {
49
+ readonly code: string;
50
+ readonly message?: string;
51
+ readonly candidateId?: string;
52
+ }
53
+ interface DaihumAiCandidateRankResponse {
54
+ readonly providerId: string;
55
+ readonly modelId: string;
56
+ readonly routeId?: string;
57
+ readonly results: readonly DaihumAiCandidateRankResult[];
58
+ readonly usage?: DaihumAiUsage;
59
+ readonly warnings?: readonly DaihumAiCandidateRankWarning[];
60
+ readonly rawResponse?: unknown;
61
+ readonly metadata?: Readonly<Record<string, unknown>>;
62
+ }
63
+ //#endregion
64
+ export { DaihumAiCandidateRankScoreKind as a, DaihumAiCandidateRankResult as i, DaihumAiCandidateRankRequest as n, DaihumAiCandidateRankWarning as o, DaihumAiCandidateRankResponse as r, DaihumAiCandidateRankCandidate as t };
65
+ //# sourceMappingURL=candidate-rank-CFpxmTMM.d.ts.map
File without changes
@@ -0,0 +1,3 @@
1
+ import "./usage-Db6aaBEO.js";
2
+ import { a as DaihumAiCandidateRankScoreKind, i as DaihumAiCandidateRankResult, n as DaihumAiCandidateRankRequest, o as DaihumAiCandidateRankWarning, r as DaihumAiCandidateRankResponse, t as DaihumAiCandidateRankCandidate } from "./candidate-rank-CFpxmTMM.js";
3
+ export { DaihumAiCandidateRankCandidate, DaihumAiCandidateRankRequest, DaihumAiCandidateRankResponse, DaihumAiCandidateRankResult, DaihumAiCandidateRankScoreKind, DaihumAiCandidateRankWarning };
@@ -0,0 +1 @@
1
+ import "./candidate-rank-DYi3Kcdp.js";
File without changes
@@ -0,0 +1,116 @@
1
+ import { t as DaihumAiUsage } from "./usage-Db6aaBEO.js";
2
+ import { a as DaihumAiToolDefinition, i as DaihumAiToolChoice, n as DaihumAiPartialToolCall, r as DaihumAiToolCall } from "./tools-VkZPo3Sc.js";
3
+
4
+ //#region src/chat.d.ts
5
+ type DaihumAiMessageRole = "system" | "user" | "assistant" | "tool";
6
+ interface DaihumAiTextPart {
7
+ readonly type: "text";
8
+ readonly text: string;
9
+ }
10
+ interface DaihumAiImagePart {
11
+ readonly type: "image";
12
+ readonly image: string | URL | Uint8Array | ArrayBuffer;
13
+ readonly mediaType?: string;
14
+ }
15
+ interface DaihumAiJsonPart {
16
+ readonly type: "json";
17
+ readonly value: unknown;
18
+ }
19
+ type DaihumAiContentPart = DaihumAiTextPart | DaihumAiImagePart | DaihumAiJsonPart | (Readonly<Record<string, unknown>> & {
20
+ readonly type: string;
21
+ });
22
+ interface DaihumAiMessage {
23
+ readonly role: DaihumAiMessageRole;
24
+ readonly content?: string | readonly DaihumAiContentPart[];
25
+ readonly name?: string;
26
+ readonly toolCallId?: string;
27
+ readonly toolCalls?: readonly DaihumAiToolCall[];
28
+ readonly metadata?: Readonly<Record<string, unknown>>;
29
+ }
30
+ type DaihumAiFinishReason = "stop" | "length" | "tool-calls" | "content-filter" | "error" | "unknown" | (string & {});
31
+ /** Recommended shape for DaihumAiChatRequest.responseFormat (the field stays
32
+ * `unknown` for adapter flexibility; adapters narrow against this). */
33
+ type DaihumAiResponseFormat = Readonly<{
34
+ kind: "text";
35
+ }> | Readonly<{
36
+ kind: "json";
37
+ }> | Readonly<{
38
+ kind: "json-schema";
39
+ name?: string;
40
+ strict?: boolean;
41
+ schema: Readonly<Record<string, unknown>>;
42
+ }>;
43
+ /**
44
+ * Pure chat model-operation payload. Carries model I/O only.
45
+ *
46
+ * NOT present (by design — these are NOT model payload):
47
+ * - routePlan -> routing concern; @daihum/ai-routing lowers a route plan into
48
+ * providerId/modelId/routeId (resolved below) + a provider call context.
49
+ * - execution context (workspaceId/actorId/dataClass/...) -> product authority;
50
+ * travels in the provider call context (@daihum/ai-provider-contracts), never here.
51
+ *
52
+ * providerId/modelId/routeId are the *already-resolved* execution target hints
53
+ * (populated by routing before the call), not a route plan.
54
+ */
55
+ interface DaihumAiChatRequest {
56
+ readonly requestId?: string;
57
+ readonly providerId?: string;
58
+ readonly modelId?: string;
59
+ readonly routeId?: string;
60
+ readonly messages: readonly DaihumAiMessage[];
61
+ readonly tools?: readonly DaihumAiToolDefinition[];
62
+ readonly toolChoice?: DaihumAiToolChoice;
63
+ readonly temperature?: number;
64
+ readonly topP?: number;
65
+ readonly maxOutputTokens?: number;
66
+ readonly reasoningBudget?: number;
67
+ readonly seed?: number;
68
+ readonly frequencyPenalty?: number;
69
+ readonly presencePenalty?: number;
70
+ readonly stopSequences?: readonly string[];
71
+ readonly responseFormat?: unknown;
72
+ readonly signal?: AbortSignal;
73
+ readonly metadata?: Readonly<Record<string, unknown>>;
74
+ }
75
+ type DaihumAiChatResponseKind = "message" | "tool-calls";
76
+ interface DaihumAiChatResponse {
77
+ readonly kind: DaihumAiChatResponseKind;
78
+ readonly providerId: string;
79
+ readonly modelId: string;
80
+ readonly routeId?: string;
81
+ readonly text?: string;
82
+ readonly toolCalls?: readonly DaihumAiToolCall[];
83
+ readonly finishReason?: DaihumAiFinishReason;
84
+ readonly usage?: DaihumAiUsage;
85
+ readonly providerRequestId?: string;
86
+ readonly rawResponse?: unknown;
87
+ readonly metadata?: Readonly<Record<string, unknown>>;
88
+ }
89
+ type DaihumAiChatStreamEvent = Readonly<{
90
+ type: "text-delta";
91
+ textDelta: string;
92
+ }> | Readonly<{
93
+ type: "tool-call-start";
94
+ toolCall: DaihumAiPartialToolCall;
95
+ }> | Readonly<{
96
+ type: "tool-call-delta";
97
+ toolCall: DaihumAiPartialToolCall;
98
+ }> | Readonly<{
99
+ type: "tool-call-end";
100
+ toolCall: DaihumAiToolCall | DaihumAiPartialToolCall;
101
+ }> | Readonly<{
102
+ type: "tool-call";
103
+ toolCall: DaihumAiToolCall;
104
+ }> | Readonly<{
105
+ type: "reasoning-delta";
106
+ reasoningDelta: string;
107
+ }> | Readonly<{
108
+ type: "finish";
109
+ response: DaihumAiChatResponse;
110
+ }> | Readonly<{
111
+ type: "error";
112
+ error: unknown;
113
+ }>;
114
+ //#endregion
115
+ export { DaihumAiContentPart as a, DaihumAiJsonPart as c, DaihumAiResponseFormat as d, DaihumAiTextPart as f, DaihumAiChatStreamEvent as i, DaihumAiMessage as l, DaihumAiChatResponse as n, DaihumAiFinishReason as o, DaihumAiChatResponseKind as r, DaihumAiImagePart as s, DaihumAiChatRequest as t, DaihumAiMessageRole as u };
116
+ //# sourceMappingURL=chat-BZgfxuBU.d.ts.map
package/dist/chat.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import "./usage-Db6aaBEO.js";
2
+ import "./tools-VkZPo3Sc.js";
3
+ import { a as DaihumAiContentPart, c as DaihumAiJsonPart, d as DaihumAiResponseFormat, f as DaihumAiTextPart, i as DaihumAiChatStreamEvent, l as DaihumAiMessage, n as DaihumAiChatResponse, o as DaihumAiFinishReason, r as DaihumAiChatResponseKind, s as DaihumAiImagePart, t as DaihumAiChatRequest, u as DaihumAiMessageRole } from "./chat-BZgfxuBU.js";
4
+ export { DaihumAiChatRequest, DaihumAiChatResponse, DaihumAiChatResponseKind, DaihumAiChatStreamEvent, DaihumAiContentPart, DaihumAiFinishReason, DaihumAiImagePart, DaihumAiJsonPart, DaihumAiMessage, DaihumAiMessageRole, DaihumAiResponseFormat, DaihumAiTextPart };
package/dist/chat.js ADDED
@@ -0,0 +1 @@
1
+ import "./chat-BEsGPeX0.js";
@@ -0,0 +1,39 @@
1
+ import { t as DaihumAiUsage } from "./usage-Db6aaBEO.js";
2
+
3
+ //#region src/embedding.d.ts
4
+
5
+ /**
6
+ * Pure embedding model-operation payload. Carries model I/O only.
7
+ * routePlan/execution-context intentionally absent (see chat.ts).
8
+ */
9
+ interface DaihumAiEmbeddingRequest {
10
+ readonly requestId?: string;
11
+ readonly providerId?: string;
12
+ readonly modelId?: string;
13
+ readonly routeId?: string;
14
+ readonly input: string | readonly string[];
15
+ readonly dimensions?: number;
16
+ readonly signal?: AbortSignal;
17
+ readonly metadata?: Readonly<Record<string, unknown>>;
18
+ }
19
+ interface DaihumAiEmbedding {
20
+ readonly inputIndex: number;
21
+ readonly vector: Float32Array;
22
+ readonly dimensions: number;
23
+ readonly providerId: string;
24
+ readonly modelId: string;
25
+ readonly metadata?: Readonly<Record<string, unknown>>;
26
+ }
27
+ interface DaihumAiEmbeddingResponse {
28
+ readonly providerId: string;
29
+ readonly modelId: string;
30
+ readonly routeId?: string;
31
+ readonly embeddings: readonly DaihumAiEmbedding[];
32
+ readonly usage?: DaihumAiUsage;
33
+ readonly providerRequestId?: string;
34
+ readonly rawResponse?: unknown;
35
+ readonly metadata?: Readonly<Record<string, unknown>>;
36
+ }
37
+ //#endregion
38
+ export { DaihumAiEmbeddingRequest as n, DaihumAiEmbeddingResponse as r, DaihumAiEmbedding as t };
39
+ //# sourceMappingURL=embedding-B7HPKvpY.d.ts.map
File without changes
@@ -0,0 +1,23 @@
1
+ //#region src/embedding-compat.d.ts
2
+ interface DaihumAiCompatibilityFingerprintInput {
3
+ readonly providerId: string;
4
+ readonly modelId?: string;
5
+ readonly routeId?: string;
6
+ readonly dimensions?: number;
7
+ readonly normalization?: string;
8
+ readonly distanceMetric?: string;
9
+ readonly chunkerId?: string;
10
+ readonly chunkStrategyId?: string;
11
+ readonly chunkStrategyVersion?: number | string;
12
+ readonly chunkStrategyConfigHash?: string;
13
+ readonly extra?: Readonly<Record<string, unknown>>;
14
+ }
15
+ interface DaihumAiCompatibilityFingerprint {
16
+ readonly algorithm: "daihum-ai.compatibility.v1";
17
+ readonly value: string;
18
+ readonly basis: DaihumAiCompatibilityFingerprintInput;
19
+ }
20
+ declare function buildDaihumAiCompatibilityFingerprint(input: DaihumAiCompatibilityFingerprintInput): DaihumAiCompatibilityFingerprint;
21
+ //#endregion
22
+ export { DaihumAiCompatibilityFingerprintInput as n, buildDaihumAiCompatibilityFingerprint as r, DaihumAiCompatibilityFingerprint as t };
23
+ //# sourceMappingURL=embedding-compat-ClR_h_ED.d.ts.map
@@ -0,0 +1,54 @@
1
+ //#region src/internal/normalize.ts
2
+ function normalizeId(value) {
3
+ if (typeof value !== "string") return void 0;
4
+ const trimmed = value.trim();
5
+ return trimmed.length > 0 ? trimmed : void 0;
6
+ }
7
+ function normalizeRequiredId(value, fieldName) {
8
+ const normalized = normalizeId(value);
9
+ if (!normalized) throw new Error(`Invalid ${fieldName}: expected a non-empty string.`);
10
+ return normalized;
11
+ }
12
+ function normalizePositiveInteger(value) {
13
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
14
+ const normalized = Math.trunc(value);
15
+ return normalized > 0 ? normalized : void 0;
16
+ }
17
+ function normalizeVersionIdentifier(value) {
18
+ if (typeof value === "number") {
19
+ if (!Number.isFinite(value)) return void 0;
20
+ const normalized = Math.trunc(value);
21
+ return normalized >= 0 ? normalized : void 0;
22
+ }
23
+ return normalizeId(value);
24
+ }
25
+ function stableObject(value) {
26
+ return Object.fromEntries(Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)));
27
+ }
28
+
29
+ //#endregion
30
+ //#region src/embedding-compat.ts
31
+ function buildDaihumAiCompatibilityFingerprint(input) {
32
+ const basis = stableObject({
33
+ providerId: normalizeRequiredId(input.providerId, "providerId"),
34
+ modelId: normalizeId(input.modelId),
35
+ routeId: normalizeId(input.routeId),
36
+ dimensions: normalizePositiveInteger(input.dimensions),
37
+ normalization: normalizeId(input.normalization),
38
+ distanceMetric: normalizeId(input.distanceMetric),
39
+ chunkerId: normalizeId(input.chunkerId),
40
+ chunkStrategyId: normalizeId(input.chunkStrategyId),
41
+ chunkStrategyVersion: normalizeVersionIdentifier(input.chunkStrategyVersion),
42
+ chunkStrategyConfigHash: normalizeId(input.chunkStrategyConfigHash),
43
+ extra: input.extra ? stableObject(input.extra) : void 0
44
+ });
45
+ return {
46
+ algorithm: "daihum-ai.compatibility.v1",
47
+ value: `daihum-ai.compatibility.v1:${JSON.stringify(basis)}`,
48
+ basis
49
+ };
50
+ }
51
+
52
+ //#endregion
53
+ export { buildDaihumAiCompatibilityFingerprint as t };
54
+ //# sourceMappingURL=embedding-compat-Ov4JeVna.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embedding-compat-Ov4JeVna.js","names":[],"sources":["../src/internal/normalize.ts","../src/embedding-compat.ts"],"sourcesContent":["// Vendored from the former @daihum/ai-core/internal/normalize so this package\n// stays a zero-dependency leaf (see embedding-compat.ts).\n\nexport function normalizeId(value: string | undefined): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function normalizeRequiredId(value: string, fieldName: string): string {\n const normalized = normalizeId(value);\n if (!normalized) {\n throw new Error(`Invalid ${fieldName}: expected a non-empty string.`);\n }\n return normalized;\n}\n\nexport function normalizePositiveInteger(value: number | undefined): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n const normalized = Math.trunc(value);\n return normalized > 0 ? normalized : undefined;\n}\n\nexport function normalizeVersionIdentifier(\n value: number | string | undefined,\n): number | string | undefined {\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) return undefined;\n const normalized = Math.trunc(value);\n return normalized >= 0 ? normalized : undefined;\n }\n return normalizeId(value);\n}\n\nexport function stableObject<T extends Readonly<Record<string, unknown>>>(value: T): T {\n return Object.fromEntries(\n Object.entries(value)\n .filter(([, entryValue]) => entryValue !== undefined)\n .sort(([left], [right]) => left.localeCompare(right)),\n ) as T;\n}\n","import {\n normalizeId,\n normalizePositiveInteger,\n normalizeRequiredId,\n normalizeVersionIdentifier,\n stableObject,\n} from \"./internal/normalize.js\";\n\nexport interface DaihumAiCompatibilityFingerprintInput {\n readonly providerId: string;\n readonly modelId?: string;\n readonly routeId?: string;\n readonly dimensions?: number;\n readonly normalization?: string;\n readonly distanceMetric?: string;\n readonly chunkerId?: string;\n readonly chunkStrategyId?: string;\n readonly chunkStrategyVersion?: number | string;\n readonly chunkStrategyConfigHash?: string;\n readonly extra?: Readonly<Record<string, unknown>>;\n}\n\nexport interface DaihumAiCompatibilityFingerprint {\n readonly algorithm: \"daihum-ai.compatibility.v1\";\n readonly value: string;\n readonly basis: DaihumAiCompatibilityFingerprintInput;\n}\n\nexport function buildDaihumAiCompatibilityFingerprint(\n input: DaihumAiCompatibilityFingerprintInput,\n): DaihumAiCompatibilityFingerprint {\n const basis = stableObject({\n providerId: normalizeRequiredId(input.providerId, \"providerId\"),\n modelId: normalizeId(input.modelId),\n routeId: normalizeId(input.routeId),\n dimensions: normalizePositiveInteger(input.dimensions),\n normalization: normalizeId(input.normalization),\n distanceMetric: normalizeId(input.distanceMetric),\n chunkerId: normalizeId(input.chunkerId),\n chunkStrategyId: normalizeId(input.chunkStrategyId),\n chunkStrategyVersion: normalizeVersionIdentifier(input.chunkStrategyVersion),\n chunkStrategyConfigHash: normalizeId(input.chunkStrategyConfigHash),\n extra: input.extra ? stableObject(input.extra) : undefined,\n });\n\n return {\n algorithm: \"daihum-ai.compatibility.v1\",\n value: `daihum-ai.compatibility.v1:${JSON.stringify(basis)}`,\n basis,\n };\n}\n"],"mappings":";AAGA,SAAgB,YAAY,OAA+C;AACzE,KAAI,OAAO,UAAU,SAAU,QAAO;CACtC,MAAM,UAAU,MAAM,MAAM;AAC5B,QAAO,QAAQ,SAAS,IAAI,UAAU;;AAGxC,SAAgB,oBAAoB,OAAe,WAA2B;CAC5E,MAAM,aAAa,YAAY,MAAM;AACrC,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,WAAW,UAAU,gCAAgC;AAEvE,QAAO;;AAGT,SAAgB,yBAAyB,OAA+C;AACtF,KAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO;CACjE,MAAM,aAAa,KAAK,MAAM,MAAM;AACpC,QAAO,aAAa,IAAI,aAAa;;AAGvC,SAAgB,2BACd,OAC6B;AAC7B,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO;EACpC,MAAM,aAAa,KAAK,MAAM,MAAM;AACpC,SAAO,cAAc,IAAI,aAAa;;AAExC,QAAO,YAAY,MAAM;;AAG3B,SAAgB,aAA0D,OAAa;AACrF,QAAO,OAAO,YACZ,OAAO,QAAQ,MAAM,CAClB,QAAQ,GAAG,gBAAgB,eAAe,OAAU,CACpD,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,MAAM,CAAC,CACxD;;;;;ACXH,SAAgB,sCACd,OACkC;CAClC,MAAM,QAAQ,aAAa;EACzB,YAAY,oBAAoB,MAAM,YAAY,aAAa;EAC/D,SAAS,YAAY,MAAM,QAAQ;EACnC,SAAS,YAAY,MAAM,QAAQ;EACnC,YAAY,yBAAyB,MAAM,WAAW;EACtD,eAAe,YAAY,MAAM,cAAc;EAC/C,gBAAgB,YAAY,MAAM,eAAe;EACjD,WAAW,YAAY,MAAM,UAAU;EACvC,iBAAiB,YAAY,MAAM,gBAAgB;EACnD,sBAAsB,2BAA2B,MAAM,qBAAqB;EAC5E,yBAAyB,YAAY,MAAM,wBAAwB;EACnE,OAAO,MAAM,QAAQ,aAAa,MAAM,MAAM,GAAG;EAClD,CAAC;AAEF,QAAO;EACL,WAAW;EACX,OAAO,8BAA8B,KAAK,UAAU,MAAM;EAC1D;EACD"}
@@ -0,0 +1,2 @@
1
+ import { n as DaihumAiCompatibilityFingerprintInput, r as buildDaihumAiCompatibilityFingerprint, t as DaihumAiCompatibilityFingerprint } from "./embedding-compat-ClR_h_ED.js";
2
+ export { DaihumAiCompatibilityFingerprint, DaihumAiCompatibilityFingerprintInput, buildDaihumAiCompatibilityFingerprint };
@@ -0,0 +1,3 @@
1
+ import { t as buildDaihumAiCompatibilityFingerprint } from "./embedding-compat-Ov4JeVna.js";
2
+
3
+ export { buildDaihumAiCompatibilityFingerprint };
@@ -0,0 +1,3 @@
1
+ import "./usage-Db6aaBEO.js";
2
+ import { n as DaihumAiEmbeddingRequest, r as DaihumAiEmbeddingResponse, t as DaihumAiEmbedding } from "./embedding-B7HPKvpY.js";
3
+ export { DaihumAiEmbedding, DaihumAiEmbeddingRequest, DaihumAiEmbeddingResponse };
@@ -0,0 +1 @@
1
+ import "./embedding-DqA2ZBzJ.js";
@@ -0,0 +1,7 @@
1
+ import { t as DaihumAiUsage } from "./usage-Db6aaBEO.js";
2
+ import { a as DaihumAiCandidateRankScoreKind, i as DaihumAiCandidateRankResult, n as DaihumAiCandidateRankRequest, o as DaihumAiCandidateRankWarning, r as DaihumAiCandidateRankResponse, t as DaihumAiCandidateRankCandidate } from "./candidate-rank-CFpxmTMM.js";
3
+ import { a as DaihumAiToolDefinition, i as DaihumAiToolChoice, n as DaihumAiPartialToolCall, o as fromDaihumAiWireToolDefinition, r as DaihumAiToolCall, s as toDaihumAiWireToolDefinition, t as DaihumAiFlatToolDefinition } from "./tools-VkZPo3Sc.js";
4
+ import { a as DaihumAiContentPart, c as DaihumAiJsonPart, d as DaihumAiResponseFormat, f as DaihumAiTextPart, i as DaihumAiChatStreamEvent, l as DaihumAiMessage, n as DaihumAiChatResponse, o as DaihumAiFinishReason, r as DaihumAiChatResponseKind, s as DaihumAiImagePart, t as DaihumAiChatRequest, u as DaihumAiMessageRole } from "./chat-BZgfxuBU.js";
5
+ import { n as DaihumAiCompatibilityFingerprintInput, r as buildDaihumAiCompatibilityFingerprint, t as DaihumAiCompatibilityFingerprint } from "./embedding-compat-ClR_h_ED.js";
6
+ import { n as DaihumAiEmbeddingRequest, r as DaihumAiEmbeddingResponse, t as DaihumAiEmbedding } from "./embedding-B7HPKvpY.js";
7
+ export { DaihumAiCandidateRankCandidate, DaihumAiCandidateRankRequest, DaihumAiCandidateRankResponse, DaihumAiCandidateRankResult, DaihumAiCandidateRankScoreKind, DaihumAiCandidateRankWarning, DaihumAiChatRequest, DaihumAiChatResponse, DaihumAiChatResponseKind, DaihumAiChatStreamEvent, DaihumAiCompatibilityFingerprint, DaihumAiCompatibilityFingerprintInput, DaihumAiContentPart, DaihumAiEmbedding, DaihumAiEmbeddingRequest, DaihumAiEmbeddingResponse, DaihumAiFinishReason, DaihumAiFlatToolDefinition, DaihumAiImagePart, DaihumAiJsonPart, DaihumAiMessage, DaihumAiMessageRole, DaihumAiPartialToolCall, DaihumAiResponseFormat, DaihumAiTextPart, DaihumAiToolCall, DaihumAiToolChoice, DaihumAiToolDefinition, DaihumAiUsage, buildDaihumAiCompatibilityFingerprint, fromDaihumAiWireToolDefinition, toDaihumAiWireToolDefinition };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { n as toDaihumAiWireToolDefinition, t as fromDaihumAiWireToolDefinition } from "./tools-DYtxGkWR.js";
2
+ import "./usage-F8ETXDpy.js";
3
+ import "./chat-BEsGPeX0.js";
4
+ import "./embedding-DqA2ZBzJ.js";
5
+ import "./candidate-rank-DYi3Kcdp.js";
6
+ import { t as buildDaihumAiCompatibilityFingerprint } from "./embedding-compat-Ov4JeVna.js";
7
+
8
+ export { buildDaihumAiCompatibilityFingerprint, fromDaihumAiWireToolDefinition, toDaihumAiWireToolDefinition };
@@ -0,0 +1,22 @@
1
+ //#region src/tools.ts
2
+ function toDaihumAiWireToolDefinition(flat) {
3
+ return {
4
+ type: "function",
5
+ function: {
6
+ name: flat.name,
7
+ description: flat.description,
8
+ parameters: flat.parameters
9
+ }
10
+ };
11
+ }
12
+ function fromDaihumAiWireToolDefinition(wire) {
13
+ return {
14
+ name: wire.function.name,
15
+ description: wire.function.description,
16
+ parameters: wire.function.parameters
17
+ };
18
+ }
19
+
20
+ //#endregion
21
+ export { toDaihumAiWireToolDefinition as n, fromDaihumAiWireToolDefinition as t };
22
+ //# sourceMappingURL=tools-DYtxGkWR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools-DYtxGkWR.js","names":[],"sources":["../src/tools.ts"],"sourcesContent":["export interface DaihumAiToolCall {\n readonly id: string;\n readonly type: \"function\";\n readonly function: {\n readonly name: string;\n readonly arguments: string;\n };\n}\n\nexport interface DaihumAiPartialToolCall {\n readonly index?: number;\n readonly id?: string;\n readonly type?: \"function\" | (string & {});\n readonly function?: {\n readonly name?: string;\n readonly arguments?: string;\n readonly argumentsDelta?: string;\n };\n readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\nexport interface DaihumAiToolDefinition {\n readonly type: \"function\";\n readonly function: {\n readonly name: string;\n readonly description?: string;\n readonly parameters?: unknown;\n };\n}\n\nexport type DaihumAiToolChoice =\n | \"auto\"\n | \"none\"\n | \"required\"\n | Readonly<{ readonly type: \"tool\"; readonly toolName: string }>\n | (string & {});\n\n/** Flat, wire-agnostic tool description (the domain-level canonical form). */\nexport interface DaihumAiFlatToolDefinition {\n readonly name: string;\n readonly description?: string;\n readonly parameters?: unknown;\n}\n\nexport function toDaihumAiWireToolDefinition(flat: DaihumAiFlatToolDefinition): DaihumAiToolDefinition {\n return { type: \"function\", function: { name: flat.name, description: flat.description, parameters: flat.parameters } };\n}\n\nexport function fromDaihumAiWireToolDefinition(wire: DaihumAiToolDefinition): DaihumAiFlatToolDefinition {\n return { name: wire.function.name, description: wire.function.description, parameters: wire.function.parameters };\n}\n"],"mappings":";AA4CA,SAAgB,6BAA6B,MAA0D;AACrG,QAAO;EAAE,MAAM;EAAY,UAAU;GAAE,MAAM,KAAK;GAAM,aAAa,KAAK;GAAa,YAAY,KAAK;GAAY;EAAE;;AAGxH,SAAgB,+BAA+B,MAA0D;AACvG,QAAO;EAAE,MAAM,KAAK,SAAS;EAAM,aAAa,KAAK,SAAS;EAAa,YAAY,KAAK,SAAS;EAAY"}
@@ -0,0 +1,43 @@
1
+ //#region src/tools.d.ts
2
+ interface DaihumAiToolCall {
3
+ readonly id: string;
4
+ readonly type: "function";
5
+ readonly function: {
6
+ readonly name: string;
7
+ readonly arguments: string;
8
+ };
9
+ }
10
+ interface DaihumAiPartialToolCall {
11
+ readonly index?: number;
12
+ readonly id?: string;
13
+ readonly type?: "function" | (string & {});
14
+ readonly function?: {
15
+ readonly name?: string;
16
+ readonly arguments?: string;
17
+ readonly argumentsDelta?: string;
18
+ };
19
+ readonly metadata?: Readonly<Record<string, unknown>>;
20
+ }
21
+ interface DaihumAiToolDefinition {
22
+ readonly type: "function";
23
+ readonly function: {
24
+ readonly name: string;
25
+ readonly description?: string;
26
+ readonly parameters?: unknown;
27
+ };
28
+ }
29
+ type DaihumAiToolChoice = "auto" | "none" | "required" | Readonly<{
30
+ readonly type: "tool";
31
+ readonly toolName: string;
32
+ }> | (string & {});
33
+ /** Flat, wire-agnostic tool description (the domain-level canonical form). */
34
+ interface DaihumAiFlatToolDefinition {
35
+ readonly name: string;
36
+ readonly description?: string;
37
+ readonly parameters?: unknown;
38
+ }
39
+ declare function toDaihumAiWireToolDefinition(flat: DaihumAiFlatToolDefinition): DaihumAiToolDefinition;
40
+ declare function fromDaihumAiWireToolDefinition(wire: DaihumAiToolDefinition): DaihumAiFlatToolDefinition;
41
+ //#endregion
42
+ export { DaihumAiToolDefinition as a, DaihumAiToolChoice as i, DaihumAiPartialToolCall as n, fromDaihumAiWireToolDefinition as o, DaihumAiToolCall as r, toDaihumAiWireToolDefinition as s, DaihumAiFlatToolDefinition as t };
43
+ //# sourceMappingURL=tools-VkZPo3Sc.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { a as DaihumAiToolDefinition, i as DaihumAiToolChoice, n as DaihumAiPartialToolCall, o as fromDaihumAiWireToolDefinition, r as DaihumAiToolCall, s as toDaihumAiWireToolDefinition, t as DaihumAiFlatToolDefinition } from "./tools-VkZPo3Sc.js";
2
+ export { DaihumAiFlatToolDefinition, DaihumAiPartialToolCall, DaihumAiToolCall, DaihumAiToolChoice, DaihumAiToolDefinition, fromDaihumAiWireToolDefinition, toDaihumAiWireToolDefinition };
package/dist/tools.js ADDED
@@ -0,0 +1,3 @@
1
+ import { n as toDaihumAiWireToolDefinition, t as fromDaihumAiWireToolDefinition } from "./tools-DYtxGkWR.js";
2
+
3
+ export { fromDaihumAiWireToolDefinition, toDaihumAiWireToolDefinition };
@@ -0,0 +1,11 @@
1
+ //#region src/usage.d.ts
2
+ interface DaihumAiUsage {
3
+ readonly inputTokens?: number;
4
+ readonly outputTokens?: number;
5
+ readonly totalTokens?: number;
6
+ readonly requestCount?: number;
7
+ readonly metadata?: Readonly<Record<string, unknown>>;
8
+ }
9
+ //#endregion
10
+ export { DaihumAiUsage as t };
11
+ //# sourceMappingURL=usage-Db6aaBEO.d.ts.map
File without changes
@@ -0,0 +1,2 @@
1
+ import { t as DaihumAiUsage } from "./usage-Db6aaBEO.js";
2
+ export { DaihumAiUsage };
package/dist/usage.js ADDED
@@ -0,0 +1 @@
1
+ import "./usage-F8ETXDpy.js";
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@daihum/ai-model-contracts",
3
+ "version": "0.1.0",
4
+ "description": "DAIHUM AI pure, serializable model-operation payload contracts: chat, embedding, candidate-rank, tools, usage, embedding-compat. Zero dependencies. Carries NO routing (routePlan), provider selection, secrets, catalog/pricing, runtime, RAG, or product authority. The stable vocabulary leaf.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ },
13
+ "./chat": {
14
+ "types": "./dist/chat.d.ts",
15
+ "import": "./dist/chat.js"
16
+ },
17
+ "./embedding": {
18
+ "types": "./dist/embedding.d.ts",
19
+ "import": "./dist/embedding.js"
20
+ },
21
+ "./candidate-rank": {
22
+ "types": "./dist/candidate-rank.d.ts",
23
+ "import": "./dist/candidate-rank.js"
24
+ },
25
+ "./tools": {
26
+ "types": "./dist/tools.d.ts",
27
+ "import": "./dist/tools.js"
28
+ },
29
+ "./usage": {
30
+ "types": "./dist/usage.d.ts",
31
+ "import": "./dist/usage.js"
32
+ },
33
+ "./embedding-compat": {
34
+ "types": "./dist/embedding-compat.d.ts",
35
+ "import": "./dist/embedding-compat.js"
36
+ },
37
+ "./package.json": "./package.json"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "src",
42
+ "README.md"
43
+ ],
44
+ "devDependencies": {
45
+ "tsdown": "^0.16.6",
46
+ "typescript": "~5.6.2"
47
+ },
48
+ "sideEffects": false,
49
+ "scripts": {
50
+ "build": "tsdown",
51
+ "clean": "rm -rf dist",
52
+ "typecheck": "tsc --noEmit"
53
+ }
54
+ }
@@ -0,0 +1,66 @@
1
+ import type { DaihumAiUsage } from "./usage.js";
2
+
3
+ /**
4
+ * Model-level candidate ranking (renamed from the former "rerank" model op;
5
+ * "rerank" is reserved for the RAG pipeline stage in @daihum/ai-rag).
6
+ *
7
+ * Operation shape: query + candidate texts -> candidate ids / order / scores.
8
+ * This is a peer of chat and embedding, NOT an optimization of chat — some
9
+ * runtimes serve it natively (e.g. an OpenRouter /rerank endpoint), others via
10
+ * a candidate-rank-from-chat adapter (@daihum/ai-candidate-rank-adapters).
11
+ */
12
+
13
+ /**
14
+ * A candidate to rank. Model-visible payload ONLY: an opaque id + the text the
15
+ * model sees. Deliberately has NO `metadata?: unknown` — that would be a
16
+ * fat-envelope backdoor for hydrated hits / provenance / authority / secrets.
17
+ * Callers map their own source ids through *ephemeral* candidateIds.
18
+ */
19
+ export interface DaihumAiCandidateRankCandidate {
20
+ readonly candidateId: string;
21
+ readonly text: string;
22
+ }
23
+
24
+ export interface DaihumAiCandidateRankRequest {
25
+ readonly requestId?: string;
26
+ readonly providerId?: string;
27
+ readonly modelId?: string;
28
+ readonly routeId?: string;
29
+ readonly query: string;
30
+ readonly candidates: readonly DaihumAiCandidateRankCandidate[];
31
+ /** If set, the response MAY be partial (top-K). Omitted candidates are not errors. */
32
+ readonly topK?: number;
33
+ readonly signal?: AbortSignal;
34
+ readonly metadata?: Readonly<Record<string, unknown>>;
35
+ }
36
+
37
+ /** Where a result's score came from. A chat-prompted ranker can order reliably
38
+ * but cannot calibrate a score; in that case `score` is omitted (rank is
39
+ * authoritative) and the RAG blend stage derives a score from rank. */
40
+ export type DaihumAiCandidateRankScoreKind = "provider" | "normalized" | "rank-derived";
41
+
42
+ export interface DaihumAiCandidateRankResult {
43
+ readonly candidateId: string;
44
+ /** 1-based, unique within the response. Response order SHOULD match rank ascending. */
45
+ readonly rank: number;
46
+ /** Optional on purpose — see DaihumAiCandidateRankScoreKind. */
47
+ readonly score?: number;
48
+ readonly scoreKind?: DaihumAiCandidateRankScoreKind;
49
+ }
50
+
51
+ export interface DaihumAiCandidateRankWarning {
52
+ readonly code: string;
53
+ readonly message?: string;
54
+ readonly candidateId?: string;
55
+ }
56
+
57
+ export interface DaihumAiCandidateRankResponse {
58
+ readonly providerId: string;
59
+ readonly modelId: string;
60
+ readonly routeId?: string;
61
+ readonly results: readonly DaihumAiCandidateRankResult[];
62
+ readonly usage?: DaihumAiUsage;
63
+ readonly warnings?: readonly DaihumAiCandidateRankWarning[];
64
+ readonly rawResponse?: unknown;
65
+ readonly metadata?: Readonly<Record<string, unknown>>;
66
+ }
package/src/chat.ts ADDED
@@ -0,0 +1,115 @@
1
+ import type {
2
+ DaihumAiPartialToolCall,
3
+ DaihumAiToolCall,
4
+ DaihumAiToolChoice,
5
+ DaihumAiToolDefinition,
6
+ } from "./tools.js";
7
+ import type { DaihumAiUsage } from "./usage.js";
8
+
9
+ export type DaihumAiMessageRole = "system" | "user" | "assistant" | "tool";
10
+
11
+ export interface DaihumAiTextPart {
12
+ readonly type: "text";
13
+ readonly text: string;
14
+ }
15
+
16
+ export interface DaihumAiImagePart {
17
+ readonly type: "image";
18
+ readonly image: string | URL | Uint8Array | ArrayBuffer;
19
+ readonly mediaType?: string;
20
+ }
21
+
22
+ export interface DaihumAiJsonPart {
23
+ readonly type: "json";
24
+ readonly value: unknown;
25
+ }
26
+
27
+ export type DaihumAiContentPart =
28
+ | DaihumAiTextPart
29
+ | DaihumAiImagePart
30
+ | DaihumAiJsonPart
31
+ | (Readonly<Record<string, unknown>> & { readonly type: string });
32
+
33
+ export interface DaihumAiMessage {
34
+ readonly role: DaihumAiMessageRole;
35
+ readonly content?: string | readonly DaihumAiContentPart[];
36
+ readonly name?: string;
37
+ readonly toolCallId?: string;
38
+ readonly toolCalls?: readonly DaihumAiToolCall[];
39
+ readonly metadata?: Readonly<Record<string, unknown>>;
40
+ }
41
+
42
+ export type DaihumAiFinishReason =
43
+ | "stop"
44
+ | "length"
45
+ | "tool-calls"
46
+ | "content-filter"
47
+ | "error"
48
+ | "unknown"
49
+ | (string & {});
50
+
51
+ /** Recommended shape for DaihumAiChatRequest.responseFormat (the field stays
52
+ * `unknown` for adapter flexibility; adapters narrow against this). */
53
+ export type DaihumAiResponseFormat =
54
+ | Readonly<{ kind: "text" }>
55
+ | Readonly<{ kind: "json" }>
56
+ | Readonly<{ kind: "json-schema"; name?: string; strict?: boolean; schema: Readonly<Record<string, unknown>> }>;
57
+
58
+ /**
59
+ * Pure chat model-operation payload. Carries model I/O only.
60
+ *
61
+ * NOT present (by design — these are NOT model payload):
62
+ * - routePlan -> routing concern; @daihum/ai-routing lowers a route plan into
63
+ * providerId/modelId/routeId (resolved below) + a provider call context.
64
+ * - execution context (workspaceId/actorId/dataClass/...) -> product authority;
65
+ * travels in the provider call context (@daihum/ai-provider-contracts), never here.
66
+ *
67
+ * providerId/modelId/routeId are the *already-resolved* execution target hints
68
+ * (populated by routing before the call), not a route plan.
69
+ */
70
+ export interface DaihumAiChatRequest {
71
+ readonly requestId?: string;
72
+ readonly providerId?: string;
73
+ readonly modelId?: string;
74
+ readonly routeId?: string;
75
+ readonly messages: readonly DaihumAiMessage[];
76
+ readonly tools?: readonly DaihumAiToolDefinition[];
77
+ readonly toolChoice?: DaihumAiToolChoice;
78
+ readonly temperature?: number;
79
+ readonly topP?: number;
80
+ readonly maxOutputTokens?: number;
81
+ readonly reasoningBudget?: number;
82
+ readonly seed?: number;
83
+ readonly frequencyPenalty?: number;
84
+ readonly presencePenalty?: number;
85
+ readonly stopSequences?: readonly string[];
86
+ readonly responseFormat?: unknown;
87
+ readonly signal?: AbortSignal;
88
+ readonly metadata?: Readonly<Record<string, unknown>>;
89
+ }
90
+
91
+ export type DaihumAiChatResponseKind = "message" | "tool-calls";
92
+
93
+ export interface DaihumAiChatResponse {
94
+ readonly kind: DaihumAiChatResponseKind;
95
+ readonly providerId: string;
96
+ readonly modelId: string;
97
+ readonly routeId?: string;
98
+ readonly text?: string;
99
+ readonly toolCalls?: readonly DaihumAiToolCall[];
100
+ readonly finishReason?: DaihumAiFinishReason;
101
+ readonly usage?: DaihumAiUsage;
102
+ readonly providerRequestId?: string;
103
+ readonly rawResponse?: unknown;
104
+ readonly metadata?: Readonly<Record<string, unknown>>;
105
+ }
106
+
107
+ export type DaihumAiChatStreamEvent =
108
+ | Readonly<{ type: "text-delta"; textDelta: string }>
109
+ | Readonly<{ type: "tool-call-start"; toolCall: DaihumAiPartialToolCall }>
110
+ | Readonly<{ type: "tool-call-delta"; toolCall: DaihumAiPartialToolCall }>
111
+ | Readonly<{ type: "tool-call-end"; toolCall: DaihumAiToolCall | DaihumAiPartialToolCall }>
112
+ | Readonly<{ type: "tool-call"; toolCall: DaihumAiToolCall }>
113
+ | Readonly<{ type: "reasoning-delta"; reasoningDelta: string }>
114
+ | Readonly<{ type: "finish"; response: DaihumAiChatResponse }>
115
+ | Readonly<{ type: "error"; error: unknown }>;
@@ -0,0 +1,51 @@
1
+ import {
2
+ normalizeId,
3
+ normalizePositiveInteger,
4
+ normalizeRequiredId,
5
+ normalizeVersionIdentifier,
6
+ stableObject,
7
+ } from "./internal/normalize.js";
8
+
9
+ export interface DaihumAiCompatibilityFingerprintInput {
10
+ readonly providerId: string;
11
+ readonly modelId?: string;
12
+ readonly routeId?: string;
13
+ readonly dimensions?: number;
14
+ readonly normalization?: string;
15
+ readonly distanceMetric?: string;
16
+ readonly chunkerId?: string;
17
+ readonly chunkStrategyId?: string;
18
+ readonly chunkStrategyVersion?: number | string;
19
+ readonly chunkStrategyConfigHash?: string;
20
+ readonly extra?: Readonly<Record<string, unknown>>;
21
+ }
22
+
23
+ export interface DaihumAiCompatibilityFingerprint {
24
+ readonly algorithm: "daihum-ai.compatibility.v1";
25
+ readonly value: string;
26
+ readonly basis: DaihumAiCompatibilityFingerprintInput;
27
+ }
28
+
29
+ export function buildDaihumAiCompatibilityFingerprint(
30
+ input: DaihumAiCompatibilityFingerprintInput,
31
+ ): DaihumAiCompatibilityFingerprint {
32
+ const basis = stableObject({
33
+ providerId: normalizeRequiredId(input.providerId, "providerId"),
34
+ modelId: normalizeId(input.modelId),
35
+ routeId: normalizeId(input.routeId),
36
+ dimensions: normalizePositiveInteger(input.dimensions),
37
+ normalization: normalizeId(input.normalization),
38
+ distanceMetric: normalizeId(input.distanceMetric),
39
+ chunkerId: normalizeId(input.chunkerId),
40
+ chunkStrategyId: normalizeId(input.chunkStrategyId),
41
+ chunkStrategyVersion: normalizeVersionIdentifier(input.chunkStrategyVersion),
42
+ chunkStrategyConfigHash: normalizeId(input.chunkStrategyConfigHash),
43
+ extra: input.extra ? stableObject(input.extra) : undefined,
44
+ });
45
+
46
+ return {
47
+ algorithm: "daihum-ai.compatibility.v1",
48
+ value: `daihum-ai.compatibility.v1:${JSON.stringify(basis)}`,
49
+ basis,
50
+ };
51
+ }
@@ -0,0 +1,36 @@
1
+ import type { DaihumAiUsage } from "./usage.js";
2
+
3
+ /**
4
+ * Pure embedding model-operation payload. Carries model I/O only.
5
+ * routePlan/execution-context intentionally absent (see chat.ts).
6
+ */
7
+ export interface DaihumAiEmbeddingRequest {
8
+ readonly requestId?: string;
9
+ readonly providerId?: string;
10
+ readonly modelId?: string;
11
+ readonly routeId?: string;
12
+ readonly input: string | readonly string[];
13
+ readonly dimensions?: number;
14
+ readonly signal?: AbortSignal;
15
+ readonly metadata?: Readonly<Record<string, unknown>>;
16
+ }
17
+
18
+ export interface DaihumAiEmbedding {
19
+ readonly inputIndex: number;
20
+ readonly vector: Float32Array;
21
+ readonly dimensions: number;
22
+ readonly providerId: string;
23
+ readonly modelId: string;
24
+ readonly metadata?: Readonly<Record<string, unknown>>;
25
+ }
26
+
27
+ export interface DaihumAiEmbeddingResponse {
28
+ readonly providerId: string;
29
+ readonly modelId: string;
30
+ readonly routeId?: string;
31
+ readonly embeddings: readonly DaihumAiEmbedding[];
32
+ readonly usage?: DaihumAiUsage;
33
+ readonly providerRequestId?: string;
34
+ readonly rawResponse?: unknown;
35
+ readonly metadata?: Readonly<Record<string, unknown>>;
36
+ }
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ // Convenience root barrel. Prefer subpath imports
2
+ // (e.g. `@daihum/ai-model-contracts/candidate-rank`) as the dominant style —
3
+ // the package is universal, the root import should not be.
4
+ export * from "./tools.js";
5
+ export * from "./usage.js";
6
+ export * from "./chat.js";
7
+ export * from "./embedding.js";
8
+ export * from "./candidate-rank.js";
9
+ export * from "./embedding-compat.js";
@@ -0,0 +1,41 @@
1
+ // Vendored from the former @daihum/ai-core/internal/normalize so this package
2
+ // stays a zero-dependency leaf (see embedding-compat.ts).
3
+
4
+ export function normalizeId(value: string | undefined): string | undefined {
5
+ if (typeof value !== "string") return undefined;
6
+ const trimmed = value.trim();
7
+ return trimmed.length > 0 ? trimmed : undefined;
8
+ }
9
+
10
+ export function normalizeRequiredId(value: string, fieldName: string): string {
11
+ const normalized = normalizeId(value);
12
+ if (!normalized) {
13
+ throw new Error(`Invalid ${fieldName}: expected a non-empty string.`);
14
+ }
15
+ return normalized;
16
+ }
17
+
18
+ export function normalizePositiveInteger(value: number | undefined): number | undefined {
19
+ if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
20
+ const normalized = Math.trunc(value);
21
+ return normalized > 0 ? normalized : undefined;
22
+ }
23
+
24
+ export function normalizeVersionIdentifier(
25
+ value: number | string | undefined,
26
+ ): number | string | undefined {
27
+ if (typeof value === "number") {
28
+ if (!Number.isFinite(value)) return undefined;
29
+ const normalized = Math.trunc(value);
30
+ return normalized >= 0 ? normalized : undefined;
31
+ }
32
+ return normalizeId(value);
33
+ }
34
+
35
+ export function stableObject<T extends Readonly<Record<string, unknown>>>(value: T): T {
36
+ return Object.fromEntries(
37
+ Object.entries(value)
38
+ .filter(([, entryValue]) => entryValue !== undefined)
39
+ .sort(([left], [right]) => left.localeCompare(right)),
40
+ ) as T;
41
+ }
package/src/tools.ts ADDED
@@ -0,0 +1,51 @@
1
+ export interface DaihumAiToolCall {
2
+ readonly id: string;
3
+ readonly type: "function";
4
+ readonly function: {
5
+ readonly name: string;
6
+ readonly arguments: string;
7
+ };
8
+ }
9
+
10
+ export interface DaihumAiPartialToolCall {
11
+ readonly index?: number;
12
+ readonly id?: string;
13
+ readonly type?: "function" | (string & {});
14
+ readonly function?: {
15
+ readonly name?: string;
16
+ readonly arguments?: string;
17
+ readonly argumentsDelta?: string;
18
+ };
19
+ readonly metadata?: Readonly<Record<string, unknown>>;
20
+ }
21
+
22
+ export interface DaihumAiToolDefinition {
23
+ readonly type: "function";
24
+ readonly function: {
25
+ readonly name: string;
26
+ readonly description?: string;
27
+ readonly parameters?: unknown;
28
+ };
29
+ }
30
+
31
+ export type DaihumAiToolChoice =
32
+ | "auto"
33
+ | "none"
34
+ | "required"
35
+ | Readonly<{ readonly type: "tool"; readonly toolName: string }>
36
+ | (string & {});
37
+
38
+ /** Flat, wire-agnostic tool description (the domain-level canonical form). */
39
+ export interface DaihumAiFlatToolDefinition {
40
+ readonly name: string;
41
+ readonly description?: string;
42
+ readonly parameters?: unknown;
43
+ }
44
+
45
+ export function toDaihumAiWireToolDefinition(flat: DaihumAiFlatToolDefinition): DaihumAiToolDefinition {
46
+ return { type: "function", function: { name: flat.name, description: flat.description, parameters: flat.parameters } };
47
+ }
48
+
49
+ export function fromDaihumAiWireToolDefinition(wire: DaihumAiToolDefinition): DaihumAiFlatToolDefinition {
50
+ return { name: wire.function.name, description: wire.function.description, parameters: wire.function.parameters };
51
+ }
package/src/usage.ts ADDED
@@ -0,0 +1,7 @@
1
+ export interface DaihumAiUsage {
2
+ readonly inputTokens?: number;
3
+ readonly outputTokens?: number;
4
+ readonly totalTokens?: number;
5
+ readonly requestCount?: number;
6
+ readonly metadata?: Readonly<Record<string, unknown>>;
7
+ }