dsh-opendesign-corouter 0.1.3 → 0.1.5

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.
@@ -7,6 +7,27 @@ function record(value) {
7
7
  return value !== null && typeof value === "object" && !Array.isArray(value);
8
8
  }
9
9
 
10
+ // src/device-auth.ts
11
+ function validateActivationUrl(value, userCode) {
12
+ if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
13
+ try {
14
+ const url = new URL(value);
15
+ if (url.origin !== "https://open-design.ai" || url.pathname !== "/cloud/cli/activate" || url.username || url.password || url.hash) return null;
16
+ const entries = [...url.searchParams];
17
+ if (entries.length > 1) return null;
18
+ if (entries.length) {
19
+ const entry = entries[0];
20
+ if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
21
+ }
22
+ return url.href;
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ function validUserCode(value) {
28
+ return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
29
+ }
30
+
10
31
  // src/protocol-options.ts
11
32
  var API_PROTOCOL_IDS = ["chat-completions", "responses", "messages"];
12
33
 
@@ -68,6 +89,7 @@ var MAX_API_KEY = 16384;
68
89
  var HTTP_ASCII = /^[\x21-\x7e]+$/u;
69
90
  var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
70
91
  var MODEL_ID = /^[A-Za-z0-9._:/-]{1,128}$/u;
92
+ var ACTIVATION_OPEN_CODES = ["opened", "no-link", "invalid-url", "unavailable", "failed"];
71
93
  var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
72
94
  var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
73
95
  var SESSION_SOURCES = ["desktop", "login", "environment"];
@@ -155,9 +177,19 @@ function parseLoginState(value) {
155
177
  if (!record(value)) throw new Error("\u767B\u5F55\u72B6\u6001\u5FC5\u987B\u662F\u5BF9\u8C61");
156
178
  const jobId = value.jobId;
157
179
  if (jobId !== null && jobId !== void 0 && typeof jobId !== "string") throw new Error("\u767B\u5F55\u4EFB\u52A1 id \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");
180
+ const state = member(value.state, LOGIN_PHASES, "\u767B\u5F55\u9636\u6BB5");
181
+ let approval = {};
182
+ if (state === "waiting" && (value.activationUrl !== void 0 || value.userCode !== void 0 || value.expiresAt !== void 0)) {
183
+ const userCode = text(value.userCode, "\u8BBE\u5907\u6388\u6743\u7801", 64);
184
+ if (!/^[A-Za-z0-9-]+$/u.test(userCode)) throw new Error("\u8BBE\u5907\u6388\u6743\u7801\u683C\u5F0F\u65E0\u6548");
185
+ const activationUrl = validateActivationUrl(value.activationUrl, userCode);
186
+ if (activationUrl === null) throw new Error("\u8BBE\u5907\u6388\u6743\u94FE\u63A5\u65E0\u6548");
187
+ approval = { activationUrl, userCode, expiresAt: isoTime(value.expiresAt, "\u8BBE\u5907\u6388\u6743\u5230\u671F\u65F6\u95F4") };
188
+ }
158
189
  return {
159
190
  jobId: typeof jobId === "string" && jobId.length > 0 ? text(jobId, "\u767B\u5F55\u4EFB\u52A1 id", MAX_JOB_ID) : null,
160
- state: member(value.state, LOGIN_PHASES, "\u767B\u5F55\u9636\u6BB5"),
191
+ state,
192
+ ...approval,
161
193
  ...value.message === void 0 ? {} : { message: text(value.message, "\u767B\u5F55\u8BF4\u660E", MAX_MESSAGE) },
162
194
  ...value.startedAt === void 0 ? {} : { startedAt: isoTime(value.startedAt, "\u767B\u5F55\u5F00\u59CB\u65F6\u95F4") },
163
195
  ...value.finishedAt === void 0 ? {} : { finishedAt: isoTime(value.finishedAt, "\u767B\u5F55\u7ED3\u675F\u65F6\u95F4") }
@@ -233,6 +265,10 @@ function parseSaveApiKeyRequest(value) {
233
265
  if (key.length > MAX_API_KEY) throw new Error(`API Key \u4E0D\u80FD\u8D85\u8FC7 ${MAX_API_KEY} \u5B57\u7B26`);
234
266
  return { value: key, expectedRevision: text(value.expectedRevision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION) };
235
267
  }
268
+ function parseActivationOpenState(value) {
269
+ if (!record(value)) throw new Error("\u6388\u6743\u9875\u6253\u5F00\u7ED3\u679C\u5FC5\u987B\u662F\u5BF9\u8C61");
270
+ return { code: member(value.code, ACTIVATION_OPEN_CODES, "\u6388\u6743\u9875\u6253\u5F00\u7ED3\u679C"), opened: flag(value.opened, "\u6388\u6743\u9875\u662F\u5426\u5DF2\u6253\u5F00") };
271
+ }
236
272
 
237
273
  // src/generated/typert.remote-client.ts
238
274
  var StatusCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#Status", create: () => z.unknown().transform((value) => parseStatus(value)) };
@@ -240,6 +276,7 @@ var QuotaSnapshotCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#
240
276
  var LoginStateCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#LoginState", create: () => z.unknown().transform((value) => parseLoginState(value)) };
241
277
  var StartLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#StartLoginRequest", create: () => z.unknown().transform((value) => parseStartLoginRequest(value)) };
242
278
  var CancelLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#CancelLoginRequest", create: () => z.unknown().transform((value) => parseCancelLoginRequest(value)) };
279
+ var ActivationOpenStateCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#ActivationOpenState", create: () => z.unknown().transform((value) => parseActivationOpenState(value)) };
243
280
  var SaveApiKeyRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#SaveApiKeyRequest", create: () => z.unknown().transform((value) => parseSaveApiKeyRequest(value)) };
244
281
  var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter", methods: {
245
282
  "openDesignCoRouter/status": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
@@ -249,6 +286,7 @@ var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter",
249
286
  "openDesignCoRouter/startLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: StartLoginRequestCodec, strictCodec: StartLoginRequestCodec }], result: LoginStateCodec },
250
287
  "openDesignCoRouter/loginStatus": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: LoginStateCodec },
251
288
  "openDesignCoRouter/cancelLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: CancelLoginRequestCodec, strictCodec: CancelLoginRequestCodec }], result: LoginStateCodec },
289
+ "openDesignCoRouter/openActivationPage": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: ActivationOpenStateCodec },
252
290
  "openDesignCoRouter/saveApiKey": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: SaveApiKeyRequestCodec, strictCodec: SaveApiKeyRequestCodec }], result: StatusCodec }
253
291
  } }, z);
254
292
  var typert_remote_client_default = TYPERT_REMOTE;
@@ -1,5 +1,5 @@
1
1
  import type { RemoteResult } from '@deepseek-ai/dsh-typert-protocol';
2
- import type { Status, QuotaSnapshot, LoginState, StartLoginRequest, CancelLoginRequest, SaveApiKeyRequest } from '../remote.js';
2
+ import type { Status, QuotaSnapshot, LoginState, StartLoginRequest, CancelLoginRequest, ActivationOpenState, SaveApiKeyRequest } from '../remote.js';
3
3
  export type CoRouterRemote = {
4
4
  status: () => Promise<RemoteResult<Status>>;
5
5
  refreshModels: () => Promise<RemoteResult<Status>>;
@@ -8,6 +8,7 @@ export type CoRouterRemote = {
8
8
  startLogin: (input: StartLoginRequest) => Promise<RemoteResult<LoginState>>;
9
9
  loginStatus: () => Promise<RemoteResult<LoginState>>;
10
10
  cancelLogin: (input: CancelLoginRequest) => Promise<RemoteResult<LoginState>>;
11
+ openActivationPage: () => Promise<RemoteResult<ActivationOpenState>>;
11
12
  saveApiKey: (input: SaveApiKeyRequest) => Promise<RemoteResult<Status>>;
12
13
  };
13
14
  declare module '@deepseek-ai/dsh-typert-protocol' {
@@ -7,6 +7,27 @@ function record(value) {
7
7
  return value !== null && typeof value === "object" && !Array.isArray(value);
8
8
  }
9
9
 
10
+ // src/device-auth.ts
11
+ function validateActivationUrl(value, userCode) {
12
+ if (typeof value !== "string" || value.length > 512 || !/^https:\/\/open-design\.ai\/cloud\/cli\/activate(?:\?[^#]*)?$/u.test(value) || /[\s\\]/u.test(value)) return null;
13
+ try {
14
+ const url = new URL(value);
15
+ if (url.origin !== "https://open-design.ai" || url.pathname !== "/cloud/cli/activate" || url.username || url.password || url.hash) return null;
16
+ const entries = [...url.searchParams];
17
+ if (entries.length > 1) return null;
18
+ if (entries.length) {
19
+ const entry = entries[0];
20
+ if (!["code", "user_code"].includes(entry[0]) || !validUserCode(entry[1]) || userCode !== void 0 && entry[1] !== userCode) return null;
21
+ }
22
+ return url.href;
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ function validUserCode(value) {
28
+ return typeof value === "string" && /^[a-z0-9][a-z0-9-]{3,31}$/iu.test(value);
29
+ }
30
+
10
31
  // src/protocol-options.ts
11
32
  var API_PROTOCOL_IDS = ["chat-completions", "responses", "messages"];
12
33
 
@@ -68,6 +89,7 @@ var MAX_API_KEY = 16384;
68
89
  var HTTP_ASCII = /^[\x21-\x7e]+$/u;
69
90
  var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
70
91
  var MODEL_ID = /^[A-Za-z0-9._:/-]{1,128}$/u;
92
+ var ACTIVATION_OPEN_CODES = ["opened", "no-link", "invalid-url", "unavailable", "failed"];
71
93
  var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
72
94
  var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
73
95
  var SESSION_SOURCES = ["desktop", "login", "environment"];
@@ -155,9 +177,19 @@ function parseLoginState(value) {
155
177
  if (!record(value)) throw new Error("\u767B\u5F55\u72B6\u6001\u5FC5\u987B\u662F\u5BF9\u8C61");
156
178
  const jobId = value.jobId;
157
179
  if (jobId !== null && jobId !== void 0 && typeof jobId !== "string") throw new Error("\u767B\u5F55\u4EFB\u52A1 id \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216 null");
180
+ const state = member(value.state, LOGIN_PHASES, "\u767B\u5F55\u9636\u6BB5");
181
+ let approval = {};
182
+ if (state === "waiting" && (value.activationUrl !== void 0 || value.userCode !== void 0 || value.expiresAt !== void 0)) {
183
+ const userCode = text(value.userCode, "\u8BBE\u5907\u6388\u6743\u7801", 64);
184
+ if (!/^[A-Za-z0-9-]+$/u.test(userCode)) throw new Error("\u8BBE\u5907\u6388\u6743\u7801\u683C\u5F0F\u65E0\u6548");
185
+ const activationUrl = validateActivationUrl(value.activationUrl, userCode);
186
+ if (activationUrl === null) throw new Error("\u8BBE\u5907\u6388\u6743\u94FE\u63A5\u65E0\u6548");
187
+ approval = { activationUrl, userCode, expiresAt: isoTime(value.expiresAt, "\u8BBE\u5907\u6388\u6743\u5230\u671F\u65F6\u95F4") };
188
+ }
158
189
  return {
159
190
  jobId: typeof jobId === "string" && jobId.length > 0 ? text(jobId, "\u767B\u5F55\u4EFB\u52A1 id", MAX_JOB_ID) : null,
160
- state: member(value.state, LOGIN_PHASES, "\u767B\u5F55\u9636\u6BB5"),
191
+ state,
192
+ ...approval,
161
193
  ...value.message === void 0 ? {} : { message: text(value.message, "\u767B\u5F55\u8BF4\u660E", MAX_MESSAGE) },
162
194
  ...value.startedAt === void 0 ? {} : { startedAt: isoTime(value.startedAt, "\u767B\u5F55\u5F00\u59CB\u65F6\u95F4") },
163
195
  ...value.finishedAt === void 0 ? {} : { finishedAt: isoTime(value.finishedAt, "\u767B\u5F55\u7ED3\u675F\u65F6\u95F4") }
@@ -233,6 +265,10 @@ function parseSaveApiKeyRequest(value) {
233
265
  if (key.length > MAX_API_KEY) throw new Error(`API Key \u4E0D\u80FD\u8D85\u8FC7 ${MAX_API_KEY} \u5B57\u7B26`);
234
266
  return { value: key, expectedRevision: text(value.expectedRevision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION) };
235
267
  }
268
+ function parseActivationOpenState(value) {
269
+ if (!record(value)) throw new Error("\u6388\u6743\u9875\u6253\u5F00\u7ED3\u679C\u5FC5\u987B\u662F\u5BF9\u8C61");
270
+ return { code: member(value.code, ACTIVATION_OPEN_CODES, "\u6388\u6743\u9875\u6253\u5F00\u7ED3\u679C"), opened: flag(value.opened, "\u6388\u6743\u9875\u662F\u5426\u5DF2\u6253\u5F00") };
271
+ }
236
272
 
237
273
  // src/generated/typert.remote-client.ts
238
274
  var StatusCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#Status", create: () => z.unknown().transform((value) => parseStatus(value)) };
@@ -240,6 +276,7 @@ var QuotaSnapshotCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#
240
276
  var LoginStateCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#LoginState", create: () => z.unknown().transform((value) => parseLoginState(value)) };
241
277
  var StartLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#StartLoginRequest", create: () => z.unknown().transform((value) => parseStartLoginRequest(value)) };
242
278
  var CancelLoginRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#CancelLoginRequest", create: () => z.unknown().transform((value) => parseCancelLoginRequest(value)) };
279
+ var ActivationOpenStateCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#ActivationOpenState", create: () => z.unknown().transform((value) => parseActivationOpenState(value)) };
243
280
  var SaveApiKeyRequestCodec = { mode: "strict", typeSymbol: "dsh-opendesign-corouter#SaveApiKeyRequest", create: () => z.unknown().transform((value) => parseSaveApiKeyRequest(value)) };
244
281
  var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter", methods: {
245
282
  "openDesignCoRouter/status": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: StatusCodec },
@@ -249,6 +286,7 @@ var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter",
249
286
  "openDesignCoRouter/startLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: StartLoginRequestCodec, strictCodec: StartLoginRequestCodec }], result: LoginStateCodec },
250
287
  "openDesignCoRouter/loginStatus": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: LoginStateCodec },
251
288
  "openDesignCoRouter/cancelLogin": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: CancelLoginRequestCodec, strictCodec: CancelLoginRequestCodec }], result: LoginStateCodec },
289
+ "openDesignCoRouter/openActivationPage": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [], result: ActivationOpenStateCodec },
252
290
  "openDesignCoRouter/saveApiKey": { service: "openDesignCoRouter", invocation: { kind: "direct" }, parameters: [{ name: "input", source: "json", codec: SaveApiKeyRequestCodec, strictCodec: SaveApiKeyRequestCodec }], result: StatusCodec }
253
291
  } }, z);
254
292
  var typert_remote_client_default = TYPERT_REMOTE;
package/lib/index.d.ts CHANGED
@@ -4,9 +4,11 @@ import { fetchModelCatalog } from './model-discovery.js';
4
4
  import type { CatalogModel } from './catalog.js';
5
5
  import { readConfig, type LiveConfig } from './config.js';
6
6
  import { resolveSession } from './auth.js';
7
+ import { type LoginOptions } from './login.js';
8
+ import { type ActivationLauncherOptions } from './browser-open.js';
7
9
  import { readQuota, type QuotaSnapshot } from './quota.js';
8
10
  import { readDesktopQuota } from './desktop-quota.js';
9
- import { type Status, type LoginState, type StartLoginRequest, type CancelLoginRequest, type SaveApiKeyRequest } from './remote.js';
11
+ import { type Status, type LoginState, type StartLoginRequest, type CancelLoginRequest, type SaveApiKeyRequest, type ActivationOpenState } from './remote.js';
10
12
  export { Config } from './config.js';
11
13
  export { CoRouterAdapter } from './adapter.js';
12
14
  export { MODELS } from './catalog.js';
@@ -18,11 +20,14 @@ export interface HostDependencies {
18
20
  readDesktopQuota: typeof readDesktopQuota;
19
21
  fetchModels?: typeof fetchModelCatalog;
20
22
  modelsChanged?: () => void;
23
+ loginOptions?: LoginOptions;
24
+ activationOptions?: ActivationLauncherOptions;
21
25
  }
22
26
  export declare class OpenDesignCoRouterService extends TypertRemoteService {
23
27
  readonly dependencies: HostDependencies;
24
28
  private readonly _config;
25
29
  private readonly _login;
30
+ private readonly _activation;
26
31
  private readonly _lifetime;
27
32
  private _revision;
28
33
  private _fingerprint;
@@ -44,7 +49,9 @@ export declare class OpenDesignCoRouterService extends TypertRemoteService {
44
49
  modelCatalog(): readonly CatalogModel[];
45
50
  constructor(ctx: Context, config: () => ReturnType<typeof readConfig>, dependencies?: HostDependencies);
46
51
  private _credentials;
47
- resolveApiKey(ref: string): Promise<string | undefined>;
52
+ private _key;
53
+ resolveApiKey(ref: string, baseURL?: string): Promise<string | undefined>;
54
+ private _invalidateModels;
48
55
  private _state;
49
56
  private _conflict;
50
57
  private _expect;
@@ -58,6 +65,7 @@ export declare class OpenDesignCoRouterService extends TypertRemoteService {
58
65
  startLogin(input: StartLoginRequest): Promise<LoginState>;
59
66
  loginStatus(): LoginState;
60
67
  cancelLogin(input: CancelLoginRequest): LoginState;
68
+ openActivationPage(): Promise<ActivationOpenState>;
61
69
  saveApiKey(input: SaveApiKeyRequest): Promise<Status>;
62
70
  }
63
71
  declare module '@deepseek-ai/cordis' {