dsh-draw 0.1.0 → 0.1.1
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/CHANGELOG.md +12 -0
- package/README.es.md +5 -4
- package/README.hi.md +5 -4
- package/README.md +5 -4
- package/README.pt.md +5 -4
- package/README.zh.md +5 -4
- package/lib/index.js +137 -9
- package/lib/types/client/DrawSettingsTab.d.ts +1 -1
- package/lib/types/client/index.d.ts +5 -5
- package/lib/types/client/present.d.ts +1 -1
- package/lib/types/client/remote.d.ts +1 -1
- package/lib/types/drawer.d.ts +15 -5
- package/lib/types/drawer.d.ts.map +1 -1
- package/lib/types/drawer.js +7 -4
- package/lib/types/engine.d.ts +3 -3
- package/lib/types/event-gate.d.ts +46 -0
- package/lib/types/event-gate.d.ts.map +1 -0
- package/lib/types/event-gate.js +69 -0
- package/lib/types/index.d.ts +15 -14
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +7 -2
- package/lib/types/quota.d.ts +11 -5
- package/lib/types/quota.d.ts.map +1 -1
- package/lib/types/quota.js +16 -6
- package/lib/types/router.d.ts +3 -3
- package/lib/types/service.d.ts +4 -4
- package/lib/types/session-events.d.ts +32 -1
- package/lib/types/session-events.d.ts.map +1 -1
- package/lib/types/session-events.js +59 -3
- package/lib/types/tool.d.ts +2 -2
- package/lib/types/translate.d.ts +1 -1
- package/lib/types/version.d.ts +1 -1
- package/lib/types/version.js +1 -1
- package/lib/types/wire.d.ts +3 -3
- package/package.json +34 -29
- package/src/drawer.ts +14 -3
- package/src/event-gate.ts +84 -0
- package/src/index.ts +7 -2
- package/src/quota.ts +16 -6
- package/src/session-events.ts +63 -3
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.1.1] - 2026-08-21
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Upgraded every `@deepseek-ai/dsh-*` peer to `>=0.1.0-rc.8 <0.2.0` and every devDependency to `0.1.0-rc.8` (rc.8 compatibility release); `@deepseek-ai/cordis` stays at `^4.0.1`.
|
|
13
|
+
- `tests/harness.ts` pins the rc.8 `ImageAttachmentLimits` face (adds `maxImageDimension`).
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Sessions that used image generation no longer refuse to reopen on rc.6/rc.7 hosts (issue #2). `draw/generated` is declared only by this package, so it sits outside the host's static `KNOWN_SESSION_EVENT_TYPES` whitelist, and those hosts' `Session.append` cannot stamp the `ignorable` envelope — every generated image left the log unloadable after restart with `SessionFormatUnsupportedError`. The append now goes through an adaptive gate (`src/event-gate.ts`): the event is logged only when the host knows the type or a mount-time probe on a detached `SessionStore` proves envelope support. On gated hosts the accounting payload rides a new in-memory fallback ledger (WeakMap-keyed by session), so quota stays exact for the live session and the log stays reloadable; durable, log-folded accounting resumes on hosts with a plugin event surface.
|
|
18
|
+
- Regression coverage: `tests/event-gate.spec.ts` pins the gate decisions, the rc.6 probe reading, fallback-ledger quota accounting, and the append-failure degradation; the assembly regenerate test now asserts the rc.6-safe behavior (clean log, exact quota).
|
|
19
|
+
|
|
8
20
|
## [0.1.0] - 2026-08-16
|
|
9
21
|
|
|
10
22
|
- Initial release: unified image_generate tool with config-driven engine routing, health-aware fallback, durable attachments, per-session quota accounting, and credential-reference key storage.
|
package/README.es.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
| Superficie | Estado |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Harness | DeepSeek Harness `0.1.0-rc.
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.8` (compatibilidad declarada para `0.1.0-rc.8`) |
|
|
28
28
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
29
|
| Motores | Cualquier endpoint de imágenes compatible con OpenAI; presets para OpenAI Images (`gpt-image-1`) y Zhipu CogView (`cogview-3-flash`) |
|
|
30
30
|
| Superficies | Herramienta host `image_generate` + tarjeta de resultado web + pestaña de ajustes de Plugins |
|
|
@@ -116,8 +116,8 @@ Ejemplo de sobrescritura en el parche de tu perfil:
|
|
|
116
116
|
## Permisos y datos
|
|
117
117
|
|
|
118
118
|
- **Permisos**: el plugin solo hace llamadas HTTPS salientes a los endpoints de motor configurados; el resto es de solo lectura. Las únicas escrituras de la pestaña de ajustes son las llamadas de establecer/eliminar credenciales en el seam oficial `ctx.credentials`.
|
|
119
|
-
- **Datos**: las imágenes generadas se guardan a través del almacén de adjuntos oficial bajo la política de adjuntos del harness. El uso de cuota se pliega desde los eventos de sesión `draw/generated
|
|
120
|
-
- **Registro de sesión**: el evento `draw/generated` registra motor, modelo, solicitud estandarizada, totales de bytes e ids de adjunto — los hechos de auditoría, nunca las claves API.
|
|
119
|
+
- **Datos**: las imágenes generadas se guardan a través del almacén de adjuntos oficial bajo la política de adjuntos del harness. El uso de cuota se pliega desde los eventos de sesión `draw/generated`, más el libro auxiliar en memoria en hosts que no pueden registrar esos eventos — nada más se almacena.
|
|
120
|
+
- **Registro de sesión**: el evento `draw/generated` registra motor, modelo, solicitud estandarizada, totales de bytes e ids de adjunto — los hechos de auditoría, nunca las claves API. El evento solo se añade cuando el host conoce el tipo o admite el sobre `ignorable` (sondeado al montar); en hosts rc.6/rc.7 la carga va al libro auxiliar en memoria, de modo que generar imágenes ya no hace que la sesión se niegue a reabrirse.
|
|
121
121
|
|
|
122
122
|
## Límites de seguridad
|
|
123
123
|
|
|
@@ -131,13 +131,14 @@ Ejemplo de sobrescritura en el parche de tu perfil:
|
|
|
131
131
|
- **Solo modelos de imagen.** Sin endpoints de vídeo, audio o edición; sin comprensión visual.
|
|
132
132
|
- **Compatibilidad de motores.** Los motores deben hablar la forma `POST /images/generations` de OpenAI (entrega base64 o URL); los extras específicos de cada proveedor quedan fuera.
|
|
133
133
|
- **La conciencia de coste es estructural.** El plugin cuenta llamadas y bytes pero no conoce el precio de los motores — combínalo con `dsh-budget` para la gobernanza de coste.
|
|
134
|
+
- **Durabilidad de cuota en rc.6/rc.7.** En hosts cuyo registro de sesión no puede llevar `draw/generated` (lista blanca estática de eventos, sin sobre `ignorable`), la cuota sigue exacta en la sesión viva desde el libro auxiliar en memoria pero se reinicia al reiniciar; la contabilidad duradera vuelve en hosts con una superficie de eventos para plugins.
|
|
134
135
|
|
|
135
136
|
## Desarrollo
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install # node ^22.19 || >=24
|
|
139
140
|
pnpm run typecheck # tsc: src + tests contra el checkout local del harness
|
|
140
|
-
pnpm run typecheck:ci # tsc contra las caras publicadas 0.1.0-rc.
|
|
141
|
+
pnpm run typecheck:ci # tsc contra las caras publicadas 0.1.0-rc.8 (sin paths)
|
|
141
142
|
pnpm test # vitest: 77 tests, 11 suites (transporte guionado, Context/Session/ToolRuntime reales)
|
|
142
143
|
pnpm run build # declaraciones tsc + bundles tsdown (lib/)
|
|
143
144
|
pnpm run verify:self-contained # las especificaciones de dependencias resuelven desde el registry
|
package/README.hi.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
| सतह | स्थिति |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Harness | DeepSeek Harness `0.1.0-rc.
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.8` (`0.1.0-rc.8` के लिए घोषित संगतता) |
|
|
28
28
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
29
|
| इंजन | कोई भी OpenAI-संगत images एंडपॉइंट; OpenAI Images (`gpt-image-1`) और Zhipu CogView (`cogview-3-flash`) प्रीसेट |
|
|
30
30
|
| सतहें | Host `image_generate` टूल + वेब परिणाम कार्ड + Plugins सेटिंग टैब |
|
|
@@ -116,8 +116,8 @@ dsh --profile web --dump-config | grep -A2 'id: dsh-draw'
|
|
|
116
116
|
## अनुमतियाँ और डेटा
|
|
117
117
|
|
|
118
118
|
- **अनुमतियाँ**: प्लगइन केवल कॉन्फ़िगर किए इंजन एंडपॉइंट पर आउटबाउंड HTTPS कॉल करता है; बाकी सब केवल-पठन है। सेटिंग टैब का एकमात्र लेखन आधिकारिक `ctx.credentials` सीम पर क्रेडेंशियल सेट/हटाना है।
|
|
119
|
-
- **डेटा**: बनी छवियाँ आधिकारिक अटैचमेंट स्टोर से हार्नेस की अपनी नीति के तहत सहेजी जाती हैं। कोटा उपयोग `draw/generated` सत्र इवेंट से मोड़ा जाता
|
|
120
|
-
- **सत्र लॉग**: `draw/generated` इवेंट इंजन, मॉडल, मानकीकृत अनुरोध, बाइट योग और अटैचमेंट आईडी दर्ज करता है — ऑडिट तथ्य, कभी API कुंजियाँ नहीं।
|
|
119
|
+
- **डेटा**: बनी छवियाँ आधिकारिक अटैचमेंट स्टोर से हार्नेस की अपनी नीति के तहत सहेजी जाती हैं। कोटा उपयोग `draw/generated` सत्र इवेंट से मोड़ा जाता है, साथ में उन होस्ट पर इन-मेमोरी फ़ॉलबैक लेजर से जो उन इवेंट को लॉग नहीं कर सकते — और कुछ संग्रहीत नहीं होता।
|
|
120
|
+
- **सत्र लॉग**: `draw/generated` इवेंट इंजन, मॉडल, मानकीकृत अनुरोध, बाइट योग और अटैचमेंट आईडी दर्ज करता है — ऑडिट तथ्य, कभी API कुंजियाँ नहीं। इवेंट तभी जोड़ा जाता है जब होस्ट उस प्रकार को जानता हो या `ignorable` एनवेलप स्वीकार करता हो (माउंट पर जांचा जाता है); rc.6/rc.7 होस्ट पर पेलोड इन-मेमोरी फ़ॉलबैक लेजर में जाता है, इसलिए इमेज बनाने से सत्र अब दोबारा खुलने से इनकार नहीं करता।
|
|
121
121
|
|
|
122
122
|
## सुरक्षा सीमाएँ
|
|
123
123
|
|
|
@@ -131,13 +131,14 @@ dsh --profile web --dump-config | grep -A2 'id: dsh-draw'
|
|
|
131
131
|
- **केवल छवि मॉडल।** कोई वीडियो, ऑडियो या संपादन एंडपॉइंट नहीं; कोई विज़ुअल समझ नहीं।
|
|
132
132
|
- **इंजन संगतता।** इंजन को OpenAI `POST /images/generations` आकार बोलना चाहिए (base64 या URL डिलीवरी); प्रदाता-विशेष अतिरिक्त दायरे से बाहर हैं।
|
|
133
133
|
- **लागत-जागरूकता संरचनात्मक है।** प्लगइन कॉल और बाइट गिनता है, इंजन मूल्य नहीं जानता — लागत प्रशासन के लिए `dsh-budget` के साथ जोड़ें।
|
|
134
|
+
- **rc.6/rc.7 पर कोटा स्थायित्व।** जिन होस्ट का सत्र लॉग `draw/generated` को सुरक्षित रूप से नहीं रख सकता (स्थिर इवेंट श्वेतसूची, कोई `ignorable` एनवेलप नहीं), कोटा इन-मेमोरी फ़ॉलबैक लेजर से जीवित सत्र में सटीक रहता है लेकिन पुनः आरंभ पर रीसेट हो जाता है; प्लगइन इवेंट सतह वाले होस्ट पर टिकाऊ लेखांकन फिर से शुरू होता है।
|
|
134
135
|
|
|
135
136
|
## विकास
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install # node ^22.19 || >=24
|
|
139
140
|
pnpm run typecheck # tsc: src + tests स्थानीय हार्नेस चेकआउट के विरुद्ध
|
|
140
|
-
pnpm run typecheck:ci # tsc प्रकाशित 0.1.0-rc.
|
|
141
|
+
pnpm run typecheck:ci # tsc प्रकाशित 0.1.0-rc.8 फ़ेस के विरुद्ध (बिना paths)
|
|
141
142
|
pnpm test # vitest: 77 टेस्ट, 11 सुइट (स्क्रिप्टेड ट्रांसपोर्ट, वास्तविक Context/Session/ToolRuntime)
|
|
142
143
|
pnpm run build # tsc घोषणाएँ + tsdown बंडल (lib/)
|
|
143
144
|
pnpm run verify:self-contained # निर्भरता स्पेक registry से हल होती हैं
|
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
| Surface | Status |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Harness | DeepSeek Harness `0.1.0-rc.
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.8` (compat declared for `0.1.0-rc.8`) |
|
|
28
28
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
29
|
| Engines | Any OpenAI-compatible images endpoint; presets for OpenAI Images (`gpt-image-1`) and Zhipu CogView (`cogview-3-flash`) |
|
|
30
30
|
| Surfaces | Host `image_generate` tool + web result card + Plugins settings tab |
|
|
@@ -116,8 +116,8 @@ Example override in your profile patch:
|
|
|
116
116
|
## Permissions & data
|
|
117
117
|
|
|
118
118
|
- **Permissions**: the plugin makes outbound HTTPS calls to the configured engine endpoints only; every other surface is read-only. The settings tab's only writes are credential set/remove calls on the official `ctx.credentials` seam.
|
|
119
|
-
- **Data**: generated images are saved through the official attachment store under the harness's own attachment policy. Quota usage is folded from the `draw/generated` session events — nothing else is stored.
|
|
120
|
-
- **Session log**: the `draw/generated` event records engine, model, standardized request, byte totals, and attachment ids — the audit facts, never the API keys.
|
|
119
|
+
- **Data**: generated images are saved through the official attachment store under the harness's own attachment policy. Quota usage is folded from the `draw/generated` session events, plus the in-memory fallback ledger on hosts that cannot log those events — nothing else is stored.
|
|
120
|
+
- **Session log**: the `draw/generated` event records engine, model, standardized request, byte totals, and attachment ids — the audit facts, never the API keys. The event is appended only when the host knows the type or honors the `ignorable` envelope (probed at mount); on rc.6/rc.7 hosts the payload goes to the in-memory fallback ledger instead, so generating images can no longer make a session refuse to reopen.
|
|
121
121
|
|
|
122
122
|
## Security boundaries
|
|
123
123
|
|
|
@@ -131,13 +131,14 @@ Example override in your profile patch:
|
|
|
131
131
|
- **Image models only.** No video, audio, or edit endpoints; no vision understanding.
|
|
132
132
|
- **Engine compatibility.** Engines must speak the OpenAI `POST /images/generations` shape (base64 or URL delivery); provider-specific extras are out of scope.
|
|
133
133
|
- **Cost awareness is structural.** The plugin counts calls and bytes but does not know engine pricing — pair with `dsh-budget` for cost governance.
|
|
134
|
+
- **Quota durability on rc.6/rc.7.** On hosts whose session log cannot carry `draw/generated` (static event whitelist, no `ignorable` envelope), quota stays exact for the live session from the in-memory fallback ledger but resets on restart; durable accounting resumes on hosts with a plugin event surface.
|
|
134
135
|
|
|
135
136
|
## Development
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install # node ^22.19 || >=24
|
|
139
140
|
pnpm run typecheck # tsc: src + tests against the local harness checkout
|
|
140
|
-
pnpm run typecheck:ci # tsc against the published 0.1.0-rc.
|
|
141
|
+
pnpm run typecheck:ci # tsc against the published 0.1.0-rc.8 faces (no paths)
|
|
141
142
|
pnpm test # vitest: 77 tests, 11 suites (scripted transport, real Context/Session/ToolRuntime)
|
|
142
143
|
pnpm run build # tsc declarations + tsdown bundles (lib/)
|
|
143
144
|
pnpm run verify:self-contained # dependency specs resolve from the registry
|
package/README.pt.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
| Superfície | Status |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Harness | DeepSeek Harness `0.1.0-rc.
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.8` (compatibilidade declarada para `0.1.0-rc.8`) |
|
|
28
28
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
29
|
| Motores | Qualquer endpoint de imagens compatível com OpenAI; presets para OpenAI Images (`gpt-image-1`) e Zhipu CogView (`cogview-3-flash`) |
|
|
30
30
|
| Superfícies | Ferramenta host `image_generate` + cartão de resultado web + aba de ajustes de Plugins |
|
|
@@ -116,8 +116,8 @@ Exemplo de sobrescrita no patch do seu perfil:
|
|
|
116
116
|
## Permissões e dados
|
|
117
117
|
|
|
118
118
|
- **Permissões**: o plugin só faz chamadas HTTPS de saída para os endpoints de motor configurados; todo o resto é somente leitura. As únicas escritas da aba de ajustes são as chamadas de definir/remover credenciais no seam oficial `ctx.credentials`.
|
|
119
|
-
- **Dados**: as imagens geradas são salvas através do armazenamento de anexos oficial sob a política de anexos do harness. O uso de cota é dobrado dos eventos de sessão `draw/generated
|
|
120
|
-
- **Registro de sessão**: o evento `draw/generated` registra motor, modelo, solicitação padronizada, totais de bytes e ids de anexo — os fatos de auditoria, nunca as chaves
|
|
119
|
+
- **Dados**: as imagens geradas são salvas através do armazenamento de anexos oficial sob a política de anexos do harness. O uso de cota é dobrado dos eventos de sessão `draw/generated`, mais o livro auxiliar em memória em hosts que não podem registrar esses eventos — nada mais é armazenado.
|
|
120
|
+
- **Registro de sessão**: o evento `draw/generated` registra motor, modelo, solicitação padronizada, totais de bytes e ids de anexo — os fatos de auditoria, nunca as chaves API. O evento só é anexado quando o host conhece o tipo ou honra o envelope `ignorable` (sondado na montagem); em hosts rc.6/rc.7 a carga vai para o livro auxiliar em memória, então gerar imagens não faz mais a sessão recusar reabrir.
|
|
121
121
|
|
|
122
122
|
## Limites de segurança
|
|
123
123
|
|
|
@@ -131,13 +131,14 @@ Exemplo de sobrescrita no patch do seu perfil:
|
|
|
131
131
|
- **Somente modelos de imagem.** Sem endpoints de vídeo, áudio ou edição; sem compreensão visual.
|
|
132
132
|
- **Compatibilidade de motores.** Os motores devem falar a forma `POST /images/generations` da OpenAI (entrega base64 ou URL); extras específicos de cada provedor ficam de fora.
|
|
133
133
|
- **Consciência de custo é estrutural.** O plugin conta chamadas e bytes, mas não conhece o preço dos motores — combine com `dsh-budget` para a governança de custo.
|
|
134
|
+
- **Durabilidade de cota em rc.6/rc.7.** Em hosts cujo registro de sessão não pode carregar `draw/generated` (lista estática de eventos, sem envelope `ignorable`), a cota continua exata na sessão viva a partir do livro auxiliar em memória, mas zera ao reiniciar; a contabilidade durável retorna em hosts com uma superfície de eventos para plugins.
|
|
134
135
|
|
|
135
136
|
## Desenvolvimento
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install # node ^22.19 || >=24
|
|
139
140
|
pnpm run typecheck # tsc: src + tests contra o checkout local do harness
|
|
140
|
-
pnpm run typecheck:ci # tsc contra as faces publicadas 0.1.0-rc.
|
|
141
|
+
pnpm run typecheck:ci # tsc contra as faces publicadas 0.1.0-rc.8 (sem paths)
|
|
141
142
|
pnpm test # vitest: 77 testes, 11 suítes (transporte roteirizado, Context/Session/ToolRuntime reais)
|
|
142
143
|
pnpm run build # declarações tsc + bundles tsdown (lib/)
|
|
143
144
|
pnpm run verify:self-contained # as especificações de dependências resolvem pelo registry
|
package/README.zh.md
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
| 方面 | 状态 |
|
|
26
26
|
|---|---|
|
|
27
|
-
| Harness | DeepSeek Harness `0.1.0-rc.
|
|
27
|
+
| Harness | DeepSeek Harness `0.1.0-rc.8`(声明兼容 `0.1.0-rc.8`) |
|
|
28
28
|
| Node | `^22.19.0 \|\| >=24.0.0` |
|
|
29
29
|
| 引擎 | 任意 OpenAI 兼容图像端点;内置 OpenAI Images(`gpt-image-1`)与智谱 CogView(`cogview-3-flash`)预设 |
|
|
30
30
|
| 界面 | Host `image_generate` 工具 + Web 结果卡片 + Plugins 设置页签 |
|
|
@@ -116,8 +116,8 @@ profile patch 中的覆盖示例:
|
|
|
116
116
|
## 权限与数据
|
|
117
117
|
|
|
118
118
|
- **权限**:插件仅对配置的引擎端点发起 HTTPS 出站请求;其余界面全部只读。设置页签唯一的写入是对官方 `ctx.credentials` 接缝的凭据设置/移除。
|
|
119
|
-
- **数据**:生成的图片经官方附件存储落盘,受 harness 附件策略约束。配额用量从 `draw/generated`
|
|
120
|
-
- **会话日志**:`draw/generated` 事件记录引擎、模型、标准化请求、字节总量与附件 id —— 审计事实,绝不包含 API
|
|
119
|
+
- **数据**:生成的图片经官方附件存储落盘,受 harness 附件策略约束。配额用量从 `draw/generated` 会话事件折叠;在无法安全落盘该事件的宿主上另加内存兜底账簿 —— 除此之外不存储任何东西。
|
|
120
|
+
- **会话日志**:`draw/generated` 事件记录引擎、模型、标准化请求、字节总量与附件 id —— 审计事实,绝不包含 API 密钥。仅当宿主收录该类型或支持 `ignorable` 信封时才落盘(挂载期探测);在 rc.6/rc.7 宿主上载荷改记内存兜底账簿,生成图片不再导致会话重启后无法打开。
|
|
121
121
|
|
|
122
122
|
## 安全边界
|
|
123
123
|
|
|
@@ -131,13 +131,14 @@ profile patch 中的覆盖示例:
|
|
|
131
131
|
- **仅图像模型。** 无视频、音频或编辑端点;无视觉理解。
|
|
132
132
|
- **引擎兼容性。** 引擎需支持 OpenAI `POST /images/generations` 形状(base64 或 URL 交付);厂商专属扩展不在范围内。
|
|
133
133
|
- **成本感知是结构性的。** 插件统计调用次数与字节,但不了解引擎定价 —— 与 `dsh-budget` 配合做成本治理。
|
|
134
|
+
- **rc.6/rc.7 上的配额持久性。** 会话日志无法安全携带 `draw/generated` 的宿主(静态事件白名单、无 `ignorable` 信封)上,配额经内存兜底账簿在活会话内保持精确,但重启后重置;宿主具备插件事件面后恢复持久记账。
|
|
134
135
|
|
|
135
136
|
## 开发
|
|
136
137
|
|
|
137
138
|
```sh
|
|
138
139
|
pnpm install # node ^22.19 || >=24
|
|
139
140
|
pnpm run typecheck # tsc:src + tests,对照本地 harness checkout
|
|
140
|
-
pnpm run typecheck:ci # tsc:对照已发布的 0.1.0-rc.
|
|
141
|
+
pnpm run typecheck:ci # tsc:对照已发布的 0.1.0-rc.8 类型(无 paths)
|
|
141
142
|
pnpm test # vitest:77 个测试、11 个套件(scripted 传输、真实 Context/Session/ToolRuntime)
|
|
142
143
|
pnpm run build # tsc 声明 + tsdown 打包(lib/)
|
|
143
144
|
pnpm run verify:self-contained # 依赖声明全部来自 registry
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { i as statusToView, n as imageToWire, r as probeToWire, t as DRAW_INVOCATIONS } from "./wire-Cc4JZ3jR.js";
|
|
2
2
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
5
|
+
import SessionStore, { KNOWN_SESSION_EVENT_TYPES, SessionId } from "@deepseek-ai/dsh-session";
|
|
4
6
|
import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
|
|
5
|
-
import { SessionId } from "@deepseek-ai/dsh-session";
|
|
6
7
|
import { AttachmentId } from "@deepseek-ai/dsh-attachment";
|
|
7
8
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
8
9
|
//#region src/config.ts
|
|
@@ -209,7 +210,9 @@ function engineById(config, id) {
|
|
|
209
210
|
//#endregion
|
|
210
211
|
//#region src/session-events.ts
|
|
211
212
|
/**
|
|
212
|
-
* Append one `draw/generated` event to a session.
|
|
213
|
+
* Append one `draw/generated` event to a session, ungated. Plugin paths use
|
|
214
|
+
* {@link commitDrawGenerated} instead; this raw form remains for tests and
|
|
215
|
+
* hosts that know the type.
|
|
213
216
|
*
|
|
214
217
|
* @param session - owning session.
|
|
215
218
|
* @param event - accounting payload.
|
|
@@ -219,6 +222,47 @@ function appendDrawGenerated(session, event) {
|
|
|
219
222
|
return session.append("draw/generated", event);
|
|
220
223
|
}
|
|
221
224
|
/**
|
|
225
|
+
* In-memory accounting ledger for hosts whose session log cannot carry
|
|
226
|
+
* `draw/generated` safely (rc.6/rc.7 static whitelist, no ignorable envelope).
|
|
227
|
+
* Keyed by Session identity: the entries live exactly as long as the session.
|
|
228
|
+
*/
|
|
229
|
+
const fallbackLedger = /* @__PURE__ */ new WeakMap();
|
|
230
|
+
/**
|
|
231
|
+
* Commit one completed generation: append the `draw/generated` event when the
|
|
232
|
+
* gate allows (with the ignorable envelope when required), otherwise record
|
|
233
|
+
* the payload in the in-memory fallback ledger. A failed append degrades to
|
|
234
|
+
* the same ledger and never breaks the draw.
|
|
235
|
+
*
|
|
236
|
+
* @param session - owning session.
|
|
237
|
+
* @param event - accounting payload.
|
|
238
|
+
* @param gate - the adaptive gate (event-gate.ts).
|
|
239
|
+
* @param warn - log warning sink for append failures.
|
|
240
|
+
*/
|
|
241
|
+
function commitDrawGenerated(session, event, gate, warn) {
|
|
242
|
+
const decision = gate("draw/generated");
|
|
243
|
+
if (decision.append) try {
|
|
244
|
+
if (decision.ignorable) session.append("draw/generated", event, { ignorable: true });
|
|
245
|
+
else session.append("draw/generated", event);
|
|
246
|
+
return;
|
|
247
|
+
} catch (error) {
|
|
248
|
+
warn(`draw session event append failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
249
|
+
}
|
|
250
|
+
const list = fallbackLedger.get(session) ?? [];
|
|
251
|
+
list.push(event);
|
|
252
|
+
fallbackLedger.set(session, list);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* The in-memory fallback records of a session, in commit order. Populated
|
|
256
|
+
* only while the host cannot carry `draw/generated` in the log; quota folds
|
|
257
|
+
* these on top of the logged events.
|
|
258
|
+
*
|
|
259
|
+
* @param session - session whose ledger is read.
|
|
260
|
+
* @returns the fallback payloads.
|
|
261
|
+
*/
|
|
262
|
+
function fallbackDrawGeneratedEvents(session) {
|
|
263
|
+
return fallbackLedger.get(session) ?? [];
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
222
266
|
* Collect the `draw/generated` events of a session in log order. Declaration
|
|
223
267
|
* merging narrows `event.type === 'draw/generated'` to the payload type.
|
|
224
268
|
*
|
|
@@ -231,9 +275,11 @@ function drawGeneratedEvents(session) {
|
|
|
231
275
|
//#endregion
|
|
232
276
|
//#region src/quota.ts
|
|
233
277
|
/**
|
|
234
|
-
* Fold one session's `draw/generated` events into current usage
|
|
278
|
+
* Fold one session's `draw/generated` events into current usage: logged events
|
|
279
|
+
* first, then the in-memory fallback ledger (disjoint — a commit lands in
|
|
280
|
+
* exactly one of them).
|
|
235
281
|
*
|
|
236
|
-
* @param session - session whose log
|
|
282
|
+
* @param session - session whose log and ledger are folded.
|
|
237
283
|
* @returns generation and byte totals.
|
|
238
284
|
*/
|
|
239
285
|
function quotaState(session) {
|
|
@@ -243,6 +289,10 @@ function quotaState(session) {
|
|
|
243
289
|
generations += 1;
|
|
244
290
|
bytes += event.data.bytes;
|
|
245
291
|
}
|
|
292
|
+
for (const event of fallbackDrawGeneratedEvents(session)) {
|
|
293
|
+
generations += 1;
|
|
294
|
+
bytes += event.bytes;
|
|
295
|
+
}
|
|
246
296
|
return {
|
|
247
297
|
generations,
|
|
248
298
|
bytes
|
|
@@ -366,15 +416,18 @@ var Drawer = class {
|
|
|
366
416
|
config;
|
|
367
417
|
router;
|
|
368
418
|
deps;
|
|
419
|
+
events;
|
|
369
420
|
/**
|
|
370
421
|
* @param config - resolved plugin configuration.
|
|
371
422
|
* @param router - the engine router.
|
|
372
423
|
* @param deps - per-call dependencies (public: the remote service reads them for probes).
|
|
424
|
+
* @param events - the gated session-event sink (log when safe, in-memory ledger otherwise).
|
|
373
425
|
*/
|
|
374
|
-
constructor(config, router, deps) {
|
|
426
|
+
constructor(config, router, deps, events) {
|
|
375
427
|
this.config = config;
|
|
376
428
|
this.router = router;
|
|
377
429
|
this.deps = deps;
|
|
430
|
+
this.events = events;
|
|
378
431
|
}
|
|
379
432
|
/**
|
|
380
433
|
* Run one generation end to end: normalize and validate, check quota,
|
|
@@ -461,7 +514,7 @@ var Drawer = class {
|
|
|
461
514
|
...ref.name !== void 0 ? { name: ref.name } : {}
|
|
462
515
|
}));
|
|
463
516
|
const elapsedMs = Date.now() - startedAt;
|
|
464
|
-
|
|
517
|
+
commitDrawGenerated(session, {
|
|
465
518
|
engine: routed.engine,
|
|
466
519
|
model: routed.model,
|
|
467
520
|
source: options.source,
|
|
@@ -472,7 +525,7 @@ var Drawer = class {
|
|
|
472
525
|
bytes: totalBytes,
|
|
473
526
|
attachmentIds: images.map((image) => image.attachmentId),
|
|
474
527
|
elapsedMs
|
|
475
|
-
});
|
|
528
|
+
}, this.events.gate, this.events.warn);
|
|
476
529
|
const after = checkQuotaGenerations(session, limits);
|
|
477
530
|
return {
|
|
478
531
|
ok: true,
|
|
@@ -504,6 +557,78 @@ var Drawer = class {
|
|
|
504
557
|
}
|
|
505
558
|
};
|
|
506
559
|
//#endregion
|
|
560
|
+
//#region src/event-gate.ts
|
|
561
|
+
/**
|
|
562
|
+
* The session-event adaptive gate. `draw/generated` is declared only in this
|
|
563
|
+
* package's types, so it sits outside every host's `KNOWN_SESSION_EVENT_TYPES`:
|
|
564
|
+
* hosts whose session reader validates a static whitelist (rc.6/rc.7) refuse to
|
|
565
|
+
* 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
|
|
569
|
+
* in-memory fallback ledger (see session-events.ts) so quota keeps working for
|
|
570
|
+
* the live session without poisoning the log.
|
|
571
|
+
*
|
|
572
|
+
* @module dsh-draw/event-gate
|
|
573
|
+
*/
|
|
574
|
+
/**
|
|
575
|
+
* Build the gate: host-known types append plainly; unknown types append with
|
|
576
|
+
* the ignorable envelope only when the host append honors it; everything else
|
|
577
|
+
* is skipped — an unknown, unmarked event would make the session refuse to
|
|
578
|
+
* load on restart under the rc.6/rc.7 static whitelist.
|
|
579
|
+
*
|
|
580
|
+
* @param knownTypes - the host's KNOWN_SESSION_EVENT_TYPES.
|
|
581
|
+
* @param ignorableAppend - whether the host append stamps the envelope.
|
|
582
|
+
* @returns the decision function.
|
|
583
|
+
*/
|
|
584
|
+
function makeEventGate(knownTypes, ignorableAppend = false) {
|
|
585
|
+
return (type) => {
|
|
586
|
+
if (knownTypes.has(type)) return {
|
|
587
|
+
append: true,
|
|
588
|
+
ignorable: false
|
|
589
|
+
};
|
|
590
|
+
if (ignorableAppend) return {
|
|
591
|
+
append: true,
|
|
592
|
+
ignorable: true
|
|
593
|
+
};
|
|
594
|
+
return {
|
|
595
|
+
append: false,
|
|
596
|
+
ignorable: false
|
|
597
|
+
};
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Probe whether the host `Session.append` stamps the ignorable envelope. Runs
|
|
602
|
+
* on a fully detached SessionStore — never host persistence — appending one
|
|
603
|
+
* 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".
|
|
606
|
+
*
|
|
607
|
+
* @returns whether the envelope is honored.
|
|
608
|
+
*/
|
|
609
|
+
function probeIgnorableAppend() {
|
|
610
|
+
try {
|
|
611
|
+
return new SessionStore(new Context()).create().append("draw/generated", {
|
|
612
|
+
engine: "probe",
|
|
613
|
+
model: "probe",
|
|
614
|
+
source: "tool",
|
|
615
|
+
prompt: "probe",
|
|
616
|
+
size: "auto",
|
|
617
|
+
quality: "auto",
|
|
618
|
+
count: 0,
|
|
619
|
+
bytes: 0,
|
|
620
|
+
attachmentIds: [],
|
|
621
|
+
elapsedMs: 0
|
|
622
|
+
}, { ignorable: true })?.ignorable === true;
|
|
623
|
+
} catch {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
/** The gate over the host's known types plus the probed envelope support. */
|
|
628
|
+
function makeHostEventGate() {
|
|
629
|
+
return makeEventGate(KNOWN_SESSION_EVENT_TYPES, probeIgnorableAppend());
|
|
630
|
+
}
|
|
631
|
+
//#endregion
|
|
507
632
|
//#region src/http.ts
|
|
508
633
|
/**
|
|
509
634
|
* A transport-level failure. `status` is absent for network/timeout failures;
|
|
@@ -1066,7 +1191,7 @@ var EngineRouter = class {
|
|
|
1066
1191
|
* @module dsh-draw/version
|
|
1067
1192
|
*/
|
|
1068
1193
|
/** Plugin version; must equal the `version` field in `package.json`. */
|
|
1069
|
-
const PLUGIN_VERSION = "0.1.
|
|
1194
|
+
const PLUGIN_VERSION = "0.1.1";
|
|
1070
1195
|
//#endregion
|
|
1071
1196
|
//#region src/service.ts
|
|
1072
1197
|
/**
|
|
@@ -1415,6 +1540,9 @@ async function apply(ctx, config) {
|
|
|
1415
1540
|
},
|
|
1416
1541
|
attachments: () => ctx.get("attachments"),
|
|
1417
1542
|
sessions: () => ctx.get("sessions")
|
|
1543
|
+
}, {
|
|
1544
|
+
gate: makeHostEventGate(),
|
|
1545
|
+
warn: (message) => logger.warn(message)
|
|
1418
1546
|
});
|
|
1419
1547
|
ctx.effect(() => ctx.tools.register(imageGenerateTool(drawer, resolved)), "dsh-draw: image_generate tool");
|
|
1420
1548
|
await ctx.plugin(DrawService, {
|
|
@@ -1426,4 +1554,4 @@ async function apply(ctx, config) {
|
|
|
1426
1554
|
logger.info(`image generation enabled: ${resolved.engines.map((engine) => engine.id).join(", ")} (preferred ${resolved.defaultEngine})`);
|
|
1427
1555
|
}
|
|
1428
1556
|
//#endregion
|
|
1429
|
-
export { Config, DEFAULT_ENGINES, DRAW_INVOCATIONS, DrawService, Drawer, EngineCallError, EngineRouter, HttpError, PLUGIN_VERSION, REDACTED, appendDrawGenerated, apply, callEngine, checkQuotaBytes, checkQuotaGenerations, defaultHttpTransport, drawGeneratedEvents, engineById, fusedSignal, imageGenerateTool, imageToWire, inject, name, normalizeRequest, probeToWire, quotaState, resolveConfig, sanitizeError, sanitizeText, sanitizeUrl, statusToView, translateRequest };
|
|
1557
|
+
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 };
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type ReactElement } from 'react';
|
|
10
10
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
11
|
-
import type { PresentedDrawPanel } from './present.
|
|
11
|
+
import type { PresentedDrawPanel } from './present.js';
|
|
12
12
|
/** Registration-side injected face: the panel RPCs (RemoteResult already unwrapped). */
|
|
13
13
|
export interface DrawSettingsTabInjected {
|
|
14
14
|
/** Read the panel snapshot. */
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* @module dsh-draw/client
|
|
9
9
|
*/
|
|
10
10
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
11
|
-
import { type DrawLocaleKey } from './locales.
|
|
12
|
-
export type { DrawResultCardInjected, DrawResultCardProps } from './DrawResultCard.
|
|
13
|
-
export type { DrawSettingsTabInjected, DrawSettingsTabProps } from './DrawSettingsTab.
|
|
14
|
-
export type { DrawLocaleKey } from './locales.
|
|
15
|
-
export { presentDrawPanel, presentDrawResult, type PresentedDrawPanel, type PresentedDrawResult, type PresentedEngineRow } from './present.
|
|
11
|
+
import { type DrawLocaleKey } from './locales.js';
|
|
12
|
+
export type { DrawResultCardInjected, DrawResultCardProps } from './DrawResultCard.js';
|
|
13
|
+
export type { DrawSettingsTabInjected, DrawSettingsTabProps } from './DrawSettingsTab.js';
|
|
14
|
+
export type { DrawLocaleKey } from './locales.js';
|
|
15
|
+
export { presentDrawPanel, presentDrawResult, type PresentedDrawPanel, type PresentedDrawResult, type PresentedEngineRow } from './present.js';
|
|
16
16
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
17
17
|
interface LocaleNamespaceMap {
|
|
18
18
|
/** Image-generation card and panel copy. */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module dsh-draw/client/present
|
|
8
8
|
*/
|
|
9
9
|
import type { ToolCallBlock } from '@deepseek-ai/dsh-client-runtime/client';
|
|
10
|
-
import type { DrawStatusSnapshot } from '../wire.
|
|
10
|
+
import type { DrawStatusSnapshot } from '../wire.js';
|
|
11
11
|
/** One image of the presented result card. */
|
|
12
12
|
export interface PresentedImage {
|
|
13
13
|
attachmentId: string;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module dsh-draw/client/remote
|
|
9
9
|
*/
|
|
10
10
|
import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
|
|
11
|
-
import type { CredentialActionResult, DrawProbeResult, DrawRegenerateResult, DrawStatusSnapshot } from '../wire.
|
|
11
|
+
import type { CredentialActionResult, DrawProbeResult, DrawRegenerateResult, DrawStatusSnapshot } from '../wire.js';
|
|
12
12
|
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
13
13
|
interface TypertRemoteNamespace$draw {
|
|
14
14
|
/** Read the panel snapshot (engines, health, credentials, quota). */
|
package/lib/types/drawer.d.ts
CHANGED
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
|
|
10
10
|
import type { Session, SessionStore } from '@deepseek-ai/dsh-session';
|
|
11
|
-
import type { ResolvedConfig } from './config.
|
|
12
|
-
import type { EngineDeps } from './engine.
|
|
13
|
-
import { type QuotaLimits, type QuotaState } from './quota.
|
|
14
|
-
import { EngineRouter, type AttemptView } from './router.
|
|
11
|
+
import type { ResolvedConfig } from './config.js';
|
|
12
|
+
import type { EngineDeps } from './engine.js';
|
|
13
|
+
import { type QuotaLimits, type QuotaState } from './quota.js';
|
|
14
|
+
import { EngineRouter, type AttemptView } from './router.js';
|
|
15
|
+
import type { EventGate } from './event-gate.js';
|
|
15
16
|
/** One durable result image as the canonical value and wire carry it. */
|
|
16
17
|
export interface DrawImage {
|
|
17
18
|
/** Opaque attachment id. */
|
|
@@ -85,6 +86,13 @@ export interface DrawerDeps {
|
|
|
85
86
|
/** Per-call session store accessor for the regenerate path. */
|
|
86
87
|
sessions?: () => SessionStore | undefined;
|
|
87
88
|
}
|
|
89
|
+
/** How the drawer commits the `draw/generated` accounting event. */
|
|
90
|
+
export interface DrawerEventSink {
|
|
91
|
+
/** The adaptive session-event gate, probed at mount. */
|
|
92
|
+
gate: EventGate;
|
|
93
|
+
/** Log warning sink for append failures. */
|
|
94
|
+
warn: (message: string) => void;
|
|
95
|
+
}
|
|
88
96
|
/**
|
|
89
97
|
* The shared generation path.
|
|
90
98
|
*/
|
|
@@ -92,12 +100,14 @@ export declare class Drawer {
|
|
|
92
100
|
private readonly config;
|
|
93
101
|
private readonly router;
|
|
94
102
|
readonly deps: DrawerDeps;
|
|
103
|
+
private readonly events;
|
|
95
104
|
/**
|
|
96
105
|
* @param config - resolved plugin configuration.
|
|
97
106
|
* @param router - the engine router.
|
|
98
107
|
* @param deps - per-call dependencies (public: the remote service reads them for probes).
|
|
108
|
+
* @param events - the gated session-event sink (log when safe, in-memory ledger otherwise).
|
|
99
109
|
*/
|
|
100
|
-
constructor(config: ResolvedConfig, router: EngineRouter, deps: DrawerDeps);
|
|
110
|
+
constructor(config: ResolvedConfig, router: EngineRouter, deps: DrawerDeps, events: DrawerEventSink);
|
|
101
111
|
/**
|
|
102
112
|
* Run one generation end to end: normalize and validate, check quota,
|
|
103
113
|
* route through the engine chain, commit images to the attachment store,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,6BAA6B,CAAA;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAA;AAC5D,OAAO,EAA0C,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AACtG,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"drawer.d.ts","sourceRoot":"","sources":["../../src/drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,6BAA6B,CAAA;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAA;AAC5D,OAAO,EAA0C,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AACtG,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAA;AAE5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,yEAAyE;AACzE,MAAM,WAAW,SAAS;IACxB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yBAAyB;AACzB,MAAM,WAAW,WAAW;IAC1B,oBAAoB;IACpB,EAAE,EAAE,IAAI,CAAA;IACR,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAA;IACd,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,IAAI,EAAE,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,CAAA;IAClD,6BAA6B;IAC7B,MAAM,EAAE,SAAS,SAAS,EAAE,CAAA;IAC5B,6CAA6C;IAC7C,KAAK,EAAE,UAAU,CAAA;IACjB,6BAA6B;IAC7B,MAAM,EAAE,WAAW,CAAA;IACnB,2DAA2D;IAC3D,YAAY,EAAE,OAAO,CAAA;IACrB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAA;IACjB,2CAA2C;IAC3C,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAA;CACjC;AAED,kDAAkD;AAClD,MAAM,MAAM,iBAAiB,GACzB,gBAAgB,GAChB,mBAAmB,GACnB,aAAa,GACb,YAAY,GACZ,yBAAyB,GACzB,oBAAoB,CAAA;AAExB,6EAA6E;AAC7E,MAAM,WAAW,WAAW;IAC1B,oBAAoB;IACpB,EAAE,EAAE,KAAK,CAAA;IACT,oCAAoC;IACpC,MAAM,EAAE,iBAAiB,CAAA;IACzB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,uDAAuD;IACvD,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;CAClC;AAED,oBAAoB;AACpB,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,WAAW,CAAA;AAEnD,kCAAkC;AAClC,MAAM,WAAW,WAAW;IAC1B,2BAA2B;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,4EAA4E;IAC5E,OAAO,EAAE,OAAO,GAAG,SAAS,CAAA;IAC5B,kEAAkE;IAClE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAA;CAC9B;AAED,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,MAAM,EAAE,UAAU,CAAA;IAClB,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,eAAe,GAAG,SAAS,CAAA;IAC/C,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,YAAY,GAAG,SAAS,CAAA;CAC1C;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,IAAI,EAAE,SAAS,CAAA;IACf,4CAA4C;IAC5C,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED;;GAEG;AACH,qBAAa,MAAM;IAQf,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,UAAU;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB;;;;;OAKG;IACH,YACmB,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,YAAY,EAC5B,IAAI,EAAE,UAAU,EACR,MAAM,EAAE,eAAe,EACtC;IAEJ;;;;;;;;OAQG;IACG,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAiFxE;IAED,yFAAyF;YAC3E,UAAU;CAqBzB"}
|
package/lib/types/drawer.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @module dsh-draw/drawer
|
|
8
8
|
*/
|
|
9
9
|
import { checkQuotaBytes, checkQuotaGenerations } from './quota.js';
|
|
10
|
-
import {
|
|
10
|
+
import { commitDrawGenerated } from './session-events.js';
|
|
11
11
|
import { normalizeRequest } from './translate.js';
|
|
12
12
|
/**
|
|
13
13
|
* The shared generation path.
|
|
@@ -16,15 +16,18 @@ export class Drawer {
|
|
|
16
16
|
config;
|
|
17
17
|
router;
|
|
18
18
|
deps;
|
|
19
|
+
events;
|
|
19
20
|
/**
|
|
20
21
|
* @param config - resolved plugin configuration.
|
|
21
22
|
* @param router - the engine router.
|
|
22
23
|
* @param deps - per-call dependencies (public: the remote service reads them for probes).
|
|
24
|
+
* @param events - the gated session-event sink (log when safe, in-memory ledger otherwise).
|
|
23
25
|
*/
|
|
24
|
-
constructor(config, router, deps) {
|
|
26
|
+
constructor(config, router, deps, events) {
|
|
25
27
|
this.config = config;
|
|
26
28
|
this.router = router;
|
|
27
29
|
this.deps = deps;
|
|
30
|
+
this.events = events;
|
|
28
31
|
}
|
|
29
32
|
/**
|
|
30
33
|
* Run one generation end to end: normalize and validate, check quota,
|
|
@@ -92,7 +95,7 @@ export class Drawer {
|
|
|
92
95
|
...(ref.name !== undefined ? { name: ref.name } : {}),
|
|
93
96
|
}));
|
|
94
97
|
const elapsedMs = Date.now() - startedAt;
|
|
95
|
-
|
|
98
|
+
commitDrawGenerated(session, {
|
|
96
99
|
engine: routed.engine,
|
|
97
100
|
model: routed.model,
|
|
98
101
|
source: options.source,
|
|
@@ -103,7 +106,7 @@ export class Drawer {
|
|
|
103
106
|
bytes: totalBytes,
|
|
104
107
|
attachmentIds: images.map(image => image.attachmentId),
|
|
105
108
|
elapsedMs,
|
|
106
|
-
});
|
|
109
|
+
}, this.events.gate, this.events.warn);
|
|
107
110
|
const after = checkQuotaGenerations(session, limits);
|
|
108
111
|
return {
|
|
109
112
|
ok: true,
|
package/lib/types/engine.d.ts
CHANGED
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* @module dsh-draw/engine
|
|
9
9
|
*/
|
|
10
10
|
import type { ImageMediaType } from '@deepseek-ai/dsh-attachment';
|
|
11
|
-
import type { ResolvedEngineConfig } from './config.
|
|
12
|
-
import { type HttpTransport } from './http.
|
|
13
|
-
import type { TranslatedImageRequest } from './translate.
|
|
11
|
+
import type { ResolvedEngineConfig } from './config.js';
|
|
12
|
+
import { type HttpTransport } from './http.js';
|
|
13
|
+
import type { TranslatedImageRequest } from './translate.js';
|
|
14
14
|
/** Failure phases of one engine call, each mapping to a router decision. */
|
|
15
15
|
export type EngineFailurePhase = 'credential' | 'request' | 'parse';
|
|
16
16
|
/**
|