zyjj-web-sdk 1.1.34 → 2.0.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/lib/api/api.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AddTaskReq, GetCosResp, GetPageInfo, MqttClientInfo, UserLoginReq, GetPageReq, GetToolDetailResp, SendCommonRequestInfo } from './entity.ts';
2
2
  import { AppInfo, TaskInfo, ToolInfo, UserInfo } from "../types/cloud.ts";
3
+ export declare const base: string;
3
4
  export declare const UserLogin: (data: UserLoginReq) => Promise<string>;
4
5
  export declare const GetAppInfo: (os: string, version: string, uid?: string) => Promise<AppInfo>;
5
6
  export declare const UserRegister: (data: UserLoginReq) => Promise<void>;
@@ -22,7 +23,7 @@ export declare const ToolInc: (id: string) => Promise<unknown>;
22
23
  export declare const GetToolTagList: () => Promise<string[]>;
23
24
  export declare const GetTencentCosInfo: () => Promise<GetCosResp>;
24
25
  export declare const GetAliynOssInfo: () => Promise<GetCosResp>;
25
- export declare const AddTask: (data: AddTaskReq) => Promise<string>;
26
+ export declare const AddTask: (data: AddTaskReq) => Promise<string | Record<string, unknown>>;
26
27
  export declare const GetTaskInfo: (id: string) => Promise<TaskInfo>;
27
28
  export declare const GetMqttTaskClientInfo: () => Promise<MqttClientInfo>;
28
29
  export declare const GetMaterialTagList: () => Promise<string[]>;
@@ -30,8 +30,8 @@ export interface GetCosToken {
30
30
  TmpSecretKey: string;
31
31
  }
32
32
  export interface AddTaskReq {
33
- task_type: number;
34
- input: string;
33
+ entity_id: string;
34
+ input: Record<string, unknown>;
35
35
  source: string;
36
36
  }
37
37
  export interface MqttClientInfo {
@@ -0,0 +1,8 @@
1
+ import { type HostCapability, type HostClientV2, type HostEvent, type HostRequest, type HostResponse } from './types.ts';
2
+ export interface HostTransportV2 {
3
+ invoke<C extends HostCapability>(request: HostRequest<C>): Promise<HostResponse<C>>;
4
+ subscribe(listener: (event: HostEvent) => void): () => void;
5
+ cancel(requestId: string): Promise<void>;
6
+ dispose?(): Promise<void>;
7
+ }
8
+ export declare function createHostClientV2(transport: HostTransportV2): HostClientV2;
@@ -0,0 +1,17 @@
1
+ import { type HostRequest, type RemoteManifestV2 } from './types.ts';
2
+ export declare const validRuntimeInfoRequest: HostRequest;
3
+ export declare const invalidTraversalRequest: {
4
+ requestId: string;
5
+ contractVersion: "2.0.0";
6
+ capability: string;
7
+ payload: {
8
+ resource: {
9
+ id: string;
10
+ name: string;
11
+ mime: string;
12
+ size: number;
13
+ uri: string;
14
+ };
15
+ };
16
+ };
17
+ export declare const remoteManifestFixture: RemoteManifestV2;
@@ -0,0 +1,8 @@
1
+ export * from './types.ts';
2
+ export * from './schema.ts';
3
+ export * from './client.ts';
4
+ export * from './manifest.ts';
5
+ export * from './task-ledger.ts';
6
+ export * from './matrix.ts';
7
+ export * from './fixtures.ts';
8
+ export * from './remote-product.ts';
@@ -0,0 +1,314 @@
1
+ var L = Object.defineProperty;
2
+ var $ = (e, t, s) => t in e ? L(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
+ var E = (e, t, s) => $(e, typeof t != "symbol" ? t + "" : t, s);
4
+ const m = "2.0.0", N = ["system.getRuntimeInfo", "navigation.openExternal", "navigation.close", "navigation.reveal", "files.pick", "files.read", "files.write", "files.stat", "files.removeTemp", "ffmpeg.execute", "ffmpeg.probe", "ffmpeg.cancel", "downloads.start", "downloads.cancel", "tasks.create", "tasks.appendEvent", "tasks.snapshot", "tasks.list", "tasks.cancel", "tasks.clear", "cloud.upload", "cloud.download", "cloud.executeTask", "transport.subscribeTask", "transport.unsubscribeTask", "settings.get", "settings.set"], _ = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]), c = (e) => typeof e == "object" && e !== null && !Array.isArray(e), i = (e, t = 1024) => typeof e == "string" && e.length > 0 && e.length <= t, p = (e, t = 0, s = Number.MAX_SAFE_INTEGER) => typeof e == "number" && Number.isInteger(e) && e >= t && e <= s, u = (e, t = 0, s = Number.MAX_SAFE_INTEGER) => typeof e == "number" && Number.isFinite(e) && e >= t && e <= s, o = (e, t) => Object.keys(e).every((s) => t.includes(s)) && t.every((s) => Object.prototype.hasOwnProperty.call(e, s)), j = (e, t, s = []) => Object.keys(e).every((d) => [...t, ...s].includes(d)) && t.every((d) => Object.prototype.hasOwnProperty.call(e, d)), w = (e) => i(e, 4096) && (() => {
5
+ try {
6
+ const t = new URL(e);
7
+ return t.protocol === "https:" || t.protocol === "http:";
8
+ } catch {
9
+ return !1;
10
+ }
11
+ })(), S = (e, t = 0) => t <= 8 && (e === null || typeof e == "boolean" || typeof e == "string" && e.length <= 16 * 1024 || typeof e == "number" && Number.isFinite(e) || Array.isArray(e) && e.length <= 256 && e.every((s) => S(s, t + 1)) || c(e) && Object.keys(e).length <= 256 && Object.values(e).every((s) => S(s, t + 1))), z = (e, t) => S(e) && new TextEncoder().encode(JSON.stringify(e)).byteLength <= t;
12
+ function I(e) {
13
+ return c(e) && o(e, ["id", "name", "mime", "size"]) && i(e.id, 128) && i(e.name, 512) && i(e.mime, 128) && p(e.size, 0, 1024 * 1024 * 1024 * 16);
14
+ }
15
+ function T(e) {
16
+ return c(e) && o(e, ["eventId", "taskId", "seq", "at", "type", "data"]) && i(e.eventId, 128) && i(e.taskId, 128) && p(e.seq, 1) && i(e.at, 64) && !Number.isNaN(Date.parse(e.at)) && ["queued", "running", "stage.started", "stage.progress", "stage.retry", "log", "completed", "failed", "cancelled"].includes(String(e.type)) && c(e.data) && Object.keys(e.data).length <= 64 && Object.values(e.data).every((t) => t === null || ["string", "number", "boolean"].includes(typeof t));
17
+ }
18
+ function D(e) {
19
+ return c(e) && o(e, []);
20
+ }
21
+ const h = (e) => i(e, 128) && /^[A-Za-z0-9_-]+$/.test(e), C = (e) => typeof e == "string" && (e === "transparent" || /^#[0-9A-Fa-f]{6}$/.test(e)), M = (e) => {
22
+ for (let t = 0; t < e.length; t += 1) {
23
+ const s = e.charCodeAt(t);
24
+ if (s <= 31 || s === 127) return !0;
25
+ }
26
+ return !1;
27
+ }, k = (e) => p(e, 16, 4096) && e % 2 === 0, F = (e) => c(e) && o(e, ["startSeconds", "durationSeconds"]) && u(e.startSeconds, 0, 86400) && u(e.durationSeconds, 1e-3, 86400) && e.startSeconds + e.durationSeconds <= 86400, O = (e) => c(e) && o(e, ["sourceId", "resource", "mediaKind"]) && h(e.sourceId) && I(e.resource) && ["video", "audio", "image"].includes(String(e.mediaKind)), R = (e) => !(!c(e) || !j(e, ["name", "mime"], ["width", "height", "fps", "videoCodec", "audioCodec", "preset", "crf"]) || !i(e.name, 256) || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,255}$/.test(e.name) || !["video/mp4", "video/webm", "audio/mpeg", "audio/mp4", "image/png"].includes(String(e.mime)) || !{
28
+ "video/mp4": /\.mp4$/i,
29
+ "video/webm": /\.webm$/i,
30
+ "audio/mpeg": /\.mp3$/i,
31
+ "audio/mp4": /\.(?:m4a|mp4)$/i,
32
+ "image/png": /\.png$/i
33
+ }[String(e.mime)].test(e.name) || e.width !== void 0 && !k(e.width) || e.height !== void 0 && !k(e.height) || e.width === void 0 != (e.height === void 0) || e.fps !== void 0 && !p(e.fps, 1, 60) || e.videoCodec !== void 0 && !["copy", "libx264", "libvpx-vp9"].includes(String(e.videoCodec)) || e.audioCodec !== void 0 && !["copy", "aac", "libopus", "libmp3lame"].includes(String(e.audioCodec)) || e.preset !== void 0 && !["ultrafast", "veryfast", "fast", "medium", "slow"].includes(String(e.preset)) || e.crf !== void 0 && !p(e.crf, 0, 51) || e.mime === "video/mp4" && e.videoCodec !== void 0 && !["copy", "libx264"].includes(String(e.videoCodec)) || e.mime === "video/webm" && e.videoCodec !== void 0 && !["copy", "libvpx-vp9"].includes(String(e.videoCodec)) || e.mime === "audio/mpeg" && e.audioCodec !== "libmp3lame" || e.mime === "audio/mp4" && e.audioCodec !== "aac"), H = (e) => c(e) && o(e, ["x", "y", "width", "height", "rotation", "opacity"]) && p(e.x, -4096, 4096) && p(e.y, -4096, 4096) && k(e.width) && k(e.height) && u(e.rotation, -360, 360) && u(e.opacity, 0, 1);
34
+ function U(e) {
35
+ if (!c(e) || !["transcode", "composition", "frame-sequence"].includes(String(e.kind))) return !1;
36
+ if (e.kind === "transcode") {
37
+ if (!j(e, ["kind", "source", "includeVideo", "includeAudio", "output"], ["trim", "loop"]) || !O(e.source) || typeof e.includeVideo != "boolean" || typeof e.includeAudio != "boolean" || !e.includeVideo && !e.includeAudio || !R(e.output) || e.trim !== void 0 && !F(e.trim) || e.loop !== void 0 && typeof e.loop != "boolean") return !1;
38
+ const n = e.source, a = e.output;
39
+ return e.loop === !0 && n.mediaKind !== "image" || e.includeVideo && n.mediaKind === "audio" || !e.includeVideo && (a.videoCodec !== void 0 || a.width !== void 0 || a.fps !== void 0) || !e.includeAudio && a.audioCodec !== void 0 ? !1 : !(a.videoCodec === "copy" && (a.width !== void 0 || a.fps !== void 0));
40
+ }
41
+ if (e.kind === "frame-sequence") {
42
+ if (!o(e, ["kind", "width", "height", "fps", "frames", "output"]) || !k(e.width) || !k(e.height) || !p(e.fps, 1, 60) || !Array.isArray(e.frames) || e.frames.length < 2 || e.frames.length > 36e3 || !R(e.output)) return !1;
43
+ const n = e.output;
44
+ if (!["video/mp4", "video/webm"].includes(String(n.mime)) || n.width !== e.width || n.height !== e.height || n.fps !== e.fps || !["libx264", "libvpx-vp9"].includes(String(n.videoCodec)) || n.audioCodec !== void 0) return !1;
45
+ const a = /* @__PURE__ */ new Set();
46
+ let y = 0;
47
+ for (const f of e.frames) {
48
+ if (!c(f) || !o(f, ["frameId", "resource"]) || !h(f.frameId) || a.has(f.frameId) || !I(f.resource) || f.resource.mime !== "image/png") return !1;
49
+ a.add(f.frameId), y += f.resource.size;
50
+ }
51
+ return y <= 512 * 1024 * 1024 && e.width * e.height * e.frames.length <= 4e9;
52
+ }
53
+ if (!o(e, ["kind", "canvas", "sources", "videoTracks", "audioTracks", "textLayers", "output"]) || !c(e.canvas) || !o(e.canvas, ["width", "height", "fps", "durationSeconds", "background"]) || !k(e.canvas.width) || !k(e.canvas.height) || !p(e.canvas.fps, 1, 60) || !u(e.canvas.durationSeconds, 0.04, 3600) || !C(e.canvas.background) || !Array.isArray(e.sources) || e.sources.length > 64 || !Array.isArray(e.videoTracks) || e.videoTracks.length > 32 || !Array.isArray(e.audioTracks) || e.audioTracks.length > 32 || !Array.isArray(e.textLayers) || e.textLayers.length > 64 || !R(e.output)) return !1;
54
+ const t = e.output;
55
+ if (!["video/mp4", "video/webm"].includes(String(t.mime)) || t.width !== e.canvas.width || t.height !== e.canvas.height || t.fps !== e.canvas.fps || !["libx264", "libvpx-vp9"].includes(String(t.videoCodec))) return !1;
56
+ const s = /* @__PURE__ */ new Map();
57
+ let d = 0;
58
+ for (const n of e.sources) {
59
+ if (!O(n)) return !1;
60
+ const a = n;
61
+ if (s.has(a.sourceId)) return !1;
62
+ s.set(a.sourceId, a), d += a.resource.size;
63
+ }
64
+ if (d > 2 * 1024 * 1024 * 1024) return !1;
65
+ const r = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Set(), g = /* @__PURE__ */ new Set();
66
+ let b = 0;
67
+ for (const n of e.videoTracks) {
68
+ if (!c(n) || !o(n, ["trackId", "mode", "layer", "clips"]) || !h(n.trackId) || r.has(n.trackId) || !["concat", "overlay"].includes(String(n.mode)) || !p(n.layer, 0, 127) || g.has(n.layer) || !Array.isArray(n.clips) || !n.clips.length || n.clips.length > 128) return !1;
69
+ r.add(n.trackId), g.add(n.layer);
70
+ let a = null, y = null;
71
+ for (const f of n.clips) {
72
+ if (!c(f) || !o(f, ["clipId", "sourceId", "timelineStartSeconds", "sourceStartSeconds", "durationSeconds", "transform"]) || !h(f.clipId) || l.has(f.clipId) || !h(f.sourceId) || !u(f.timelineStartSeconds, 0, 3600) || !u(f.sourceStartSeconds, 0, 86400) || !u(f.durationSeconds, 0.04, 3600) || f.timelineStartSeconds + f.durationSeconds > e.canvas.durationSeconds + 1e-3 || !H(f.transform)) return !1;
73
+ const x = s.get(f.sourceId);
74
+ if (!x || !["video", "image"].includes(String(x.mediaKind)) || x.mediaKind === "image" && f.sourceStartSeconds !== 0 || n.mode === "concat" && a !== null && Math.abs(f.timelineStartSeconds - a) > 1e-3) return !1;
75
+ const A = f.transform, V = `${A.x}:${A.y}:${A.width}:${A.height}`;
76
+ if (n.mode === "concat" && y !== null && V !== y) return !1;
77
+ n.mode === "concat" && (y = V), a = f.timelineStartSeconds + f.durationSeconds, l.add(f.clipId), b += 1;
78
+ }
79
+ }
80
+ for (const n of e.audioTracks) {
81
+ if (!c(n) || !o(n, ["trackId", "clips"]) || !h(n.trackId) || r.has(n.trackId) || !Array.isArray(n.clips) || !n.clips.length || n.clips.length > 128) return !1;
82
+ r.add(n.trackId);
83
+ for (const a of n.clips) {
84
+ if (!c(a) || !o(a, ["clipId", "sourceId", "timelineStartSeconds", "sourceStartSeconds", "durationSeconds", "volume"]) || !h(a.clipId) || l.has(a.clipId) || !h(a.sourceId) || !u(a.timelineStartSeconds, 0, 3600) || !u(a.sourceStartSeconds, 0, 86400) || !u(a.durationSeconds, 0.04, 3600) || a.timelineStartSeconds + a.durationSeconds > e.canvas.durationSeconds + 1e-3 || !u(a.volume, 0, 4)) return !1;
85
+ const y = s.get(a.sourceId);
86
+ if (!y || !["video", "audio"].includes(String(y.mediaKind))) return !1;
87
+ l.add(a.clipId), b += 1;
88
+ }
89
+ }
90
+ for (const n of e.textLayers) {
91
+ if (!c(n) || !o(n, ["layerId", "text", "timelineStartSeconds", "durationSeconds", "x", "y", "fontSize", "color", "background", "opacity", "layer"]) || !h(n.layerId) || l.has(n.layerId) || !i(n.text, 512) || M(n.text) || !u(n.timelineStartSeconds, 0, 3600) || !u(n.durationSeconds, 0.04, 3600) || n.timelineStartSeconds + n.durationSeconds > e.canvas.durationSeconds + 1e-3 || !p(n.x, -4096, 4096) || !p(n.y, -4096, 4096) || !p(n.fontSize, 8, 400) || !C(n.color) || !C(n.background) || !u(n.opacity, 0, 1) || !p(n.layer, 0, 127) || g.has(n.layer)) return !1;
92
+ g.add(n.layer), l.add(n.layerId);
93
+ }
94
+ return e.audioTracks.length && !["aac", "libopus"].includes(String(t.audioCodec)) || !e.audioTracks.length && t.audioCodec !== void 0 ? !1 : b <= 256 && b + e.textLayers.length > 0;
95
+ }
96
+ function B(e, t) {
97
+ return c(t) ? ["system.getRuntimeInfo", "navigation.close", "tasks.list", "tasks.clear"].includes(e) ? D(t) : e === "navigation.openExternal" ? o(t, ["url"]) && w(t.url) : e === "navigation.reveal" || e === "files.read" || e === "files.stat" || e === "files.removeTemp" || e === "ffmpeg.probe" ? o(t, ["resource"]) && I(t.resource) : e === "cloud.upload" ? Object.keys(t).every((s) => ["resource", "taskId"].includes(s)) && Object.prototype.hasOwnProperty.call(t, "resource") && I(t.resource) && (t.taskId === void 0 || i(t.taskId, 128)) : e === "files.pick" ? o(t, ["accept", "multiple"]) && Array.isArray(t.accept) && t.accept.length <= 16 && t.accept.every((s) => i(s, 128)) && typeof t.multiple == "boolean" : e === "files.write" ? o(t, ["name", "mime", "bytesBase64"]) && i(t.name, 512) && i(t.mime, 128) && i(t.bytesBase64, 32 * 1024 * 1024) : e === "ffmpeg.execute" ? o(t, ["taskId", "plan"]) && i(t.taskId, 128) && U(t.plan) : e === "ffmpeg.cancel" || e === "tasks.snapshot" || e === "tasks.cancel" ? o(t, ["taskId"]) && i(t.taskId, 128) : e === "downloads.start" ? o(t, ["resource", "name"]) && I(t.resource) && i(t.name, 256) : e === "downloads.cancel" ? o(t, ["downloadId"]) && i(t.downloadId, 128) : e === "tasks.create" ? o(t, ["taskId", "releaseId", "schedulerVersion", "planSnapshot", "state", "lastEventSeq"]) && i(t.taskId, 128) && i(t.releaseId, 128) && i(t.schedulerVersion, 32) && c(t.planSnapshot) && S(t.planSnapshot) && t.state === "queued" && t.lastEventSeq === 0 : e === "tasks.appendEvent" ? o(t, ["taskId", "event"]) && i(t.taskId, 128) && T(t.event) && t.taskId === t.event.taskId : e === "cloud.download" ? o(t, ["url", "name"]) && w(t.url) && i(t.name, 256) : e === "cloud.executeTask" ? o(t, ["taskId", "entityId", "input", "execution"]) && i(t.taskId, 128) && i(t.entityId, 128) && c(t.input) && S(t.input) && ["sync", "async"].includes(String(t.execution)) : e === "transport.subscribeTask" ? o(t, ["taskId", "afterSeq"]) && i(t.taskId, 128) && p(t.afterSeq, 0) : e === "transport.unsubscribeTask" ? o(t, ["subscriptionId"]) && i(t.subscriptionId, 128) : e === "settings.get" ? o(t, ["key"]) && i(t.key, 128) : o(t, ["key", "value"]) && i(t.key, 128) && ["string", "number", "boolean"].includes(typeof t.value) : !1;
98
+ }
99
+ function P(e) {
100
+ return !c(e) || !o(e, ["requestId", "contractVersion", "capability", "payload"]) || !i(e.requestId, 128) || e.contractVersion !== m || !i(e.capability, 128) ? { ok: !1, issue: "invalid envelope" } : N.includes(e.capability) ? B(e.capability, e.payload) ? { ok: !0, value: e } : { ok: !1, issue: "invalid payload" } : { ok: !1, issue: "unknown capability" };
101
+ }
102
+ function K(e, t) {
103
+ return T(e) ? !t && !["queued", "running", "cancelled"].includes(e.type) ? { ok: !1, issue: "invalid initial task state transition" } : t && (t.taskId !== e.taskId || e.seq !== t.seq + 1 || t.eventId === e.eventId || _.has(t.type)) ? { ok: !1, issue: "invalid task event sequence" } : (t == null ? void 0 : t.type) === "queued" && !["running", "log", "cancelled", "failed"].includes(e.type) ? { ok: !1, issue: "invalid queued task transition" } : t && ["running", "stage.started", "stage.progress", "stage.retry", "log"].includes(t.type) && !["stage.started", "stage.progress", "stage.retry", "log", "completed", "failed", "cancelled"].includes(e.type) ? { ok: !1, issue: "invalid running task transition" } : { ok: !0, value: e } : { ok: !1, issue: "invalid task event" };
104
+ }
105
+ function Z(e) {
106
+ return c(e) && o(e, ["subscriptionId", "taskId", "type", "event"]) && i(e.subscriptionId, 128) && i(e.taskId, 128) && e.type === "task.event" && T(e.event) && e.taskId === e.event.taskId ? { ok: !0, value: e } : { ok: !1, issue: "invalid host event" };
107
+ }
108
+ function q(e) {
109
+ return c(e) && o(e, ["taskId", "releaseId", "schedulerVersion", "planSnapshot", "state", "lastEventSeq"]) && i(e.taskId, 128) && i(e.releaseId, 128) && i(e.schedulerVersion, 32) && c(e.planSnapshot) && S(e.planSnapshot) && ["queued", "running", "completed", "failed", "cancelled"].includes(String(e.state)) && p(e.lastEventSeq, 0);
110
+ }
111
+ function J(e, t) {
112
+ return e === "tasks.list" ? Array.isArray(t) && t.every(q) : c(t) ? ["navigation.openExternal", "navigation.close", "navigation.reveal", "transport.unsubscribeTask", "settings.set"].includes(e) ? o(t, []) : e === "system.getRuntimeInfo" ? o(t, ["platform", "contractVersion", "capabilities"]) && ["web", "electron"].includes(String(t.platform)) && t.contractVersion === m && Array.isArray(t.capabilities) && t.capabilities.every((s) => N.includes(s)) : e === "files.pick" ? o(t, ["resources"]) && Array.isArray(t.resources) && t.resources.every(I) : e === "files.read" ? o(t, ["bytesBase64"]) && typeof t.bytesBase64 == "string" && t.bytesBase64.length <= 32 * 1024 * 1024 : e === "files.write" || e === "cloud.download" ? o(t, ["resource"]) && I(t.resource) : e === "files.stat" ? o(t, ["name", "mime", "size"]) && i(t.name, 512) && i(t.mime, 128) && p(t.size, 0, 1024 * 1024 * 1024 * 16) : e === "files.removeTemp" ? o(t, ["removed"]) && i(t.removed, 128) : e === "ffmpeg.execute" ? o(t, ["outputs", "exitCode"]) && Array.isArray(t.outputs) && t.outputs.every(I) && p(t.exitCode, 0, 255) : e === "ffmpeg.probe" ? o(t, ["durationSeconds", "streams"]) && (t.durationSeconds === null || typeof t.durationSeconds == "number" && t.durationSeconds >= 0) && Array.isArray(t.streams) && t.streams.every((s) => c(s) && o(s, ["codec", "kind"]) && i(s.codec, 64) && ["video", "audio", "other"].includes(String(s.kind))) : e === "ffmpeg.cancel" || e === "tasks.cancel" ? o(t, ["cancelled"]) && i(t.cancelled, 128) : e === "downloads.start" ? o(t, ["downloadId"]) && i(t.downloadId, 128) : e === "downloads.cancel" ? o(t, ["cancelled"]) && i(t.cancelled, 128) : e === "tasks.create" ? q(t) : e === "tasks.appendEvent" ? o(t, ["acceptedSeq"]) && p(t.acceptedSeq, 1) : e === "tasks.snapshot" ? o(t, ["snapshot", "events"]) && (t.snapshot === null || q(t.snapshot)) && Array.isArray(t.events) && t.events.every(T) : e === "tasks.clear" ? o(t, ["cleared"]) && p(t.cleared, 0) : e === "cloud.upload" ? o(t, ["key", "backend"]) && i(t.key, 1024) && ["tencent-cos", "aliyun-oss"].includes(String(t.backend)) : e === "cloud.executeTask" ? o(t, ["backendTaskId", "output"]) && (t.backendTaskId === null || i(t.backendTaskId, 128)) && (t.output === null || c(t.output) && z(t.output, 64 * 1024)) : e === "transport.subscribeTask" ? o(t, ["subscriptionId"]) && i(t.subscriptionId, 128) : e === "settings.get" ? o(t, ["value"]) && (t.value === null || ["string", "number", "boolean"].includes(typeof t.value)) : !1 : !1;
113
+ }
114
+ function Q(e, t) {
115
+ if (!c(t) || !i(t.requestId, 128) || t.contractVersion !== m || typeof t.ok != "boolean") return { ok: !1, issue: "invalid host response envelope" };
116
+ if (t.ok) return o(t, ["requestId", "contractVersion", "ok", "data"]) && J(e, t.data) ? { ok: !0, value: t } : { ok: !1, issue: "invalid host response data" };
117
+ const s = t.error;
118
+ return o(t, ["requestId", "contractVersion", "ok", "error"]) && c(s) && o(s, ["code", "message", "retryable"]) && ["INVALID_REQUEST", "CONTRACT_VERSION_MISMATCH", "CAPABILITY_DENIED", "RESOURCE_DENIED", "NOT_FOUND", "CANCELLED", "CONFLICT", "INTERNAL"].includes(String(s.code)) && i(s.message, 1024) && typeof s.retryable == "boolean" ? { ok: !0, value: t } : { ok: !1, issue: "invalid host response error" };
119
+ }
120
+ function G(e) {
121
+ const t = c(e) && typeof e.issuedAt == "string" ? Date.parse(e.issuedAt) : Number.NaN;
122
+ if (!c(e) || !o(e, ["releaseId", "contractVersion", "uiEntry", "schedulerEntry", "assets", "requiredCapabilities", "issuedAt", "keyId", "signature"]) || !i(e.releaseId, 128) || e.contractVersion !== m || !w(e.uiEntry) || !w(e.schedulerEntry) || !Array.isArray(e.assets) || !Array.isArray(e.requiredCapabilities) || !i(e.issuedAt, 64) || Number.isNaN(t) || t > Date.now() + 3e5 || Date.now() - t > 1e3 * 60 * 60 * 24 * 30 || !i(e.keyId, 128) || !/^[A-Za-z0-9._-]+$/.test(e.keyId) || !i(e.signature, 8192)) return { ok: !1, issue: "invalid Remote manifest envelope" };
123
+ const s = /* @__PURE__ */ new Set();
124
+ for (const r of e.assets) {
125
+ if (!c(r) || !o(r, ["url", "size", "sha256", "kind", "contentType"]) || !w(r.url) || !p(r.size, 0, 512 * 1024 * 1024) || !/^[a-f0-9]{64}$/i.test(String(r.sha256)) || !["js", "css", "wasm", "asset"].includes(String(r.kind)) || !i(r.contentType, 128) || s.has(r.url) || r.kind === "js" && !["text/javascript", "application/javascript"].includes(String(r.contentType)) || r.kind === "css" && r.contentType !== "text/css" || r.kind === "wasm" && r.contentType !== "application/wasm") return { ok: !1, issue: "invalid Remote asset" };
126
+ s.add(r.url);
127
+ }
128
+ const d = e.assets.filter((r) => r.url === e.uiEntry || r.url === e.schedulerEntry);
129
+ return !s.has(e.uiEntry) || !s.has(e.schedulerEntry) || d.some((r) => r.kind !== "js") || !e.requiredCapabilities.every((r) => N.includes(r)) ? { ok: !1, issue: "invalid Remote manifest references" } : { ok: !0, value: e };
130
+ }
131
+ function v(e) {
132
+ return {
133
+ invoke: async (t) => {
134
+ const s = P(t), d = t && typeof t == "object" ? t : {}, r = typeof d.requestId == "string" && d.requestId.length > 0 && d.requestId.length <= 128 ? d.requestId : "invalid-request";
135
+ if (d.contractVersion !== m)
136
+ return { requestId: r, contractVersion: m, ok: !1, error: { code: "CONTRACT_VERSION_MISMATCH", message: "Host Contract v2 is required", retryable: !1 } };
137
+ if (!s.ok) return { requestId: r, contractVersion: m, ok: !1, error: { code: "INVALID_REQUEST", message: s.issue, retryable: !1 } };
138
+ try {
139
+ const l = await e.invoke(s.value), g = Q(t.capability, l);
140
+ return !g.ok || l.requestId !== t.requestId ? { requestId: r, contractVersion: m, ok: !1, error: { code: "INTERNAL", message: "Host returned an invalid Contract v2 response", retryable: !1 } } : g.value;
141
+ } catch (l) {
142
+ return { requestId: r, contractVersion: m, ok: !1, error: { code: "INTERNAL", message: l instanceof Error ? l.message : "Host transport failed", retryable: !0 } };
143
+ }
144
+ },
145
+ subscribe(t) {
146
+ return e.subscribe((s) => {
147
+ const d = Z(s);
148
+ d.ok && t(d.value);
149
+ });
150
+ },
151
+ async cancel(t) {
152
+ if (typeof t != "string" || t.length < 1 || t.length > 128) throw new Error("invalid requestId");
153
+ await e.cancel(t);
154
+ },
155
+ async dispose() {
156
+ var t;
157
+ await ((t = e.dispose) == null ? void 0 : t.call(e));
158
+ }
159
+ };
160
+ }
161
+ function X(e) {
162
+ return [...new Uint8Array(e)].map((t) => t.toString(16).padStart(2, "0")).join("");
163
+ }
164
+ function Y(e, t) {
165
+ return t.includes(new URL(e).origin);
166
+ }
167
+ async function ee(e, t) {
168
+ const s = G(e);
169
+ if (!s.ok) throw new Error(s.issue);
170
+ if (!e.requiredCapabilities.every((r) => t.capabilities.includes(r))) throw new Error("Remote capability is not available");
171
+ if (!await t.verifySignature(e)) throw new Error("Remote signature is invalid");
172
+ const d = /* @__PURE__ */ new Map();
173
+ for (const r of e.assets) {
174
+ if (!Y(r.url, t.allowOrigins) || r.size < 0 || !/^[a-f0-9]{64}$/i.test(r.sha256)) throw new Error("Remote asset is not allowed");
175
+ const l = await t.fetcher(r.url);
176
+ if (l.contentType.split(";", 1)[0].trim().toLowerCase() !== r.contentType.toLowerCase()) throw new Error(`Remote asset content-type mismatch: ${r.url}`);
177
+ if (l.bytes.byteLength !== r.size) throw new Error(`Remote asset size mismatch: ${r.url}`);
178
+ if (X(await crypto.subtle.digest("SHA-256", l.bytes)) !== r.sha256.toLowerCase()) throw new Error(`Remote asset hash mismatch: ${r.url}`);
179
+ d.set(r.url, l.bytes);
180
+ }
181
+ if (!d.has(e.uiEntry) || !d.has(e.schedulerEntry)) throw new Error("Remote entry is not declared as an asset");
182
+ return { manifest: e, assets: d };
183
+ }
184
+ class te {
185
+ constructor() {
186
+ E(this, "snapshots", /* @__PURE__ */ new Map());
187
+ E(this, "events", /* @__PURE__ */ new Map());
188
+ E(this, "requests", /* @__PURE__ */ new Map());
189
+ }
190
+ fingerprint(t) {
191
+ const s = (d) => Array.isArray(d) ? `[${d.map(s).join(",")}]` : d && typeof d == "object" ? `{${Object.entries(d).sort(([r], [l]) => r.localeCompare(l)).map(([r, l]) => `${JSON.stringify(r)}:${s(l)}`).join(",")}}` : JSON.stringify(d) ?? "null";
192
+ return s(t);
193
+ }
194
+ repeated(t, s, d) {
195
+ const r = this.requests.get(t);
196
+ if (r) {
197
+ if (r.operation !== s || r.fingerprint !== this.fingerprint(d)) throw new Error("CONFLICT: requestId replay payload differs");
198
+ return r.result;
199
+ }
200
+ }
201
+ apply(t) {
202
+ const s = this.snapshots.get(t.taskId);
203
+ if (!s) throw new Error("task not found");
204
+ const d = this.events.get(t.taskId) || [], r = K(t, d.at(-1) || null);
205
+ if (!r.ok) throw new Error(r.issue);
206
+ d.push(t), this.events.set(t.taskId, d);
207
+ const l = t.type === "running" ? "running" : t.type === "completed" ? "completed" : t.type === "failed" ? "failed" : t.type === "cancelled" ? "cancelled" : s.state;
208
+ return this.snapshots.set(t.taskId, { ...s, state: l, lastEventSeq: t.seq }), t.seq;
209
+ }
210
+ create(t) {
211
+ const s = this.snapshots.get(t.taskId);
212
+ return s || (this.snapshots.set(t.taskId, t), this.events.set(t.taskId, []), t);
213
+ }
214
+ append(t, s) {
215
+ const d = this.repeated(t, "append", s);
216
+ if (d !== void 0) return d;
217
+ const r = this.apply(s);
218
+ return this.requests.set(t, { operation: "append", fingerprint: this.fingerprint(s), result: r }), r;
219
+ }
220
+ cancel(t, s, d) {
221
+ const r = this.repeated(t, "cancel", { taskId: s });
222
+ if (r !== void 0) return r;
223
+ const l = this.snapshots.get(s);
224
+ if (!l) throw new Error("task not found");
225
+ const g = this.apply({ eventId: t, taskId: s, seq: l.lastEventSeq + 1, at: d, type: "cancelled", data: {} });
226
+ return this.requests.set(t, { operation: "cancel", fingerprint: this.fingerprint({ taskId: s }), result: g }), g;
227
+ }
228
+ read(t) {
229
+ return { snapshot: this.snapshots.get(t) || null, events: [...this.events.get(t) || []] };
230
+ }
231
+ }
232
+ const se = [
233
+ ["system.getRuntimeInfo", !1],
234
+ ["navigation.openExternal", !1],
235
+ ["navigation.close", !1],
236
+ ["navigation.reveal", !1],
237
+ ["files.pick", !1],
238
+ ["files.read", !1],
239
+ ["files.write", !1],
240
+ ["files.stat", !1],
241
+ ["files.removeTemp", !1],
242
+ ["ffmpeg.execute", !0],
243
+ ["ffmpeg.probe", !1],
244
+ ["ffmpeg.cancel", !0],
245
+ ["downloads.start", !1],
246
+ ["downloads.cancel", !1],
247
+ ["tasks.create", !0],
248
+ ["tasks.appendEvent", !0],
249
+ ["tasks.snapshot", !1],
250
+ ["tasks.list", !1],
251
+ ["tasks.cancel", !0],
252
+ ["tasks.clear", !1],
253
+ ["cloud.upload", !0],
254
+ ["cloud.download", !1],
255
+ ["cloud.executeTask", !0],
256
+ ["transport.subscribeTask", !1],
257
+ ["transport.unsubscribeTask", !1],
258
+ ["settings.get", !1],
259
+ ["settings.set", !1]
260
+ ].map(([e, t]) => ({ capability: e, response: !0, event: t })), re = {
261
+ requestId: "fixture-runtime-info",
262
+ contractVersion: m,
263
+ capability: "system.getRuntimeInfo",
264
+ payload: {}
265
+ }, ne = {
266
+ requestId: "fixture-traversal",
267
+ contractVersion: m,
268
+ capability: "files.read",
269
+ payload: { resource: { id: "x", name: "x", mime: "text/plain", size: 1, uri: "../secret" } }
270
+ }, oe = {
271
+ releaseId: "fixture-release",
272
+ contractVersion: m,
273
+ uiEntry: "https://remote.example.test/runtime.js",
274
+ schedulerEntry: "https://remote.example.test/runtime.js",
275
+ assets: [{ url: "https://remote.example.test/runtime.js", size: 0, sha256: "0".repeat(64), kind: "js", contentType: "text/javascript" }],
276
+ requiredCapabilities: ["system.getRuntimeInfo"],
277
+ issuedAt: "2026-01-01T00:00:00.000Z",
278
+ keyId: "fixture",
279
+ signature: "fixture"
280
+ }, ie = [
281
+ "system.getRuntimeInfo",
282
+ "files.pick",
283
+ "files.read",
284
+ "files.write",
285
+ "files.removeTemp",
286
+ "ffmpeg.execute",
287
+ "ffmpeg.probe",
288
+ "downloads.start",
289
+ "tasks.create",
290
+ "tasks.appendEvent",
291
+ "tasks.list",
292
+ "tasks.cancel",
293
+ "cloud.upload",
294
+ "cloud.download",
295
+ "cloud.executeTask",
296
+ "transport.subscribeTask",
297
+ "transport.unsubscribeTask"
298
+ ];
299
+ export {
300
+ m as CONTRACT_VERSION_V2,
301
+ ie as REMOTE_PRODUCT_REQUIRED_CAPABILITIES,
302
+ te as TaskLedgerV2,
303
+ se as capabilityMatrix,
304
+ v as createHostClientV2,
305
+ ne as invalidTraversalRequest,
306
+ oe as remoteManifestFixture,
307
+ re as validRuntimeInfoRequest,
308
+ Z as validateHostEvent,
309
+ P as validateHostRequest,
310
+ Q as validateHostResponse,
311
+ G as validateRemoteManifest,
312
+ K as validateTaskEvent,
313
+ ee as verifyRemoteRelease
314
+ };
@@ -0,0 +1,15 @@
1
+ import { type HostCapability, type RemoteManifestV2 } from './types.ts';
2
+ export interface VerifiedRemoteRelease {
3
+ manifest: RemoteManifestV2;
4
+ assets: Map<string, Uint8Array>;
5
+ }
6
+ export interface RemoteVerificationOptions {
7
+ allowOrigins: string[];
8
+ capabilities: HostCapability[];
9
+ verifySignature(manifest: RemoteManifestV2): Promise<boolean>;
10
+ fetcher(url: string): Promise<{
11
+ bytes: Uint8Array;
12
+ contentType: string;
13
+ }>;
14
+ }
15
+ export declare function verifyRemoteRelease(manifest: RemoteManifestV2, options: RemoteVerificationOptions): Promise<VerifiedRemoteRelease>;
@@ -0,0 +1,8 @@
1
+ import type { HostCapability } from './types.ts';
2
+ export interface CapabilityMatrixRow {
3
+ capability: HostCapability;
4
+ response: true;
5
+ event: boolean;
6
+ }
7
+ /** Single audit source: every v2 invocation has a response; task lifecycle changes emit an event. */
8
+ export declare const capabilityMatrix: readonly CapabilityMatrixRow[];
@@ -0,0 +1,2 @@
1
+ /** Audited directly against Remote Product Runtime's production Host calls. */
2
+ export declare const REMOTE_PRODUCT_REQUIRED_CAPABILITIES: readonly ["system.getRuntimeInfo", "files.pick", "files.read", "files.write", "files.removeTemp", "ffmpeg.execute", "ffmpeg.probe", "downloads.start", "tasks.create", "tasks.appendEvent", "tasks.list", "tasks.cancel", "cloud.upload", "cloud.download", "cloud.executeTask", "transport.subscribeTask", "transport.unsubscribeTask"];
@@ -0,0 +1,13 @@
1
+ import { type HostCapability, type HostEvent, type HostRequest, type HostResponse, type RemoteManifestV2, type TaskEventRecordV2 } from './types.ts';
2
+ export type ValidationResult<T> = {
3
+ ok: true;
4
+ value: T;
5
+ } | {
6
+ ok: false;
7
+ issue: string;
8
+ };
9
+ export declare function validateHostRequest(input: unknown): ValidationResult<HostRequest>;
10
+ export declare function validateTaskEvent(recordValue: unknown, previous: TaskEventRecordV2 | null): ValidationResult<TaskEventRecordV2>;
11
+ export declare function validateHostEvent(input: unknown): ValidationResult<HostEvent>;
12
+ export declare function validateHostResponse(capability: HostCapability, input: unknown): ValidationResult<HostResponse>;
13
+ export declare function validateRemoteManifest(input: unknown): ValidationResult<RemoteManifestV2>;
@@ -0,0 +1,16 @@
1
+ import type { TaskEventRecordV2, TaskSnapshotV2 } from './types.ts';
2
+ export declare class TaskLedgerV2 {
3
+ private readonly snapshots;
4
+ private readonly events;
5
+ private readonly requests;
6
+ private fingerprint;
7
+ private repeated;
8
+ private apply;
9
+ create(snapshot: TaskSnapshotV2): TaskSnapshotV2;
10
+ append(requestId: string, event: TaskEventRecordV2): number;
11
+ cancel(requestId: string, taskId: string, at: string): number;
12
+ read(taskId: string): {
13
+ snapshot: TaskSnapshotV2 | null;
14
+ events: TaskEventRecordV2[];
15
+ };
16
+ }