@hypit/hypit 0.2.3 → 0.2.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.
Files changed (35) hide show
  1. package/package.json +5 -1
  2. package/packages/media-execution/src/execute.ts +3 -2
  3. package/packages/provider-hiapi/README.md +75 -0
  4. package/packages/provider-hiapi/package.json +24 -0
  5. package/packages/provider-hiapi/src/activation.ts +62 -0
  6. package/packages/provider-hiapi/src/errors.ts +44 -0
  7. package/packages/provider-hiapi/src/index.ts +2 -0
  8. package/packages/provider-hiapi/src/mapping.ts +129 -0
  9. package/packages/provider-hiapi/src/provider.ts +215 -0
  10. package/packages/provider-hiapi/src/routes.ts +154 -0
  11. package/packages/provider-monid/README.md +60 -0
  12. package/packages/provider-monid/package.json +19 -0
  13. package/packages/provider-monid/src/activation.ts +62 -0
  14. package/packages/provider-monid/src/errors.ts +55 -0
  15. package/packages/provider-monid/src/index.ts +2 -0
  16. package/packages/provider-monid/src/mapping.ts +33 -0
  17. package/packages/provider-monid/src/provider.ts +242 -0
  18. package/packages/provider-monid/src/routes.ts +103 -0
  19. package/packages/provider-pollo/README.md +59 -0
  20. package/packages/provider-pollo/package.json +22 -0
  21. package/packages/provider-pollo/src/activation.ts +62 -0
  22. package/packages/provider-pollo/src/errors.ts +41 -0
  23. package/packages/provider-pollo/src/index.ts +2 -0
  24. package/packages/provider-pollo/src/mapping.ts +60 -0
  25. package/packages/provider-pollo/src/provider.ts +194 -0
  26. package/packages/provider-pollo/src/routes.ts +120 -0
  27. package/packages/provider-tokendance/README.md +67 -0
  28. package/packages/provider-tokendance/package.json +21 -0
  29. package/packages/provider-tokendance/src/activation.ts +62 -0
  30. package/packages/provider-tokendance/src/errors.ts +47 -0
  31. package/packages/provider-tokendance/src/index.ts +2 -0
  32. package/packages/provider-tokendance/src/mapping.ts +60 -0
  33. package/packages/provider-tokendance/src/provider.ts +268 -0
  34. package/packages/provider-tokendance/src/routes.ts +192 -0
  35. package/packages/video-cli/package.json +4 -0
@@ -0,0 +1,192 @@
1
+ import {
2
+ compileWireRequest,
3
+ selectWireModelForRequest,
4
+ generationTypes,
5
+ sealGeneratedImageSet,
6
+ sealGeneratedVideoSet,
7
+ } from "@hypit/generation";
8
+ import type { GenerationArtifactUrlResolver, GenerationRequest, GenerationWireMapping } from "@hypit/generation";
9
+ import { canonicalize } from "@hypit/protocol";
10
+ import type { BlobRef, CapabilityRef, CanonicalValue, StoredValue, TypeRef } from "@hypit/protocol";
11
+ import type { EndpointRequest, EndpointSupport } from "@hypit/endpoint-kit";
12
+ import { tokenDanceMappings } from "./mapping.js";
13
+
14
+ /** Which TokenDance protocol a capability submits through. */
15
+ export type TokenDanceProtocol = "ark-video" | "ark-image" | "minimax-video";
16
+
17
+ export type TokenDancePreparedRequest = {
18
+ readonly model: string;
19
+ readonly protocol: TokenDanceProtocol;
20
+ readonly compile: (resolve: GenerationArtifactUrlResolver) => Promise<Record<string, unknown>>;
21
+ };
22
+
23
+ /** Documented byte limits for one protocol's media inputs; an absent kind is not accepted inline. */
24
+ export type TokenDanceMediaLimits = {
25
+ readonly image?: number;
26
+ readonly video?: number;
27
+ readonly audio?: number;
28
+ /** Documented cap on the whole JSON request body, when inline media count toward it. */
29
+ readonly body?: number;
30
+ };
31
+
32
+ const MB = 1_000_000;
33
+
34
+ /**
35
+ * Ark: images under 30 MB and audio at most 15 MB may travel as Base64 within a 64 MB request body;
36
+ * videos take URLs only. MiniMax: every kind is uploaded through its file API within these sizes.
37
+ */
38
+ export const tokenDanceMediaLimits: Readonly<Record<TokenDanceProtocol, TokenDanceMediaLimits>> = {
39
+ "ark-video": { image: 30 * MB, audio: 15 * MB, body: 64 * MB },
40
+ "ark-image": { image: 30 * MB },
41
+ "minimax-video": { image: 30 * MB, video: 50 * MB, audio: 15 * MB },
42
+ };
43
+
44
+ export type TokenDanceRoute = GenerationWireMapping & {
45
+ readonly key: string;
46
+ readonly returns: TypeRef;
47
+ readonly protocol: TokenDanceProtocol;
48
+ readonly mediaLimits: TokenDanceMediaLimits;
49
+ readonly supports: (request: EndpointRequest) => EndpointSupport;
50
+ readonly prepare: (constraints: CanonicalValue) => TokenDancePreparedRequest;
51
+ readonly packageResult: (artifacts: readonly BlobRef[]) => StoredValue;
52
+ };
53
+
54
+ function scalar(request: GenerationRequest, port: string): string | number | boolean | undefined {
55
+ const value = request.ports[port]?.[0];
56
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : undefined;
57
+ }
58
+ function present(request: GenerationRequest, port: string): boolean {
59
+ return (request.ports[port]?.length ?? 0) > 0;
60
+ }
61
+ function strings(value: unknown): readonly string[] {
62
+ return Array.isArray(value) ? value.filter((item): item is string => typeof item === "string" && item.length > 0) : [];
63
+ }
64
+
65
+ /** Seedream 5.0 lite pixel sizes for each resolution tier and aspect ratio, from the Ark image API reference. */
66
+ const SEEDREAM_SIZES: Readonly<Record<string, Readonly<Record<string, string>>>> = {
67
+ basic: { "1:1": "2048x2048", "4:3": "2304x1728", "3:4": "1728x2304", "16:9": "2848x1600", "9:16": "1600x2848", "3:2": "2496x1664", "2:3": "1664x2496", "21:9": "3136x1344" },
68
+ high: { "1:1": "3072x3072", "4:3": "3456x2592", "3:4": "2592x3456", "16:9": "4096x2304", "9:16": "2304x4096", "3:2": "3744x2496", "2:3": "2496x3744", "21:9": "4704x2016" },
69
+ ultra: { "1:1": "4096x4096", "4:3": "4704x3520", "3:4": "3520x4704", "16:9": "5504x3040", "9:16": "3040x5504", "3:2": "4992x3328", "2:3": "3328x4992", "21:9": "6240x2656" },
70
+ };
71
+
72
+ function rejection(mapping: GenerationWireMapping, request: GenerationRequest): string | undefined {
73
+ const ratio = scalar(request, "aspectRatio");
74
+ if (mapping.capability.module.name === "@hypit/seedance") {
75
+ if (mapping.capability.name === "seedance-2.5" && present(request, "firstFrame") && ratio !== "adaptive") {
76
+ return `Seedance 2.5 frame mode on TokenDance takes only aspect-ratio adaptive, not ${String(ratio)}`;
77
+ }
78
+ return undefined;
79
+ }
80
+ if (mapping.capability.module.name === "@hypit/seedream") {
81
+ const quality = String(scalar(request, "quality"));
82
+ if (SEEDREAM_SIZES[quality]?.[String(ratio)] === undefined) {
83
+ return `TokenDance Seedream 5.0 lite has no size for quality ${quality} at ${String(ratio)}`;
84
+ }
85
+ return undefined;
86
+ }
87
+ if (mapping.capability.module.name === "@hypit/minimax-h3") {
88
+ const hasMedia = ["referenceImage", "referenceVideo", "referenceAudio", "firstFrame", "lastFrame"]
89
+ .some((port) => present(request, port));
90
+ if (!hasMedia && (ratio === undefined || ratio === "adaptive")) {
91
+ return "MiniMax H3 text-to-video on TokenDance requires an explicit aspect-ratio";
92
+ }
93
+ }
94
+ return undefined;
95
+ }
96
+
97
+ function contentItem(type: "image_url" | "video_url" | "audio_url", url: string, role: string) {
98
+ return { type, [type]: { url }, role };
99
+ }
100
+
101
+ /** Ark and MiniMax both take one `content` array of typed, role-tagged items. */
102
+ function contentArray(input: Record<string, unknown>) {
103
+ const first = input.first_frame;
104
+ const last = input.last_frame;
105
+ return [
106
+ { type: "text", text: input.text },
107
+ ...(typeof first === "string" ? [contentItem("image_url", first, "first_frame")] : []),
108
+ ...(typeof last === "string" ? [contentItem("image_url", last, "last_frame")] : []),
109
+ ...strings(input.reference_image).map((url) => contentItem("image_url", url, "reference_image")),
110
+ ...strings(input.reference_video).map((url) => contentItem("video_url", url, "reference_video")),
111
+ ...strings(input.reference_audio).map((url) => contentItem("audio_url", url, "reference_audio")),
112
+ ];
113
+ }
114
+
115
+ function arkVideoBody(model: string, input: Record<string, unknown>): Record<string, unknown> {
116
+ return {
117
+ model,
118
+ content: contentArray(input),
119
+ resolution: input.resolution,
120
+ ratio: input.ratio,
121
+ duration: input.duration,
122
+ generate_audio: input.generate_audio,
123
+ ...(input.web_search === true ? { tools: [{ type: "web_search" }] } : {}),
124
+ };
125
+ }
126
+
127
+ function arkImageBody(model: string, input: Record<string, unknown>): Record<string, unknown> {
128
+ const images = strings(input.image);
129
+ return {
130
+ model,
131
+ prompt: input.prompt,
132
+ ...(images.length === 1 ? { image: images[0] } : images.length > 1 ? { image: images } : {}),
133
+ size: SEEDREAM_SIZES[String(input.quality)]![String(input.aspect_ratio)]!,
134
+ output_format: input.output_format,
135
+ response_format: "url",
136
+ watermark: false,
137
+ };
138
+ }
139
+
140
+ function minimaxVideoBody(model: string, input: Record<string, unknown>): Record<string, unknown> {
141
+ return {
142
+ model,
143
+ content: contentArray(input),
144
+ resolution: input.resolution,
145
+ duration: input.duration,
146
+ ...(typeof input.ratio === "string" ? { ratio: input.ratio } : {}),
147
+ };
148
+ }
149
+
150
+ function capabilityKey(capability: CapabilityRef): string {
151
+ return `${capability.module.name}@${capability.module.version}#${capability.name}`;
152
+ }
153
+
154
+ export const tokenDanceRoutes: readonly TokenDanceRoute[] = tokenDanceMappings.map((mapping) => {
155
+ const protocol: TokenDanceProtocol = mapping.capability.module.name === "@hypit/minimax-h3" ? "minimax-video"
156
+ : mapping.result === "image" ? "ark-image" : "ark-video";
157
+ const body = protocol === "ark-video" ? arkVideoBody : protocol === "ark-image" ? arkImageBody : minimaxVideoBody;
158
+ return {
159
+ ...mapping,
160
+ key: capabilityKey(mapping.capability),
161
+ returns: mapping.result === "image" ? generationTypes.imageSet : generationTypes.videoSet,
162
+ protocol,
163
+ mediaLimits: tokenDanceMediaLimits[protocol],
164
+ supports: (request) => {
165
+ const reason = rejection(mapping, request.constraints as unknown as GenerationRequest);
166
+ return reason === undefined ? { status: "supported" } : { status: "unsupported", reason };
167
+ },
168
+ prepare: (constraints) => {
169
+ const request = constraints as unknown as GenerationRequest;
170
+ const reason = rejection(mapping, request);
171
+ if (reason !== undefined) throw new Error(reason);
172
+ const model = selectWireModelForRequest(mapping, request);
173
+ return {
174
+ model,
175
+ protocol,
176
+ compile: async (resolve) => body(model, (await compileWireRequest(mapping, request, resolve)).input as Record<string, unknown>),
177
+ };
178
+ },
179
+ packageResult: (artifacts) => ({
180
+ kind: "inline",
181
+ value: canonicalize(mapping.result === "image"
182
+ ? sealGeneratedImageSet({ images: artifacts })
183
+ : sealGeneratedVideoSet({ videos: artifacts })),
184
+ }),
185
+ };
186
+ });
187
+
188
+ const byCapability = new Map(tokenDanceRoutes.map((route) => [route.key, route]));
189
+
190
+ export function tokenDanceRouteForCapability(capability: CapabilityRef): TokenDanceRoute | undefined {
191
+ return byCapability.get(capabilityKey(capability));
192
+ }
@@ -23,7 +23,11 @@
23
23
  "@hypit/package-loader-node": "workspace:*",
24
24
  "@hypit/project-context-node": "workspace:*",
25
25
  "@hypit/protocol": "workspace:*",
26
+ "@hypit/provider-hiapi": "workspace:*",
26
27
  "@hypit/provider-hypihub": "workspace:*",
28
+ "@hypit/provider-monid": "workspace:*",
29
+ "@hypit/provider-pollo": "workspace:*",
30
+ "@hypit/provider-tokendance": "workspace:*",
27
31
  "@hypit/runtime": "workspace:*",
28
32
  "@hypit/runtime-kit": "workspace:*",
29
33
  "@hypit/runtime-host-node": "workspace:*",