dsh-opencode-go 0.1.7 → 0.1.9

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/index.js CHANGED
@@ -705,6 +705,54 @@ import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completio
705
705
  import { openAIResponsesApi } from "@earendil-works/pi-ai/api/openai-responses.lazy";
706
706
  import { attributionHeaders, LlmError as LlmError5 } from "@deepseek-ai/dsh-llm";
707
707
 
708
+ // src/models-contract.ts
709
+ function validReleaseDate(value) {
710
+ return typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value;
711
+ }
712
+ function isNewModel(model, now = Date.now()) {
713
+ if (model.deprecated || !validReleaseDate(model.releaseDate)) return false;
714
+ const days = Math.floor(now / 864e5) - Date.parse(model.releaseDate) / 864e5;
715
+ return days >= 0 && days < 7;
716
+ }
717
+ function sortModels(models, now = Date.now()) {
718
+ const rank = (model) => model.deprecated ? 2 : isNewModel(model, now) ? 0 : 1;
719
+ return [...models].sort((a, b) => rank(a) - rank(b) || (isNewModel(a, now) && isNewModel(b, now) ? b.releaseDate.localeCompare(a.releaseDate) : 0));
720
+ }
721
+ function parseGoModels(value) {
722
+ if (!Array.isArray(value)) throw new Error("Invalid OpenCode Go model list");
723
+ return value.map((entry) => {
724
+ if (!entry || typeof entry !== "object") throw new Error("Invalid OpenCode Go model");
725
+ const row = entry;
726
+ if (typeof row.id !== "string" || !row.id) throw new Error("Missing OpenCode Go model id");
727
+ const model = { id: row.id };
728
+ if (typeof row.name === "string") model.name = row.name;
729
+ for (const key of ["contextWindow", "maxTokens"]) {
730
+ if (typeof row[key] === "number" && Number.isSafeInteger(row[key]) && row[key] > 0) model[key] = row[key];
731
+ }
732
+ if (typeof row.deprecated === "boolean") model.deprecated = row.deprecated;
733
+ if (validReleaseDate(row.releaseDate)) model.releaseDate = row.releaseDate;
734
+ return model;
735
+ });
736
+ }
737
+ var codec = {
738
+ mode: "strict",
739
+ typeSymbol: "dsh-opencode-go#GoModels",
740
+ schema: { parse: parseGoModels },
741
+ create: () => ({ parse: parseGoModels })
742
+ };
743
+ var modelsRemote = {
744
+ package: "dsh-opencode-go",
745
+ descriptors: [{
746
+ id: "dsh-opencode-go#opencodeGoModels/read",
747
+ service: "opencodeGoModels",
748
+ namespace: "opencodeGoModels",
749
+ method: "read",
750
+ invocation: { kind: "direct" },
751
+ parameters: [],
752
+ result: codec
753
+ }]
754
+ };
755
+
708
756
  // src/model-metadata.ts
709
757
  var MODEL_METADATA_URL = "https://models.dev/api.json";
710
758
  function record(value) {
@@ -755,7 +803,13 @@ function readModelMetadata(body, baseURL, builtin) {
755
803
  const entries = record(provider.models);
756
804
  const models = /* @__PURE__ */ new Map();
757
805
  const errors = /* @__PURE__ */ new Map();
806
+ const details = /* @__PURE__ */ new Map();
758
807
  for (const [id, value] of Object.entries(entries)) {
808
+ const data = record(value);
809
+ details.set(id, {
810
+ deprecated: data.status === "deprecated",
811
+ ...validReleaseDate(data.release_date) ? { releaseDate: data.release_date } : {}
812
+ });
759
813
  try {
760
814
  const metadata = record(value);
761
815
  const npm = record(metadata.provider).npm ?? provider.npm;
@@ -801,7 +855,7 @@ function readModelMetadata(body, baseURL, builtin) {
801
855
  errors.set(id, error instanceof Error ? error.message : String(error));
802
856
  }
803
857
  }
804
- return { models, errors };
858
+ return { models, errors, details };
805
859
  }
806
860
 
807
861
  // src/catalog.ts
@@ -916,9 +970,10 @@ var OpencodeGoCatalog = class {
916
970
  this.onFallback({ url: MODEL_METADATA_URL, error: metadataResult.reason, kept: known.size });
917
971
  }
918
972
  if (listing.status === "rejected") {
919
- const models2 = this.served?.models ?? known;
973
+ const models2 = this.served?.models ?? /* @__PURE__ */ new Map();
920
974
  this.onFallback({ url: `${this.baseURL.replace(/\/+$/, "")}/models`, error: listing.reason, kept: models2.size });
921
975
  return {
976
+ details: this.served?.details ?? /* @__PURE__ */ new Map(),
922
977
  models: models2,
923
978
  unavailable: this.served?.unavailable ?? /* @__PURE__ */ new Map(),
924
979
  provider: buildProvider(this.baseURL, [...models2.values()]),
@@ -939,6 +994,7 @@ var OpencodeGoCatalog = class {
939
994
  }
940
995
  if (unavailable.size > 0) this.onOmitted([...unavailable.keys()]);
941
996
  return {
997
+ details: new Map(listing.value.map((id) => [id, metadata?.details.get(id) ?? {}])),
942
998
  models,
943
999
  unavailable,
944
1000
  provider: buildProvider(this.baseURL, [...models.values()]),
@@ -965,6 +1021,9 @@ async function discoverCatalogModels(catalog) {
965
1021
  if (!snapshot.live) {
966
1022
  throw new LlmError5("llm-opencode-go: the live model listing is unreachable; try again later", "DISCOVERY_FAILED");
967
1023
  }
1024
+ return describeCatalog(snapshot);
1025
+ }
1026
+ function describeCatalog(snapshot) {
968
1027
  return [
969
1028
  ...[...snapshot.models.values()].map((model) => ({
970
1029
  id: model.id,
@@ -975,6 +1034,11 @@ async function discoverCatalogModels(catalog) {
975
1034
  ...[...snapshot.unavailable].map(([id, reason]) => ({ id, name: `${id} (metadata unavailable: ${reason})` }))
976
1035
  ];
977
1036
  }
1037
+ async function discoverSettingsModels(catalog) {
1038
+ const snapshot = await catalog.snapshot(true);
1039
+ if (!snapshot.live) throw new LlmError5("llm-opencode-go: the live model listing is unreachable; try again later", "DISCOVERY_FAILED");
1040
+ return sortModels(describeCatalog(snapshot).map((model) => ({ ...model, ...snapshot.details.get(model.id) })));
1041
+ }
978
1042
 
979
1043
  // src/config.ts
980
1044
  import { MAX_TIMER_DELAY_MS } from "@deepseek-ai/dsh-timeout";
@@ -984,6 +1048,7 @@ var DEFAULT_REFRESH_MINUTES = 60;
984
1048
  var DEFAULT_STREAM_IDLE_TIMEOUT_MS = 3e5;
985
1049
  var fields = {
986
1050
  enabled: z.boolean().default(true),
1051
+ showDeprecatedModels: z.boolean().default(false),
987
1052
  apiKeyEnv: z.string().role("credential-ref").default(DEFAULT_API_KEY_ENV),
988
1053
  baseURL: z.string().default(DEFAULT_BASE_URL),
989
1054
  refreshMinutes: z.number().step(1).min(1).max(7 * 24 * 60).default(DEFAULT_REFRESH_MINUTES),
@@ -1077,8 +1142,9 @@ var OpencodeGoAdapter = class extends LlmAdapter {
1077
1142
  return { id: provider, name: DISPLAY_NAME };
1078
1143
  }
1079
1144
  async listModels(_provider) {
1080
- const snapshot = await this.catalogOf(this.options.config()).snapshot(true);
1081
- return [...snapshot.models.values()].map((model) => ({
1145
+ const config = this.options.config();
1146
+ const snapshot = await this.catalogOf(config).snapshot(true);
1147
+ return [...snapshot.models.values()].filter((model) => config.showDeprecatedModels || !snapshot.details.get(model.id)?.deprecated).map((model) => ({
1082
1148
  provider: PROVIDER_ID,
1083
1149
  id: model.id,
1084
1150
  name: model.name,
@@ -1271,15 +1337,6 @@ var GoUsageService = class extends TypertRemoteService {
1271
1337
  constructor(ctx, options) {
1272
1338
  super(ctx, "opencodeGoUsage");
1273
1339
  this.options = options;
1274
- ctx.inject(["typert"], (scope) => {
1275
- scope.effect(() => scope.typert.register({
1276
- package: usageRemote.package,
1277
- face: "host",
1278
- schemas: [],
1279
- model: { services: [], events: [], objects: [] },
1280
- invocations: usageRemote.descriptors
1281
- }));
1282
- });
1283
1340
  }
1284
1341
  async read() {
1285
1342
  const baseURL = assertBaseURL(this.options.baseURL()).replace(/\/$/, "");
@@ -1296,6 +1353,37 @@ var GoUsageService = class extends TypertRemoteService {
1296
1353
  }
1297
1354
  };
1298
1355
 
1356
+ // src/models.ts
1357
+ import { TypertRemoteService as TypertRemoteService2 } from "@deepseek-ai/dsh-typert-protocol";
1358
+ var GoModelsService = class extends TypertRemoteService2 {
1359
+ constructor(ctx, options) {
1360
+ super(ctx, "opencodeGoModels");
1361
+ this.options = options;
1362
+ }
1363
+ read() {
1364
+ return discoverSettingsModels(this.options.catalog());
1365
+ }
1366
+ };
1367
+
1368
+ // src/remote-contract.ts
1369
+ var goRemote = {
1370
+ package: "dsh-opencode-go",
1371
+ descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors]
1372
+ };
1373
+
1374
+ // src/remotes.ts
1375
+ function registerGoRemotes(ctx) {
1376
+ ctx.inject(["typert"], (scope) => {
1377
+ scope.effect(() => scope.typert.register({
1378
+ package: goRemote.package,
1379
+ face: "host",
1380
+ schemas: [],
1381
+ model: { services: [], events: [], objects: [] },
1382
+ invocations: goRemote.descriptors
1383
+ }));
1384
+ });
1385
+ }
1386
+
1299
1387
  // src/index.ts
1300
1388
  var name = "llm-opencode-go";
1301
1389
  var inject = ["llm"];
@@ -1315,6 +1403,7 @@ function apply(ctx, raw) {
1315
1403
  "MISSING_CREDENTIAL"
1316
1404
  );
1317
1405
  };
1406
+ registerGoRemotes(ctx);
1318
1407
  ctx.plugin(GoUsageService, { baseURL: () => current().baseURL, resolveApiKey });
1319
1408
  const logger = {
1320
1409
  fallback: ({ url, error }) => {
@@ -1341,6 +1430,8 @@ function apply(ctx, raw) {
1341
1430
  ctx.logger.warn(`llm-opencode-go: unusable replay state on assistant history; sending provider-neutral content (${reason})`);
1342
1431
  }
1343
1432
  });
1433
+ ctx.plugin(GoModelsService, { catalog: () => adapter.catalogOf(current()) });
1434
+ let pickerVisibility = current().showDeprecatedModels;
1344
1435
  let registration;
1345
1436
  const applyRoute = (configured) => {
1346
1437
  if (configured && current().enabled && registration === void 0) {
@@ -1358,6 +1449,10 @@ function apply(ctx, raw) {
1358
1449
  }
1359
1450
  };
1360
1451
  const syncRoute = () => {
1452
+ if (pickerVisibility !== current().showDeprecatedModels) {
1453
+ pickerVisibility = current().showDeprecatedModels;
1454
+ registration?.replace([PROVIDER_ID]);
1455
+ }
1361
1456
  const credentials = ctx.get("credentials");
1362
1457
  if (credentials === void 0) {
1363
1458
  applyRoute(launchEnvironmentOf(ctx).get(current().apiKeyEnv)?.value !== void 0);
@@ -1,9 +1,12 @@
1
1
  import type { Api, Model, Provider } from '@earendil-works/pi-ai';
2
2
  import type { LlmDiscoveredModel } from '@deepseek-ai/dsh-llm';
3
+ import { type GoModel } from './models-contract.ts';
4
+ import type { ModelMetadata } from './model-metadata.ts';
3
5
  export declare const PROVIDER_ID = "opencode-go";
4
6
  export declare const DISPLAY_NAME = "OpenCode Go";
5
7
  export declare const DEFAULT_BASE_URL = "https://opencode.ai/zen/go/v1";
6
8
  export interface CatalogSnapshot {
9
+ readonly details: ModelMetadata['details'];
7
10
  readonly models: ReadonlyMap<string, Model<Api>>;
8
11
  /** Advertised ids with missing/unsupported metadata stay visible with a diagnostic. */
9
12
  readonly unavailable: ReadonlyMap<string, string>;
@@ -41,3 +44,5 @@ export declare class OpencodeGoCatalog {
41
44
  }
42
45
  /** Explicit discovery always revalidates both sources, including during the runtime TTL. */
43
46
  export declare function discoverCatalogModels(catalog: OpencodeGoCatalog): Promise<readonly LlmDiscoveredModel[]>;
47
+ /** Settings retain deprecated gateway entries regardless of picker visibility. */
48
+ export declare function discoverSettingsModels(catalog: OpencodeGoCatalog): Promise<readonly GoModel[]>;
@@ -0,0 +1,13 @@
1
+ import type { OpencodeGoModelLimit, OpencodeGoModelLimits, OpencodeGoModels } from './section-controller.ts';
2
+ import type { en } from './locales.ts';
3
+ type Translate = (key: keyof typeof en, params?: Record<string, unknown>) => string;
4
+ export declare function hasCapacityOverride(limit: OpencodeGoModelLimit | null | undefined): boolean;
5
+ /** One gateway-backed list and its selected model's staged capacity settings. */
6
+ export declare function ModelEditor({ models, draft, t, disabled, onEdit }: {
7
+ models: OpencodeGoModels;
8
+ draft: OpencodeGoModelLimits;
9
+ t: Translate;
10
+ disabled: boolean;
11
+ onEdit: (next: OpencodeGoModelLimits) => void;
12
+ }): import("react").JSX.Element;
13
+ export {};
@@ -36,7 +36,22 @@ export declare const en: {
36
36
  limitsModel: string;
37
37
  limitsContext: string;
38
38
  limitsOutput: string;
39
- limitsAdvertised: string;
39
+ capacityDefault: string;
40
+ capacityMissing: string;
41
+ showDeprecatedLabel: string;
42
+ showDeprecatedHint: string;
43
+ pickerFailed: string;
44
+ deprecatedBadge: string;
45
+ deprecatedHint: string;
46
+ newHint: string;
47
+ releasedOn: string;
48
+ releaseSource: string;
49
+ modelDetails: string;
50
+ filterLabel: string;
51
+ filterAll: string;
52
+ filterNew: string;
53
+ filterCustom: string;
54
+ filterDeprecated: string;
40
55
  limitsResetModel: string;
41
56
  limitsResetAll: string;
42
57
  limitsNoMatches: string;
@@ -9,7 +9,8 @@
9
9
  * covers everything the page shows.
10
10
  */
11
11
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
12
- import type { LlmDiscoveredModel } from '@deepseek-ai/dsh-api-remotes/client';
12
+ import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
13
+ import type { GoModel } from '../models-contract.ts';
13
14
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
14
15
  import type { SettingsScope } from './settings.ts';
15
16
  import { type FieldState, type FormActions, type FormShell } from './staged-form.ts';
@@ -19,6 +20,8 @@ export declare const OPENCODE_GO_NS = "llm-opencode-go";
19
20
  export interface OpencodeGoSettings {
20
21
  /** Whether the adapter serves its route; false withdraws it from every picker. */
21
22
  enabled?: boolean;
23
+ /** Include gateway-served deprecated models in conversation pickers. */
24
+ showDeprecatedModels?: boolean;
22
25
  /** Credential reference naming the environment key. */
23
26
  apiKeyEnv?: string;
24
27
  /** The gateway endpoint; also the live listing base. */
@@ -60,7 +63,7 @@ export type OpencodeGoModels =
60
63
  readonly status: 'ready';
61
64
  readonly count: number;
62
65
  readonly preview: readonly string[];
63
- readonly entries: readonly LlmDiscoveredModel[];
66
+ readonly entries: readonly GoModel[];
64
67
  }
65
68
  /** The listing could not be read; `message` is the Host's own diagnostic. */
66
69
  | {
@@ -75,6 +78,9 @@ export interface OpencodeGoSectionState extends FormShell {
75
78
  * a withdrawn route is what the user is trying to observe.
76
79
  */
77
80
  enabled: boolean;
81
+ showDeprecatedModels: boolean;
82
+ pickerSaving: boolean;
83
+ pickerFailed: boolean;
78
84
  /** Credential reference naming the environment key. */
79
85
  apiKeyEnv: FieldState;
80
86
  /** The gateway endpoint. */
@@ -115,16 +121,20 @@ export interface OpencodeGoSectionFace extends FormActions {
115
121
  * @param next - the state the switch asks for.
116
122
  */
117
123
  setEnabled: (next: boolean) => void;
124
+ setShowDeprecatedModels: (next: boolean) => void;
118
125
  }
119
126
  /** Bridges the `llm-opencode-go` scope and the credentials domain onto the page. */
120
127
  export declare class OpencodeGoSectionController {
121
128
  private readonly scope;
122
129
  private readonly ctx;
130
+ private readonly readModels;
123
131
  private readonly form;
124
132
  private readonly store;
125
133
  private credential;
126
134
  private models;
127
135
  private modelsRequest;
136
+ private pickerSaving;
137
+ private pickerFailed;
128
138
  private face;
129
139
  private readonly unsubscribe;
130
140
  /**
@@ -132,7 +142,7 @@ export declare class OpencodeGoSectionController {
132
142
  * @param ctx - the page plugin's context, whose `remote.credentials` namespace
133
143
  * answers for the credential the section references.
134
144
  */
135
- constructor(scope: SettingsScope<OpencodeGoSettings>, ctx: ClientContext);
145
+ constructor(scope: SettingsScope<OpencodeGoSettings>, ctx: ClientContext, readModels?: () => Promise<RemoteResult<readonly GoModel[]>>);
136
146
  /** Release subscriptions without disposing the host's shared form. */
137
147
  dispose(): void;
138
148
  private projection;
@@ -160,6 +170,8 @@ export declare class OpencodeGoSectionController {
160
170
  * @param next - the state the switch asks for.
161
171
  */
162
172
  setEnabled(next: boolean): void;
173
+ /** Visibility is immediate; failed writes leave the committed switch state visible. */
174
+ setShowDeprecatedModels(next: boolean): Promise<void>;
163
175
  /**
164
176
  * Read the gateway's model listing through the Host's discovery for this
165
177
  * adapter. Called when the page mounts and again from its refresh control.
@@ -38,6 +38,8 @@ export interface OpencodeGoConfig {
38
38
  * false registers nothing.
39
39
  */
40
40
  enabled: boolean;
41
+ /** Include models marked deprecated by models.dev in conversation pickers. */
42
+ showDeprecatedModels: boolean;
41
43
  /** Credential reference: the environment variable the key resolves from. */
42
44
  apiKeyEnv: string;
43
45
  /** The gateway endpoint; also the base of the live model listing. */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Dedicated OpenCode Go adapter plugin. Registers one `opencode-go` route
3
- * whose catalog is the curated table intersected with the gateway's live model
4
- * listing, and installs the `llm-opencode-go` settings section: the Web UI
3
+ * whose catalog follows the gateway's live model listing and models.dev
4
+ * metadata, and installs the `llm-opencode-go` settings section: the Web UI
5
5
  * renders it as its own settings page where the API key and every knob are
6
6
  * edited, and a change reaches the next request without a restart. The plugin
7
7
  * exists because the gateway has wire requirements a generic pi-ai route
@@ -1,8 +1,10 @@
1
1
  /** Convert OpenCode's online models.dev metadata into the SDK's three wire protocols. */
2
2
  import type { Api, Model } from '@earendil-works/pi-ai';
3
+ import { type GoModel } from './models-contract.ts';
3
4
  export declare const MODEL_METADATA_URL = "https://models.dev/api.json";
4
5
  export interface ModelMetadata {
5
6
  readonly models: ReadonlyMap<string, Model<Api>>;
7
+ readonly details: ReadonlyMap<string, Pick<GoModel, 'deprecated' | 'releaseDate'>>;
6
8
  readonly errors: ReadonlyMap<string, string>;
7
9
  }
8
10
  /** Anthropic's SDK appends /v1/messages; the OpenAI SDKs append paths below /v1. */
@@ -0,0 +1,23 @@
1
+ /** Settings discovery includes lifecycle data that the host's generic model DTO omits. */
2
+ import type { RemoteResult, TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
3
+ export interface GoModel {
4
+ id: string;
5
+ name?: string;
6
+ contextWindow?: number;
7
+ maxTokens?: number;
8
+ deprecated?: boolean;
9
+ releaseDate?: string;
10
+ }
11
+ export declare function validReleaseDate(value: unknown): value is string;
12
+ /** Calendar dates are supplied without a timezone; compare UTC dates consistently. */
13
+ export declare function isNewModel(model: GoModel, now?: number): boolean;
14
+ export declare function sortModels(models: readonly GoModel[], now?: number): GoModel[];
15
+ export declare function parseGoModels(value: unknown): GoModel[];
16
+ declare module '@deepseek-ai/dsh-typert-protocol' {
17
+ interface TypertRemoteNamespaceMap {
18
+ opencodeGoModels: {
19
+ read(): Promise<RemoteResult<readonly GoModel[]>>;
20
+ };
21
+ }
22
+ }
23
+ export declare const modelsRemote: TypertRemoteContribution;
@@ -0,0 +1,12 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
3
+ import { type OpencodeGoCatalog } from './catalog.ts';
4
+ import type { GoModel } from './models-contract.ts';
5
+ /** Uses the same gateway snapshot as the adapter, including models hidden from pickers. */
6
+ export declare class GoModelsService extends TypertRemoteService {
7
+ private readonly options;
8
+ constructor(ctx: Context, options: {
9
+ catalog: () => OpencodeGoCatalog;
10
+ });
11
+ read(): Promise<readonly GoModel[]>;
12
+ }
@@ -0,0 +1,3 @@
1
+ import type { TypertRemoteContribution } from '@deepseek-ai/dsh-typert-protocol';
2
+ /** A registry owns one contribution per package; mount all plugin endpoints together. */
3
+ export declare const goRemote: TypertRemoteContribution;
@@ -0,0 +1,3 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ /** Register once per plugin mount, after either registry activation order. */
3
+ export declare function registerGoRemotes(ctx: Context): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-opencode-go",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "OpenCode Go model provider and settings UI for DeepSeek Harness",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "engines": {
16
16
  "node": "^22.19.0 || >=24.0.0",
17
- "dsh": ">=0.1.5-rc.1 <0.1.6-0 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1"
17
+ "dsh": ">=0.1.5-rc.1 <0.1.6-0 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2"
18
18
  },
19
19
  "main": "./lib/index.js",
20
20
  "types": "./lib/types/index.d.ts",
@@ -60,26 +60,26 @@
60
60
  "verify:headless": "node scripts/headless-smoke.mjs"
61
61
  },
62
62
  "peerDependencies": {
63
- "@deepseek-ai/cordis": "4.0.2 || 4.0.3",
64
- "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
65
- "@deepseek-ai/dsh-api-remotes": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
66
- "@deepseek-ai/dsh-api-settings-controller": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
67
- "@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
68
- "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
69
- "@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
70
- "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
71
- "@deepseek-ai/dsh-client-ui-model-selection": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
72
- "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
73
- "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
74
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
75
- "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
76
- "@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
77
- "@deepseek-ai/dsh-launch-environment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
78
- "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
79
- "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
80
- "@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
81
- "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
82
- "@deepseek-ai/dsh-typert-registry": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1"
63
+ "@deepseek-ai/cordis": "4.0.2 || 4.0.3 || 4.0.4",
64
+ "@deepseek-ai/dsh-api-gateway": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
65
+ "@deepseek-ai/dsh-api-remotes": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
66
+ "@deepseek-ai/dsh-api-settings-controller": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
67
+ "@deepseek-ai/dsh-attachment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
68
+ "@deepseek-ai/dsh-client-locale": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
69
+ "@deepseek-ai/dsh-client-store": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
70
+ "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
71
+ "@deepseek-ai/dsh-client-ui-model-selection": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
72
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
73
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
74
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
75
+ "@deepseek-ai/dsh-credentials": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
76
+ "@deepseek-ai/dsh-fs": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
77
+ "@deepseek-ai/dsh-launch-environment": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
78
+ "@deepseek-ai/dsh-llm": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
79
+ "@deepseek-ai/dsh-settings": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
80
+ "@deepseek-ai/dsh-timeout": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
81
+ "@deepseek-ai/dsh-typert-protocol": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2",
82
+ "@deepseek-ai/dsh-typert-registry": ">=0.1.5-rc.1 <0.1.6 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1 || 0.1.7-alpha.2"
83
83
  },
84
84
  "dependencies": {
85
85
  "@deepseek-ai/dsh-brand": "0.1.6-alpha.1",
@@ -122,6 +122,7 @@
122
122
  "@types/node": "^22.20.0",
123
123
  "@types/react": "~18.3.1",
124
124
  "@types/react-dom": "~18.3.0",
125
+ "@types/semver": "7.8.0",
125
126
  "anser": "^2.3.5",
126
127
  "clsx": "^2.0.0",
127
128
  "diff": "^9.0.0",
@@ -153,6 +154,7 @@
153
154
  "micromark-util-types": "^2.0.2",
154
155
  "react": "^18.2.0",
155
156
  "react-dom": "^18.2.0",
157
+ "semver": "7.8.5",
156
158
  "shiki": "^4.3.1",
157
159
  "typescript": "6.0.3",
158
160
  "vitest": "^4.1.8",