dsh-draw 0.2.12 → 0.2.15
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 +31 -0
- package/{README.es.md → README-es.md} +19 -7
- package/{README.hi.md → README-hi.md} +19 -7
- package/{README.pt.md → README-pt.md} +19 -7
- package/{README.zh.md → README-zh.md} +19 -7
- package/README.md +19 -8
- package/lib/client.js +69 -65
- package/lib/client.js.map +1 -1
- package/lib/index.js +49 -7
- package/lib/typert.host.js +1 -1
- package/lib/types/client/index.d.ts +12 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/index.js +23 -5
- package/lib/types/client/remote.d.ts +110 -31
- package/lib/types/client/remote.d.ts.map +1 -1
- package/lib/types/client/styles.d.ts.map +1 -1
- package/lib/types/client/styles.js +24 -7
- package/lib/types/event-gate.d.ts +24 -2
- package/lib/types/event-gate.d.ts.map +1 -1
- package/lib/types/event-gate.js +31 -3
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +19 -2
- package/lib/types/session-events.d.ts.map +1 -1
- package/lib/types/session-events.js +9 -2
- package/lib/types/typert.host.d.ts +110 -31
- package/lib/types/typert.host.d.ts.map +1 -1
- package/lib/types/version.d.ts +1 -1
- package/lib/types/version.js +1 -1
- package/lib/types/wire.d.ts +220 -62
- package/lib/types/wire.d.ts.map +1 -1
- package/lib/types/wire.js +21 -35
- package/lib/{wire-DLW8WmDW.js → wire-BvocRNv3.js} +26 -55
- package/package.json +38 -36
- package/src/client/index.ts +20 -5
- package/src/client/styles.ts +24 -6
- package/src/event-gate.ts +45 -3
- package/src/index.ts +16 -2
- package/src/session-events.ts +9 -2
- package/src/version.ts +1 -1
- package/src/wire.ts +22 -35
|
@@ -5027,6 +5027,21 @@ function superRefine(fn, params) {
|
|
|
5027
5027
|
*
|
|
5028
5028
|
* @module dsh-draw/wire
|
|
5029
5029
|
*/
|
|
5030
|
+
/**
|
|
5031
|
+
* Strict wire codec carrying BOTH published and checkout faces: the
|
|
5032
|
+
* `schema` field feeds the npm-published 0.1.5-rc.2 line, `create` feeds the
|
|
5033
|
+
* checkout 0.1.6-alpha.1+ line (schemas materialize lazily on first use).
|
|
5034
|
+
* Built through a variable, so neither typecheck ruler flags the other
|
|
5035
|
+
* face's field as excess.
|
|
5036
|
+
*/
|
|
5037
|
+
function strictWire(typeSymbol, schema) {
|
|
5038
|
+
return Object.freeze({
|
|
5039
|
+
mode: "strict",
|
|
5040
|
+
typeSymbol,
|
|
5041
|
+
schema,
|
|
5042
|
+
create: () => schema
|
|
5043
|
+
});
|
|
5044
|
+
}
|
|
5030
5045
|
/** Strict wire schema for {@link DrawStatusSnapshot} (zod v4, both Typert faces). */
|
|
5031
5046
|
const DRAW_STATUS_SCHEMA = object({
|
|
5032
5047
|
pluginVersion: string(),
|
|
@@ -5171,11 +5186,7 @@ const DRAW_STATUS_DESCRIPTOR = Object.freeze({
|
|
|
5171
5186
|
method: "status",
|
|
5172
5187
|
invocation: Object.freeze({ kind: "direct" }),
|
|
5173
5188
|
parameters: Object.freeze([]),
|
|
5174
|
-
result:
|
|
5175
|
-
mode: "strict",
|
|
5176
|
-
typeSymbol: "dsh-draw/types#DrawStatusSnapshot",
|
|
5177
|
-
schema: DRAW_STATUS_SCHEMA
|
|
5178
|
-
}),
|
|
5189
|
+
result: strictWire("dsh-draw/types#DrawStatusSnapshot", DRAW_STATUS_SCHEMA),
|
|
5179
5190
|
sourceLocation: Object.freeze({
|
|
5180
5191
|
file: "src/wire.ts",
|
|
5181
5192
|
line: 1,
|
|
@@ -5195,17 +5206,9 @@ const DRAW_PROBE_DESCRIPTOR = Object.freeze({
|
|
|
5195
5206
|
name: "engineId",
|
|
5196
5207
|
wire: "engineId",
|
|
5197
5208
|
source: "json",
|
|
5198
|
-
codec:
|
|
5199
|
-
mode: "strict",
|
|
5200
|
-
typeSymbol: "dsh-draw/types#EngineId",
|
|
5201
|
-
schema: ENGINE_ID_CODEC
|
|
5202
|
-
})
|
|
5209
|
+
codec: strictWire("dsh-draw/types#EngineId", ENGINE_ID_CODEC)
|
|
5203
5210
|
})]),
|
|
5204
|
-
result:
|
|
5205
|
-
mode: "strict",
|
|
5206
|
-
typeSymbol: "dsh-draw/types#DrawProbeResult",
|
|
5207
|
-
schema: DRAW_PROBE_SCHEMA
|
|
5208
|
-
}),
|
|
5211
|
+
result: strictWire("dsh-draw/types#DrawProbeResult", DRAW_PROBE_SCHEMA),
|
|
5209
5212
|
sourceLocation: Object.freeze({
|
|
5210
5213
|
file: "src/wire.ts",
|
|
5211
5214
|
line: 1,
|
|
@@ -5227,26 +5230,14 @@ const DRAW_SET_CREDENTIAL_DESCRIPTOR = Object.freeze({
|
|
|
5227
5230
|
name: "engineId",
|
|
5228
5231
|
wire: "engineId",
|
|
5229
5232
|
source: "json",
|
|
5230
|
-
codec:
|
|
5231
|
-
mode: "strict",
|
|
5232
|
-
typeSymbol: "dsh-draw/types#EngineId",
|
|
5233
|
-
schema: ENGINE_ID_CODEC
|
|
5234
|
-
})
|
|
5233
|
+
codec: strictWire("dsh-draw/types#EngineId", ENGINE_ID_CODEC)
|
|
5235
5234
|
}), Object.freeze({
|
|
5236
5235
|
name: "value",
|
|
5237
5236
|
wire: "value",
|
|
5238
5237
|
source: "json",
|
|
5239
|
-
codec:
|
|
5240
|
-
mode: "strict",
|
|
5241
|
-
typeSymbol: "dsh-draw/types#CredentialValue",
|
|
5242
|
-
schema: CREDENTIAL_VALUE_CODEC
|
|
5243
|
-
})
|
|
5238
|
+
codec: strictWire("dsh-draw/types#CredentialValue", CREDENTIAL_VALUE_CODEC)
|
|
5244
5239
|
})]),
|
|
5245
|
-
result:
|
|
5246
|
-
mode: "strict",
|
|
5247
|
-
typeSymbol: "dsh-draw/types#CredentialActionResult",
|
|
5248
|
-
schema: CREDENTIAL_ACTION_SCHEMA
|
|
5249
|
-
}),
|
|
5240
|
+
result: strictWire("dsh-draw/types#CredentialActionResult", CREDENTIAL_ACTION_SCHEMA),
|
|
5250
5241
|
sourceLocation: Object.freeze({
|
|
5251
5242
|
file: "src/wire.ts",
|
|
5252
5243
|
line: 1,
|
|
@@ -5266,17 +5257,9 @@ const DRAW_UNSET_CREDENTIAL_DESCRIPTOR = Object.freeze({
|
|
|
5266
5257
|
name: "engineId",
|
|
5267
5258
|
wire: "engineId",
|
|
5268
5259
|
source: "json",
|
|
5269
|
-
codec:
|
|
5270
|
-
mode: "strict",
|
|
5271
|
-
typeSymbol: "dsh-draw/types#EngineId",
|
|
5272
|
-
schema: ENGINE_ID_CODEC
|
|
5273
|
-
})
|
|
5260
|
+
codec: strictWire("dsh-draw/types#EngineId", ENGINE_ID_CODEC)
|
|
5274
5261
|
})]),
|
|
5275
|
-
result:
|
|
5276
|
-
mode: "strict",
|
|
5277
|
-
typeSymbol: "dsh-draw/types#CredentialActionResult",
|
|
5278
|
-
schema: CREDENTIAL_ACTION_SCHEMA
|
|
5279
|
-
}),
|
|
5262
|
+
result: strictWire("dsh-draw/types#CredentialActionResult", CREDENTIAL_ACTION_SCHEMA),
|
|
5280
5263
|
sourceLocation: Object.freeze({
|
|
5281
5264
|
file: "src/wire.ts",
|
|
5282
5265
|
line: 1,
|
|
@@ -5299,26 +5282,14 @@ const DRAW_REGENERATE_DESCRIPTOR = Object.freeze({
|
|
|
5299
5282
|
name: "sessionId",
|
|
5300
5283
|
wire: "sessionId",
|
|
5301
5284
|
source: "json",
|
|
5302
|
-
codec:
|
|
5303
|
-
mode: "strict",
|
|
5304
|
-
typeSymbol: "dsh-draw/types#SessionId",
|
|
5305
|
-
schema: SESSION_ID_CODEC
|
|
5306
|
-
})
|
|
5285
|
+
codec: strictWire("dsh-draw/types#SessionId", SESSION_ID_CODEC)
|
|
5307
5286
|
}), Object.freeze({
|
|
5308
5287
|
name: "args",
|
|
5309
5288
|
wire: "args",
|
|
5310
5289
|
source: "json",
|
|
5311
|
-
codec:
|
|
5312
|
-
mode: "strict",
|
|
5313
|
-
typeSymbol: "dsh-draw/types#RegenerateArgs",
|
|
5314
|
-
schema: REGENERATE_ARGS_CODEC
|
|
5315
|
-
})
|
|
5290
|
+
codec: strictWire("dsh-draw/types#RegenerateArgs", REGENERATE_ARGS_CODEC)
|
|
5316
5291
|
})]),
|
|
5317
|
-
result:
|
|
5318
|
-
mode: "strict",
|
|
5319
|
-
typeSymbol: "dsh-draw/types#DrawRegenerateResult",
|
|
5320
|
-
schema: DRAW_REGENERATE_SCHEMA
|
|
5321
|
-
}),
|
|
5292
|
+
result: strictWire("dsh-draw/types#DrawRegenerateResult", DRAW_REGENERATE_SCHEMA),
|
|
5322
5293
|
sourceLocation: Object.freeze({
|
|
5323
5294
|
file: "src/wire.ts",
|
|
5324
5295
|
line: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-draw",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "Unified static-image generation router for DeepSeek Harness: one image_generate tool with standard parameters, config-driven OpenAI-compatible engine routing (OpenAI Images, Zhipu CogView, and any compatible endpoint) with health-aware fallback, durable workspace attachment results, per-session quota accounting, an in-conversation result card, and a Plugins settings panel that stores API keys as credential references.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,13 +43,14 @@
|
|
|
43
43
|
"SECURITY.md",
|
|
44
44
|
"THIRD_PARTY_NOTICES.md",
|
|
45
45
|
"README.md",
|
|
46
|
-
"README
|
|
47
|
-
"README
|
|
48
|
-
"README
|
|
49
|
-
"README
|
|
46
|
+
"README-zh.md",
|
|
47
|
+
"README-es.md",
|
|
48
|
+
"README-pt.md",
|
|
49
|
+
"README-hi.md",
|
|
50
50
|
"LICENSE"
|
|
51
51
|
],
|
|
52
52
|
"dsh": {
|
|
53
|
+
"manifestVersion": 1,
|
|
53
54
|
"bundle": {
|
|
54
55
|
"patch": "./cordis.patch.yml"
|
|
55
56
|
},
|
|
@@ -88,7 +89,7 @@
|
|
|
88
89
|
"attachments:write"
|
|
89
90
|
],
|
|
90
91
|
"compatibility": {
|
|
91
|
-
"dshVersions": ["0.1.2-rc.1","0.1.5-rc.
|
|
92
|
+
"dshVersions": ["0.1.2-rc.1","0.1.5-rc.2"]
|
|
92
93
|
},
|
|
93
94
|
"capability": {
|
|
94
95
|
"id": "image-generate-tool",
|
|
@@ -116,24 +117,25 @@
|
|
|
116
117
|
"text-to-image"
|
|
117
118
|
],
|
|
118
119
|
"engines": {
|
|
119
|
-
"node": "^22.19.0 || >=24.0.0"
|
|
120
|
+
"node": "^22.19.0 || >=24.0.0",
|
|
121
|
+
"dsh": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0"
|
|
120
122
|
},
|
|
121
123
|
"packageManager": "pnpm@11.7.0",
|
|
122
124
|
"peerDependencies": {
|
|
123
125
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
124
|
-
"@deepseek-ai/dsh-attachment": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
125
|
-
"@deepseek-ai/dsh-brand": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
126
|
-
"@deepseek-ai/dsh-credentials": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
127
|
-
"@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
128
|
-
"@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
129
|
-
"@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
130
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
126
|
+
"@deepseek-ai/dsh-attachment": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
127
|
+
"@deepseek-ai/dsh-brand": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
128
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
129
|
+
"@deepseek-ai/dsh-llm": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
130
|
+
"@deepseek-ai/dsh-session": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
131
|
+
"@deepseek-ai/dsh-tools": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
132
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
131
133
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
132
|
-
"@deepseek-ai/dsh-client-connection": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
133
|
-
"@deepseek-ai/dsh-client-locale": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
134
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
135
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0",
|
|
136
|
-
"@deepseek-ai/dsh-client-ui-tool": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0"
|
|
134
|
+
"@deepseek-ai/dsh-client-connection": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
135
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
136
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
137
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0",
|
|
138
|
+
"@deepseek-ai/dsh-client-ui-tool": ">=0.1.2-rc.1 <0.2.0 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-0 <0.2.0"
|
|
137
139
|
},
|
|
138
140
|
"peerDependenciesMeta": {
|
|
139
141
|
"@deepseek-ai/dsh-client-connection": {
|
|
@@ -158,26 +160,26 @@
|
|
|
158
160
|
"zod": "^4.4.3"
|
|
159
161
|
},
|
|
160
162
|
"devDependencies": {
|
|
161
|
-
"@deepseek-ai/dsh-util-values": "0.1.5-rc.
|
|
163
|
+
"@deepseek-ai/dsh-util-values": "0.1.5-rc.2",
|
|
162
164
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
163
165
|
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
164
166
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
165
|
-
"@deepseek-ai/dsh-agent": "0.1.5-rc.
|
|
166
|
-
"@deepseek-ai/dsh-api-remotes": "0.1.5-rc.
|
|
167
|
-
"@deepseek-ai/dsh-attachment": "0.1.5-rc.
|
|
168
|
-
"@deepseek-ai/dsh-attachment-local": "0.1.5-rc.
|
|
169
|
-
"@deepseek-ai/dsh-brand": "0.1.5-rc.
|
|
170
|
-
"@deepseek-ai/dsh-client-connection": "0.1.5-rc.
|
|
171
|
-
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.
|
|
172
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.
|
|
173
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.
|
|
174
|
-
"@deepseek-ai/dsh-client-ui-tool": "0.1.5-rc.
|
|
175
|
-
"@deepseek-ai/dsh-credentials": "0.1.5-rc.
|
|
176
|
-
"@deepseek-ai/dsh-credentials-local": "0.1.5-rc.
|
|
177
|
-
"@deepseek-ai/dsh-llm": "0.1.5-rc.
|
|
178
|
-
"@deepseek-ai/dsh-session": "0.1.5-rc.
|
|
179
|
-
"@deepseek-ai/dsh-tools": "0.1.5-rc.
|
|
180
|
-
"@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.
|
|
167
|
+
"@deepseek-ai/dsh-agent": "0.1.5-rc.2",
|
|
168
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.5-rc.2",
|
|
169
|
+
"@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
|
|
170
|
+
"@deepseek-ai/dsh-attachment-local": "0.1.5-rc.2",
|
|
171
|
+
"@deepseek-ai/dsh-brand": "0.1.5-rc.2",
|
|
172
|
+
"@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
|
|
173
|
+
"@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
|
|
174
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.5-rc.2",
|
|
175
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
|
|
176
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.1.5-rc.2",
|
|
177
|
+
"@deepseek-ai/dsh-credentials": "0.1.5-rc.2",
|
|
178
|
+
"@deepseek-ai/dsh-credentials-local": "0.1.5-rc.2",
|
|
179
|
+
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
180
|
+
"@deepseek-ai/dsh-session": "0.1.5-rc.2",
|
|
181
|
+
"@deepseek-ai/dsh-tools": "0.1.5-rc.2",
|
|
182
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
|
|
181
183
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
182
184
|
"@types/node": "^22.19.0",
|
|
183
185
|
"@types/react": "18.3.31",
|
package/src/client/index.ts
CHANGED
|
@@ -121,17 +121,32 @@ export async function apply(ctx: ClientContext): Promise<void> {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
|
-
* Read the current session id from the sessions store face (structural:
|
|
125
|
-
*
|
|
124
|
+
* Read the current session id from the sessions store face (structural: the
|
|
125
|
+
* store shape differs across harness lines, so only the leaves are read).
|
|
126
|
+
*
|
|
127
|
+
* On the 0.1.6 line `SessionListState.current` no longer exists, so the card's
|
|
128
|
+
* regenerate belongs to the session the main view retains: pick the listed
|
|
129
|
+
* session whose `retainedBy.mainView` is set — the same rule the upstream
|
|
130
|
+
* session store applies when it resolves its main binding. Without a retained
|
|
131
|
+
* session the guard returns undefined and the caller reports it instead of
|
|
132
|
+
* regenerating against an unknown session.
|
|
126
133
|
*/
|
|
127
|
-
function currentSessionId(sessions: unknown): string | undefined {
|
|
134
|
+
export function currentSessionId(sessions: unknown): string | undefined {
|
|
128
135
|
try {
|
|
129
136
|
const list = (sessions as { list?: unknown } | null)?.list
|
|
130
137
|
if (typeof list !== 'object' || list === null) return undefined
|
|
131
138
|
const getSnapshot = (list as { getSnapshot?: unknown }).getSnapshot
|
|
132
139
|
if (typeof getSnapshot !== 'function') return undefined
|
|
133
|
-
const
|
|
134
|
-
|
|
140
|
+
const byId = (getSnapshot as () => { byId?: unknown })().byId
|
|
141
|
+
if (typeof byId !== 'object' || byId === null) return undefined
|
|
142
|
+
for (const candidate of Object.values(byId as Record<string, unknown>)) {
|
|
143
|
+
if (typeof candidate !== 'object' || candidate === null) continue
|
|
144
|
+
const retained = (candidate as { retainedBy?: { mainView?: unknown } }).retainedBy
|
|
145
|
+
const mainView = typeof retained?.mainView === 'number' ? retained.mainView : 0
|
|
146
|
+
const id = (candidate as { id?: unknown }).id
|
|
147
|
+
if (mainView > 0 && typeof id === 'string') return id
|
|
148
|
+
}
|
|
149
|
+
return undefined
|
|
135
150
|
} catch {
|
|
136
151
|
return undefined
|
|
137
152
|
}
|
package/src/client/styles.ts
CHANGED
|
@@ -9,12 +9,22 @@
|
|
|
9
9
|
|
|
10
10
|
const STYLE_ID = 'dsh-draw-client-styles'
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Live installs of this stylesheet. The sheet is shared by every mount of the
|
|
14
|
+
* browser half, so ownership is counted: the node stays as long as any mount
|
|
15
|
+
* is alive, and the LAST disposer removes the node this module inserted.
|
|
16
|
+
* Removing it on the first unmount (or never removing it) is what produced the
|
|
17
|
+
* styles-lost window and the leaked node respectively.
|
|
18
|
+
*/
|
|
19
|
+
let liveInstalls = 0
|
|
20
|
+
|
|
12
21
|
/** Install the scoped stylesheet once; returns the removal disposer. */
|
|
13
22
|
export function installDrawStyles(): () => void {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
liveInstalls += 1
|
|
24
|
+
if (document.getElementById(STYLE_ID) === null) {
|
|
25
|
+
const style = document.createElement('style')
|
|
26
|
+
style.id = STYLE_ID
|
|
27
|
+
style.textContent = `
|
|
18
28
|
.dshdraw-card { display: flex; flex-direction: column; gap: 8px; padding: 4px 0; }
|
|
19
29
|
.dshdraw-grid { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
20
30
|
.dshdraw-figure { display: flex; flex-direction: column; gap: 4px; max-width: 320px; }
|
|
@@ -37,8 +47,16 @@ export function installDrawStyles(): () => void {
|
|
|
37
47
|
.dshdraw-badge.warn { color: #9a6700; border-color: #9a6700; }
|
|
38
48
|
.dshdraw-input { flex: 1; min-width: 180px; border: 1px solid var(--dsh-border, #d0d7de); border-radius: 6px; padding: 4px 8px; font-size: 12px; background: transparent; color: inherit; }
|
|
39
49
|
`
|
|
40
|
-
|
|
50
|
+
document.head.append(style)
|
|
51
|
+
}
|
|
52
|
+
let disposed = false
|
|
41
53
|
return () => {
|
|
42
|
-
|
|
54
|
+
if (disposed) return
|
|
55
|
+
disposed = true
|
|
56
|
+
liveInstalls -= 1
|
|
57
|
+
if (liveInstalls <= 0) {
|
|
58
|
+
liveInstalls = 0
|
|
59
|
+
document.getElementById(STYLE_ID)?.remove()
|
|
60
|
+
}
|
|
43
61
|
}
|
|
44
62
|
}
|
package/src/event-gate.ts
CHANGED
|
@@ -81,7 +81,49 @@ export function probeIgnorableAppend(): boolean {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
/**
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
/**
|
|
85
|
+
* The host gate: the decision function plus the probe result it was built
|
|
86
|
+
* from. The result is recorded on the function instead of being thrown away,
|
|
87
|
+
* so status surfaces can report which regime the session is in.
|
|
88
|
+
*/
|
|
89
|
+
export interface HostEventGate extends EventGate {
|
|
90
|
+
/** Whether the mount-time probe found `ignorable` envelope support. */
|
|
91
|
+
readonly ignorableAppend: boolean
|
|
92
|
+
/** The host-known type set the gate was built over. */
|
|
93
|
+
readonly knownTypes: ReadonlySet<string>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The gate over the host's known types plus the probed envelope support.
|
|
98
|
+
*
|
|
99
|
+
* A refusal used to be completely silent: the accounting moved to the
|
|
100
|
+
* in-memory fallback ledger and nothing said so. The first refusal now warns
|
|
101
|
+
* once through `warn` (the mount-time probe result is also readable on the
|
|
102
|
+
* returned function), so a degraded session is visible without spamming the
|
|
103
|
+
* log on every commit.
|
|
104
|
+
*
|
|
105
|
+
* @param warn - sink for the one-time degradation warning.
|
|
106
|
+
* @returns the gate carrying its probe result.
|
|
107
|
+
*/
|
|
108
|
+
export function makeHostEventGate(warn: (message: string) => void = () => {}): HostEventGate {
|
|
109
|
+
const ignorableAppend = probeIgnorableAppend()
|
|
110
|
+
const gate = makeEventGate(KNOWN_SESSION_EVENT_TYPES, ignorableAppend)
|
|
111
|
+
let warned = false
|
|
112
|
+
const hostGate = ((type: string): EventGateDecision => {
|
|
113
|
+
const decision = gate(type)
|
|
114
|
+
if (!decision.append && !warned) {
|
|
115
|
+
warned = true
|
|
116
|
+
warn(
|
|
117
|
+
'dsh-draw: this host neither knows the draw/generated event type nor honors the ignorable envelope, '
|
|
118
|
+
+ 'so the audit event is not written; the in-memory fallback ledger keeps quota exact for this session '
|
|
119
|
+
+ 'and resets when the session restarts',
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
return decision
|
|
123
|
+
}) as HostEventGate
|
|
124
|
+
Object.defineProperties(hostGate, {
|
|
125
|
+
ignorableAppend: { value: ignorableAppend, enumerable: true },
|
|
126
|
+
knownTypes: { value: KNOWN_SESSION_EVENT_TYPES, enumerable: true },
|
|
127
|
+
})
|
|
128
|
+
return hostGate
|
|
87
129
|
}
|
package/src/index.ts
CHANGED
|
@@ -95,12 +95,26 @@ export async function apply(ctx: Context, config: Config): Promise<void> {
|
|
|
95
95
|
},
|
|
96
96
|
attachments: () => ctx.get('attachments') as AttachmentStore | undefined,
|
|
97
97
|
sessions: () => ctx.get('sessions') as SessionStore | undefined,
|
|
98
|
-
}, { gate: makeHostEventGate(), warn: (message) => logger.warn(message) })
|
|
98
|
+
}, { gate: makeHostEventGate((message) => logger.warn(message)), warn: (message) => logger.warn(message) })
|
|
99
99
|
|
|
100
100
|
// Service Provider — ctx.tools.register mounts the image_generate tool and
|
|
101
101
|
// the `draw` Remote service; every registration is an effect on this fiber.
|
|
102
102
|
ctx.effect(() => ctx.tools.register(imageGenerateTool(drawer, resolved)), 'dsh-draw: image_generate tool')
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
// A02: the mount is awaited, so hold it in an effect registered BEFORE the
|
|
105
|
+
// await. A disposal that lands while DrawService is still mounting then
|
|
106
|
+
// unwinds the child fiber through the effect instead of leaving a
|
|
107
|
+
// half-applied mount; the post-await fiber check keeps the success log from
|
|
108
|
+
// claiming a mount that was already torn down, and a real mount failure
|
|
109
|
+
// still propagates.
|
|
110
|
+
const serviceFiber = ctx.plugin(DrawService, { config: resolved, router, drawer, credentials: credentials() })
|
|
111
|
+
ctx.effect(() => () => { void serviceFiber.dispose() }, 'dsh-draw: draw service')
|
|
112
|
+
try {
|
|
113
|
+
await serviceFiber
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (ctx.fiber.uid === null) return // unwound by our own disposer, not a mount failure
|
|
116
|
+
throw error
|
|
117
|
+
}
|
|
118
|
+
if (ctx.fiber.uid === null) return
|
|
105
119
|
logger.info(`image generation enabled: ${resolved.engines.map(engine => engine.id).join(', ')} (preferred ${resolved.defaultEngine})`)
|
|
106
120
|
}
|
package/src/session-events.ts
CHANGED
|
@@ -129,8 +129,15 @@ export function fallbackDrawGeneratedEvents(session: Session): readonly DrawGene
|
|
|
129
129
|
* @returns the accounting events.
|
|
130
130
|
*/
|
|
131
131
|
export function drawGeneratedEvents(session: Session): readonly import('@deepseek-ai/dsh-session').SessionEvent<'draw/generated'>[] {
|
|
132
|
-
//
|
|
133
|
-
//
|
|
132
|
+
// `Session.snapshotEvents()` is deprecated on the 0.1.6 line ("new calls are
|
|
133
|
+
// prohibited"), and this is an existing call. The migration target is the
|
|
134
|
+
// optional `sessionQuery` service (`readSession(sessionId).events`, the
|
|
135
|
+
// complete raw log — `readSurface` would NOT do: draw/generated is a
|
|
136
|
+
// non-surface audit type). Migrating it is not a local edit: quota folding
|
|
137
|
+
// (`quotaState` / `checkQuotaGenerations` / `checkQuotaBytes`) is synchronous
|
|
138
|
+
// and consumed by the tool path, the Remote status snapshot and the card, so
|
|
139
|
+
// the move turns that whole API async. Tracked for a dedicated card; the
|
|
140
|
+
// `.events` fallback below stays for the pre-alpha.5 peer floor.
|
|
134
141
|
const snapshot: readonly import('@deepseek-ai/dsh-session').SessionEvent[] = typeof session.snapshotEvents === 'function'
|
|
135
142
|
? session.snapshotEvents()
|
|
136
143
|
: (session as unknown as { events: readonly import('@deepseek-ai/dsh-session').SessionEvent[] }).events
|
package/src/version.ts
CHANGED
package/src/wire.ts
CHANGED
|
@@ -11,6 +11,17 @@
|
|
|
11
11
|
|
|
12
12
|
import { z } from 'zod'
|
|
13
13
|
import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol'
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Strict wire codec carrying BOTH published and checkout faces: the
|
|
17
|
+
* `schema` field feeds the npm-published 0.1.5-rc.2 line, `create` feeds the
|
|
18
|
+
* checkout 0.1.6-alpha.1+ line (schemas materialize lazily on first use).
|
|
19
|
+
* Built through a variable, so neither typecheck ruler flags the other
|
|
20
|
+
* face's field as excess.
|
|
21
|
+
*/
|
|
22
|
+
function strictWire<T>(typeSymbol: string, schema: T) {
|
|
23
|
+
return Object.freeze({ ...{ mode: 'strict' as const, typeSymbol, schema }, create: () => schema })
|
|
24
|
+
}
|
|
14
25
|
import type { AttemptView, EngineStatus, ProbeOutcome } from './router.ts'
|
|
15
26
|
import type { QuotaLimits, QuotaState } from './quota.ts'
|
|
16
27
|
import type { DrawImage } from './drawer.ts'
|
|
@@ -282,11 +293,7 @@ export const DRAW_STATUS_DESCRIPTOR = Object.freeze({
|
|
|
282
293
|
method: 'status',
|
|
283
294
|
invocation: Object.freeze({ kind: 'direct' }),
|
|
284
295
|
parameters: Object.freeze([]),
|
|
285
|
-
result:
|
|
286
|
-
mode: 'strict',
|
|
287
|
-
typeSymbol: 'dsh-draw/types#DrawStatusSnapshot',
|
|
288
|
-
schema: DRAW_STATUS_SCHEMA,
|
|
289
|
-
}),
|
|
296
|
+
result: strictWire('dsh-draw/types#DrawStatusSnapshot', DRAW_STATUS_SCHEMA),
|
|
290
297
|
sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
|
|
291
298
|
} as const) satisfies InvocationDescriptor
|
|
292
299
|
|
|
@@ -303,17 +310,9 @@ export const DRAW_PROBE_DESCRIPTOR = Object.freeze({
|
|
|
303
310
|
name: 'engineId',
|
|
304
311
|
wire: 'engineId',
|
|
305
312
|
source: 'json',
|
|
306
|
-
codec:
|
|
307
|
-
mode: 'strict',
|
|
308
|
-
typeSymbol: 'dsh-draw/types#EngineId',
|
|
309
|
-
schema: ENGINE_ID_CODEC,
|
|
310
|
-
}),
|
|
313
|
+
codec: strictWire('dsh-draw/types#EngineId', ENGINE_ID_CODEC),
|
|
311
314
|
} satisfies InvocationDescriptor['parameters'][number])]),
|
|
312
|
-
result:
|
|
313
|
-
mode: 'strict',
|
|
314
|
-
typeSymbol: 'dsh-draw/types#DrawProbeResult',
|
|
315
|
-
schema: DRAW_PROBE_SCHEMA,
|
|
316
|
-
}),
|
|
315
|
+
result: strictWire('dsh-draw/types#DrawProbeResult', DRAW_PROBE_SCHEMA),
|
|
317
316
|
sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
|
|
318
317
|
} as const) satisfies InvocationDescriptor
|
|
319
318
|
|
|
@@ -333,20 +332,16 @@ export const DRAW_SET_CREDENTIAL_DESCRIPTOR = Object.freeze({
|
|
|
333
332
|
name: 'engineId',
|
|
334
333
|
wire: 'engineId',
|
|
335
334
|
source: 'json',
|
|
336
|
-
codec:
|
|
335
|
+
codec: strictWire('dsh-draw/types#EngineId', ENGINE_ID_CODEC),
|
|
337
336
|
} satisfies InvocationDescriptor['parameters'][number]),
|
|
338
337
|
Object.freeze({
|
|
339
338
|
name: 'value',
|
|
340
339
|
wire: 'value',
|
|
341
340
|
source: 'json',
|
|
342
|
-
codec:
|
|
341
|
+
codec: strictWire('dsh-draw/types#CredentialValue', CREDENTIAL_VALUE_CODEC),
|
|
343
342
|
} satisfies InvocationDescriptor['parameters'][number]),
|
|
344
343
|
]),
|
|
345
|
-
result:
|
|
346
|
-
mode: 'strict',
|
|
347
|
-
typeSymbol: 'dsh-draw/types#CredentialActionResult',
|
|
348
|
-
schema: CREDENTIAL_ACTION_SCHEMA,
|
|
349
|
-
}),
|
|
344
|
+
result: strictWire('dsh-draw/types#CredentialActionResult', CREDENTIAL_ACTION_SCHEMA),
|
|
350
345
|
sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
|
|
351
346
|
} as const) satisfies InvocationDescriptor
|
|
352
347
|
|
|
@@ -363,13 +358,9 @@ export const DRAW_UNSET_CREDENTIAL_DESCRIPTOR = Object.freeze({
|
|
|
363
358
|
name: 'engineId',
|
|
364
359
|
wire: 'engineId',
|
|
365
360
|
source: 'json',
|
|
366
|
-
codec:
|
|
361
|
+
codec: strictWire('dsh-draw/types#EngineId', ENGINE_ID_CODEC),
|
|
367
362
|
} satisfies InvocationDescriptor['parameters'][number])]),
|
|
368
|
-
result:
|
|
369
|
-
mode: 'strict',
|
|
370
|
-
typeSymbol: 'dsh-draw/types#CredentialActionResult',
|
|
371
|
-
schema: CREDENTIAL_ACTION_SCHEMA,
|
|
372
|
-
}),
|
|
363
|
+
result: strictWire('dsh-draw/types#CredentialActionResult', CREDENTIAL_ACTION_SCHEMA),
|
|
373
364
|
sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
|
|
374
365
|
} as const) satisfies InvocationDescriptor
|
|
375
366
|
|
|
@@ -390,20 +381,16 @@ export const DRAW_REGENERATE_DESCRIPTOR = Object.freeze({
|
|
|
390
381
|
name: 'sessionId',
|
|
391
382
|
wire: 'sessionId',
|
|
392
383
|
source: 'json',
|
|
393
|
-
codec:
|
|
384
|
+
codec: strictWire('dsh-draw/types#SessionId', SESSION_ID_CODEC),
|
|
394
385
|
} satisfies InvocationDescriptor['parameters'][number]),
|
|
395
386
|
Object.freeze({
|
|
396
387
|
name: 'args',
|
|
397
388
|
wire: 'args',
|
|
398
389
|
source: 'json',
|
|
399
|
-
codec:
|
|
390
|
+
codec: strictWire('dsh-draw/types#RegenerateArgs', REGENERATE_ARGS_CODEC),
|
|
400
391
|
} satisfies InvocationDescriptor['parameters'][number]),
|
|
401
392
|
]),
|
|
402
|
-
result:
|
|
403
|
-
mode: 'strict',
|
|
404
|
-
typeSymbol: 'dsh-draw/types#DrawRegenerateResult',
|
|
405
|
-
schema: DRAW_REGENERATE_SCHEMA,
|
|
406
|
-
}),
|
|
393
|
+
result: strictWire('dsh-draw/types#DrawRegenerateResult', DRAW_REGENERATE_SCHEMA),
|
|
407
394
|
sourceLocation: Object.freeze({ file: 'src/wire.ts', line: 1, column: 1 }),
|
|
408
395
|
} as const) satisfies InvocationDescriptor
|
|
409
396
|
|