@deepseek-ai/dsh-client-ui-plugin-recommendations 0.0.0-stage → 0.2.2-alpha.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.
package/lib/client.js ADDED
@@ -0,0 +1,775 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@deepseek-ai/dsh-client-ui-plugin-recommendations",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let zod = require("zod");
8
+ let react = require("react");
9
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
10
+ let react_jsx_runtime = require("react/jsx-runtime");
11
+ let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
12
+ //#region ../../typert/protocol/src/remote-info.ts
13
+ /**
14
+ * Retain one generated definition per endpoint without constructing parsers or projections.
15
+ * The class instance builds its shared descriptor/method index on first access;
16
+ * input schemas and JSON Schema projections are cached only when requested.
17
+ * @param spec - compiler-produced method facts and Zod factories.
18
+ * @param zod - the generated artifact's Zod runtime for named-input parsers.
19
+ * @returns a lazy, mountable info instance with no registration or transport effects.
20
+ */
21
+ function createTypertRemoteInfo(spec, zod) {
22
+ return new RemoteInfo(spec, zod);
23
+ }
24
+ var RemoteInfo = class {
25
+ spec;
26
+ zod;
27
+ index;
28
+ constructor(spec, zod) {
29
+ this.spec = spec;
30
+ this.zod = zod;
31
+ }
32
+ get package() {
33
+ return this.spec.package;
34
+ }
35
+ get descriptors() {
36
+ return this.resolve().descriptors;
37
+ }
38
+ get methods() {
39
+ return this.resolve().methods;
40
+ }
41
+ resolve() {
42
+ if (this.index !== void 0) return this.index;
43
+ const zod = this.zod;
44
+ const descriptors = [];
45
+ const methods = Object.create(null);
46
+ for (const [endpoint, definition] of Object.entries(this.spec.methods)) {
47
+ const separator = endpoint.indexOf("/");
48
+ const namespace = endpoint.slice(0, separator);
49
+ const method = endpoint.slice(separator + 1);
50
+ const parameters = definition.parameters.map((parameter) => ({
51
+ ...parameter,
52
+ wire: parameter.wire ?? parameter.name
53
+ }));
54
+ const descriptor = {
55
+ ...definition,
56
+ id: `${this.spec.package}#${endpoint}`,
57
+ namespace,
58
+ method,
59
+ parameters,
60
+ result: definition.result.description === void 0 ? definition.result : new ResultValue(definition.result)
61
+ };
62
+ if (definition.invocation.kind === "direct") {
63
+ const inputs = [];
64
+ methods[endpoint] = Object.assign(descriptor, {
65
+ input(options) {
66
+ const strict = options?.strict === true;
67
+ return inputs[strict ? 1 : 0] ??= new NamedInput(parameters, strict, zod);
68
+ },
69
+ invoke(remote, input, signal) {
70
+ const named = input;
71
+ const values = parameters.map((parameter) => named[parameter.wire]);
72
+ if (definition.cancellation !== void 0) values.push(signal);
73
+ const receiver = Reflect.get(remote, namespace);
74
+ return Reflect.get(receiver, method).apply(receiver, values);
75
+ }
76
+ });
77
+ }
78
+ descriptors.push(descriptor);
79
+ }
80
+ return this.index = {
81
+ descriptors,
82
+ methods
83
+ };
84
+ }
85
+ };
86
+ function optional(parameter) {
87
+ return parameter.source === "json" && parameter.acceptsUndefined === true;
88
+ }
89
+ var NamedInput = class {
90
+ parameters;
91
+ strict;
92
+ zod;
93
+ schema;
94
+ projection;
95
+ constructor(parameters, strict, zod) {
96
+ this.parameters = parameters;
97
+ this.strict = strict;
98
+ this.zod = zod;
99
+ }
100
+ codec(parameter) {
101
+ return this.strict ? parameter.strictCodec : parameter.codec;
102
+ }
103
+ create = () => this.schema ??= this.zod.strictObject(Object.fromEntries(this.parameters.map((parameter) => {
104
+ const value = this.codec(parameter).create();
105
+ return [parameter.wire, optional(parameter) ? value.optional() : value.nonoptional()];
106
+ })));
107
+ get jsonSchema() {
108
+ return this.project().jsonSchema;
109
+ }
110
+ get jsonSchemaError() {
111
+ return this.project().jsonSchemaError;
112
+ }
113
+ project() {
114
+ if (this.projection !== void 0) return this.projection;
115
+ const unavailable = this.parameters.find((parameter) => this.codec(parameter).jsonSchema === void 0);
116
+ if (unavailable !== void 0) return this.projection = { jsonSchemaError: this.codec(unavailable).jsonSchemaError ?? `No JSON Schema for parameter ${unavailable.wire}` };
117
+ return this.projection = { jsonSchema: {
118
+ type: "object",
119
+ properties: Object.fromEntries(this.parameters.map((parameter) => [parameter.wire, {
120
+ ...this.codec(parameter).jsonSchema,
121
+ ...parameter.description === void 0 ? {} : { description: parameter.description }
122
+ }])),
123
+ required: this.parameters.filter((parameter) => !optional(parameter)).map((parameter) => parameter.wire),
124
+ additionalProperties: false
125
+ } };
126
+ }
127
+ };
128
+ var ResultValue = class {
129
+ spec;
130
+ projection;
131
+ constructor(spec) {
132
+ this.spec = spec;
133
+ }
134
+ get mode() {
135
+ return this.spec.mode;
136
+ }
137
+ get typeSymbol() {
138
+ return this.spec.typeSymbol;
139
+ }
140
+ get create() {
141
+ return this.spec.create;
142
+ }
143
+ get decode() {
144
+ return this.spec.decode;
145
+ }
146
+ get encode() {
147
+ return this.spec.encode;
148
+ }
149
+ get description() {
150
+ return this.spec.description;
151
+ }
152
+ get jsonSchemaError() {
153
+ return this.spec.jsonSchemaError;
154
+ }
155
+ get jsonSchema() {
156
+ if (this.projection === void 0) {
157
+ const schema = this.spec.jsonSchema;
158
+ this.projection = { value: schema === void 0 ? void 0 : {
159
+ ...schema,
160
+ description: this.spec.description
161
+ } };
162
+ }
163
+ return this.projection.value;
164
+ }
165
+ };
166
+ //#endregion
167
+ //#region ../plugin-recommendations/lib/typert.remote-client.js
168
+ let _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0$schema$value;
169
+ const _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0$schema = () => _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0$schema$value ??= zod.z.string();
170
+ let _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1$schema$value;
171
+ const _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1$schema = () => _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1$schema$value ??= zod.z.string();
172
+ let _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_result$schema$value;
173
+ const _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_result$schema = () => _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_result$schema$value ??= zod.z.union([zod.z.object({
174
+ "status": zod.z.literal("available").readonly(),
175
+ "title": zod.z.union([zod.z.string(), zod.z.intersection(zod.z.object({ "en": zod.z.string().readonly() }), zod.z.record(zod.z.string(), zod.z.string()).readonly())]).readonly(),
176
+ "description": zod.z.union([zod.z.string(), zod.z.intersection(zod.z.object({ "en": zod.z.string().readonly() }), zod.z.record(zod.z.string(), zod.z.string()).readonly())]).readonly(),
177
+ "enabled": zod.z.boolean().readonly()
178
+ }), zod.z.object({
179
+ "status": zod.z.literal("refused").readonly(),
180
+ "reason": zod.z.union([
181
+ zod.z.literal("unknown"),
182
+ zod.z.literal("unavailable"),
183
+ zod.z.literal("not-live-root"),
184
+ zod.z.literal("closing")
185
+ ]).readonly()
186
+ })]);
187
+ let _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0_strict$schema$value;
188
+ const _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0_strict$schema = () => _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0_strict$schema$value ??= zod.z.string();
189
+ let _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1_strict$schema$value;
190
+ const _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1_strict$schema = () => _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1_strict$schema$value ??= zod.z.string();
191
+ const TYPERT_REMOTE = createTypertRemoteInfo({
192
+ package: "@deepseek-ai/dsh-plugin-recommendations",
193
+ methods: { "pluginRecommendations/describe": {
194
+ service: "pluginRecommendations",
195
+ description: "Read the current catalog text for a logged card.",
196
+ invocation: { kind: "direct" },
197
+ scope: {
198
+ context: "agent",
199
+ wire: "agentId"
200
+ },
201
+ parameters: [{
202
+ name: "agent",
203
+ wire: "agentId",
204
+ description: "Exact live root resolved by the Gateway from the Session id.",
205
+ source: "lookup",
206
+ lookup: "agent",
207
+ codec: {
208
+ mode: "strict",
209
+ typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
210
+ create: _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0$schema,
211
+ jsonSchema: { "type": "string" }
212
+ },
213
+ strictCodec: {
214
+ mode: "strict",
215
+ typeSymbol: "@deepseek-ai/dsh-session/types#SessionId",
216
+ create: _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_0_strict$schema,
217
+ jsonSchema: { "type": "string" }
218
+ }
219
+ }, {
220
+ name: "callId",
221
+ description: "The card's `propose_action` call id, never a package supplied by the browser.",
222
+ source: "json",
223
+ codec: {
224
+ mode: "strict",
225
+ typeSymbol: "@deepseek-ai/dsh-llm/brand#ToolCallId",
226
+ create: _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1$schema,
227
+ jsonSchema: { "type": "string" }
228
+ },
229
+ strictCodec: {
230
+ mode: "strict",
231
+ typeSymbol: "@deepseek-ai/dsh-llm/brand#ToolCallId",
232
+ create: _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_parameter_1_strict$schema,
233
+ jsonSchema: { "type": "string" }
234
+ }
235
+ }],
236
+ result: {
237
+ mode: "strict",
238
+ typeSymbol: "@deepseek-ai/dsh-plugin-recommendations/types#RecommendationDetails",
239
+ create: _deepseek_ai_dsh_plugin_recommendations_pluginRecommendations_describe_result$schema,
240
+ description: "the plugin's title, description and selection, or a refusal when the card names no available official plugin.",
241
+ jsonSchemaError: "typert tool schema: selected dictionaries require string keys and unconstrained JSON values"
242
+ },
243
+ sourceLocation: {
244
+ "file": "packages/experimental/plugin-recommendations/src/index.ts",
245
+ "line": 88,
246
+ "column": 9
247
+ }
248
+ } }
249
+ }, zod.z);
250
+ //#endregion
251
+ //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/experimental/client-ui-plugin-recommendations/src/client/Card.module.css.mjs
252
+ const css = ".KaT4gq_header{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);justify-content:space-between;align-items:center;gap:12px;padding:10px 20px;font-size:12px;line-height:1.5;display:flex}.KaT4gq_badge{font-size:12px}.KaT4gq_body{padding:20px}.KaT4gq_details{box-sizing:border-box;border-radius:var(--dsw-radius-sm);width:calc(100% + 16px);color:inherit;font:inherit;text-align:start;cursor:pointer;background:0 0;border:0;margin:-8px;padding:8px;transition:background-color .12s;display:block}@media (hover:hover){.KaT4gq_details:hover{background:var(--dsw-alias-interactive-bg-hover)}}.KaT4gq_details:focus-visible{background:var(--dsw-alias-interactive-bg-hover);box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline:none}.KaT4gq_title{overflow-wrap:anywhere;font-size:16px;font-weight:500;line-height:1.5;display:block}.KaT4gq_description{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:8px 0 0;font-size:13px;line-height:1.7;display:block}.KaT4gq_placeholder{vertical-align:middle;border-radius:var(--dsw-radius-xs);background:var(--dsw-alias-bg-skeleton);width:50%;height:.8em;display:inline-block}.KaT4gq_footer{border-top:.5px solid var(--dsw-alias-border-l1);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin-top:16px;padding-top:16px;display:flex}.KaT4gq_scope{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5}.KaT4gq_actions{align-items:center;gap:8px;margin-left:auto;display:flex}.KaT4gq_status{border-top:.5px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-label-secondary);margin:16px 0 0;padding-top:12px;font-size:12px;line-height:1.6}";
253
+ const tagId = "@deepseek-ai/dsh-client-ui-plugin-recommendations/Card.module.css";
254
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
255
+ const tag = document.createElement("style");
256
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-plugin-recommendations";
257
+ tag.dataset.pluginCss = tagId;
258
+ tag.textContent = css;
259
+ document.head.appendChild(tag);
260
+ }
261
+ var Card_module_css_default = {
262
+ "actions": "KaT4gq_actions",
263
+ "badge": "KaT4gq_badge",
264
+ "body": "KaT4gq_body",
265
+ "description": "KaT4gq_description",
266
+ "details": "KaT4gq_details",
267
+ "footer": "KaT4gq_footer",
268
+ "header": "KaT4gq_header",
269
+ "placeholder": "KaT4gq_placeholder",
270
+ "scope": "KaT4gq_scope",
271
+ "status": "KaT4gq_status",
272
+ "title": "KaT4gq_title"
273
+ };
274
+ //#endregion
275
+ //#region lib/types/client/Card.js
276
+ /** Body of an `enable_official_plugin` card: the plugin's catalog text, its details link, the user's choice and its outcome. */
277
+ const detailsSchema = zod.z.object({ name: zod.z.string() });
278
+ /** Recorded decision data the body reads; see `PluginData` for its meaning. */
279
+ const dataSchema = zod.z.object({
280
+ application: zod.z.literal("restart-required").optional(),
281
+ errorCode: zod.z.string().optional()
282
+ });
283
+ /** Phases that still offer Enable and Not now; any other recorded phase is settled. */
284
+ const OPEN_PHASES = ["failed", "unconfirmed"];
285
+ /** Refusal reasons with their own copy; any other reason reads as unavailable. */
286
+ const REASON_KEYS = [
287
+ "unknown",
288
+ "unavailable",
289
+ "access-denied",
290
+ "not-live-root",
291
+ "closing"
292
+ ];
293
+ function reasonKey(reason) {
294
+ return REASON_KEYS.find((key) => key === reason) ?? "unavailable";
295
+ }
296
+ /** Status copy of a recorded phase; `restart-required` refines enabled. */
297
+ function statusKey(phase, data) {
298
+ switch (phase) {
299
+ case "dismissed":
300
+ case "replaced":
301
+ case "already-enabled":
302
+ case "failed":
303
+ case "unconfirmed": return phase;
304
+ case "enabled": return data.application === "restart-required" ? "restart-required" : "enabled";
305
+ default: return;
306
+ }
307
+ }
308
+ /**
309
+ * Display one plugin card: its current catalog title and description, the user's choice and its outcome.
310
+ * Until the plugin's first catalog lookup returns, a placeholder line and the disabled actions hold the final layout.
311
+ * A refused or lost lookup leaves Not now and a retry of the lookup, but not Enable.
312
+ * @param props - card, state, actions and plugin-lifetime services.
313
+ * @returns the card body.
314
+ */
315
+ function PluginCardBody({ proposal, decision, sessionId, summary, act, catalog, describe, openDetails, resolveText, t }) {
316
+ const details = detailsSchema.safeParse(proposal.details);
317
+ const name = details.success ? details.data.name : void 0;
318
+ const cached = (0, react.useSyncExternalStore)((0, react.useCallback)((listener) => catalog.subscribe(listener), [catalog]), () => {
319
+ const entries = catalog.getSnapshot();
320
+ return name !== void 0 && Object.hasOwn(entries, name) ? entries[name] : void 0;
321
+ });
322
+ const [lookup, setLookup] = (0, react.useState)();
323
+ const [attempt, setAttempt] = (0, react.useState)(0);
324
+ const [pending, setPending] = (0, react.useState)();
325
+ const [error, setError] = (0, react.useState)();
326
+ const descriptionId = (0, react.useId)();
327
+ const phase = decision?.phase;
328
+ (0, react.useEffect)(() => {
329
+ if (name === void 0) return void 0;
330
+ let current = true;
331
+ describe(sessionId, proposal.callId).then((value) => {
332
+ if (!current) return;
333
+ if (value?.status === "available") catalog.set({
334
+ ...catalog.getSnapshot(),
335
+ [name]: value
336
+ });
337
+ setLookup(value ?? null);
338
+ }, () => {
339
+ if (current) setLookup(null);
340
+ });
341
+ return () => {
342
+ current = false;
343
+ };
344
+ }, [
345
+ catalog,
346
+ describe,
347
+ sessionId,
348
+ proposal.callId,
349
+ name,
350
+ phase,
351
+ attempt
352
+ ]);
353
+ if (name === void 0) return (0, react_jsx_runtime.jsx)("div", {
354
+ className: Card_module_css_default.body,
355
+ children: summary
356
+ });
357
+ const current = lookup === null || lookup?.status === "refused" ? lookup : cached ?? lookup;
358
+ const loading = current === void 0;
359
+ const available = current?.status === "available" ? current : void 0;
360
+ const parsed = dataSchema.safeParse(decision?.data ?? {});
361
+ const data = parsed.success ? parsed.data : {};
362
+ const settled = phase !== void 0 && !OPEN_PHASES.includes(phase);
363
+ const status = phase === void 0 ? available?.enabled ? "already-enabled" : void 0 : statusKey(phase, data);
364
+ const offered = !settled && available?.enabled !== true;
365
+ const enable = offered && (available !== void 0 || loading);
366
+ const lookupProblem = settled || current === void 0 || current?.status === "available" ? void 0 : current === null ? "lookup-failed" : current.reason;
367
+ const failure = phase === "failed" && data.errorCode !== void 0 ? data.errorCode === "incompatible-version" ? "version-error" : "management-error" : void 0;
368
+ const title = available === void 0 ? proposal.title : resolveText(available.title);
369
+ const run = async (verb) => {
370
+ setPending(verb);
371
+ setError(void 0);
372
+ try {
373
+ const result = await act(verb);
374
+ if (result === void 0) setError("transport");
375
+ else if (result.status === "refused" || result.status === "unconfirmed") setError(reasonKey(result.reason));
376
+ } catch {
377
+ setError("transport");
378
+ } finally {
379
+ setPending(void 0);
380
+ }
381
+ };
382
+ const busy = pending !== void 0;
383
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("header", {
384
+ className: Card_module_css_default.header,
385
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("heading") }), (0, react_jsx_runtime.jsx)("span", {
386
+ className: Card_module_css_default.badge,
387
+ children: t("official")
388
+ })]
389
+ }), (0, react_jsx_runtime.jsxs)("div", {
390
+ className: Card_module_css_default.body,
391
+ "aria-busy": loading || void 0,
392
+ children: [
393
+ (0, react_jsx_runtime.jsxs)("button", {
394
+ type: "button",
395
+ className: Card_module_css_default.details,
396
+ onClick: () => {
397
+ openDetails(name);
398
+ },
399
+ "aria-label": t("detailsFor", { title }),
400
+ "aria-describedby": available === void 0 ? void 0 : descriptionId,
401
+ children: [(0, react_jsx_runtime.jsx)("strong", {
402
+ className: Card_module_css_default.title,
403
+ children: title
404
+ }), (loading || available !== void 0) && (0, react_jsx_runtime.jsx)("span", {
405
+ id: descriptionId,
406
+ className: Card_module_css_default.description,
407
+ children: available === void 0 ? (0, react_jsx_runtime.jsx)("span", { className: Card_module_css_default.placeholder }) : resolveText(available.description)
408
+ })]
409
+ }),
410
+ status !== void 0 && (0, react_jsx_runtime.jsx)("p", {
411
+ role: "status",
412
+ className: Card_module_css_default.status,
413
+ children: t(status)
414
+ }),
415
+ failure !== void 0 && (0, react_jsx_runtime.jsx)("p", {
416
+ role: "alert",
417
+ className: Card_module_css_default.status,
418
+ children: t(failure)
419
+ }),
420
+ lookupProblem !== void 0 && (0, react_jsx_runtime.jsx)("p", {
421
+ role: "alert",
422
+ className: Card_module_css_default.status,
423
+ children: t(lookupProblem)
424
+ }),
425
+ offered && error !== void 0 && (0, react_jsx_runtime.jsx)("p", {
426
+ role: "alert",
427
+ className: Card_module_css_default.status,
428
+ children: t(error)
429
+ }),
430
+ offered && (0, react_jsx_runtime.jsxs)("footer", {
431
+ className: Card_module_css_default.footer,
432
+ children: [(0, react_jsx_runtime.jsx)("span", {
433
+ className: Card_module_css_default.scope,
434
+ children: t("scope")
435
+ }), (0, react_jsx_runtime.jsxs)("div", {
436
+ className: Card_module_css_default.actions,
437
+ children: [
438
+ lookupProblem !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
439
+ variant: "ghost",
440
+ size: "sm",
441
+ disabled: busy,
442
+ onClick: () => {
443
+ setLookup(void 0);
444
+ setAttempt((value) => value + 1);
445
+ },
446
+ children: t("retryLookup")
447
+ }),
448
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
449
+ variant: "ghost",
450
+ size: "sm",
451
+ disabled: busy || loading,
452
+ onClick: () => {
453
+ run("dismiss");
454
+ },
455
+ children: t(pending === "dismiss" ? "working" : "dismiss")
456
+ }),
457
+ enable && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
458
+ variant: "primary",
459
+ size: "sm",
460
+ disabled: busy || loading,
461
+ onClick: () => {
462
+ run("enable");
463
+ },
464
+ children: t(pending === "enable" ? "working" : phase === void 0 ? "enable" : "retry")
465
+ })
466
+ ]
467
+ })]
468
+ })
469
+ ]
470
+ })] });
471
+ }
472
+ //#endregion
473
+ //#region lib/types/client/locales.js
474
+ /** Typed product copy for recommendation cards. */
475
+ const zh = {
476
+ heading: "推荐插件",
477
+ official: "官方",
478
+ detailsFor: "查看详情:{title}",
479
+ "version-error": "插件与当前 DSH 版本不兼容,请更新 DSH 后重试。",
480
+ "management-error": "无法启用插件,请打开详情检查错误后重试。",
481
+ enable: "启用",
482
+ dismiss: "暂不需要",
483
+ working: "正在处理…",
484
+ scope: "启用后可在所有会话中使用",
485
+ enabled: "已启用",
486
+ "already-enabled": "已在插件页开启,可查看详情了解运行状态",
487
+ dismissed: "已忽略",
488
+ replaced: "已替换",
489
+ "restart-required": "已保存,重启 DSH 后生效",
490
+ failed: "启用失败。可重试或在插件页检查。",
491
+ retry: "重试启用",
492
+ unconfirmed: "无法确认插件是否已启用,可重试确认。",
493
+ "lookup-failed": "无法读取插件信息,请重试。",
494
+ retryLookup: "重试",
495
+ unavailable: "这个插件当前无法启用,请在插件页检查。",
496
+ unknown: "找不到这条推荐,请重新打开会话。",
497
+ "access-denied": "没有修改此配置的权限。",
498
+ "not-live-root": "请在原会话中操作这条推荐。",
499
+ closing: "服务正在重载,请稍后重试。",
500
+ transport: "无法确认操作结果,请刷新后重试。"
501
+ };
502
+ /** English card copy. */
503
+ const en = {
504
+ heading: "Recommended plugin",
505
+ official: "Official",
506
+ detailsFor: "View details: {title}",
507
+ "version-error": "This plugin is incompatible with this DSH version. Update DSH and retry.",
508
+ "management-error": "Could not enable the plugin. Open its details to check the error and retry.",
509
+ enable: "Enable",
510
+ dismiss: "Not now",
511
+ working: "Working…",
512
+ scope: "Available in all conversations when enabled",
513
+ enabled: "Enabled",
514
+ "already-enabled": "Already selected in Plugins. Open details to check its runtime status.",
515
+ dismissed: "Dismissed",
516
+ replaced: "Replaced",
517
+ "restart-required": "Saved. Restart DSH to apply.",
518
+ failed: "Could not enable. Retry or check Plugins.",
519
+ retry: "Retry enabling",
520
+ unconfirmed: "Could not confirm whether the plugin was enabled. Retry to check.",
521
+ "lookup-failed": "Could not load this plugin’s details. Try again.",
522
+ retryLookup: "Try again",
523
+ unavailable: "This plugin cannot be enabled now. Check Plugins.",
524
+ unknown: "This recommendation is unavailable. Reopen the conversation.",
525
+ "access-denied": "You do not have permission to change this profile.",
526
+ "not-live-root": "Use this recommendation in its original conversation.",
527
+ closing: "The service is reloading. Try again shortly.",
528
+ transport: "Could not confirm the result. Refresh and try again."
529
+ };
530
+ /** Japanese card copy. */
531
+ const ja = {
532
+ heading: "おすすめのプラグイン",
533
+ official: "公式",
534
+ detailsFor: "詳細を表示:{title}",
535
+ "version-error": "このプラグインは現在の DSH バージョンと互換性がありません。DSH を更新してから再試行してください。",
536
+ "management-error": "プラグインを有効にできませんでした。詳細を開いてエラーを確認し、再試行してください。",
537
+ enable: "有効にする",
538
+ dismiss: "今はしない",
539
+ working: "処理中…",
540
+ scope: "有効にするとすべての会話で使えます",
541
+ enabled: "有効化済み",
542
+ "already-enabled": "プラグイン画面で有効になっています。詳細で動作状況を確認できます。",
543
+ dismissed: "却下済み",
544
+ replaced: "置き換え済み",
545
+ "restart-required": "保存しました。適用するには DSH を再起動してください。",
546
+ failed: "有効にできませんでした。再試行するか、プラグイン画面を確認してください。",
547
+ retry: "再度有効にする",
548
+ unconfirmed: "プラグインが有効になったか確認できませんでした。再試行して確認してください。",
549
+ "lookup-failed": "プラグインの情報を読み込めませんでした。もう一度お試しください。",
550
+ retryLookup: "再試行",
551
+ unavailable: "このプラグインは現在有効にできません。プラグイン画面を確認してください。",
552
+ unknown: "この推薦は利用できません。会話を開き直してください。",
553
+ "access-denied": "このプロファイルを変更する権限がありません。",
554
+ "not-live-root": "元の会話でこの推薦を操作してください。",
555
+ closing: "サービスを再読み込み中です。しばらくしてから再試行してください。",
556
+ transport: "結果を確認できませんでした。更新してから再試行してください。"
557
+ };
558
+ /** Spanish card copy. */
559
+ const es = {
560
+ heading: "Complemento recomendado",
561
+ official: "Oficial",
562
+ detailsFor: "Ver detalles: {title}",
563
+ "version-error": "Este complemento no es compatible con esta versión de DSH. Actualiza DSH y vuelve a intentarlo.",
564
+ "management-error": "No se pudo habilitar el complemento. Abre sus detalles para revisar el error y vuelve a intentarlo.",
565
+ enable: "Habilitar",
566
+ dismiss: "Ahora no",
567
+ working: "Procesando…",
568
+ scope: "Disponible en todas las conversaciones una vez habilitado",
569
+ enabled: "Habilitado",
570
+ "already-enabled": "Ya está seleccionado en Complementos. Abre los detalles para ver su estado de ejecución.",
571
+ dismissed: "Descartado",
572
+ replaced: "Reemplazado",
573
+ "restart-required": "Guardado. Reinicia DSH para aplicarlo.",
574
+ failed: "No se pudo habilitar. Reintenta o revisa Complementos.",
575
+ retry: "Reintentar habilitación",
576
+ unconfirmed: "No se pudo confirmar si el complemento se habilitó. Reintenta para comprobarlo.",
577
+ "lookup-failed": "No se pudieron cargar los detalles de este complemento. Inténtalo de nuevo.",
578
+ retryLookup: "Intentar de nuevo",
579
+ unavailable: "Este complemento no se puede habilitar ahora. Revisa Complementos.",
580
+ unknown: "Esta recomendación no está disponible. Vuelve a abrir la conversación.",
581
+ "access-denied": "No tienes permiso para cambiar este perfil.",
582
+ "not-live-root": "Usa esta recomendación en su conversación original.",
583
+ closing: "El servicio se está recargando. Inténtalo de nuevo en breve.",
584
+ transport: "No se pudo confirmar el resultado. Actualiza e inténtalo de nuevo."
585
+ };
586
+ /** French card copy. */
587
+ const fr = {
588
+ heading: "Plugin recommandé",
589
+ official: "Officiel",
590
+ detailsFor: "Voir les détails : {title}",
591
+ "version-error": "Ce plugin n’est pas compatible avec cette version de DSH. Mettez à jour DSH et réessayez.",
592
+ "management-error": "Impossible d’activer le plugin. Ouvrez ses détails pour vérifier l’erreur, puis réessayez.",
593
+ enable: "Activer",
594
+ dismiss: "Pas maintenant",
595
+ working: "Traitement…",
596
+ scope: "Disponible dans toutes les conversations une fois activé",
597
+ enabled: "Activé",
598
+ "already-enabled": "Déjà sélectionné dans Plugins. Ouvrez les détails pour vérifier son état d’exécution.",
599
+ dismissed: "Ignoré",
600
+ replaced: "Remplacé",
601
+ "restart-required": "Enregistré. Redémarrez DSH pour l’appliquer.",
602
+ failed: "Impossible d’activer. Réessayez ou vérifiez Plugins.",
603
+ retry: "Réessayer l’activation",
604
+ unconfirmed: "Impossible de confirmer si le plugin a été activé. Réessayez pour vérifier.",
605
+ "lookup-failed": "Impossible de charger les détails de ce plugin. Réessayez.",
606
+ retryLookup: "Réessayer",
607
+ unavailable: "Ce plugin ne peut pas être activé pour le moment. Vérifiez Plugins.",
608
+ unknown: "Cette recommandation n’est pas disponible. Rouvrez la conversation.",
609
+ "access-denied": "Vous n’avez pas l’autorisation de modifier ce profil.",
610
+ "not-live-root": "Utilisez cette recommandation dans sa conversation d’origine.",
611
+ closing: "Le service se recharge. Réessayez dans un instant.",
612
+ transport: "Impossible de confirmer le résultat. Actualisez et réessayez."
613
+ };
614
+ /** German card copy. */
615
+ const de = {
616
+ heading: "Empfohlenes Plugin",
617
+ official: "Offiziell",
618
+ detailsFor: "Details anzeigen: {title}",
619
+ "version-error": "Dieses Plugin ist mit dieser DSH-Version nicht kompatibel. Aktualisieren Sie DSH und versuchen Sie es erneut.",
620
+ "management-error": "Das Plugin konnte nicht aktiviert werden. Öffnen Sie die Details, um den Fehler zu prüfen, und versuchen Sie es erneut.",
621
+ enable: "Aktivieren",
622
+ dismiss: "Nicht jetzt",
623
+ working: "Wird verarbeitet…",
624
+ scope: "Nach dem Aktivieren in allen Gesprächen verfügbar",
625
+ enabled: "Aktiviert",
626
+ "already-enabled": "Bereits unter Plugins ausgewählt. Öffnen Sie die Details, um den Laufzeitstatus zu prüfen.",
627
+ dismissed: "Verworfen",
628
+ replaced: "Ersetzt",
629
+ "restart-required": "Gespeichert. Starten Sie DSH neu, um die Änderung anzuwenden.",
630
+ failed: "Aktivierung fehlgeschlagen. Versuchen Sie es erneut oder prüfen Sie Plugins.",
631
+ retry: "Aktivierung wiederholen",
632
+ unconfirmed: "Es konnte nicht bestätigt werden, ob das Plugin aktiviert wurde. Versuchen Sie es erneut, um es zu prüfen.",
633
+ "lookup-failed": "Die Details dieses Plugins konnten nicht geladen werden. Versuchen Sie es erneut.",
634
+ retryLookup: "Erneut versuchen",
635
+ unavailable: "Dieses Plugin kann derzeit nicht aktiviert werden. Prüfen Sie Plugins.",
636
+ unknown: "Diese Empfehlung ist nicht verfügbar. Öffnen Sie das Gespräch erneut.",
637
+ "access-denied": "Sie haben keine Berechtigung, dieses Profil zu ändern.",
638
+ "not-live-root": "Verwenden Sie diese Empfehlung in ihrem ursprünglichen Gespräch.",
639
+ closing: "Der Dienst wird neu geladen. Versuchen Sie es gleich erneut.",
640
+ transport: "Das Ergebnis konnte nicht bestätigt werden. Aktualisieren Sie die Seite und versuchen Sie es erneut."
641
+ };
642
+ /** Russian card copy. */
643
+ const ru = {
644
+ heading: "Рекомендуемый плагин",
645
+ official: "Официальный",
646
+ detailsFor: "Подробнее: {title}",
647
+ "version-error": "Этот плагин несовместим с текущей версией DSH. Обновите DSH и повторите попытку.",
648
+ "management-error": "Не удалось включить плагин. Откройте его подробности, чтобы проверить ошибку, и повторите попытку.",
649
+ enable: "Включить",
650
+ dismiss: "Не сейчас",
651
+ working: "Обработка…",
652
+ scope: "После включения доступен во всех разговорах",
653
+ enabled: "Включено",
654
+ "already-enabled": "Уже выбран в разделе «Плагины». Откройте подробности, чтобы проверить состояние работы.",
655
+ dismissed: "Отклонено",
656
+ replaced: "Заменено",
657
+ "restart-required": "Сохранено. Перезапустите DSH, чтобы применить изменение.",
658
+ failed: "Не удалось включить. Повторите попытку или проверьте раздел «Плагины».",
659
+ retry: "Повторить включение",
660
+ unconfirmed: "Не удалось подтвердить, включен ли плагин. Повторите попытку, чтобы проверить.",
661
+ "lookup-failed": "Не удалось загрузить сведения об этом плагине. Повторите попытку.",
662
+ retryLookup: "Повторить",
663
+ unavailable: "Этот плагин сейчас нельзя включить. Проверьте раздел «Плагины».",
664
+ unknown: "Эта рекомендация недоступна. Откройте разговор заново.",
665
+ "access-denied": "У вас нет разрешения на изменение этого профиля.",
666
+ "not-live-root": "Используйте эту рекомендацию в исходном разговоре.",
667
+ closing: "Сервис перезагружается. Повторите попытку чуть позже.",
668
+ transport: "Не удалось подтвердить результат. Обновите страницу и повторите попытку."
669
+ };
670
+ /** Portuguese card copy. */
671
+ const pt = {
672
+ heading: "Plug-in recomendado",
673
+ official: "Oficial",
674
+ detailsFor: "Ver detalhes: {title}",
675
+ "version-error": "Este plug-in não é compatível com esta versão do DSH. Atualize o DSH e tente novamente.",
676
+ "management-error": "Não foi possível ativar o plug-in. Abra os detalhes para verificar o erro e tente novamente.",
677
+ enable: "Ativar",
678
+ dismiss: "Agora não",
679
+ working: "Processando…",
680
+ scope: "Disponível em todas as conversas após a ativação",
681
+ enabled: "Ativado",
682
+ "already-enabled": "Já selecionado em Plug-ins. Abra os detalhes para verificar o status de execução.",
683
+ dismissed: "Dispensado",
684
+ replaced: "Substituído",
685
+ "restart-required": "Salvo. Reinicie o DSH para aplicar.",
686
+ failed: "Não foi possível ativar. Tente novamente ou verifique Plug-ins.",
687
+ retry: "Tentar ativar novamente",
688
+ unconfirmed: "Não foi possível confirmar se o plug-in foi ativado. Tente novamente para verificar.",
689
+ "lookup-failed": "Não foi possível carregar os detalhes deste plug-in. Tente novamente.",
690
+ retryLookup: "Tentar novamente",
691
+ unavailable: "Este plug-in não pode ser ativado agora. Verifique Plug-ins.",
692
+ unknown: "Esta recomendação não está disponível. Reabra a conversa.",
693
+ "access-denied": "Você não tem permissão para alterar este perfil.",
694
+ "not-live-root": "Use esta recomendação na conversa original.",
695
+ closing: "O serviço está sendo recarregado. Tente novamente em instantes.",
696
+ transport: "Não foi possível confirmar o resultado. Atualize e tente novamente."
697
+ };
698
+ //#endregion
699
+ //#region lib/types/client/mount.js
700
+ /** Register the official plugin card body, its catalog-text Remote and its localized copy. */
701
+ /** Services the body needs; the shared card plugin provides `actionCards`. */
702
+ const inject = [
703
+ "locale",
704
+ "remote",
705
+ "actionCards",
706
+ "pluginNavigation"
707
+ ];
708
+ /** Mount the catalog-text Remote, then register the body for the same plugin lifetime.
709
+ * @param ctx - Client plugin context.
710
+ * @param contribution - Generated Remote descriptors supplied by the built entry.
711
+ * @returns disposer removing the body before the Remote contribution.
712
+ */
713
+ async function mountRecommendations(ctx, contribution) {
714
+ const unmount = await ctx.remote.$mount(contribution);
715
+ const body = ctx.inject(["remote.pluginRecommendations"], registerBody);
716
+ try {
717
+ await body;
718
+ } catch (error) {
719
+ await body.dispose();
720
+ await unmount();
721
+ throw error;
722
+ }
723
+ return async () => {
724
+ await body.dispose();
725
+ await unmount();
726
+ };
727
+ }
728
+ function registerBody(ctx) {
729
+ const services = {
730
+ catalog: (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({}),
731
+ describe: async (sessionId, callId) => {
732
+ const result = await ctx.remote.pluginRecommendations.describe(sessionId, callId);
733
+ return result.ok ? result.value : void 0;
734
+ },
735
+ openDetails: (packageName) => {
736
+ ctx.pluginNavigation.openBundle(packageName);
737
+ },
738
+ resolveText: (text) => ctx.locale.resolveText(text)
739
+ };
740
+ ctx.effect(() => ctx.locale.register("pluginRecommendations", {
741
+ en,
742
+ zh,
743
+ ja,
744
+ es,
745
+ fr,
746
+ de,
747
+ ru,
748
+ pt
749
+ }), "plugin-recommendations: locale");
750
+ ctx.effect(() => ctx.actionCards.register({
751
+ action: "enable_official_plugin",
752
+ locale: "pluginRecommendations",
753
+ Body: (props) => (0, react.createElement)(PluginCardBody, {
754
+ ...props,
755
+ ...services
756
+ })
757
+ }), "plugin-recommendations: card body");
758
+ }
759
+ //#endregion
760
+ //#region lib/types/client/index.js
761
+ /** Mount recommendation UI and its optional Remote.
762
+ * @param ctx - Client plugin context.
763
+ * @returns disposer for both contributions.
764
+ */
765
+ async function apply(ctx) {
766
+ return await mountRecommendations(ctx, TYPERT_REMOTE);
767
+ }
768
+ //#endregion
769
+ exports.apply = apply;
770
+ exports.inject = inject;
771
+ return module.exports;
772
+ }
773
+ });
774
+
775
+ //# sourceMappingURL=client.js.map