dsh-draw 0.1.3 → 0.2.2

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 (48) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.es.md +39 -32
  3. package/README.hi.md +39 -32
  4. package/README.md +41 -34
  5. package/README.pt.md +39 -32
  6. package/README.zh.md +39 -32
  7. package/cordis.patch.yml +5 -1
  8. package/lib/client.js +3 -2
  9. package/lib/client.js.map +1 -1
  10. package/lib/index.js +180 -13
  11. package/lib/types/client/DrawResultCard.d.ts +1 -1
  12. package/lib/types/client/DrawResultCard.d.ts.map +1 -1
  13. package/lib/types/client/index.d.ts +1 -1
  14. package/lib/types/client/index.d.ts.map +1 -1
  15. package/lib/types/client/index.js +3 -2
  16. package/lib/types/client/present.d.ts +40 -1
  17. package/lib/types/client/present.d.ts.map +1 -1
  18. package/lib/types/config.d.ts +6 -0
  19. package/lib/types/config.d.ts.map +1 -1
  20. package/lib/types/config.js +8 -0
  21. package/lib/types/event-gate.d.ts +8 -5
  22. package/lib/types/event-gate.d.ts.map +1 -1
  23. package/lib/types/event-gate.js +8 -5
  24. package/lib/types/index.d.ts +1 -0
  25. package/lib/types/index.d.ts.map +1 -1
  26. package/lib/types/index.js +1 -0
  27. package/lib/types/provider.d.ts +39 -0
  28. package/lib/types/provider.d.ts.map +1 -0
  29. package/lib/types/provider.js +192 -0
  30. package/lib/types/router.d.ts +1 -3
  31. package/lib/types/router.d.ts.map +1 -1
  32. package/lib/types/router.js +3 -7
  33. package/lib/types/session-events.d.ts +10 -8
  34. package/lib/types/session-events.d.ts.map +1 -1
  35. package/lib/types/session-events.js +12 -9
  36. package/lib/types/version.d.ts +1 -1
  37. package/lib/types/version.js +1 -1
  38. package/package.json +32 -6
  39. package/src/client/DrawResultCard.tsx +1 -2
  40. package/src/client/index.ts +18 -3
  41. package/src/client/present.ts +42 -1
  42. package/src/config.ts +15 -0
  43. package/src/event-gate.ts +9 -6
  44. package/src/index.ts +1 -0
  45. package/src/provider.ts +237 -0
  46. package/src/router.ts +4 -8
  47. package/src/session-events.ts +13 -10
  48. package/src/version.ts +1 -1
package/lib/index.js CHANGED
@@ -39,6 +39,7 @@ const DEFAULT_ENGINES = Object.freeze([Object.freeze({
39
39
  baseUrl: "https://api.openai.com/v1",
40
40
  model: "gpt-image-1",
41
41
  apiKeyRef: "OPENAI_API_KEY",
42
+ provider: "openai",
42
43
  enabled: true,
43
44
  sizeMap: Object.freeze({
44
45
  square: "1024x1024",
@@ -55,6 +56,7 @@ const DEFAULT_ENGINES = Object.freeze([Object.freeze({
55
56
  baseUrl: "https://open.bigmodel.cn/api/paas/v4",
56
57
  model: "cogview-3-flash",
57
58
  apiKeyRef: "ZHIPU_API_KEY",
59
+ provider: "openai",
58
60
  enabled: true,
59
61
  sizeMap: Object.freeze({
60
62
  square: "1024x1024",
@@ -81,6 +83,11 @@ const Config = z.object({
81
83
  baseUrl: z.string().min(1).max(2048),
82
84
  model: z.string().min(1).max(128),
83
85
  apiKeyRef: z.string().min(1).max(128),
86
+ provider: z.union([
87
+ "openai",
88
+ "replicate",
89
+ "fal"
90
+ ]),
84
91
  enabled: z.boolean(),
85
92
  sizeMap: z.object({
86
93
  square: z.string().min(1).max(64),
@@ -141,6 +148,8 @@ function resolveConfig(config) {
141
148
  if (model === "") throw new Error(`dsh-draw: engine "${id}" model must be a non-empty string of at most 128 characters`);
142
149
  const apiKeyRef = typeof engine.apiKeyRef === "string" && API_KEY_REF_PATTERN.test(engine.apiKeyRef) ? engine.apiKeyRef : "";
143
150
  if (apiKeyRef === "") throw new Error(`dsh-draw: engine "${id}" apiKeyRef ${JSON.stringify(engine.apiKeyRef)} must be an environment-variable name`);
151
+ const provider = engine.provider ?? "openai";
152
+ if (provider !== "openai" && provider !== "replicate" && provider !== "fal") throw new Error(`dsh-draw: engine "${id}" provider must be one of "openai", "replicate", "fal", got ${JSON.stringify(provider)}`);
144
153
  const sizeMap = engine.sizeMap === void 0 ? DEFAULT_SIZE_MAP : engine.sizeMap;
145
154
  for (const key of [
146
155
  "square",
@@ -166,6 +175,7 @@ function resolveConfig(config) {
166
175
  baseUrl: baseUrl.replace(/\/+$/u, ""),
167
176
  model,
168
177
  apiKeyRef,
178
+ provider,
169
179
  enabled,
170
180
  sizeMap: Object.freeze({ ...sizeMap }),
171
181
  qualitySupported,
@@ -223,7 +233,8 @@ function appendDrawGenerated(session, event) {
223
233
  }
224
234
  /**
225
235
  * In-memory accounting ledger for hosts whose session log cannot carry
226
- * `draw/generated` safely (rc.6/rc.7 static whitelist, no ignorable envelope).
236
+ * `draw/generated` safely (rc.6/rc.7 static whitelist and the envelope-less
237
+ * `0.1.2-alpha.1`, which fails closed on unknown types at read).
227
238
  * Keyed by Session identity: the entries live exactly as long as the session.
228
239
  */
229
240
  const fallbackLedger = /* @__PURE__ */ new WeakMap();
@@ -563,9 +574,11 @@ var Drawer = class {
563
574
  * package's types, so it sits outside every host's `KNOWN_SESSION_EVENT_TYPES`:
564
575
  * hosts whose session reader validates a static whitelist (rc.6/rc.7) refuse to
565
576
  * reopen a session containing the event unless it carries the `ignorable`
566
- * envelope — and those hosts' `Session.append` cannot stamp it. The gate
567
- * therefore appends only when the type is host-known or a mount-time probe
568
- * proves envelope support; otherwise the accounting payload goes to the
577
+ * envelope — and those hosts' `Session.append` cannot stamp it. The
578
+ * `0.1.2-alpha.1` host removed the envelope entirely and fails closed on
579
+ * unknown event types at read, so the probe never reports support there. The
580
+ * gate therefore appends only when the type is host-known or a mount-time
581
+ * probe proves envelope support; otherwise the accounting payload goes to the
569
582
  * in-memory fallback ledger (see session-events.ts) so quota keeps working for
570
583
  * the live session without poisoning the log.
571
584
  *
@@ -601,8 +614,9 @@ function makeEventGate(knownTypes, ignorableAppend = false) {
601
614
  * Probe whether the host `Session.append` stamps the ignorable envelope. Runs
602
615
  * on a fully detached SessionStore — never host persistence — appending one
603
616
  * probe event with `{ ignorable: true }` and reading the marker back. rc.6's
604
- * append silently drops the unknown options key (probe false); every failure
605
- * is contained as "unsupported".
617
+ * append silently drops the unknown options key (probe false), and the
618
+ * envelope-less `0.1.2-alpha.1` append takes no options at all (probe false);
619
+ * every failure is contained as "unsupported".
606
620
  *
607
621
  * @returns whether the envelope is honored.
608
622
  */
@@ -948,6 +962,163 @@ async function downloadImageUrl(engine, url, credential, deps, signal) {
948
962
  }
949
963
  }
950
964
  //#endregion
965
+ //#region src/provider.ts
966
+ /** The OpenAI-compatible adapter: delegates to the existing `/images/generations` path. */
967
+ const openaiProvider = {
968
+ vocabulary: "openai",
969
+ generate(engine, request, deps, signal) {
970
+ return callEngine(engine, translateRequest(engine, request), deps, signal);
971
+ }
972
+ };
973
+ /** Replicate prediction polling interval (ms). */
974
+ const REPLICATE_POLL_INTERVAL_MS = 1e3;
975
+ /** Maximum prediction polls before the call fails as a slow request. */
976
+ const REPLICATE_MAX_POLLS = 120;
977
+ /** Parse one concrete `WIDTHxHEIGHT` size string into dimensions. */
978
+ function dimensionsOf(size) {
979
+ const match = /^(\d{2,5})x(\d{2,5})$/u.exec(size);
980
+ if (match === null) return void 0;
981
+ return {
982
+ width: Number(match[1]),
983
+ height: Number(match[2])
984
+ };
985
+ }
986
+ /** Resolve an engine credential, failing closed when it is unconfigured. */
987
+ async function requireCredential(engine, deps) {
988
+ const credential = await deps.resolveCredential(engine.apiKeyRef);
989
+ if (credential === void 0) throw new EngineCallError("credential", "unconfigured", `engine "${engine.id}" has no resolved credential reference ${engine.apiKeyRef}`);
990
+ return credential;
991
+ }
992
+ /** Parse a JSON response body, failing with a structured parse error. */
993
+ function parseJson(engine, body) {
994
+ let parsed;
995
+ try {
996
+ parsed = JSON.parse(new TextDecoder().decode(body));
997
+ } catch (cause) {
998
+ throw new EngineCallError("parse", "parse", `engine "${engine.id}" returned a non-JSON response`, { cause });
999
+ }
1000
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new EngineCallError("parse", "parse", `engine "${engine.id}" returned a non-object payload`);
1001
+ return parsed;
1002
+ }
1003
+ /** Download one image URL with an explicit authorization header value. */
1004
+ async function downloadImage(engine, url, authorization, deps, signal) {
1005
+ const response = await deps.transport.request({
1006
+ method: "GET",
1007
+ url,
1008
+ headers: { authorization },
1009
+ ...signal === void 0 ? {} : { signal }
1010
+ });
1011
+ if (response.status < 200 || response.status >= 300) throw new EngineCallError("request", "http", `engine "${engine.id}" image download failed with HTTP ${response.status}`, { status: response.status });
1012
+ return response.body;
1013
+ }
1014
+ /** Sleep without swallowing the caller's abort (checked by the caller's loop). */
1015
+ function sleep(ms) {
1016
+ return new Promise((resolve) => setTimeout(resolve, ms));
1017
+ }
1018
+ /** The provider registry, keyed by vocabulary. */
1019
+ const PROVIDERS = Object.freeze({
1020
+ openai: openaiProvider,
1021
+ replicate: {
1022
+ vocabulary: "replicate",
1023
+ async generate(engine, request, deps, signal) {
1024
+ const credential = await requireCredential(engine, deps);
1025
+ const dimensions = dimensionsOf(engine.sizeMap[request.size ?? "square"]);
1026
+ const input = {
1027
+ prompt: request.prompt,
1028
+ num_outputs: request.count ?? 1,
1029
+ ...dimensions === void 0 ? {} : {
1030
+ width: dimensions.width,
1031
+ height: dimensions.height
1032
+ }
1033
+ };
1034
+ const create = await deps.transport.request({
1035
+ method: "POST",
1036
+ url: `${engine.baseUrl}/models/${engine.model}/predictions`,
1037
+ headers: {
1038
+ "content-type": "application/json",
1039
+ authorization: `Bearer ${credential}`
1040
+ },
1041
+ body: new TextEncoder().encode(JSON.stringify({ input })),
1042
+ ...signal === void 0 ? {} : { signal }
1043
+ });
1044
+ if (create.status === 401 || create.status === 403) throw new EngineCallError("request", "auth", `engine "${engine.id}" rejected the credential (HTTP ${create.status})`, { status: create.status });
1045
+ if (create.status < 200 || create.status >= 300) throw new EngineCallError("request", "http", `engine "${engine.id}" failed with HTTP ${create.status}`, { status: create.status });
1046
+ let prediction = parseJson(engine, create.body);
1047
+ const id = typeof prediction["id"] === "string" ? prediction["id"] : "";
1048
+ const urls = typeof prediction["urls"] === "object" && prediction["urls"] !== null ? prediction["urls"] : {};
1049
+ const pollUrl = typeof urls["get"] === "string" && urls["get"] !== "" ? urls["get"] : `${engine.baseUrl}/predictions/${id}`;
1050
+ for (let poll = 0; poll < REPLICATE_MAX_POLLS; poll += 1) {
1051
+ signal?.throwIfAborted();
1052
+ const status = typeof prediction["status"] === "string" ? prediction["status"] : "";
1053
+ if (status === "succeeded") break;
1054
+ if (status === "failed" || status === "canceled") throw new EngineCallError("request", "http", `engine "${engine.id}" prediction ${status}`);
1055
+ await sleep(REPLICATE_POLL_INTERVAL_MS);
1056
+ const polled = await deps.transport.request({
1057
+ method: "GET",
1058
+ url: pollUrl,
1059
+ headers: { authorization: `Bearer ${credential}` },
1060
+ ...signal === void 0 ? {} : { signal }
1061
+ });
1062
+ if (polled.status < 200 || polled.status >= 300) throw new EngineCallError("request", "http", `engine "${engine.id}" prediction poll failed with HTTP ${polled.status}`, { status: polled.status });
1063
+ prediction = parseJson(engine, polled.body);
1064
+ }
1065
+ if (prediction["status"] !== "succeeded") throw new EngineCallError("request", "http", `engine "${engine.id}" prediction did not finish within ${REPLICATE_MAX_POLLS} polls`);
1066
+ const output = prediction["output"];
1067
+ if (!Array.isArray(output)) throw new EngineCallError("parse", "parse", `engine "${engine.id}" prediction has no output array`);
1068
+ const images = [];
1069
+ for (const item of output) {
1070
+ if (typeof item !== "string" || item === "") throw new EngineCallError("parse", "parse", `engine "${engine.id}" prediction returned a non-URL output entry`);
1071
+ images.push({
1072
+ data: await downloadImage(engine, item, `Bearer ${credential}`, deps, signal),
1073
+ mediaType: engine.imageMediaType
1074
+ });
1075
+ }
1076
+ if (images.length === 0) throw new EngineCallError("parse", "parse", `engine "${engine.id}" prediction returned no images`);
1077
+ return images;
1078
+ }
1079
+ },
1080
+ fal: {
1081
+ vocabulary: "fal",
1082
+ async generate(engine, request, deps, signal) {
1083
+ const credential = await requireCredential(engine, deps);
1084
+ const body = {
1085
+ prompt: request.prompt,
1086
+ image_size: engine.sizeMap[request.size ?? "square"],
1087
+ num_images: request.count ?? 1
1088
+ };
1089
+ const response = await deps.transport.request({
1090
+ method: "POST",
1091
+ url: `${engine.baseUrl}/${engine.model}`,
1092
+ headers: {
1093
+ "content-type": "application/json",
1094
+ authorization: `Key ${credential}`
1095
+ },
1096
+ body: new TextEncoder().encode(JSON.stringify(body)),
1097
+ ...signal === void 0 ? {} : { signal }
1098
+ });
1099
+ if (response.status === 401 || response.status === 403) throw new EngineCallError("request", "auth", `engine "${engine.id}" rejected the credential (HTTP ${response.status})`, { status: response.status });
1100
+ if (response.status < 200 || response.status >= 300) throw new EngineCallError("request", "http", `engine "${engine.id}" failed with HTTP ${response.status}`, { status: response.status });
1101
+ const entries = parseJson(engine, response.body)["images"];
1102
+ if (!Array.isArray(entries)) throw new EngineCallError("parse", "parse", `engine "${engine.id}" response has no images array`);
1103
+ const images = [];
1104
+ for (const raw of entries) {
1105
+ const url = typeof raw === "object" && raw !== null ? raw["url"] : void 0;
1106
+ if (typeof url !== "string" || url === "") throw new EngineCallError("parse", "parse", `engine "${engine.id}" returned an image entry without a URL`);
1107
+ images.push({
1108
+ data: await downloadImage(engine, url, `Key ${credential}`, deps, signal),
1109
+ mediaType: engine.imageMediaType
1110
+ });
1111
+ }
1112
+ if (images.length === 0) throw new EngineCallError("parse", "parse", `engine "${engine.id}" returned no images`);
1113
+ return images;
1114
+ }
1115
+ }
1116
+ });
1117
+ /** Resolve the provider for one vocabulary (always present — the config gate restricts the value). */
1118
+ function providerFor(vocabulary) {
1119
+ return PROVIDERS[vocabulary];
1120
+ }
1121
+ //#endregion
951
1122
  //#region src/router.ts
952
1123
  /**
953
1124
  * The engine chain with per-engine health and cooldown. All mutations are
@@ -1001,7 +1172,7 @@ var EngineRouter = class {
1001
1172
  }
1002
1173
  tried += 1;
1003
1174
  try {
1004
- const images = await callEngine(engine, this.translate(engine, request), deps, signal);
1175
+ const images = await providerFor(engine.provider).generate(engine, request, deps, signal);
1005
1176
  this.recordSuccess(engine.id);
1006
1177
  attempts.push({
1007
1178
  engine: engine.id,
@@ -1145,10 +1316,6 @@ var EngineRouter = class {
1145
1316
  message: `engine "${engine.id}" is cooling down after repeated failures`
1146
1317
  };
1147
1318
  }
1148
- /** Translate the standard request against one engine (the pure translate step). */
1149
- translate(engine, request) {
1150
- return translateRequest(engine, request);
1151
- }
1152
1319
  /** Record a success: reset consecutive failures and cooldown. */
1153
1320
  recordSuccess(engineId) {
1154
1321
  const health = this.health.get(engineId);
@@ -1192,7 +1359,7 @@ var EngineRouter = class {
1192
1359
  * @module dsh-draw/version
1193
1360
  */
1194
1361
  /** Plugin version; must equal the `version` field in `package.json`. */
1195
- const PLUGIN_VERSION = "0.1.3";
1362
+ const PLUGIN_VERSION = "0.2.2";
1196
1363
  //#endregion
1197
1364
  //#region src/service.ts
1198
1365
  /**
@@ -1555,4 +1722,4 @@ async function apply(ctx, config) {
1555
1722
  logger.info(`image generation enabled: ${resolved.engines.map((engine) => engine.id).join(", ")} (preferred ${resolved.defaultEngine})`);
1556
1723
  }
1557
1724
  //#endregion
1558
- export { Config, DEFAULT_ENGINES, DRAW_INVOCATIONS, DrawService, Drawer, EngineCallError, EngineRouter, HttpError, PLUGIN_VERSION, REDACTED, appendDrawGenerated, apply, callEngine, checkQuotaBytes, checkQuotaGenerations, commitDrawGenerated, defaultHttpTransport, drawGeneratedEvents, engineById, fallbackDrawGeneratedEvents, fusedSignal, imageGenerateTool, imageToWire, inject, makeEventGate, makeHostEventGate, name, normalizeRequest, probeIgnorableAppend, probeToWire, quotaState, resolveConfig, sanitizeError, sanitizeText, sanitizeUrl, statusToView, translateRequest };
1725
+ export { Config, DEFAULT_ENGINES, DRAW_INVOCATIONS, DrawService, Drawer, EngineCallError, EngineRouter, HttpError, PLUGIN_VERSION, PROVIDERS, REDACTED, appendDrawGenerated, apply, callEngine, checkQuotaBytes, checkQuotaGenerations, commitDrawGenerated, defaultHttpTransport, drawGeneratedEvents, engineById, fallbackDrawGeneratedEvents, fusedSignal, imageGenerateTool, imageToWire, inject, makeEventGate, makeHostEventGate, name, normalizeRequest, probeIgnorableAppend, probeToWire, providerFor, quotaState, resolveConfig, sanitizeError, sanitizeText, sanitizeUrl, statusToView, translateRequest };
@@ -12,7 +12,7 @@
12
12
  */
13
13
  import { type ReactElement } from 'react';
14
14
  import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
15
- import type { ToolCallBlock } from '@deepseek-ai/dsh-client-runtime/client';
15
+ import { type ToolCallBlock } from './present.js';
16
16
  /**
17
17
  * Standard owner currency for one keyed tool view (mirror of the harness
18
18
  * ui-tool contract `ToolCallOwnerProps`, which the package index does not
@@ -1 +1 @@
1
- {"version":3,"file":"DrawResultCard.d.ts","sourceRoot":"","sources":["../../../src/client/DrawResultCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAG3E;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,KAAK,EAAE,aAAa,CAAA;IACpB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,OAAO;QACf,qEAAqE;QACrE,oBAAoB,EAAE;YAAE,IAAI,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,SAAS,CAAC;YAAC,KAAK,EAAE,kBAAkB,CAAA;SAAE,CAAA;KACrF;CACF;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAED,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAC7B,YAAY,CAAC,oBAAoB,CAAC,GAChC,WAAW,CAAC,MAAM,CAAC,GACnB,UAAU,CAAC,sBAAsB,CAAC,CAAA;AAEtC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CAqCvE"}
1
+ {"version":3,"file":"DrawResultCard.d.ts","sourceRoot":"","sources":["../../../src/client/DrawResultCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAgC,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAC7F,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,mEAAmE;IACnE,MAAM,EAAE,MAAM,CAAA;IACd,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAA;IAChB,kDAAkD;IAClD,KAAK,EAAE,aAAa,CAAA;IACpB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,OAAO;QACf,qEAAqE;QACrE,oBAAoB,EAAE;YAAE,IAAI,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,SAAS,CAAC;YAAC,KAAK,EAAE,kBAAkB,CAAA;SAAE,CAAA;KACrF;CACF;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAED,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAC7B,YAAY,CAAC,oBAAoB,CAAC,GAChC,WAAW,CAAC,MAAM,CAAC,GACnB,UAAU,CAAC,sBAAsB,CAAC,CAAA;AAEtC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CAqCvE"}
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * @module dsh-draw/client
9
9
  */
10
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
10
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
11
11
  import { type DrawLocaleKey } from './locales.js';
12
12
  export type { DrawResultCardInjected, DrawResultCardProps } from './DrawResultCard.js';
13
13
  export type { DrawSettingsTabInjected, DrawSettingsTabProps } from './DrawSettingsTab.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAS3E,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAMzD,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACvF,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE9I,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,4CAA4C;QAC5C,MAAM,EAAE,aAAa,CAAA;KACtB;CACF;AAED,iDAAiD;AACjD,eAAO,MAAM,EAAE,SAAS,CAAA;AAExB,kFAAkF;AAClF,eAAO,MAAM,IAAI,aAAa,CAAA;AAE9B,2FAA2F;AAC3F,eAAO,MAAM,MAAM,UAA4C,CAAA;AAE/D;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAWnE,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAMzD,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AACvF,YAAY,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAE9I,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,4CAA4C;QAC5C,MAAM,EAAE,aAAa,CAAA;KACtB;CACF;AAED,iDAAiD;AACjD,eAAO,MAAM,EAAE,SAAS,CAAA;AAExB,kFAAkF;AAClF,eAAO,MAAM,IAAI,aAAa,CAAA;AAE9B,2FAA2F;AAC3F,eAAO,MAAM,MAAM,UAA4C,CAAA;AAc/D;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAsD7D"}
@@ -34,13 +34,14 @@ export async function apply(ctx) {
34
34
  await ctx.remote.$mount(DRAW_REMOTE);
35
35
  ctx.inject(['remote.draw'], (scope) => {
36
36
  const t = scope.locale.bind(NS);
37
+ const slots = scope.get('slots');
37
38
  const unwrap = (result, method) => {
38
39
  if (!result.ok) {
39
40
  throw new Error(`draw.${method} failed: ${result.error.code}: ${result.error.message}`);
40
41
  }
41
42
  return result.value;
42
43
  };
43
- scope.slots.inject('tool.call.toolview', () => scope.slots.register({
44
+ slots.inject('tool.call.toolview', () => slots.register({
44
45
  name: 'tool.call.toolview',
45
46
  key: 'image_generate',
46
47
  locale: NS,
@@ -53,7 +54,7 @@ export async function apply(ctx) {
53
54
  },
54
55
  }),
55
56
  }, DrawResultCard));
56
- scope.slots.inject('settings.plugins.tab', () => scope.slots.register({
57
+ slots.inject('settings.plugins.tab', () => slots.register({
57
58
  name: 'settings.plugins.tab',
58
59
  id: 'draw',
59
60
  order: 40,
@@ -6,8 +6,47 @@
6
6
  *
7
7
  * @module dsh-draw/client/present
8
8
  */
9
- import type { ToolCallBlock } from '@deepseek-ai/dsh-client-runtime/client';
10
9
  import type { DrawStatusSnapshot } from '../wire.js';
10
+ /**
11
+ * Local structural contract for the frozen tool-call block the card reads.
12
+ * Declared locally because the owning packages publish the block union
13
+ * differently across host lines: the published `0.1.1-rc.2` line keeps it in
14
+ * the removed `dsh-client-runtime` package, and the unreleased
15
+ * `0.1.2-alpha.1` host owns it in the unpublished `dsh-client-ui-chat`. The
16
+ * runtime contract is structural — the presenter only discriminates on
17
+ * `kind` and reads the call head, error flag, and meta.
18
+ */
19
+ /** One frozen running tool call (no `kind`; the presenter's first guard drops it). */
20
+ export interface RunningToolCallBlock {
21
+ /** Tool call identity, stable across running and settled forms. */
22
+ callId: string;
23
+ /** Wire tool name. */
24
+ name: string;
25
+ /** Verbatim serialized arguments. */
26
+ argsRaw: string;
27
+ /** Owning turn. */
28
+ turn: number;
29
+ /** Owning step. */
30
+ step: number;
31
+ /** Unix epoch ms when the call was logged. */
32
+ time: number;
33
+ }
34
+ /** One settled tool result (fields the presenter reads). */
35
+ export interface SettledToolResultBlock {
36
+ kind: 'tool-result';
37
+ isError: boolean;
38
+ /** Call head; null when window truncation left the call outside. */
39
+ call: {
40
+ name: string;
41
+ argsRaw: string;
42
+ } | null;
43
+ /** Tool-owned presentation metadata (the card's engine/quota/limits facts). */
44
+ meta?: unknown;
45
+ }
46
+ /** Frozen running-or-settled tool block. */
47
+ export type ToolCallBlock = RunningToolCallBlock | SettledToolResultBlock;
48
+ /** Settled tool-result node only. */
49
+ export type ToolResultNode = SettledToolResultBlock;
11
50
  /** One image of the presented result card. */
12
51
  export interface PresentedImage {
13
52
  attachmentId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"present.d.ts","sourceRoot":"","sources":["../../../src/client/present.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEpD,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,uCAAuC;AACvC,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAA;IACd,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAA;IACrB,mCAAmC;IACnC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAA;IACjC,8CAA8C;IAC9C,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7C,wBAAwB;IACxB,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IACpD,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;CAC1C;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,mBAAmB,GAAG,SAAS,CAuCvF;AAED,sDAAsD;AACtD,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,EAAE,OAAO,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACtC,KAAK,EAAE;QAAE,wBAAwB,EAAE,MAAM,CAAC;QAAC,kBAAkB,EAAE,MAAM,CAAA;KAAE,CAAA;IACvE,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,kBAAkB,EAAE,GAAG,GAAE,MAAM,MAAiB,GAAG,kBAAkB,CAqB/G"}
1
+ {"version":3,"file":"present.d.ts","sourceRoot":"","sources":["../../../src/client/present.ts"],"names":[],"mappings":"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"}
@@ -51,6 +51,8 @@ export interface EngineSizeMap {
51
51
  }
52
52
  /** Whether generated images arrive as base64 payloads or downloadable URLs. */
53
53
  export type EngineResponseFormat = 'b64_json' | 'url';
54
+ /** The image-generation vocabularies a configured engine may declare (provider seam). */
55
+ export type EngineVocabulary = 'openai' | 'replicate' | 'fal';
54
56
  /** One OpenAI-compatible image-generation endpoint the router may use. */
55
57
  export interface EngineConfig {
56
58
  /** Stable engine id used in tool args, results, and the settings panel. */
@@ -61,6 +63,8 @@ export interface EngineConfig {
61
63
  model: string;
62
64
  /** Credential reference (environment-variable name) the API key resolves from; never a literal key. */
63
65
  apiKeyRef: string;
66
+ /** Which request/response vocabulary this engine speaks (default `openai`). */
67
+ provider?: EngineVocabulary;
64
68
  /** Whether the router may use this engine (default true). */
65
69
  enabled?: boolean;
66
70
  /** Standard-size → concrete-size translation (default: the OpenAI sizes). */
@@ -109,6 +113,8 @@ export interface ResolvedEngineConfig {
109
113
  model: string;
110
114
  /** Credential reference the API key resolves from. */
111
115
  apiKeyRef: string;
116
+ /** Request/response vocabulary this engine speaks. */
117
+ provider: EngineVocabulary;
112
118
  /** Whether the router may use this engine. */
113
119
  enabled: boolean;
114
120
  /** Standard-size → concrete-size translation. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAEjE,2DAA2D;AAC3D,eAAO,MAAM,0BAA0B,SAAU,CAAA;AAEjD,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,SAAU,CAAA;AAE7C,uDAAuD;AACvD,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAE5C,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,KAAK,CAAA;AAErC,8CAA8C;AAC9C,eAAO,MAAM,yBAAyB,OAAQ,CAAA;AAE9C,wCAAwC;AACxC,eAAO,MAAM,iBAAiB,QAAS,CAAA;AAEvC,+CAA+C;AAC/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD,sDAAsD;AACtD,eAAO,MAAM,2BAA2B,SAAU,CAAA;AAElD,oDAAoD;AACpD,eAAO,MAAM,6BAA6B,QAAoB,CAAA;AAE9D,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,QAAyB,CAAA;AAE3D,qEAAqE;AACrE,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAEvC,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,QAAS,CAAA;AAEzC,sCAAsC;AACtC,eAAO,MAAM,eAAe,UAAY,CAAA;AAExC,uFAAuF;AACvF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAA;AAEvE,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAA;IACd,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAA;CACb;AAED,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,KAAK,CAAA;AAErD,yFAAyF;AACzF,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,KAAK,CAAA;AAE7D,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,EAAE,EAAE,MAAM,CAAA;IACV,gGAAgG;IAChG,OAAO,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,uGAAuG;IACvG,SAAS,EAAE,MAAM,CAAA;IACjB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,gBAAgB,CAAA;IAC3B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,4EAA4E;IAC5E,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,oGAAoG;IACpG,cAAc,CAAC,EAAE,oBAAoB,CAAA;IACrC,8DAA8D;IAC9D,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED,4BAA4B;AAC5B,MAAM,WAAW,MAAM;IACrB,oFAAoF;IACpF,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,4GAA4G;IAC5G,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oEAAoE;IACpE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,qDAAqD;IACrD,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,gEAAgE;IAChE,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,yFAAyF;IACzF,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,uEAAuE;AACvE,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,CA2BhE,CAAA;AAEF,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,aAAa,CAKnD,CAAA;AAEF,+CAA+C;AAC/C,MAAM,WAAW,oBAAoB;IACnC,wBAAwB;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAA;IACjB,sDAAsD;IACtD,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAA;IAChB,iDAAiD;IACjD,OAAO,EAAE,aAAa,CAAA;IACtB,8DAA8D;IAC9D,gBAAgB,EAAE,OAAO,CAAA;IACzB,4DAA4D;IAC5D,cAAc,EAAE,OAAO,CAAA;IACvB,kCAAkC;IAClC,cAAc,EAAE,oBAAoB,CAAA;IACpC,wCAAwC;IACxC,cAAc,EAAE,cAAc,CAAA;CAC/B;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,4BAA4B;IAC5B,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACxC,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAA;IACrB,mDAAmD;IACnD,gBAAgB,EAAE,MAAM,CAAA;IACxB,0CAA0C;IAC1C,gBAAgB,EAAE,MAAM,CAAA;IACxB,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAA;IACvB,uCAAuC;IACvC,wBAAwB,EAAE,MAAM,CAAA;IAChC,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,CAAA;IAC1B,6DAA6D;IAC7D,gBAAgB,EAAE,MAAM,CAAA;IACxB,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,6DAA6D;AAC7D,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CA2B3B,CAAA;AAOF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAkHxE;AAED,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAE/F"}
@@ -42,6 +42,7 @@ export const DEFAULT_ENGINES = Object.freeze([
42
42
  baseUrl: 'https://api.openai.com/v1',
43
43
  model: 'gpt-image-1',
44
44
  apiKeyRef: 'OPENAI_API_KEY',
45
+ provider: 'openai',
45
46
  enabled: true,
46
47
  sizeMap: Object.freeze({ square: '1024x1024', landscape: '1536x1024', portrait: '1024x1536', auto: 'auto' }),
47
48
  qualitySupported: true,
@@ -54,6 +55,7 @@ export const DEFAULT_ENGINES = Object.freeze([
54
55
  baseUrl: 'https://open.bigmodel.cn/api/paas/v4',
55
56
  model: 'cogview-3-flash',
56
57
  apiKeyRef: 'ZHIPU_API_KEY',
58
+ provider: 'openai',
57
59
  enabled: true,
58
60
  sizeMap: Object.freeze({ square: '1024x1024', landscape: '1344x768', portrait: '768x1344', auto: '1024x1024' }),
59
61
  qualitySupported: false,
@@ -76,6 +78,7 @@ export const Config = z.object({
76
78
  baseUrl: z.string().min(1).max(2048),
77
79
  model: z.string().min(1).max(128),
78
80
  apiKeyRef: z.string().min(1).max(128),
81
+ provider: z.union(['openai', 'replicate', 'fal']),
79
82
  enabled: z.boolean(),
80
83
  sizeMap: z.object({
81
84
  square: z.string().min(1).max(64),
@@ -141,6 +144,10 @@ export function resolveConfig(config) {
141
144
  const apiKeyRef = typeof engine.apiKeyRef === 'string' && API_KEY_REF_PATTERN.test(engine.apiKeyRef) ? engine.apiKeyRef : '';
142
145
  if (apiKeyRef === '')
143
146
  throw new Error(`dsh-draw: engine "${id}" apiKeyRef ${JSON.stringify(engine.apiKeyRef)} must be an environment-variable name`);
147
+ const provider = engine.provider ?? 'openai';
148
+ if (provider !== 'openai' && provider !== 'replicate' && provider !== 'fal') {
149
+ throw new Error(`dsh-draw: engine "${id}" provider must be one of "openai", "replicate", "fal", got ${JSON.stringify(provider)}`);
150
+ }
144
151
  const sizeMap = engine.sizeMap === undefined ? DEFAULT_SIZE_MAP : engine.sizeMap;
145
152
  for (const key of ['square', 'landscape', 'portrait', 'auto']) {
146
153
  const value = sizeMap[key];
@@ -170,6 +177,7 @@ export function resolveConfig(config) {
170
177
  baseUrl: baseUrl.replace(/\/+$/u, ''),
171
178
  model,
172
179
  apiKeyRef,
180
+ provider,
173
181
  enabled,
174
182
  sizeMap: Object.freeze({ ...sizeMap }),
175
183
  qualitySupported,
@@ -3,9 +3,11 @@
3
3
  * package's types, so it sits outside every host's `KNOWN_SESSION_EVENT_TYPES`:
4
4
  * hosts whose session reader validates a static whitelist (rc.6/rc.7) refuse to
5
5
  * reopen a session containing the event unless it carries the `ignorable`
6
- * envelope — and those hosts' `Session.append` cannot stamp it. The gate
7
- * therefore appends only when the type is host-known or a mount-time probe
8
- * proves envelope support; otherwise the accounting payload goes to the
6
+ * envelope — and those hosts' `Session.append` cannot stamp it. The
7
+ * `0.1.2-alpha.1` host removed the envelope entirely and fails closed on
8
+ * unknown event types at read, so the probe never reports support there. The
9
+ * gate therefore appends only when the type is host-known or a mount-time
10
+ * probe proves envelope support; otherwise the accounting payload goes to the
9
11
  * in-memory fallback ledger (see session-events.ts) so quota keeps working for
10
12
  * the live session without poisoning the log.
11
13
  *
@@ -35,8 +37,9 @@ export declare function makeEventGate(knownTypes: ReadonlySet<string>, ignorable
35
37
  * Probe whether the host `Session.append` stamps the ignorable envelope. Runs
36
38
  * on a fully detached SessionStore — never host persistence — appending one
37
39
  * probe event with `{ ignorable: true }` and reading the marker back. rc.6's
38
- * append silently drops the unknown options key (probe false); every failure
39
- * is contained as "unsupported".
40
+ * append silently drops the unknown options key (probe false), and the
41
+ * envelope-less `0.1.2-alpha.1` append takes no options at all (probe false);
42
+ * every failure is contained as "unsupported".
40
43
  *
41
44
  * @returns whether the envelope is honored.
42
45
  */
@@ -1 +1 @@
1
- {"version":3,"file":"event-gate.d.ts","sourceRoot":"","sources":["../../src/event-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAA;IACf,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,CAAA;AAE3D;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,UAAQ,GAAG,SAAS,CAMjG;AAKD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAoB9C;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C"}
1
+ {"version":3,"file":"event-gate.d.ts","sourceRoot":"","sources":["../../src/event-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,2CAA2C;IAC3C,MAAM,EAAE,OAAO,CAAA;IACf,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,kDAAkD;AAClD,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,CAAA;AAE3D;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,UAAQ,GAAG,SAAS,CAMjG;AAKD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAoB9C;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C"}
@@ -3,9 +3,11 @@
3
3
  * package's types, so it sits outside every host's `KNOWN_SESSION_EVENT_TYPES`:
4
4
  * hosts whose session reader validates a static whitelist (rc.6/rc.7) refuse to
5
5
  * reopen a session containing the event unless it carries the `ignorable`
6
- * envelope — and those hosts' `Session.append` cannot stamp it. The gate
7
- * therefore appends only when the type is host-known or a mount-time probe
8
- * proves envelope support; otherwise the accounting payload goes to the
6
+ * envelope — and those hosts' `Session.append` cannot stamp it. The
7
+ * `0.1.2-alpha.1` host removed the envelope entirely and fails closed on
8
+ * unknown event types at read, so the probe never reports support there. The
9
+ * gate therefore appends only when the type is host-known or a mount-time
10
+ * probe proves envelope support; otherwise the accounting payload goes to the
9
11
  * in-memory fallback ledger (see session-events.ts) so quota keeps working for
10
12
  * the live session without poisoning the log.
11
13
  *
@@ -36,8 +38,9 @@ export function makeEventGate(knownTypes, ignorableAppend = false) {
36
38
  * Probe whether the host `Session.append` stamps the ignorable envelope. Runs
37
39
  * on a fully detached SessionStore — never host persistence — appending one
38
40
  * probe event with `{ ignorable: true }` and reading the marker back. rc.6's
39
- * append silently drops the unknown options key (probe false); every failure
40
- * is contained as "unsupported".
41
+ * append silently drops the unknown options key (probe false), and the
42
+ * envelope-less `0.1.2-alpha.1` append takes no options at all (probe false);
43
+ * every failure is contained as "unsupported".
41
44
  *
42
45
  * @returns whether the envelope is honored.
43
46
  */
@@ -25,6 +25,7 @@ export { imageGenerateTool } from './tool.js';
25
25
  export { DrawService } from './service.js';
26
26
  export { defaultHttpTransport, fusedSignal, type HttpTransport, type HttpRequest, type HttpResponse, HttpError } from './http.js';
27
27
  export { callEngine, EngineCallError, type EngineDeps, type ProducedImage } from './engine.js';
28
+ export { providerFor, PROVIDERS, type EngineProvider, type EngineVocabulary } from './provider.js';
28
29
  export { translateRequest, normalizeRequest, type StandardImageRequest } from './translate.js';
29
30
  export { quotaState, checkQuotaGenerations, checkQuotaBytes, type QuotaLimits, type QuotaState } from './quota.js';
30
31
  export { sanitizeUrl, sanitizeText, sanitizeError, REDACTED } from './sanitize.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAMlD,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAA;AAQnD,eAAO,MAAM,IAAI,aAAa,CAAA;AAE9B,oEAAoE;AACpE,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,MAAM,IAAI,UAAU,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAChI,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAClI,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACjI,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC9F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACzJ,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAChI,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAK7G;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAMlD,OAAO,EAAE,MAAM,EAAiB,MAAM,aAAa,CAAA;AAQnD,eAAO,MAAM,IAAI,aAAa,CAAA;AAE9B,oEAAoE;AACpE,eAAO,MAAM,MAAM,UAAY,CAAA;AAE/B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,MAAM,IAAI,UAAU,EAAE,KAAK,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAChI,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAClG,OAAO,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAClI,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AACjI,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9F,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAClG,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAC9F,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACzJ,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAChI,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAK7G;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCvE"}
@@ -31,6 +31,7 @@ export { imageGenerateTool } from './tool.js';
31
31
  export { DrawService } from './service.js';
32
32
  export { defaultHttpTransport, fusedSignal, HttpError } from './http.js';
33
33
  export { callEngine, EngineCallError } from './engine.js';
34
+ export { providerFor, PROVIDERS } from './provider.js';
34
35
  export { translateRequest, normalizeRequest } from './translate.js';
35
36
  export { quotaState, checkQuotaGenerations, checkQuotaBytes } from './quota.js';
36
37
  export { sanitizeUrl, sanitizeText, sanitizeError, REDACTED } from './sanitize.js';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The engine-provider seam: one adapter per image-generation vocabulary. The
3
+ * OpenAI provider is the existing OpenAI-compatible `POST /images/generations`
4
+ * adapter; `replicate` and `fal` adapters speak those vendors' native request
5
+ * and response shapes (prediction polling and `fal.run` queue respectively).
6
+ * A configured engine declares its vocabulary (`provider`); the router
7
+ * dispatches through {@link providerFor}, so cooldown fallback, quota, and the
8
+ * audit path stay vocabulary-agnostic.
9
+ *
10
+ * @module dsh-draw/provider
11
+ */
12
+ import type { ResolvedEngineConfig } from './config.js';
13
+ import { type EngineDeps, type ProducedImage } from './engine.js';
14
+ import type { StandardImageRequest } from './translate.js';
15
+ /** The image-generation vocabularies a configured engine may declare. */
16
+ export type EngineVocabulary = 'openai' | 'replicate' | 'fal';
17
+ /**
18
+ * One engine adapter: translates the standard tool request into a vendor
19
+ * request, calls it, and returns produced image bytes. A provider must never
20
+ * leak the credential — `deps.resolveCredential` resolves it per call.
21
+ */
22
+ export interface EngineProvider {
23
+ /** Which vocabulary this adapter speaks. */
24
+ readonly vocabulary: EngineVocabulary;
25
+ /**
26
+ * Generate images for one standardized request.
27
+ * @param engine - resolved engine configuration.
28
+ * @param request - normalized standard request.
29
+ * @param deps - transport and credential resolution.
30
+ * @param signal - caller cancellation.
31
+ * @returns the produced images.
32
+ */
33
+ generate(engine: ResolvedEngineConfig, request: StandardImageRequest, deps: EngineDeps, signal?: AbortSignal): Promise<ProducedImage[]>;
34
+ }
35
+ /** The provider registry, keyed by vocabulary. */
36
+ export declare const PROVIDERS: Readonly<Record<EngineVocabulary, EngineProvider>>;
37
+ /** Resolve the provider for one vocabulary (always present — the config gate restricts the value). */
38
+ export declare function providerFor(vocabulary: EngineVocabulary): EngineProvider;
39
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAGL,KAAK,UAAU,EACf,KAAK,aAAa,EACnB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAG1D,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,KAAK,CAAA;AAE7D;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAA;IACrC;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;CACxI;AAwLD,kDAAkD;AAClD,eAAO,MAAM,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAIvE,CAAA;AAEF,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,UAAU,EAAE,gBAAgB,GAAG,cAAc,CAExE"}