@yadsh/dsh-sleev 0.0.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/lib/client.js ADDED
@@ -0,0 +1,504 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "dsh-sleev",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let react = require("react");
8
+ let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
9
+ let react_jsx_runtime = require("react/jsx-runtime");
10
+ //#region src/client/settings-controller.ts
11
+ const DEFAULTS = {
12
+ routes: [],
13
+ routePrefixes: ["sleev-"],
14
+ maxRecentCalls: 100,
15
+ logLevel: "info"
16
+ };
17
+ function lines(values) {
18
+ return values.join("\n");
19
+ }
20
+ function parseLines(value) {
21
+ return [...new Set(value.split(/\r?\n/u).map((part) => part.trim()).filter(Boolean))];
22
+ }
23
+ function equal(left, right) {
24
+ return JSON.stringify(left) === JSON.stringify(right);
25
+ }
26
+ /** Staged form controller matching DSH's built-in plugin settings cards. */
27
+ var SleevSettingsController = class {
28
+ scope;
29
+ drafts = /* @__PURE__ */ new Map();
30
+ store;
31
+ unsubscribe;
32
+ saving = false;
33
+ failed = false;
34
+ constructor(scope) {
35
+ this.scope = scope;
36
+ this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(this.project());
37
+ this.unsubscribe = scope.subscribe(() => this.publish());
38
+ }
39
+ inject() {
40
+ return {
41
+ hooks: { sleevSettings: this.store },
42
+ edit: (field, value) => {
43
+ const parsed = this.parse(field, value);
44
+ if (parsed !== void 0 && equal(parsed, this.effective()[field])) this.drafts.delete(field);
45
+ else this.drafts.set(field, {
46
+ text: value,
47
+ reset: false
48
+ });
49
+ this.failed = false;
50
+ this.publish();
51
+ },
52
+ save: () => void this.save(),
53
+ discard: () => {
54
+ this.drafts.clear();
55
+ this.failed = false;
56
+ this.publish();
57
+ },
58
+ resetField: (field) => {
59
+ if (this.stored(field)) this.drafts.set(field, {
60
+ text: this.format(field, this.base()[field]),
61
+ reset: true
62
+ });
63
+ else this.drafts.delete(field);
64
+ this.failed = false;
65
+ this.publish();
66
+ }
67
+ };
68
+ }
69
+ dispose() {
70
+ this.unsubscribe();
71
+ }
72
+ base() {
73
+ return {
74
+ ...DEFAULTS,
75
+ ...this.scope.getSnapshot().base
76
+ };
77
+ }
78
+ effective() {
79
+ return {
80
+ ...DEFAULTS,
81
+ ...this.scope.getSnapshot().value
82
+ };
83
+ }
84
+ stored(field) {
85
+ const user = this.scope.getSnapshot().user;
86
+ return user !== void 0 && Object.hasOwn(user, field);
87
+ }
88
+ format(field, value) {
89
+ return field === "routes" || field === "routePrefixes" ? lines(value) : String(value);
90
+ }
91
+ parse(field, text) {
92
+ if (field === "routes" || field === "routePrefixes") return parseLines(text);
93
+ if (field === "maxRecentCalls") {
94
+ const value = Number(text.trim());
95
+ return Number.isSafeInteger(value) && value > 0 ? value : void 0;
96
+ }
97
+ return [
98
+ "off",
99
+ "info",
100
+ "debug"
101
+ ].includes(text) ? text : void 0;
102
+ }
103
+ fieldState(field) {
104
+ const draft = this.drafts.get(field);
105
+ if (draft === void 0) return {
106
+ text: this.format(field, this.effective()[field]),
107
+ overridden: this.stored(field),
108
+ invalid: false
109
+ };
110
+ return {
111
+ text: draft.text,
112
+ overridden: !draft.reset,
113
+ invalid: !draft.reset && this.parse(field, draft.text) === void 0
114
+ };
115
+ }
116
+ plan() {
117
+ const effective = this.effective();
118
+ const result = [];
119
+ for (const [field, draft] of this.drafts) {
120
+ if (draft.reset) {
121
+ if (this.stored(field)) result.push({
122
+ field,
123
+ draft,
124
+ action: "unset",
125
+ invalid: false
126
+ });
127
+ continue;
128
+ }
129
+ const value = this.parse(field, draft.text);
130
+ if (value !== void 0 && equal(value, effective[field])) continue;
131
+ result.push({
132
+ field,
133
+ draft,
134
+ action: "set",
135
+ value,
136
+ invalid: value === void 0
137
+ });
138
+ }
139
+ return result;
140
+ }
141
+ project() {
142
+ const snapshot = this.scope.getSnapshot();
143
+ const plan = this.plan();
144
+ return {
145
+ available: snapshot.status === "ready",
146
+ writable: snapshot.writable,
147
+ dirty: plan.length > 0,
148
+ invalid: plan.some((entry) => entry.invalid),
149
+ saving: this.saving,
150
+ failed: this.failed,
151
+ routes: this.fieldState("routes"),
152
+ routePrefixes: this.fieldState("routePrefixes"),
153
+ maxRecentCalls: this.fieldState("maxRecentCalls"),
154
+ logLevel: this.fieldState("logLevel")
155
+ };
156
+ }
157
+ async save() {
158
+ const state = this.project();
159
+ if (!state.dirty || state.invalid || state.saving || !state.writable) return;
160
+ const writes = this.plan();
161
+ this.saving = true;
162
+ this.failed = false;
163
+ this.publish();
164
+ try {
165
+ for (const write of writes) if (write.action === "unset") await this.scope.unset(write.field);
166
+ else await this.scope.set(write.field, write.value);
167
+ const user = this.scope.getSnapshot().user;
168
+ if (writes.every((write) => write.action === "unset" ? user === void 0 || !Object.hasOwn(user, write.field) : equal(user?.[write.field], write.value))) {
169
+ for (const write of writes) if (this.drafts.get(write.field) === write.draft) this.drafts.delete(write.field);
170
+ } else this.failed = true;
171
+ } catch {
172
+ this.failed = true;
173
+ } finally {
174
+ this.saving = false;
175
+ this.publish();
176
+ }
177
+ }
178
+ publish() {
179
+ this.store.set(this.project());
180
+ }
181
+ };
182
+ //#endregion
183
+ //#region src/shared/settings.ts
184
+ /** Stable raw namespace shared by the Host registration and browser card. */
185
+ const SLEEV_SETTINGS_NAMESPACE_ID = "sleev";
186
+ //#endregion
187
+ //#region src/client/index.tsx
188
+ const LOCALE_NAMESPACE = "dsh-sleev";
189
+ const SETTINGS_NAMESPACE = SLEEV_SETTINGS_NAMESPACE_ID;
190
+ const en = {
191
+ title: "Sleev",
192
+ description: "Observed routes and telemetry retention.",
193
+ expand: "Show settings",
194
+ collapse: "Hide settings",
195
+ unsaved: "Unsaved",
196
+ overridden: "Overridden",
197
+ reset: "Reset to default",
198
+ routes: "Exact routes",
199
+ routesHint: "One DSH provider alias per line. Empty means no exact matches.",
200
+ routePrefixes: "Route prefixes",
201
+ routePrefixesHint: "One prefix per line. The default is sleev-.",
202
+ maxRecentCalls: "Recent calls retained",
203
+ maxRecentCallsHint: "Maximum secret-free telemetry records kept in memory.",
204
+ logLevel: "Telemetry logging",
205
+ logLevelHint: "Controls structured call start/end logging.",
206
+ logOff: "Off",
207
+ logInfo: "Completed calls",
208
+ logDebug: "Call starts and completions",
209
+ invalidNumber: "Enter a positive whole number.",
210
+ readOnly: "This deployment stores settings read-only.",
211
+ saveFailed: "The deployment did not accept these values.",
212
+ discard: "Discard",
213
+ save: "Save",
214
+ saving: "Saving…"
215
+ };
216
+ const zh = {
217
+ title: "Sleev",
218
+ description: "观测路由和遥测保留设置。",
219
+ expand: "展开设置",
220
+ collapse: "收起设置",
221
+ unsaved: "未保存",
222
+ overridden: "已覆盖",
223
+ reset: "恢复默认值",
224
+ routes: "精确路由",
225
+ routesHint: "每行一个 DSH 提供商别名。留空表示不进行精确匹配。",
226
+ routePrefixes: "路由前缀",
227
+ routePrefixesHint: "每行一个前缀。默认值为 sleev-。",
228
+ maxRecentCalls: "保留最近调用数",
229
+ maxRecentCallsHint: "内存中最多保留多少条无敏感信息的遥测记录。",
230
+ logLevel: "遥测日志",
231
+ logLevelHint: "控制结构化调用开始和结束日志。",
232
+ logOff: "关闭",
233
+ logInfo: "仅完成的调用",
234
+ logDebug: "调用开始和完成",
235
+ invalidNumber: "请输入正整数。",
236
+ readOnly: "此部署的设置为只读。",
237
+ saveFailed: "部署未接受这些值。",
238
+ discard: "放弃修改",
239
+ save: "保存",
240
+ saving: "保存中…"
241
+ };
242
+ const CARD_STYLES = `
243
+ .dsh-sleev-card{list-style:none;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:var(--dsw-alias-bg-layer-3);transition:border-color .16s ease,background .16s ease}
244
+ .dsh-sleev-card:hover{border-color:var(--dsw-alias-border-label-dimmed)}
245
+ .dsh-sleev-card.dsh-sleev-card-open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-label-dimmed)}
246
+ .dsh-sleev-header{width:100%;appearance:none;border:0;background:none;font:inherit;color:inherit;text-align:left;cursor:pointer;display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:12px}
247
+ .dsh-sleev-header:focus-visible,.dsh-sleev-button:focus-visible,.dsh-sleev-reset:focus-visible,.dsh-sleev-input:focus-visible{outline:2px solid var(--dsw-alias-border-brand);outline-offset:2px}
248
+ .dsh-sleev-head-text{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
249
+ .dsh-sleev-name{font-size:15px;font-weight:600;line-height:1.4;color:var(--dsw-alias-label-primary)}
250
+ .dsh-sleev-description{font-size:13px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
251
+ .dsh-sleev-chevron{flex:none;color:var(--dsw-alias-label-tertiary);transition:transform .16s ease;font-size:16px;line-height:1}
252
+ .dsh-sleev-card-open .dsh-sleev-chevron{transform:rotate(180deg)}
253
+ .dsh-sleev-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
254
+ .dsh-sleev-read-only{margin:12px 0 0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
255
+ .dsh-sleev-pill{border-radius:999px;padding:1px 8px;font-size:11px;line-height:17px;font-weight:500;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);white-space:nowrap}
256
+ .dsh-sleev-field{display:flex;flex-direction:column;gap:6px;padding:12px 0}
257
+ .dsh-sleev-field+.dsh-sleev-field{border-top:1px solid var(--dsw-alias-border-l2)}
258
+ .dsh-sleev-field-head{display:flex;align-items:center;gap:8px}
259
+ .dsh-sleev-label{flex:1;min-width:0;font-size:13px;font-weight:500;line-height:1.5;color:var(--dsw-alias-label-primary)}
260
+ .dsh-sleev-badges{display:inline-flex;align-items:center;gap:8px}
261
+ .dsh-sleev-reset{appearance:none;border:0;background:none;padding:0;font:inherit;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-secondary);cursor:pointer}
262
+ .dsh-sleev-reset:disabled{opacity:.4;cursor:default}
263
+ .dsh-sleev-input{box-sizing:border-box;width:100%;min-height:34px;padding:0 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);font:inherit;font-size:13px;line-height:1.5;color:var(--dsw-alias-label-primary)}
264
+ textarea.dsh-sleev-input{height:64px;min-height:48px;padding:8px 12px;resize:vertical}
265
+ .dsh-sleev-input:focus{border-color:var(--dsw-alias-border-brand);outline:none}
266
+ .dsh-sleev-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}
267
+ .dsh-sleev-input[aria-invalid=true]{border-color:var(--dsw-alias-border-error)}
268
+ .dsh-sleev-hint,.dsh-sleev-error{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
269
+ .dsh-sleev-error{color:var(--dsw-alias-label-error)}
270
+ .dsh-sleev-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 0 4px;border-top:1px solid var(--dsw-alias-border-l2)}
271
+ .dsh-sleev-save-error{flex:1;margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-error)}
272
+ .dsh-sleev-button{appearance:none;border:1px solid transparent;border-radius:8px;padding:5px 14px;font:inherit;font-size:13px;line-height:1.5;cursor:pointer}
273
+ .dsh-sleev-discard{border-color:var(--dsw-alias-border-l2);background:none;color:var(--dsw-alias-label-secondary)}
274
+ .dsh-sleev-save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}
275
+ .dsh-sleev-button:disabled{opacity:.4;cursor:default}
276
+ `;
277
+ function SettingsField(props) {
278
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
279
+ className: "dsh-sleev-field",
280
+ children: [
281
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
282
+ className: "dsh-sleev-field-head",
283
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
284
+ htmlFor: props.id,
285
+ className: "dsh-sleev-label",
286
+ children: props.label
287
+ }), props.state.overridden ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
288
+ className: "dsh-sleev-badges",
289
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
290
+ className: "dsh-sleev-pill",
291
+ children: props.overriddenLabel
292
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
293
+ type: "button",
294
+ className: "dsh-sleev-reset",
295
+ disabled: !props.writable,
296
+ onClick: props.onReset,
297
+ children: props.resetLabel
298
+ })]
299
+ }) : null]
300
+ }),
301
+ props.children,
302
+ props.state.invalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
303
+ className: "dsh-sleev-error",
304
+ children: props.invalidLabel
305
+ }) : null,
306
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
307
+ className: "dsh-sleev-hint",
308
+ children: props.hint
309
+ })
310
+ ]
311
+ });
312
+ }
313
+ /** Settings card contributed to the official Plugins → Plugin configuration tab. */
314
+ function SleevSettingsCard(props) {
315
+ const [open, setOpen] = (0, react.useState)(false);
316
+ const state = props.useSleevSettings((snapshot) => snapshot);
317
+ if (!state.available) return null;
318
+ const blocked = !state.dirty || state.invalid || state.saving || !state.writable;
319
+ const edit = (field) => (event) => props.edit(field, event.target.value);
320
+ const common = (field) => ({
321
+ state: state[field],
322
+ writable: state.writable,
323
+ overriddenLabel: props.t("overridden"),
324
+ resetLabel: props.t("reset"),
325
+ onReset: () => props.resetField(field)
326
+ });
327
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
328
+ className: `dsh-sleev-card${open ? " dsh-sleev-card-open" : ""}`,
329
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
330
+ type: "button",
331
+ className: "dsh-sleev-header",
332
+ "aria-expanded": open,
333
+ "aria-label": `${props.t(open ? "collapse" : "expand")}: Sleev`,
334
+ onClick: () => setOpen(!open),
335
+ children: [
336
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
337
+ className: "dsh-sleev-head-text",
338
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
339
+ className: "dsh-sleev-name",
340
+ children: props.t("title")
341
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
342
+ className: "dsh-sleev-description",
343
+ children: props.t("description")
344
+ })]
345
+ }),
346
+ state.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
347
+ className: "dsh-sleev-pill",
348
+ children: props.t("unsaved")
349
+ }) : null,
350
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
351
+ className: "dsh-sleev-chevron",
352
+ "aria-hidden": "true",
353
+ children: "⌄"
354
+ })
355
+ ]
356
+ }), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
357
+ className: "dsh-sleev-body",
358
+ children: [
359
+ !state.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
360
+ className: "dsh-sleev-read-only",
361
+ role: "status",
362
+ children: props.t("readOnly")
363
+ }) : null,
364
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsField, {
365
+ id: "sleev-routes",
366
+ label: props.t("routes"),
367
+ hint: props.t("routesHint"),
368
+ ...common("routes"),
369
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
370
+ id: "sleev-routes",
371
+ className: "dsh-sleev-input",
372
+ value: state.routes.text,
373
+ disabled: !state.writable,
374
+ onChange: edit("routes")
375
+ })
376
+ }),
377
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsField, {
378
+ id: "sleev-route-prefixes",
379
+ label: props.t("routePrefixes"),
380
+ hint: props.t("routePrefixesHint"),
381
+ ...common("routePrefixes"),
382
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
383
+ id: "sleev-route-prefixes",
384
+ className: "dsh-sleev-input",
385
+ value: state.routePrefixes.text,
386
+ disabled: !state.writable,
387
+ onChange: edit("routePrefixes")
388
+ })
389
+ }),
390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsField, {
391
+ id: "sleev-max-recent-calls",
392
+ label: props.t("maxRecentCalls"),
393
+ hint: props.t("maxRecentCallsHint"),
394
+ invalidLabel: props.t("invalidNumber"),
395
+ ...common("maxRecentCalls"),
396
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
397
+ id: "sleev-max-recent-calls",
398
+ className: "dsh-sleev-input",
399
+ type: "number",
400
+ min: 1,
401
+ step: 1,
402
+ value: state.maxRecentCalls.text,
403
+ disabled: !state.writable,
404
+ "aria-invalid": state.maxRecentCalls.invalid,
405
+ onChange: edit("maxRecentCalls")
406
+ })
407
+ }),
408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SettingsField, {
409
+ id: "sleev-log-level",
410
+ label: props.t("logLevel"),
411
+ hint: props.t("logLevelHint"),
412
+ ...common("logLevel"),
413
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
414
+ id: "sleev-log-level",
415
+ className: "dsh-sleev-input",
416
+ value: state.logLevel.text,
417
+ disabled: !state.writable,
418
+ onChange: edit("logLevel"),
419
+ children: [
420
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
421
+ value: "off",
422
+ children: props.t("logOff")
423
+ }),
424
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
425
+ value: "info",
426
+ children: props.t("logInfo")
427
+ }),
428
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
429
+ value: "debug",
430
+ children: props.t("logDebug")
431
+ })
432
+ ]
433
+ })
434
+ }),
435
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
436
+ className: "dsh-sleev-footer",
437
+ children: [
438
+ state.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
439
+ className: "dsh-sleev-save-error",
440
+ role: "status",
441
+ children: props.t("saveFailed")
442
+ }) : null,
443
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
444
+ type: "button",
445
+ className: "dsh-sleev-button dsh-sleev-discard",
446
+ disabled: !state.dirty || state.saving,
447
+ onClick: props.discard,
448
+ children: props.t("discard")
449
+ }),
450
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
451
+ type: "button",
452
+ className: "dsh-sleev-button dsh-sleev-save",
453
+ disabled: blocked,
454
+ onClick: props.save,
455
+ children: props.t(state.saving ? "saving" : "save")
456
+ })
457
+ ]
458
+ })
459
+ ]
460
+ }) : null]
461
+ });
462
+ }
463
+ const inject = [
464
+ "slots",
465
+ "settingsScope",
466
+ "locale"
467
+ ];
468
+ /** Register Sleev's localized settings card in the official keyed plugin slot. */
469
+ function apply(ctx) {
470
+ ctx.effect(() => {
471
+ const style = document.createElement("style");
472
+ style.dataset.dshSleev = "settings";
473
+ style.textContent = CARD_STYLES;
474
+ document.head.append(style);
475
+ return () => style.remove();
476
+ }, "dsh-sleev: settings styles");
477
+ ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, {
478
+ en,
479
+ zh
480
+ }), "dsh-sleev: settings dictionaries");
481
+ const controller = new SleevSettingsController(ctx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE }));
482
+ ctx.slots.inject("settings.plugin.item", () => {
483
+ const unregister = ctx.slots.register({
484
+ name: "settings.plugin.item",
485
+ key: SETTINGS_NAMESPACE,
486
+ locale: LOCALE_NAMESPACE,
487
+ inject: () => controller.inject()
488
+ }, SleevSettingsCard);
489
+ return () => {
490
+ controller.dispose();
491
+ unregister();
492
+ };
493
+ });
494
+ }
495
+ //#endregion
496
+ exports.SleevSettingsCard = SleevSettingsCard;
497
+ exports.SleevSettingsController = SleevSettingsController;
498
+ exports.apply = apply;
499
+ exports.inject = inject;
500
+ return module.exports;
501
+ }
502
+ });
503
+
504
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,44 @@
1
+ //#region src/host/optimizer/sleev/headers.ts
2
+ /** Default loopback listener installed by the Sleev CLI. */
3
+ const DEFAULT_SLEEV_GATEWAY_URL = "http://127.0.0.1:17321/v1";
4
+ /**
5
+ * Temporary compatibility choice for DSH's pi-ai transport.
6
+ *
7
+ * Sleev does not currently document a native DeepSeek Harness id. Keep this
8
+ * value visible and user-overridable rather than presenting it as guaranteed.
9
+ */
10
+ const EXPERIMENTAL_DSH_HARNESS_ID = "pi";
11
+ function safeHeaderValue(value, field) {
12
+ const normalized = value.trim();
13
+ if (normalized.length === 0) throw new Error(`dsh-sleev: ${field} must be non-empty`);
14
+ if (/\r|\n/u.test(normalized)) throw new Error(`dsh-sleev: ${field} cannot contain a line break`);
15
+ return normalized;
16
+ }
17
+ function upstreamUrl(value) {
18
+ const normalized = safeHeaderValue(value, "baseUrl");
19
+ let parsed;
20
+ try {
21
+ parsed = new URL(normalized);
22
+ } catch {
23
+ throw new Error("dsh-sleev: baseUrl must be an absolute HTTP(S) URL");
24
+ }
25
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error("dsh-sleev: baseUrl must use HTTP or HTTPS");
26
+ return normalized;
27
+ }
28
+ /**
29
+ * Build only the public Sleev routing headers. Authorization remains owned by
30
+ * DSH credentials and llm-pi-ai, so this result can be logged or inspected.
31
+ */
32
+ function buildSleevHeaders(target) {
33
+ const harness = safeHeaderValue(target.harnessId, "harnessId");
34
+ if (target.kind === "provider") return Object.freeze({
35
+ "sleev-provider": safeHeaderValue(target.provider, "provider"),
36
+ "sleev-harness": harness
37
+ });
38
+ return Object.freeze({
39
+ "sleev-base-url": upstreamUrl(target.baseUrl),
40
+ "sleev-harness": harness
41
+ });
42
+ }
43
+ //#endregion
44
+ export { DEFAULT_SLEEV_GATEWAY_URL, EXPERIMENTAL_DSH_HARNESS_ID, buildSleevHeaders };