dsh-opendesign-corouter 0.1.4 → 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.
- package/README.md +3 -3
- package/SECURITY.md +1 -1
- package/THIRD_PARTY_NOTICES.md +22 -1
- package/lib/browser-open.d.ts +104 -0
- package/lib/client.d.ts +8 -2
- package/lib/client.js +64 -8
- package/lib/device-auth.d.ts +3 -1
- package/lib/generated/typert.host.js +7 -0
- package/lib/generated/typert.remote-client.d.ts +2 -1
- package/lib/generated/typert.remote-client.js +7 -0
- package/lib/index.d.ts +5 -1
- package/lib/index.js +301 -7
- package/lib/index.js.map +3 -3
- package/lib/login.d.ts +10 -0
- package/lib/remote.d.ts +7 -0
- package/package.json +2 -2
package/lib/index.js
CHANGED
|
@@ -2194,7 +2194,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2194
2194
|
|
|
2195
2195
|
// src/device-auth.ts
|
|
2196
2196
|
var DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
2197
|
-
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
2197
|
+
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.5";
|
|
2198
2198
|
var DEVICE_REQUEST_TIMEOUT_MS = 2e4;
|
|
2199
2199
|
var DEVICE_RESPONSE_MAX_BYTES = 65536;
|
|
2200
2200
|
var DEVICE_POLL_MIN_MS = 1e3;
|
|
@@ -2406,6 +2406,11 @@ var ConsoleLogin = class {
|
|
|
2406
2406
|
} : {}
|
|
2407
2407
|
};
|
|
2408
2408
|
}
|
|
2409
|
+
/** Host-only: the live approval link, so the Host can open it in a bounded window. */
|
|
2410
|
+
activationLink() {
|
|
2411
|
+
const status = this.status();
|
|
2412
|
+
return status.state === "waiting" ? status.activationUrl : void 0;
|
|
2413
|
+
}
|
|
2409
2414
|
/** Synchronous/non-blocking and idempotent while capture/network/commit is pending. */
|
|
2410
2415
|
start(request) {
|
|
2411
2416
|
if (this.disposed) throw new LoginError("opendesign/login-disposed");
|
|
@@ -2421,7 +2426,8 @@ var ConsoleLogin = class {
|
|
|
2421
2426
|
status: { jobId: null, state: "launching", startedAt: new Date(started).toISOString(), message: "\u6B63\u5728\u7533\u8BF7\u5B98\u65B9\u8BBE\u5907\u6388\u6743\u7801" },
|
|
2422
2427
|
captured: void 0,
|
|
2423
2428
|
committing: false,
|
|
2424
|
-
cancelRequested: false
|
|
2429
|
+
cancelRequested: false,
|
|
2430
|
+
settled: false
|
|
2425
2431
|
};
|
|
2426
2432
|
job.status.jobId = job.id;
|
|
2427
2433
|
this.job = job;
|
|
@@ -2446,7 +2452,11 @@ var ConsoleLogin = class {
|
|
|
2446
2452
|
}
|
|
2447
2453
|
dispose() {
|
|
2448
2454
|
this.disposed = true;
|
|
2449
|
-
|
|
2455
|
+
const job = this.job;
|
|
2456
|
+
if (job) {
|
|
2457
|
+
this.requestCancellation(job, "\u670D\u52A1\u5DF2\u5378\u8F7D\uFF0C\u767B\u5F55\u5DF2\u53D6\u6D88");
|
|
2458
|
+
this.settle(job);
|
|
2459
|
+
}
|
|
2450
2460
|
}
|
|
2451
2461
|
alive(job) {
|
|
2452
2462
|
return this.job === job && !this.disposed && !job.controller.signal.aborted && ACTIVE.has(job.status.state);
|
|
@@ -2495,6 +2505,16 @@ var ConsoleLogin = class {
|
|
|
2495
2505
|
this.clearCode(job);
|
|
2496
2506
|
this.stopTimer(job);
|
|
2497
2507
|
job.controller.abort();
|
|
2508
|
+
this.settle(job);
|
|
2509
|
+
}
|
|
2510
|
+
/** Report one terminal transition per job, exactly once. */
|
|
2511
|
+
settle(job) {
|
|
2512
|
+
if (job.settled) return;
|
|
2513
|
+
job.settled = true;
|
|
2514
|
+
try {
|
|
2515
|
+
this.options.onSettled?.();
|
|
2516
|
+
} catch {
|
|
2517
|
+
}
|
|
2498
2518
|
}
|
|
2499
2519
|
async run(job) {
|
|
2500
2520
|
const signal = job.controller.signal;
|
|
@@ -2514,7 +2534,7 @@ var ConsoleLogin = class {
|
|
|
2514
2534
|
}
|
|
2515
2535
|
this.armExpiry(job);
|
|
2516
2536
|
job.status.state = "waiting";
|
|
2517
|
-
job.status.message = "\u8BF7\u5728\u5E38\u7528\u6D4F\u89C8\u5668\u6253\u5F00\u5B98\u65B9\u6388\u6743\u9875\uFF0C\
|
|
2537
|
+
job.status.message = "\u8BF7\u5728\u6388\u6743\u7A97\u53E3\u6216\u5E38\u7528\u6D4F\u89C8\u5668\u6253\u5F00\u5B98\u65B9\u6388\u6743\u9875\uFF0C\u767B\u5F55\u5E76\u786E\u8BA4\u8BBE\u5907\u7801";
|
|
2518
2538
|
job.status.activationUrl = device.activationUrl;
|
|
2519
2539
|
job.status.userCode = device.userCode;
|
|
2520
2540
|
job.status.expiresAt = new Date(job.deadline).toISOString();
|
|
@@ -2572,6 +2592,258 @@ function failureMessage(error) {
|
|
|
2572
2592
|
return "\u8BBE\u5907\u6388\u6743\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u5F00\u59CB";
|
|
2573
2593
|
}
|
|
2574
2594
|
|
|
2595
|
+
// src/browser-open.ts
|
|
2596
|
+
var ACTIVATION_NAVIGATE_TIMEOUT_MS = 15e3;
|
|
2597
|
+
var ACTIVATION_OPEN_BUDGET_MS = 2e4;
|
|
2598
|
+
var ACTIVATION_CLOSE_TIMEOUT_MS = 5e3;
|
|
2599
|
+
function chromeLaunchOptions() {
|
|
2600
|
+
return {
|
|
2601
|
+
channel: "chrome",
|
|
2602
|
+
headless: false,
|
|
2603
|
+
chromiumSandbox: true,
|
|
2604
|
+
ignoreDefaultArgs: ["--enable-automation"],
|
|
2605
|
+
args: ["--disable-blink-features=AutomationControlled"]
|
|
2606
|
+
};
|
|
2607
|
+
}
|
|
2608
|
+
var ActivationLauncher = class {
|
|
2609
|
+
browser;
|
|
2610
|
+
page;
|
|
2611
|
+
pending;
|
|
2612
|
+
disposal;
|
|
2613
|
+
/** In-flight window closure, shared so disposal can join it. */
|
|
2614
|
+
closing;
|
|
2615
|
+
/** Closures of handles that were never adopted; disposal joins them too. */
|
|
2616
|
+
tracked = [];
|
|
2617
|
+
/** Chrome starts in flight, so disposal waits for the handle they will produce. */
|
|
2618
|
+
starting = [];
|
|
2619
|
+
disposed = false;
|
|
2620
|
+
/** Bumped by `close()`: an attempt from an older session must not resurrect a window. */
|
|
2621
|
+
session = 0;
|
|
2622
|
+
options;
|
|
2623
|
+
constructor(options = {}) {
|
|
2624
|
+
this.options = options;
|
|
2625
|
+
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Show `url` in the temporary window, reusing one already open. Concurrent calls share
|
|
2628
|
+
* a single attempt: the caller's button stays honest about what actually happened.
|
|
2629
|
+
*/
|
|
2630
|
+
async open(url) {
|
|
2631
|
+
if (validateActivationUrl(url) === null) return { code: "invalid-url", opened: false };
|
|
2632
|
+
if (this.disposed) return { code: "failed", opened: false };
|
|
2633
|
+
if (this.pending) return this.pending;
|
|
2634
|
+
const attempt = this.attempt(url);
|
|
2635
|
+
this.pending = attempt;
|
|
2636
|
+
try {
|
|
2637
|
+
return await attempt;
|
|
2638
|
+
} finally {
|
|
2639
|
+
if (this.pending === attempt) this.pending = void 0;
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
/**
|
|
2643
|
+
* Close the temporary window and stay usable: a cancelled or expired job takes its
|
|
2644
|
+
* window away, while the next login may open a new one.
|
|
2645
|
+
*/
|
|
2646
|
+
async close() {
|
|
2647
|
+
this.session++;
|
|
2648
|
+
await this.closeCurrent();
|
|
2649
|
+
}
|
|
2650
|
+
/**
|
|
2651
|
+
* Retire the launcher for good. Cleanup is best-effort and bounded: it joins in-flight
|
|
2652
|
+
* starts and closures, but a browser that ignores `close()` may outlive the 5 s wait.
|
|
2653
|
+
*/
|
|
2654
|
+
async dispose() {
|
|
2655
|
+
this.disposed = true;
|
|
2656
|
+
this.session++;
|
|
2657
|
+
if (this.disposal) return this.disposal;
|
|
2658
|
+
this.disposal = (async () => {
|
|
2659
|
+
await this.bounded(Date.now() + ACTIVATION_CLOSE_TIMEOUT_MS, async () => {
|
|
2660
|
+
await Promise.allSettled(this.starting);
|
|
2661
|
+
});
|
|
2662
|
+
await this.closing;
|
|
2663
|
+
await this.closeCurrent();
|
|
2664
|
+
await this.bounded(Date.now() + ACTIVATION_CLOSE_TIMEOUT_MS, async () => {
|
|
2665
|
+
await Promise.all(this.tracked);
|
|
2666
|
+
});
|
|
2667
|
+
})();
|
|
2668
|
+
return this.disposal;
|
|
2669
|
+
}
|
|
2670
|
+
/**
|
|
2671
|
+
* Close the window this launcher owns right now. Ownership is taken before the async
|
|
2672
|
+
* close, so a job that adopts a new window afterwards is not affected by this closure.
|
|
2673
|
+
* The closure promise is shared so a later `dispose()` joins it.
|
|
2674
|
+
*/
|
|
2675
|
+
async closeCurrent() {
|
|
2676
|
+
if (this.closing === void 0) {
|
|
2677
|
+
const browser = this.browser;
|
|
2678
|
+
this.browser = void 0;
|
|
2679
|
+
this.page = void 0;
|
|
2680
|
+
if (browser === void 0) return;
|
|
2681
|
+
this.closing = closeBounded(browser);
|
|
2682
|
+
}
|
|
2683
|
+
const closing = this.closing;
|
|
2684
|
+
try {
|
|
2685
|
+
await closing;
|
|
2686
|
+
} finally {
|
|
2687
|
+
if (this.closing === closing) this.closing = void 0;
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
async attempt(url) {
|
|
2691
|
+
const session = this.session;
|
|
2692
|
+
const budget = this.options.timeoutMs ?? ACTIVATION_OPEN_BUDGET_MS;
|
|
2693
|
+
const deadline = Date.now() + budget;
|
|
2694
|
+
try {
|
|
2695
|
+
if (this.options.available?.() === false) return { code: "unavailable", opened: false };
|
|
2696
|
+
const browser = await this.ensureBrowser(session, deadline);
|
|
2697
|
+
if (browser === void 0) return { code: this.stale(session) ? "failed" : "unavailable", opened: false };
|
|
2698
|
+
if (this.stale(session)) {
|
|
2699
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2700
|
+
return { code: "failed", opened: false };
|
|
2701
|
+
}
|
|
2702
|
+
const page = await this.ensurePage(browser, session, deadline);
|
|
2703
|
+
if (page === void 0) {
|
|
2704
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2705
|
+
return { code: "failed", opened: false };
|
|
2706
|
+
}
|
|
2707
|
+
const remaining = Math.max(1, Math.min(ACTIVATION_NAVIGATE_TIMEOUT_MS, deadline - Date.now()));
|
|
2708
|
+
await page.goto(url, { waitUntil: "domcontentloaded", timeout: remaining });
|
|
2709
|
+
if (this.stale(session)) {
|
|
2710
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2711
|
+
return { code: "failed", opened: false };
|
|
2712
|
+
}
|
|
2713
|
+
return { code: "opened", opened: true };
|
|
2714
|
+
} catch {
|
|
2715
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2716
|
+
return { code: "failed", opened: false };
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
/** The job that started this attempt ended, or the launcher retired. */
|
|
2720
|
+
stale(session) {
|
|
2721
|
+
return this.disposed || session !== this.session;
|
|
2722
|
+
}
|
|
2723
|
+
async ensureBrowser(session, deadline) {
|
|
2724
|
+
const open = this.browser;
|
|
2725
|
+
if (open !== void 0) {
|
|
2726
|
+
try {
|
|
2727
|
+
if (open.isConnected()) return open;
|
|
2728
|
+
} catch {
|
|
2729
|
+
}
|
|
2730
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2731
|
+
}
|
|
2732
|
+
for (let round = 0; round < 2; round++) {
|
|
2733
|
+
await this.bounded(deadline, async () => {
|
|
2734
|
+
await Promise.allSettled([this.closing, ...this.tracked, ...this.starting]);
|
|
2735
|
+
});
|
|
2736
|
+
if (this.stale(session) || Date.now() >= deadline) return void 0;
|
|
2737
|
+
if (this.closing === void 0 && this.tracked.length === 0 && this.starting.length === 0) break;
|
|
2738
|
+
}
|
|
2739
|
+
if (this.stale(session) || Date.now() >= deadline) return void 0;
|
|
2740
|
+
const launch = this.options.launch ?? defaultLaunch;
|
|
2741
|
+
const starting = launch();
|
|
2742
|
+
this.starting.push(starting);
|
|
2743
|
+
const browser = await this.bounded(deadline, () => starting);
|
|
2744
|
+
void starting.then((handle) => {
|
|
2745
|
+
if (handle !== browser) void this.trackClose(handle);
|
|
2746
|
+
}).catch(() => void 0).finally(() => {
|
|
2747
|
+
this.starting = this.starting.filter((item) => item !== starting);
|
|
2748
|
+
});
|
|
2749
|
+
if (browser === void 0) return void 0;
|
|
2750
|
+
if (this.stale(session)) {
|
|
2751
|
+
void this.trackClose(browser);
|
|
2752
|
+
return void 0;
|
|
2753
|
+
}
|
|
2754
|
+
this.adopt(browser);
|
|
2755
|
+
return browser;
|
|
2756
|
+
}
|
|
2757
|
+
async ensurePage(browser, session, deadline) {
|
|
2758
|
+
if (this.page !== void 0) return this.page;
|
|
2759
|
+
const page = await this.bounded(deadline, () => browser.newPage(), (late) => {
|
|
2760
|
+
void this.trackPageClose(late);
|
|
2761
|
+
});
|
|
2762
|
+
if (page === void 0) return void 0;
|
|
2763
|
+
if (this.stale(session) || this.browser !== browser) {
|
|
2764
|
+
await this.bounded(deadline, () => this.closeCurrent());
|
|
2765
|
+
return void 0;
|
|
2766
|
+
}
|
|
2767
|
+
this.page = page;
|
|
2768
|
+
return page;
|
|
2769
|
+
}
|
|
2770
|
+
/** A handle that arrived too late is closed, and still counts as work disposal joins. */
|
|
2771
|
+
trackClose(browser) {
|
|
2772
|
+
const closing = closeBounded(browser);
|
|
2773
|
+
this.tracked.push(closing);
|
|
2774
|
+
void closing.finally(() => {
|
|
2775
|
+
this.tracked = this.tracked.filter((item) => item !== closing);
|
|
2776
|
+
});
|
|
2777
|
+
return closing;
|
|
2778
|
+
}
|
|
2779
|
+
trackPageClose(page) {
|
|
2780
|
+
try {
|
|
2781
|
+
return Promise.resolve(page.close?.()).catch(() => void 0);
|
|
2782
|
+
} catch {
|
|
2783
|
+
return Promise.resolve();
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
adopt(browser) {
|
|
2787
|
+
this.browser = browser;
|
|
2788
|
+
browser.on?.("disconnected", () => {
|
|
2789
|
+
if (this.browser === browser) {
|
|
2790
|
+
this.browser = void 0;
|
|
2791
|
+
this.page = void 0;
|
|
2792
|
+
}
|
|
2793
|
+
});
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* Bound one launch step by the attempt's shared deadline. A step that settles only
|
|
2797
|
+
* after that deadline still hands its handle back: dropping it would leak a Chrome
|
|
2798
|
+
* process nobody can close.
|
|
2799
|
+
*/
|
|
2800
|
+
async bounded(deadline, start, discardOnLate) {
|
|
2801
|
+
let timer;
|
|
2802
|
+
let expired = false;
|
|
2803
|
+
const work = (async () => {
|
|
2804
|
+
try {
|
|
2805
|
+
return await start();
|
|
2806
|
+
} catch {
|
|
2807
|
+
return void 0;
|
|
2808
|
+
}
|
|
2809
|
+
})().then((value) => {
|
|
2810
|
+
if (expired && value !== void 0) discardOnLate?.(value);
|
|
2811
|
+
return value;
|
|
2812
|
+
});
|
|
2813
|
+
const timeout = new Promise((resolve) => {
|
|
2814
|
+
timer = setTimeout(() => {
|
|
2815
|
+
expired = true;
|
|
2816
|
+
resolve(void 0);
|
|
2817
|
+
}, Math.max(1, deadline - Date.now()));
|
|
2818
|
+
});
|
|
2819
|
+
try {
|
|
2820
|
+
return await Promise.race([work, timeout]);
|
|
2821
|
+
} finally {
|
|
2822
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
};
|
|
2826
|
+
function closeBounded(browser) {
|
|
2827
|
+
let timer;
|
|
2828
|
+
return Promise.race([
|
|
2829
|
+
(async () => {
|
|
2830
|
+
try {
|
|
2831
|
+
await browser.close();
|
|
2832
|
+
} catch {
|
|
2833
|
+
}
|
|
2834
|
+
})(),
|
|
2835
|
+
new Promise((resolve) => {
|
|
2836
|
+
timer = setTimeout(resolve, ACTIVATION_CLOSE_TIMEOUT_MS);
|
|
2837
|
+
})
|
|
2838
|
+
]).finally(() => {
|
|
2839
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
2840
|
+
});
|
|
2841
|
+
}
|
|
2842
|
+
async function defaultLaunch() {
|
|
2843
|
+
const playwright = await import("playwright-core");
|
|
2844
|
+
return playwright.chromium.launch(chromeLaunchOptions());
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2575
2847
|
// src/quota.ts
|
|
2576
2848
|
import { attributionHeaders as attributionHeaders3 } from "@deepseek-ai/dsh-llm";
|
|
2577
2849
|
var API_BASE = "https://amr-api.open-design.ai/api/v1";
|
|
@@ -2859,6 +3131,7 @@ var MAX_API_KEY = 16384;
|
|
|
2859
3131
|
var HTTP_ASCII = /^[\x21-\x7e]+$/u;
|
|
2860
3132
|
var ENV_REF = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
2861
3133
|
var MODEL_ID2 = /^[A-Za-z0-9._:/-]{1,128}$/u;
|
|
3134
|
+
var ACTIVATION_OPEN_CODES = ["opened", "no-link", "invalid-url", "unavailable", "failed"];
|
|
2862
3135
|
var LOGIN_PHASES = ["idle", "launching", "waiting", "verifying", "success", "cancelled", "error"];
|
|
2863
3136
|
var QUOTA_STATES = ["ok", "partial", "need-login", "error"];
|
|
2864
3137
|
var SESSION_SOURCES = ["desktop", "login", "environment"];
|
|
@@ -3034,6 +3307,10 @@ function parseSaveApiKeyRequest(value) {
|
|
|
3034
3307
|
if (key.length > MAX_API_KEY) throw new Error(`API Key \u4E0D\u80FD\u8D85\u8FC7 ${MAX_API_KEY} \u5B57\u7B26`);
|
|
3035
3308
|
return { value: key, expectedRevision: text(value.expectedRevision, "\u914D\u7F6E\u7248\u672C", MAX_REVISION) };
|
|
3036
3309
|
}
|
|
3310
|
+
function parseActivationOpenState(value) {
|
|
3311
|
+
if (!record(value)) throw new Error("\u6388\u6743\u9875\u6253\u5F00\u7ED3\u679C\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
3312
|
+
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") };
|
|
3313
|
+
}
|
|
3037
3314
|
|
|
3038
3315
|
// src/index.ts
|
|
3039
3316
|
var name = "llm-opendesign-corouter";
|
|
@@ -3048,14 +3325,15 @@ function grantOf(value) {
|
|
|
3048
3325
|
if (typeof value.payload.cookie !== "string") return;
|
|
3049
3326
|
return { cookie: value.payload.cookie, ...typeof value.payload.expiresAt === "number" ? { expiresAt: value.payload.expiresAt } : {} };
|
|
3050
3327
|
}
|
|
3051
|
-
var _saveApiKey_dec, _cancelLogin_dec, _loginStatus_dec, _startLogin_dec, _refreshQuotaNow_dec, _refreshQuota_dec, _refreshModels_dec, _status_dec, _a, _init;
|
|
3052
|
-
var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status_dec = [Remote("status")], _refreshModels_dec = [Remote("refreshModels")], _refreshQuota_dec = [Remote("refreshQuota")], _refreshQuotaNow_dec = [Remote("refreshQuotaNow")], _startLogin_dec = [Remote("startLogin")], _loginStatus_dec = [Remote("loginStatus")], _cancelLogin_dec = [Remote("cancelLogin")], _saveApiKey_dec = [Remote("saveApiKey")], _a) {
|
|
3328
|
+
var _saveApiKey_dec, _openActivationPage_dec, _cancelLogin_dec, _loginStatus_dec, _startLogin_dec, _refreshQuotaNow_dec, _refreshQuota_dec, _refreshModels_dec, _status_dec, _a, _init;
|
|
3329
|
+
var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status_dec = [Remote("status")], _refreshModels_dec = [Remote("refreshModels")], _refreshQuota_dec = [Remote("refreshQuota")], _refreshQuotaNow_dec = [Remote("refreshQuotaNow")], _startLogin_dec = [Remote("startLogin")], _loginStatus_dec = [Remote("loginStatus")], _cancelLogin_dec = [Remote("cancelLogin")], _openActivationPage_dec = [Remote("openActivationPage")], _saveApiKey_dec = [Remote("saveApiKey")], _a) {
|
|
3053
3330
|
constructor(ctx, config, dependencies = { resolveSession, readQuota, readDesktopQuota }) {
|
|
3054
3331
|
super(ctx, "openDesignCoRouter");
|
|
3055
3332
|
this.dependencies = dependencies;
|
|
3056
3333
|
__runInitializers(_init, 5, this);
|
|
3057
3334
|
__publicField(this, "_config");
|
|
3058
3335
|
__publicField(this, "_login");
|
|
3336
|
+
__publicField(this, "_activation");
|
|
3059
3337
|
__publicField(this, "_lifetime", new AbortController());
|
|
3060
3338
|
__publicField(this, "_revision", randomUUID2());
|
|
3061
3339
|
__publicField(this, "_fingerprint", "");
|
|
@@ -3098,10 +3376,19 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3098
3376
|
this._modelsFingerprint = "";
|
|
3099
3377
|
this._invalidateModels();
|
|
3100
3378
|
}
|
|
3101
|
-
},
|
|
3379
|
+
}, {
|
|
3380
|
+
...dependencies.loginOptions,
|
|
3381
|
+
// The Host owns the temporary window, so it closes it on every terminal transition —
|
|
3382
|
+
// including expiry, which happens on a timer even when no UI is polling.
|
|
3383
|
+
onSettled: () => {
|
|
3384
|
+
void this._activation.close();
|
|
3385
|
+
}
|
|
3386
|
+
});
|
|
3387
|
+
this._activation = new ActivationLauncher(dependencies.activationOptions);
|
|
3102
3388
|
ctx.effect(() => () => {
|
|
3103
3389
|
this._lifetime.abort();
|
|
3104
3390
|
this._login.dispose();
|
|
3391
|
+
return this._activation.dispose();
|
|
3105
3392
|
});
|
|
3106
3393
|
}
|
|
3107
3394
|
dependencies;
|
|
@@ -3353,6 +3640,12 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3353
3640
|
cancelLogin(input) {
|
|
3354
3641
|
return parseLoginState(this._login.cancel(parseCancelLoginRequest(input)));
|
|
3355
3642
|
}
|
|
3643
|
+
async openActivationPage() {
|
|
3644
|
+
const url = this._login.activationLink();
|
|
3645
|
+
if (url === void 0) return { code: "no-link", opened: false };
|
|
3646
|
+
const result = await this._activation.open(url);
|
|
3647
|
+
return parseActivationOpenState({ code: result.code, opened: result.opened });
|
|
3648
|
+
}
|
|
3356
3649
|
async saveApiKey(input) {
|
|
3357
3650
|
const request = parseSaveApiKeyRequest(input), state = await this._state();
|
|
3358
3651
|
this._expect(request.expectedRevision);
|
|
@@ -3372,6 +3665,7 @@ __decorateElement(_init, 1, "refreshQuotaNow", _refreshQuotaNow_dec, OpenDesignC
|
|
|
3372
3665
|
__decorateElement(_init, 1, "startLogin", _startLogin_dec, OpenDesignCoRouterService);
|
|
3373
3666
|
__decorateElement(_init, 1, "loginStatus", _loginStatus_dec, OpenDesignCoRouterService);
|
|
3374
3667
|
__decorateElement(_init, 1, "cancelLogin", _cancelLogin_dec, OpenDesignCoRouterService);
|
|
3668
|
+
__decorateElement(_init, 1, "openActivationPage", _openActivationPage_dec, OpenDesignCoRouterService);
|
|
3375
3669
|
__decorateElement(_init, 1, "saveApiKey", _saveApiKey_dec, OpenDesignCoRouterService);
|
|
3376
3670
|
__decoratorMetadata(_init, OpenDesignCoRouterService);
|
|
3377
3671
|
function apply(ctx, config) {
|