@yadsh/dsh-sleev 0.0.2 → 0.0.3

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 CHANGED
@@ -240,17 +240,19 @@ window.__ModuleLoader__.load({
240
240
  saving: "保存中…"
241
241
  };
242
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}
243
+ .dsh-plugin-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
244
+ .dsh-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed)}
245
+ .dsh-plugin-card--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
246
+ .dsh-plugin-card__header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}
247
+ .dsh-plugin-card__header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
248
+ .dsh-plugin-card__head-text{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}
249
+ .dsh-plugin-card__name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
250
+ .dsh-plugin-card__description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
251
+ .dsh-plugin-card__badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
252
+ .dsh-plugin-card__chevron{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}
253
+ .dsh-plugin-card--open .dsh-plugin-card__chevron{transform:rotate(180deg)}
254
+ .dsh-plugin-card__body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
255
+ .dsh-sleev-button:focus-visible,.dsh-sleev-reset:focus-visible,.dsh-sleev-input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
254
256
  .dsh-sleev-read-only{margin:12px 0 0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}
255
257
  .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
258
  .dsh-sleev-field{display:flex;flex-direction:column;gap:6px;padding:12px 0}
@@ -274,6 +276,20 @@ textarea.dsh-sleev-input{height:64px;min-height:48px;padding:8px 12px;resize:ver
274
276
  .dsh-sleev-save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}
275
277
  .dsh-sleev-button:disabled{opacity:.4;cursor:default}
276
278
  `;
279
+ function ChevronDown() {
280
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
281
+ className: "dsh-plugin-card__chevron",
282
+ viewBox: "0 0 14 14",
283
+ fill: "none",
284
+ "aria-hidden": "true",
285
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
286
+ d: "m3.5 5.25 3.5 3.5 3.5-3.5",
287
+ stroke: "currentColor",
288
+ strokeLinecap: "round",
289
+ strokeLinejoin: "round"
290
+ })
291
+ });
292
+ }
277
293
  function SettingsField(props) {
278
294
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
279
295
  className: "dsh-sleev-field",
@@ -325,36 +341,32 @@ textarea.dsh-sleev-input{height:64px;min-height:48px;padding:8px 12px;resize:ver
325
341
  onReset: () => props.resetField(field)
326
342
  });
327
343
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
328
- className: `dsh-sleev-card${open ? " dsh-sleev-card-open" : ""}`,
344
+ className: `dsh-plugin-card${open ? " dsh-plugin-card--open" : ""}`,
329
345
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
330
346
  type: "button",
331
- className: "dsh-sleev-header",
347
+ className: "dsh-plugin-card__header",
332
348
  "aria-expanded": open,
333
349
  "aria-label": `${props.t(open ? "collapse" : "expand")}: Sleev`,
334
350
  onClick: () => setOpen(!open),
335
351
  children: [
336
352
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
337
- className: "dsh-sleev-head-text",
353
+ className: "dsh-plugin-card__head-text",
338
354
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
339
- className: "dsh-sleev-name",
355
+ className: "dsh-plugin-card__name",
340
356
  children: props.t("title")
341
357
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
342
- className: "dsh-sleev-description",
358
+ className: "dsh-plugin-card__description",
343
359
  children: props.t("description")
344
360
  })]
345
361
  }),
346
362
  state.dirty ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
347
- className: "dsh-sleev-pill",
363
+ className: "dsh-plugin-card__badge",
348
364
  children: props.t("unsaved")
349
365
  }) : null,
350
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
351
- className: "dsh-sleev-chevron",
352
- "aria-hidden": "true",
353
- children: "⌄"
354
- })
366
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, {})
355
367
  ]
356
368
  }), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
357
- className: "dsh-sleev-body",
369
+ className: "dsh-plugin-card__body",
358
370
  children: [
359
371
  !state.writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
360
372
  className: "dsh-sleev-read-only",
package/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Service } from "@deepseek-ai/cordis";
2
2
  import { installSettingsSection, settingsNamespace } from "@deepseek-ai/dsh-settings";
3
+ import { createHostLoggerSink, getPluginLogger } from "@yadsh/dsh-plugin-log";
3
4
  import z from "@deepseek-ai/schemastery";
4
5
  import { isAgentLoopRequest } from "@deepseek-ai/dsh-llm";
5
6
  import { randomUUID } from "node:crypto";
@@ -141,13 +142,12 @@ var CallTelemetryStore = class {
141
142
  const startedAt = this.now();
142
143
  let usage;
143
144
  let finished = false;
144
- if (startConfig.logLevel === "debug") this.logger.debug(`dsh-sleev: call-start ${JSON.stringify({
145
+ if (startConfig.logLevel === "debug") this.logger.debug("sleev.call.start", {
145
146
  callId,
146
147
  provider: options.provider,
147
148
  model: options.model,
148
- kind,
149
- sessionId: options.sessionId
150
- })}`);
149
+ kind
150
+ });
151
151
  return {
152
152
  observeUsage: (value) => {
153
153
  usage = normalizeUsage(value);
@@ -176,9 +176,20 @@ var CallTelemetryStore = class {
176
176
  this.completed.push(telemetry);
177
177
  const finishConfig = this.reconfigure();
178
178
  if (finishConfig.logLevel !== "off") {
179
- const message = `dsh-sleev: call-end ${JSON.stringify(telemetry)}`;
180
- if (finishConfig.logLevel === "debug") this.logger.debug(message);
181
- else this.logger.info(message);
179
+ const fields = {
180
+ callId: telemetry.callId,
181
+ provider: telemetry.provider,
182
+ model: telemetry.model,
183
+ kind: telemetry.kind,
184
+ durationMs: telemetry.durationMs,
185
+ ...telemetry.providerUsage === void 0 ? {} : {
186
+ providerUsage: telemetry.providerUsage,
187
+ derived: telemetry.derived
188
+ },
189
+ result: telemetry.result
190
+ };
191
+ if (finishConfig.logLevel === "debug") this.logger.debug("sleev.call.end", fields);
192
+ else this.logger.info("sleev.call.end", fields);
182
193
  }
183
194
  }
184
195
  };
@@ -197,6 +208,9 @@ var CallTelemetryStore = class {
197
208
  //#endregion
198
209
  //#region src/index.ts
199
210
  const name = "dsh-sleev";
211
+ function pluginLogLevel(level) {
212
+ return level === "off" ? "silent" : level;
213
+ }
200
214
  /** User-editable settings section rendered by the browser client card. */
201
215
  const SLEEV_SETTINGS_NAMESPACE = settingsNamespace(SLEEV_SETTINGS_NAMESPACE_ID);
202
216
  /** Host-side observer service. Routing itself remains owned by llm-pi-ai. */
@@ -204,6 +218,7 @@ var SleevIntegrationService = class extends Service {
204
218
  static inject = ["llm"];
205
219
  static Config = ConfigSchema;
206
220
  telemetry;
221
+ logger;
207
222
  constructor(ctx, input = {}) {
208
223
  super(ctx, "sleev");
209
224
  const resolvedEntry = resolveConfig(input);
@@ -214,12 +229,26 @@ var SleevIntegrationService = class extends Service {
214
229
  logLevel: resolvedEntry.logLevel
215
230
  };
216
231
  let configSource = () => entry;
217
- this.telemetry = new CallTelemetryStore(ctx.logger, () => resolveConfig(configSource()));
232
+ this.logger = getPluginLogger({
233
+ pluginId: "dsh-sleev",
234
+ level: pluginLogLevel(resolvedEntry.logLevel),
235
+ console: "trace",
236
+ consoleSink: createHostLoggerSink(ctx.logger)
237
+ });
238
+ ctx.effect(() => async () => this.logger.close(), "dsh-sleev.logger");
239
+ this.telemetry = new CallTelemetryStore(this.logger.child("telemetry"), () => resolveConfig(configSource()));
218
240
  installSettingsSection(ctx, SLEEV_SETTINGS_NAMESPACE, ConfigSchema, entry, {
219
241
  setSource: (current) => {
220
242
  configSource = current;
221
243
  },
222
- onChange: () => this.telemetry.reconfigure()
244
+ onChange: () => {
245
+ const config = this.telemetry.reconfigure();
246
+ this.logger.setLevel(pluginLogLevel(config.logLevel));
247
+ this.logger.info("telemetry.config.updated", {
248
+ logLevel: config.logLevel,
249
+ maxRecentCalls: config.maxRecentCalls
250
+ });
251
+ }
223
252
  });
224
253
  ctx.on("llm/stream", (options, next) => {
225
254
  const config = resolveConfig(configSource());
@@ -227,10 +256,10 @@ var SleevIntegrationService = class extends Service {
227
256
  const handle = this.telemetry.begin(options, classifyRequest(options));
228
257
  return observeStream(next(), handle);
229
258
  }, { global: true });
230
- if (resolvedEntry.logLevel !== "off") ctx.logger.info(`dsh-sleev: observer active ${JSON.stringify({
259
+ if (resolvedEntry.logLevel !== "off") this.logger.info("plugin.ready", {
231
260
  routes: resolvedEntry.routes,
232
261
  routePrefixes: resolvedEntry.routePrefixes
233
- })}`);
262
+ });
234
263
  }
235
264
  /** Bounded completed-call snapshot; no prompts, headers, or credentials. */
236
265
  listRecentCalls() {
@@ -3,8 +3,8 @@ import type { ResolvedConfig } from "../shared/config.js";
3
3
  import type { CallResult, OptimizerCallTelemetry, RequestKind } from "../shared/telemetry.js";
4
4
  /** Minimal logger face used by Cordis and isolated unit tests. */
5
5
  export interface TelemetryLogger {
6
- debug(message: string): void;
7
- info(message: string): void;
6
+ debug(event: string, fields?: Record<string, unknown>): void;
7
+ info(event: string, fields?: Record<string, unknown>): void;
8
8
  }
9
9
  /** Mutable handle kept only for the duration of a streaming call. */
10
10
  export interface CallHandle {
@@ -14,6 +14,7 @@ export declare class SleevIntegrationService extends Service {
14
14
  static inject: string[];
15
15
  static Config: import("@deepseek-ai/schemastery").default<Config>;
16
16
  private readonly telemetry;
17
+ private readonly logger;
17
18
  constructor(ctx: Context, input?: Config);
18
19
  /** Bounded completed-call snapshot; no prompts, headers, or credentials. */
19
20
  listRecentCalls(): readonly OptimizerCallTelemetry[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yadsh/dsh-sleev",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Sleev routing observability for DeepSeek Harness",
5
5
  "repository": {
6
6
  "type": "git",
@@ -79,7 +79,9 @@
79
79
  "@deepseek-ai/dsh-settings": ">=0.1.1-rc.2 <0.2.0",
80
80
  "react": "^18.2.0"
81
81
  },
82
- "dependencies": {},
82
+ "dependencies": {
83
+ "@yadsh/dsh-plugin-log": "^0.2.0"
84
+ },
83
85
  "devDependencies": {
84
86
  "@deepseek-ai/cordis": "4.0.1",
85
87
  "@deepseek-ai/schemastery": "3.18.1",