@eddyskywalker/dsh-chatgpt-subscription 0.1.0 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2 - 2026-08-16
4
+
5
+ - 优化过程详情折叠(Process folding)的初始化时机与节点匹配探测逻辑。
6
+ - 增强客户端 DOM 观察与挂载测试用例覆盖。
7
+
8
+ ## 0.1.1 - 2026-08-16
9
+
10
+ - 新增执行过程详情与思考过程的可折叠展示机制(Collapsible process detail folding)。
11
+ - 增强客户端与服务端 Responses 过程解析及 UI 交互。
12
+
3
13
  ## 0.1.0 - 2026-08-16
4
14
 
5
15
  - 首个正式版本发布。
package/lib/client.js CHANGED
@@ -592,6 +592,233 @@ window.__ModuleLoader__.load({
592
592
  }
593
593
  };
594
594
  //#endregion
595
+ //#region src/client/process-folding.ts
596
+ const ROW_CLASS = "dsh-codex-process-row";
597
+ const GROUP_HEAD_CLASS = "dsh-codex-process-group-head";
598
+ const GROUP_COLLAPSED_CLASS = "dsh-codex-process-group-collapsed";
599
+ const GROUP_HIDDEN_CLASS = "dsh-codex-process-group-hidden";
600
+ const USER_TOGGLED_ATTR = "data-dsh-codex-process-user-toggled";
601
+ const TITLE_ATTR = "data-dsh-codex-process-title";
602
+ const TITLE = "Click to expand or collapse process details";
603
+ const DEFAULT_AUTO_COLLAPSE_MS = 2500;
604
+ const MAX_PROCESS_LABELS_PER_ROW = 3;
605
+ const MAX_SCAN_ROOTS_PER_FRAME = 80;
606
+ const MAX_TEXT_SAMPLE = 2e4;
607
+ const PROCESS_CANDIDATE_SELECTOR = "article,section,li,div,p,h1,h2,h3,h4,h5,h6,[role=\"listitem\"]";
608
+ const PROCESS_PREFIX_PATTERN = "(?:上下文注入|Think|Search|Code|代码|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Web(?:\\s+Search)?|Tool|工具|思考)";
609
+ const COMMAND_PATTERN = /(?:Code|代码|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Tool|工具)/i;
610
+ const SEARCH_PATTERN = /(?:Search|Web\s+Search|搜索)/i;
611
+ const PROCESS_PREFIX_RE = new RegExp(`^\\s*(?:[•●◦▪▫·#-]\\s*)?${PROCESS_PREFIX_PATTERN}\\s*(?:[·::-]|$)`, "i");
612
+ const PROCESS_LINE_RE = new RegExp(`(?:^|\\n)\\s*(?:[•●◦▪▫·#-]\\s*)?${PROCESS_PREFIX_PATTERN}\\s*(?:[·::-]|$)`, "gi");
613
+ function installProcessFolding(options = {}) {
614
+ if (typeof document === "undefined") return () => void 0;
615
+ if (document.body === null) {
616
+ let dispose = () => void 0;
617
+ let started = false;
618
+ const start = () => {
619
+ if (started) return;
620
+ started = true;
621
+ dispose = installProcessFolding(options);
622
+ };
623
+ document.addEventListener("DOMContentLoaded", start, { once: true });
624
+ return () => {
625
+ document.removeEventListener("DOMContentLoaded", start);
626
+ dispose();
627
+ };
628
+ }
629
+ const autoCollapseMs = options.autoCollapseMs ?? DEFAULT_AUTO_COLLAPSE_MS;
630
+ const groups = /* @__PURE__ */ new Map();
631
+ const pending = /* @__PURE__ */ new Set();
632
+ let frame = null;
633
+ const scheduleFlush = () => {
634
+ if (frame !== null) return;
635
+ frame = requestAnimationFrame(() => {
636
+ frame = null;
637
+ flush();
638
+ });
639
+ };
640
+ const queue = (element) => {
641
+ if (element === null || !element.isConnected) return;
642
+ pending.add(element);
643
+ scheduleFlush();
644
+ };
645
+ const scheduleAutoCollapse = (head) => {
646
+ const state = groups.get(head);
647
+ if (state === void 0 || head.hasAttribute(USER_TOGGLED_ATTR)) return;
648
+ if (state.timer !== null) clearTimeout(state.timer);
649
+ state.timer = setTimeout(() => {
650
+ state.timer = null;
651
+ if (head.isConnected && !head.hasAttribute(USER_TOGGLED_ATTR)) setGroupCollapsed(head, true);
652
+ }, autoCollapseMs);
653
+ };
654
+ const syncGroup = (rows, previous) => {
655
+ const head = rows[0];
656
+ const title = titleForProcessRows(rows);
657
+ const click = (event) => {
658
+ if (isInteractiveTarget(event.target)) return;
659
+ markUserToggled(head);
660
+ setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS));
661
+ };
662
+ const keydown = (event) => {
663
+ if (event.key !== "Enter" && event.key !== " ") return;
664
+ event.preventDefault();
665
+ markUserToggled(head);
666
+ setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS));
667
+ };
668
+ groups.set(head, {
669
+ rows,
670
+ click,
671
+ keydown,
672
+ timer: null
673
+ });
674
+ for (const row of rows) row.classList.add(ROW_CLASS);
675
+ head.classList.add(GROUP_HEAD_CLASS);
676
+ if (!head.hasAttribute("tabindex")) head.tabIndex = 0;
677
+ head.setAttribute("aria-expanded", String(!(previous?.collapsed ?? false)));
678
+ head.setAttribute(TITLE_ATTR, title);
679
+ head.title ||= TITLE;
680
+ if (previous?.userToggled === true) head.setAttribute(USER_TOGGLED_ATTR, "true");
681
+ head.addEventListener("click", click);
682
+ head.addEventListener("keydown", keydown);
683
+ setGroupCollapsed(head, previous?.collapsed ?? false);
684
+ scheduleAutoCollapse(head);
685
+ };
686
+ const rebuildParentGroups = (parent) => {
687
+ const previous = /* @__PURE__ */ new Map();
688
+ for (const [head, state] of groups) {
689
+ if (head.parentElement !== parent) continue;
690
+ previous.set(head, {
691
+ collapsed: head.classList.contains(GROUP_COLLAPSED_CLASS),
692
+ userToggled: head.hasAttribute(USER_TOGGLED_ATTR)
693
+ });
694
+ cleanupGroup(head, state);
695
+ groups.delete(head);
696
+ }
697
+ let rows = [];
698
+ const flushRows = () => {
699
+ if (rows.length > 0) syncGroup(rows, previous.get(rows[0]));
700
+ rows = [];
701
+ };
702
+ for (const child of Array.from(parent.children)) if (child instanceof HTMLElement && isProcessRow(child)) rows.push(child);
703
+ else flushRows();
704
+ flushRows();
705
+ };
706
+ const flush = () => {
707
+ const parents = /* @__PURE__ */ new Set();
708
+ let scanned = 0;
709
+ for (const root of Array.from(pending)) {
710
+ pending.delete(root);
711
+ if (!root.isConnected) continue;
712
+ for (const row of findProcessRows(root)) if (row.parentElement !== null) parents.add(row.parentElement);
713
+ const grouped = nearestGroupHead(root);
714
+ if (grouped !== null && grouped.parentElement !== null) parents.add(grouped.parentElement);
715
+ scanned++;
716
+ if (scanned >= MAX_SCAN_ROOTS_PER_FRAME && pending.size > 0) {
717
+ scheduleFlush();
718
+ break;
719
+ }
720
+ }
721
+ for (const parent of parents) rebuildParentGroups(parent);
722
+ };
723
+ const observer = new MutationObserver((mutations) => {
724
+ for (const mutation of mutations) {
725
+ if (mutation.type === "characterData") {
726
+ queue(nodeElement(mutation.target)?.closest(PROCESS_CANDIDATE_SELECTOR) ?? nodeElement(mutation.target));
727
+ continue;
728
+ }
729
+ for (const node of mutation.addedNodes) queue(nodeElement(node));
730
+ }
731
+ });
732
+ observer.observe(document.body, {
733
+ childList: true,
734
+ characterData: true,
735
+ subtree: true
736
+ });
737
+ queue(document.body);
738
+ return () => {
739
+ observer.disconnect();
740
+ if (frame !== null) cancelAnimationFrame(frame);
741
+ pending.clear();
742
+ for (const [head, state] of groups) cleanupGroup(head, state);
743
+ groups.clear();
744
+ };
745
+ }
746
+ function cleanupGroup(head, state) {
747
+ if (state.timer !== null) clearTimeout(state.timer);
748
+ head.removeEventListener("click", state.click);
749
+ head.removeEventListener("keydown", state.keydown);
750
+ for (const row of state.rows) row.classList.remove(ROW_CLASS, GROUP_HIDDEN_CLASS);
751
+ head.classList.remove(GROUP_HEAD_CLASS, GROUP_COLLAPSED_CLASS);
752
+ head.removeAttribute("aria-expanded");
753
+ head.removeAttribute(USER_TOGGLED_ATTR);
754
+ head.removeAttribute(TITLE_ATTR);
755
+ if (head.title === TITLE) head.removeAttribute("title");
756
+ }
757
+ function findProcessRows(root) {
758
+ const rows = [];
759
+ if (root instanceof HTMLElement && isProcessRow(root)) rows.push(root);
760
+ for (const element of root.querySelectorAll(PROCESS_CANDIDATE_SELECTOR)) if (element instanceof HTMLElement && isProcessRow(element)) rows.push(element);
761
+ return rows;
762
+ }
763
+ function isProcessRow(element) {
764
+ if (element.closest(".dsh-codex-page") !== null || shouldIgnore(element)) return false;
765
+ const raw = (element.textContent ?? "").slice(0, MAX_TEXT_SAMPLE);
766
+ const normalized = raw.replace(/\s+/g, " ").trim();
767
+ if (!PROCESS_PREFIX_RE.test(normalized)) return false;
768
+ const stats = processTextStats(raw);
769
+ if (stats.processLabels === 0 || stats.processLabels > MAX_PROCESS_LABELS_PER_ROW) return false;
770
+ return !(element.children.length > 0 && stats.hasNonProcessLine);
771
+ }
772
+ function processTextStats(text) {
773
+ PROCESS_LINE_RE.lastIndex = 0;
774
+ let processLabels = 0;
775
+ while (PROCESS_LINE_RE.exec(text) !== null) processLabels++;
776
+ const hasNonProcessLine = text.split(/\r?\n/).map((line) => line.replace(/\s+/g, " ").trim()).some((line) => line !== "" && !PROCESS_PREFIX_RE.test(line));
777
+ return {
778
+ processLabels,
779
+ hasNonProcessLine
780
+ };
781
+ }
782
+ function setGroupCollapsed(head, collapsed) {
783
+ const state = findCurrentGroupState(head);
784
+ if (state === null) return;
785
+ head.classList.toggle(GROUP_COLLAPSED_CLASS, collapsed);
786
+ head.setAttribute("aria-expanded", String(!collapsed));
787
+ for (const row of state.rows.slice(1)) row.classList.toggle(GROUP_HIDDEN_CLASS, collapsed);
788
+ }
789
+ function findCurrentGroupState(head) {
790
+ const rows = [head];
791
+ let sibling = head.nextElementSibling;
792
+ while (sibling instanceof HTMLElement && isProcessRow(sibling)) {
793
+ rows.push(sibling);
794
+ sibling = sibling.nextElementSibling;
795
+ }
796
+ return rows.length > 0 ? { rows } : null;
797
+ }
798
+ function markUserToggled(head) {
799
+ head.setAttribute(USER_TOGGLED_ATTR, "true");
800
+ }
801
+ function nearestGroupHead(element) {
802
+ const decorated = element.closest(`.${GROUP_HEAD_CLASS}`);
803
+ return decorated instanceof HTMLElement ? decorated : null;
804
+ }
805
+ function titleForProcessRows(rows) {
806
+ const text = rows.map((row) => row.textContent ?? "").join("\n");
807
+ if (COMMAND_PATTERN.test(text)) return "运行了命令";
808
+ if (SEARCH_PATTERN.test(text)) return "进行了搜索";
809
+ return "思考过程";
810
+ }
811
+ function nodeElement(node) {
812
+ if (node instanceof Element) return node;
813
+ return node.parentElement;
814
+ }
815
+ function shouldIgnore(element) {
816
+ return element.closest("textarea,input,select,button,a,[contenteditable=\"true\"],script,style") !== null;
817
+ }
818
+ function isInteractiveTarget(target) {
819
+ return target instanceof Element && target.closest("button,a,input,textarea,select,[role=\"button\"],[contenteditable=\"true\"]") !== null;
820
+ }
821
+ //#endregion
595
822
  //#region src/client/styles.ts
596
823
  const STYLE_ID = "@eddyskywalker/dsh-chatgpt-subscription/main";
597
824
  const CSS = `
@@ -636,9 +863,16 @@ window.__ModuleLoader__.load({
636
863
  .dsh-codex-skeleton span{animation:dsh-codex-pulse 1.4s ease-in-out infinite;background:var(--dsw-alias-bg-layer-2);border-radius:5px;height:42px}
637
864
  .dsh-codex-skeleton span:nth-child(2){animation-delay:.12s}.dsh-codex-skeleton span:nth-child(3){animation-delay:.24s}
638
865
  .dsh-codex-sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0 0 0 0);white-space:nowrap}
866
+ .dsh-codex-process-group-head{border-radius:6px;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}
867
+ .dsh-codex-process-group-head:hover{background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,rgba(127,127,127,.18)) 72%,transparent)}
868
+ .dsh-codex-process-group-head:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}
869
+ .dsh-codex-process-group-head.dsh-codex-process-group-collapsed{align-items:center!important;color:transparent!important;display:flex!important;font-size:0!important;line-height:28px!important;max-height:28px!important;min-height:28px!important;overflow:hidden!important;opacity:.78}
870
+ .dsh-codex-process-group-head.dsh-codex-process-group-collapsed>*{display:none!important}
871
+ .dsh-codex-process-group-head.dsh-codex-process-group-collapsed::before{color:var(--dsw-alias-label-secondary);content:"▸ " attr(data-dsh-codex-process-title);display:block;font-size:13px;line-height:28px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
872
+ .dsh-codex-process-group-hidden{display:none!important}
639
873
  @keyframes dsh-codex-pulse{0%,100%{opacity:.55}50%{opacity:1}}
640
874
  @media(max-width:560px){.dsh-codex-row{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}}
641
- @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}
875
+ @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span,.dsh-codex-process-group-head{transition:none}.dsh-codex-skeleton span{animation:none}}
642
876
  `;
643
877
  function installStyles() {
644
878
  if (document.querySelector(`style[data-plugin-css="${STYLE_ID}"]`) !== null) return () => void 0;
@@ -655,6 +889,7 @@ window.__ModuleLoader__.load({
655
889
  function apply(ctx) {
656
890
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
657
891
  ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
892
+ ctx.effect(() => installProcessFolding(), "dsh-chatgpt-subscription: process folding");
658
893
  ctx.slots.inject("settings.section", () => ctx.slots.register({
659
894
  name: "settings.section",
660
895
  id: "codex-subscription",
package/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../src/compat.ts","../src/client/api.ts","../src/client/CodexSubscriptionSection.tsx","../src/client/locales.ts","../src/client/styles.ts","../src/client/index.tsx"],"sourcesContent":["/**\n * Compatibility constants for the ChatGPT-backed Codex flow. The backend and\n * OAuth parameters are not a public third-party API contract, so every such\n * value is isolated here for review and rollback.\n */\nexport const CHATGPT_OAUTH_ISSUER = 'https://auth.openai.com' as const\nexport const CHATGPT_OAUTH_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann' as const\nexport const OAUTH_CALLBACK_HOST = 'localhost' as const\nexport const OAUTH_CALLBACK_PORT = 1455 as const\nexport const OAUTH_CALLBACK_PATH = '/auth/callback' as const\nexport const OAUTH_REDIRECT_URI = `http://${OAUTH_CALLBACK_HOST}:${OAUTH_CALLBACK_PORT}${OAUTH_CALLBACK_PATH}` as const\nexport const OAUTH_SCOPE = 'openid profile email offline_access' as const\nexport const OAUTH_ORIGINATOR = 'opencode' as const\nexport const OAUTH_LOGIN_TIMEOUT_MS = 5 * 60_000\nexport const TOKEN_REFRESH_MARGIN_MS = 60_000\nexport const ROUTE_PREFIX = '/api/dsh-chatgpt-subscription' as const\nexport const PLUGIN_VERSION = '0.1.0-alpha.0' as const\n\nexport const CODEX_API_BASE = 'https://chatgpt.com/backend-api/codex' as const\nexport const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses` as const\nexport const CODEX_USAGE_URL = 'https://chatgpt.com/backend-api/wham/usage' as const\nexport const CODEX_ORIGINATOR = 'opencode' as const\nexport const QUOTA_CACHE_MS = 60_000\nexport const QUOTA_MIN_UPSTREAM_INTERVAL_MS = 15_000\n\nexport const OAUTH_AUTHORIZE_URL = `${CHATGPT_OAUTH_ISSUER}/oauth/authorize` as const\nexport const OAUTH_TOKEN_URL = `${CHATGPT_OAUTH_ISSUER}/oauth/token` as const\n","import { ROUTE_PREFIX } from '../compat.ts'\nimport type {\n ApiEnvelope,\n LoginEventDto,\n LoginStartDto,\n PluginStatusDto,\n QuotaStatusDto,\n ConnectionTestDto,\n} from '../shared/contracts.ts'\n\nexport class SubscriptionApi {\n status(): Promise<PluginStatusDto> {\n return request<PluginStatusDto>(`${ROUTE_PREFIX}/status`)\n }\n\n startLogin(): Promise<LoginStartDto> {\n return post<LoginStartDto>(`${ROUTE_PREFIX}/login/start`, {})\n }\n\n cancelLogin(loginId: string): Promise<{ cancelled: boolean }> {\n return post(`${ROUTE_PREFIX}/login/cancel`, { loginId })\n }\n\n logout(): Promise<{ authenticated: false }> {\n return post(`${ROUTE_PREFIX}/logout`, {})\n }\n\n refresh(): Promise<PluginStatusDto> {\n return post(`${ROUTE_PREFIX}/token/refresh`, {})\n }\n\n refreshQuota(): Promise<QuotaStatusDto> {\n return post(`${ROUTE_PREFIX}/quota/refresh`, {})\n }\n\n testConnection(): Promise<ConnectionTestDto> {\n return post(`${ROUTE_PREFIX}/connection/test`, {})\n }\n\n events(loginId: string): EventSource {\n return new EventSource(`${ROUTE_PREFIX}/login/events?loginId=${encodeURIComponent(loginId)}`)\n }\n}\n\nasync function post<T>(url: string, body: Record<string, unknown>): Promise<T> {\n return request<T>(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n}\n\nasync function request<T>(url: string, init?: RequestInit): Promise<T> {\n const response = await fetch(url, { ...init, credentials: 'same-origin' })\n const envelope = await response.json() as ApiEnvelope<T>\n if (!response.ok || !envelope.ok) {\n throw new Error(envelope.ok ? `Request failed (${response.status})` : envelope.error.message)\n }\n return envelope.value\n}\n\nexport function parseLoginEvent(event: MessageEvent<string>): LoginEventDto | null {\n try {\n const value = JSON.parse(event.data) as LoginEventDto\n return typeof value === 'object' && value !== null && typeof value.type === 'string' ? value : null\n } catch {\n return null\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { PluginStatusDto, QuotaBucketDto, QuotaWindowDto } from '../shared/contracts.ts'\nimport { SubscriptionApi, parseLoginEvent } from './api.ts'\nimport { NS } from './locales.ts'\n\ntype Props = PropsRuntime<'settings.section'> & PropsLocale<typeof NS>\ntype BusyAction = 'login' | 'token' | 'quota' | 'test' | 'logout' | null\ntype Translate = Props['t']\n\nconst MODELS = ['gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.2']\n\nexport function CodexSubscriptionSection({ t }: Props): React.JSX.Element {\n const apiRef = useRef(new SubscriptionApi())\n const eventSourceRef = useRef<EventSource | null>(null)\n const [status, setStatus] = useState<PluginStatusDto | null>(null)\n const [busy, setBusy] = useState<BusyAction>(null)\n const [error, setError] = useState<string | null>(null)\n const [authUrl, setAuthUrl] = useState<string | null>(null)\n const [popupBlocked, setPopupBlocked] = useState(false)\n const [connection, setConnection] = useState<{ latencyMs: number; checkedAt: number } | null>(null)\n\n const load = useCallback(async (quiet = false) => {\n if (!quiet) setError(null)\n try {\n const next = await apiRef.current.status()\n setStatus(next)\n if (next.error !== undefined) setError(next.error.message)\n } catch (cause) {\n if (!quiet) setError(messageOf(cause))\n }\n }, [])\n\n useEffect(() => {\n void load()\n const refreshWhenVisible = (): void => {\n if (document.visibilityState === 'visible') void load(true)\n }\n document.addEventListener('visibilitychange', refreshWhenVisible)\n const timer = window.setInterval(refreshWhenVisible, 60_000)\n return () => {\n window.clearInterval(timer)\n document.removeEventListener('visibilitychange', refreshWhenVisible)\n eventSourceRef.current?.close()\n }\n }, [load])\n\n const watchLogin = useCallback((loginId: string) => {\n eventSourceRef.current?.close()\n const source = apiRef.current.events(loginId)\n eventSourceRef.current = source\n const finish = async (message?: string): Promise<void> => {\n source.close()\n eventSourceRef.current = null\n setBusy(null)\n setAuthUrl(null)\n if (message !== undefined) setError(message)\n // Preserve the terminal OAuth error while refreshing the account DTO.\n await load(true)\n }\n source.addEventListener('completed', (event) => {\n const parsed = parseLoginEvent(event as MessageEvent<string>)\n if (parsed?.type === 'completed') void finish()\n })\n source.addEventListener('cancelled', () => void finish())\n source.addEventListener('failed', (event) => {\n const parsed = parseLoginEvent(event as MessageEvent<string>)\n void finish(parsed?.type === 'failed' ? parsed.error.message : 'ChatGPT sign-in failed.')\n })\n }, [load])\n\n useEffect(() => {\n const loginId = status?.login.active ? status.login.loginId : null\n if (loginId !== null && loginId !== undefined && eventSourceRef.current === null) watchLogin(loginId)\n }, [status?.login.active, status?.login.loginId, watchLogin])\n\n const startLogin = async (): Promise<void> => {\n setBusy('login')\n setError(null)\n setPopupBlocked(false)\n const popup = window.open('about:blank', 'dsh-chatgpt-oauth', 'popup,width=560,height=760')\n try {\n const login = await apiRef.current.startLogin()\n setAuthUrl(login.authUrl)\n if (popup === null) setPopupBlocked(true)\n else popup.location.replace(login.authUrl)\n watchLogin(login.loginId)\n await load(true)\n } catch (cause) {\n popup?.close()\n setBusy(null)\n setError(messageOf(cause))\n }\n }\n\n const cancelLogin = async (): Promise<void> => {\n const loginId = status?.login.loginId\n if (loginId === null || loginId === undefined) return\n setBusy('login')\n try {\n await apiRef.current.cancelLogin(loginId)\n eventSourceRef.current?.close()\n eventSourceRef.current = null\n setAuthUrl(null)\n await load()\n } catch (cause) {\n setError(messageOf(cause))\n } finally {\n setBusy(null)\n }\n }\n\n const refreshToken = async (): Promise<void> => run('token', async () => {\n setStatus(await apiRef.current.refresh())\n })\n\n const refreshQuota = async (): Promise<void> => run('quota', async () => {\n const quota = await apiRef.current.refreshQuota()\n setStatus((current) => current === null ? current : { ...current, quota })\n })\n\n const testConnection = async (): Promise<void> => run('test', async () => {\n const result = await apiRef.current.testConnection()\n setConnection({ latencyMs: result.latencyMs, checkedAt: result.checkedAt })\n })\n\n const logout = async (): Promise<void> => run('logout', async () => {\n await apiRef.current.logout()\n eventSourceRef.current?.close()\n eventSourceRef.current = null\n setAuthUrl(null)\n setConnection(null)\n await load()\n })\n\n const run = async (action: Exclude<BusyAction, null>, task: () => Promise<void>): Promise<void> => {\n setBusy(action)\n setError(null)\n try {\n await task()\n } catch (cause) {\n setError(messageOf(cause))\n } finally {\n setBusy(null)\n }\n }\n\n const account = status?.account\n return <section className=\"dsh-codex-page\" aria-labelledby=\"dsh-codex-title\">\n <header>\n <h2 id=\"dsh-codex-title\" className=\"dsh-codex-title\">{t('title')}</h2>\n <p className=\"dsh-codex-intro\">{t('intro')}</p>\n </header>\n\n {error !== null ? <div className=\"dsh-codex-errorbar\" role=\"alert\">\n <span>{error}</span>\n {status === null ? <Button disabled={busy !== null} onClick={() => load()}>{t('retry')}</Button> : null}\n </div> : null}\n\n {status === null && error === null ? <Skeleton label={t('loading')} /> : <>\n <Section title={t('account')}>\n <InfoRow label={status?.authenticated ? t('signedIn') : t('signedOut')} value={account?.email ?? '—'} />\n {status?.authenticated ? <>\n <InfoRow label={t('plan')} value={account?.planType ?? t('unknown')} />\n <InfoRow label={t('accountId')} value={account?.accountIdSuffix ?? '—'} />\n <InfoRow label={t('expires')} value={formatDate(account?.tokenExpiresAt)} />\n </> : null}\n <InfoRow label={t('storage')} value={t('storageValue')} />\n <p className=\"dsh-codex-notice\">{t('securityNotice')}</p>\n {status?.login.active ? <p className=\"dsh-codex-muted\" role=\"status\">{t('pending')}</p> : null}\n {popupBlocked ? <p className=\"dsh-codex-error\">{t('popupBlocked')}</p> : null}\n {authUrl !== null ? <a className=\"dsh-codex-link\" href={authUrl} target=\"_blank\" rel=\"noreferrer\">{t('continueLogin')}</a> : null}\n <div className=\"dsh-codex-actions\">\n {status?.login.active\n ? <Button disabled={busy !== null} onClick={cancelLogin}>{t('cancel')}</Button>\n : <Button primary disabled={busy !== null} onClick={startLogin}>{status?.authenticated ? t('signInAgain') : t('signIn')}</Button>}\n {status?.authenticated ? <>\n <Button disabled={busy !== null} onClick={refreshToken}>{t('refreshToken')}</Button>\n <Button disabled={busy !== null} onClick={logout}>{t('signOut')}</Button>\n </> : null}\n </div>\n </Section>\n\n <Section title={t('connection')}>\n <InfoRow label={t('provider')} value=\"Codex(ChatGPT 订阅) · codex-chatgpt\" />\n <InfoRow label={t('connectionState')} value={connection === null ? t('untested') : t('connected')} />\n {connection !== null ? <InfoRow label={t('latency')} value={`${connection.latencyMs} ms · ${formatDate(connection.checkedAt)}`} /> : null}\n <div className=\"dsh-codex-models\" aria-label={t('models')}>\n {MODELS.map((model) => <code key={model}>{model}</code>)}\n </div>\n <div className=\"dsh-codex-actions\">\n <Button disabled={!status?.authenticated || busy !== null} onClick={testConnection}>{busy === 'test' ? t('testing') : t('testConnection')}</Button>\n </div>\n </Section>\n\n <Section title={t('quota')} aside={<Button disabled={!status?.authenticated || busy !== null} onClick={refreshQuota}>{busy === 'quota' ? t('refreshing') : t('refreshQuota')}</Button>}>\n <p className=\"dsh-codex-muted\">{t('quotaIntro')}</p>\n {status?.quota.state === 'signed-out' ? <p className=\"dsh-codex-empty\">{t('quotaSignedOut')}</p> : null}\n {status?.quota.buckets.map((bucket) => <QuotaBucket key={bucket.id} bucket={bucket} t={t} />)}\n {status?.quota.state === 'empty' ? <p className=\"dsh-codex-empty\">{t('noQuota')}</p> : null}\n {status?.quota.stale ? <p className=\"dsh-codex-warning\" role=\"status\">{t('stale')}</p> : null}\n {status?.quota.error ? <p className=\"dsh-codex-error\" role=\"alert\">{status.quota.error.message}</p> : null}\n {status?.quota.fetchedAt ? <p className=\"dsh-codex-timestamp\">{t('updated')}: {formatDate(status.quota.fetchedAt)}</p> : null}\n </Section>\n </>}\n\n <span className=\"dsh-codex-sr\" aria-live=\"polite\">{busy === null ? '' : busy}</span>\n </section>\n}\n\nfunction Section({ title, aside, children }: { title: string; aside?: React.ReactNode; children: React.ReactNode }): React.JSX.Element {\n return <section className=\"dsh-codex-group\">\n <div className=\"dsh-codex-grouphead\"><h3>{title}</h3>{aside}</div>\n {children}\n </section>\n}\n\nfunction Button({ primary = false, disabled, onClick, children }: { primary?: boolean; disabled?: boolean; onClick: () => void | Promise<void>; children: React.ReactNode }): React.JSX.Element {\n return <button className={`dsh-codex-button${primary ? ' dsh-codex-button-primary' : ''}`} type=\"button\" disabled={disabled} onClick={() => void onClick()}>{children}</button>\n}\n\nfunction InfoRow({ label, value }: { label: string; value: string }): React.JSX.Element {\n return <div className=\"dsh-codex-row\"><span className=\"dsh-codex-label\">{label}</span><span className=\"dsh-codex-value\">{value}</span></div>\n}\n\nfunction QuotaBucket({ bucket, t }: { bucket: QuotaBucketDto; t: Translate }): React.JSX.Element {\n return <article className=\"dsh-codex-quota-card\">\n <div className=\"dsh-codex-quota-title\"><strong>{bucket.name}</strong>{bucket.planType ? <span>{bucket.planType}</span> : null}</div>\n {bucket.primary ? <QuotaBar label={windowLabel(bucket.primary.windowDurationMins, t)} window={bucket.primary} t={t} /> : null}\n {bucket.secondary ? <QuotaBar label={windowLabel(bucket.secondary.windowDurationMins, t)} window={bucket.secondary} t={t} /> : null}\n </article>\n}\n\nexport function QuotaBar({ label, window, t }: { label: string; window: QuotaWindowDto; t: Translate }): React.JSX.Element {\n const percent = window.usedPercent\n const level = percent >= 95 ? 'danger' : percent >= 80 ? 'warning' : 'normal'\n const remaining = Math.max(0, 100 - percent)\n return <div className=\"dsh-codex-meter-wrap\">\n <div className=\"dsh-codex-meter-label\"><span>{label}</span><strong>{formatPercent(percent)}</strong></div>\n <div className={`dsh-codex-meter dsh-codex-meter-${level}`} role=\"progressbar\" aria-label={`${label}: ${formatPercent(percent)} ${t('used')}`} aria-valuemin={0} aria-valuemax={100} aria-valuenow={percent}>\n <span style={{ width: `${percent}%` }} />\n </div>\n <div className=\"dsh-codex-meter-meta\">\n <span>{percent >= 100 ? `${t('exhausted')} · ${formatPercent(remaining)} ${t('remaining')}` : `${formatPercent(percent)} ${t('used')} · ${formatPercent(remaining)} ${t('remaining')}`}</span>\n <span>{window.resetsAt === null ? '—' : `${t('resets')}: ${formatReset(window.resetsAt)}`}</span>\n </div>\n </div>\n}\n\nfunction Skeleton({ label }: { label: string }): React.JSX.Element {\n return <div className=\"dsh-codex-skeleton\" role=\"status\" aria-label={label}><span /><span /></div>\n}\n\nexport function windowLabel(minutes: number | null, t: Translate): string {\n if (minutes === null) return t('limitWindow')\n const [value, unit]: [number, Intl.NumberFormatOptions['unit']] = minutes >= 1440 && minutes % 1440 === 0\n ? [minutes / 1440, 'day']\n : minutes >= 60 && minutes % 60 === 0\n ? [minutes / 60, 'hour']\n : [Math.round(minutes), 'minute']\n return `${new Intl.NumberFormat(undefined, { style: 'unit', unit, unitDisplay: 'long' }).format(value)} ${t('limitWindow')}`\n}\n\nfunction formatPercent(value: number): string {\n return `${new Intl.NumberFormat(undefined, { maximumFractionDigits: 1 }).format(value)}%`\n}\n\nfunction formatDate(seconds: number | undefined): string {\n if (seconds === undefined) return '—'\n return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(seconds * 1000)\n}\n\nexport function formatReset(seconds: number): string {\n const absolute = formatDate(seconds)\n const diff = seconds * 1000 - Date.now()\n const abs = Math.abs(diff)\n const [amount, unit]: [number, Intl.RelativeTimeFormatUnit] = abs >= 86_400_000\n ? [Math.round(diff / 86_400_000), 'day']\n : abs >= 3_600_000\n ? [Math.round(diff / 3_600_000), 'hour']\n : [Math.round(diff / 60_000), 'minute']\n return `${absolute} (${new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' }).format(amount, unit)})`\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","export const NS = 'dsh-chatgpt-subscription' as const\n\nexport const zh = {\n title: 'Codex 订阅',\n intro: '使用 ChatGPT 账号登录,在 DSH 中使用订阅可用的 Codex 模型。',\n account: '账号',\n signedOut: '尚未登录',\n signedIn: '已登录',\n plan: '套餐',\n accountId: '账号 ID',\n expires: '令牌到期',\n storage: '凭据存储',\n storageValue: 'Windows DPAPI(当前用户加密)',\n securityNotice: '令牌仅保存在 Host 端的 DPAPI 加密文件中,不会进入浏览器、settings.yaml 或日志。',\n signIn: '使用 ChatGPT 登录',\n signInAgain: '重新登录',\n cancel: '取消登录',\n signOut: '注销',\n refreshToken: '刷新凭据',\n pending: '请在浏览器中完成登录。',\n popupBlocked: '浏览器拦截了登录窗口,请使用下面的链接继续。',\n continueLogin: '打开 ChatGPT 登录页',\n loading: '正在读取状态…',\n connection: '连接',\n provider: 'Provider',\n connectionState: '连接状态',\n connected: '可用',\n untested: '尚未测试',\n testConnection: '测试连接',\n testing: '测试中…',\n latency: '最近延迟',\n models: '可用模型',\n quota: '用量与限额',\n quotaIntro: '数据来自 ChatGPT Codex 用量服务。页面可见时最多每 60 秒刷新一次。',\n refreshQuota: '刷新用量',\n refreshing: '刷新中…',\n noQuota: '当前套餐未返回可显示的限额窗口。',\n quotaSignedOut: '登录后可查看订阅限额。',\n stale: '显示的是上次成功获取的数据。',\n updated: '更新时间',\n primary: '主要窗口',\n secondary: '次要窗口',\n limitWindow: '额度',\n used: '已使用',\n remaining: '剩余',\n exhausted: '额度已用尽',\n resets: '重置',\n retry: '重试',\n unknown: '未知',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n title: 'Codex subscription',\n intro: 'Sign in with ChatGPT to use Codex models available to your subscription in DSH.',\n account: 'Account',\n signedOut: 'Not signed in',\n signedIn: 'Signed in',\n plan: 'Plan',\n accountId: 'Account ID',\n expires: 'Token expires',\n storage: 'Credential storage',\n storageValue: 'Windows DPAPI (current-user encrypted)',\n securityNotice: 'Tokens stay in a Host-side DPAPI-encrypted file and never enter the browser, settings.yaml, or logs.',\n signIn: 'Sign in with ChatGPT',\n signInAgain: 'Sign in again',\n cancel: 'Cancel sign-in',\n signOut: 'Sign out',\n refreshToken: 'Refresh credentials',\n pending: 'Complete sign-in in your browser.',\n popupBlocked: 'The sign-in window was blocked. Use the link below to continue.',\n continueLogin: 'Open ChatGPT sign-in',\n loading: 'Reading status…',\n connection: 'Connection',\n provider: 'Provider',\n connectionState: 'Connection status',\n connected: 'Available',\n untested: 'Not tested',\n testConnection: 'Test connection',\n testing: 'Testing…',\n latency: 'Last latency',\n models: 'Available models',\n quota: 'Usage and limits',\n quotaIntro: 'Data comes from the ChatGPT Codex usage service and refreshes at most once per minute while visible.',\n refreshQuota: 'Refresh usage',\n refreshing: 'Refreshing…',\n noQuota: 'Your plan did not return any displayable limit windows.',\n quotaSignedOut: 'Sign in to view subscription limits.',\n stale: 'Showing the last successfully fetched data.',\n updated: 'Updated',\n primary: 'Primary window',\n secondary: 'Secondary window',\n limitWindow: 'limit',\n used: 'used',\n remaining: 'remaining',\n exhausted: 'Quota exhausted',\n resets: 'Resets',\n retry: 'Retry',\n unknown: 'Unknown',\n}\n\nexport type LocaleKey = keyof typeof zh\nexport const dictionaries = { zh, en }\n","const STYLE_ID = '@eddyskywalker/dsh-chatgpt-subscription/main'\n\nconst CSS = `\n.dsh-codex-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}\n.dsh-codex-page *{box-sizing:border-box}\n.dsh-codex-title{font-size:15px;font-weight:650;line-height:1.4;margin:0 0 5px}\n.dsh-codex-intro,.dsh-codex-muted{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1.55;margin:0}\n.dsh-codex-group{border-top:1px solid var(--dsw-alias-border-l2);min-width:0}\n.dsh-codex-grouphead{align-items:center;display:flex;gap:12px;justify-content:space-between;min-height:48px}\n.dsh-codex-grouphead h3{font-size:14px;font-weight:650;margin:0}\n.dsh-codex-row{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;gap:20px;justify-content:space-between;min-height:44px;padding:8px 0}\n.dsh-codex-label{color:var(--dsw-alias-label-secondary);font-size:13px;flex:0 0 auto}\n.dsh-codex-value{font-size:13px;min-width:0;overflow-wrap:anywhere;text-align:right}\n.dsh-codex-actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;padding-top:12px}\n.dsh-codex-button{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:13px;line-height:1;padding:8px 13px;white-space:nowrap}\n.dsh-codex-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.dsh-codex-button:focus-visible,.dsh-codex-link:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}\n.dsh-codex-button:disabled{cursor:default;opacity:.5}\n.dsh-codex-button-primary{background:var(--dsw-alias-button-info-fill,#397ee8);border-color:transparent;color:var(--dsw-alias-button-info-label,#fff)}\n.dsh-codex-notice{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55;margin:12px 0 0;padding:10px 12px}\n.dsh-codex-error,.dsh-codex-warning{font-size:12px;line-height:1.5;margin:8px 0 0}\n.dsh-codex-error{color:var(--dsw-alias-label-danger,#d94b4b)}\n.dsh-codex-warning{color:var(--dsw-alias-label-warning,#c77a18)}\n.dsh-codex-errorbar{align-items:center;background:color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 9%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 28%,transparent);border-radius:7px;color:var(--dsw-alias-label-danger,#d94b4b);display:flex;font-size:13px;gap:12px;justify-content:space-between;padding:10px 12px}\n.dsh-codex-link{color:var(--dsw-alias-label-link,#3278d4);display:inline-block;font-size:13px;margin-top:8px}\n.dsh-codex-models{display:flex;flex-wrap:wrap;gap:6px;padding-top:12px}\n.dsh-codex-models code{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:5px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:4px 6px}\n.dsh-codex-quota-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;margin-top:12px;padding:12px}\n.dsh-codex-quota-title{align-items:center;display:flex;font-size:13px;gap:8px;justify-content:space-between}\n.dsh-codex-quota-title span{color:var(--dsw-alias-label-tertiary);font-size:11px;text-transform:uppercase}\n.dsh-codex-meter-wrap{margin-top:13px}\n.dsh-codex-meter-label,.dsh-codex-meter-meta{display:flex;gap:10px;justify-content:space-between}\n.dsh-codex-meter-label{font-size:12px;margin-bottom:6px}\n.dsh-codex-meter-meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.45;margin-top:6px}\n.dsh-codex-meter{background:var(--dsw-alias-bg-layer-1,rgba(127,127,127,.15));border-radius:999px;height:7px;overflow:hidden;width:100%}\n.dsh-codex-meter>span{background:var(--dsw-alias-button-info-fill,#397ee8);border-radius:inherit;display:block;height:100%;max-width:100%;min-width:0;transition:width .25s ease}\n.dsh-codex-meter-warning>span{background:var(--dsw-alias-label-warning,#d58a24)}\n.dsh-codex-meter-danger>span{background:var(--dsw-alias-label-danger,#d94b4b)}\n.dsh-codex-empty{border:1px dashed var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-tertiary);font-size:12px;margin:12px 0 0;padding:16px;text-align:center}\n.dsh-codex-timestamp{color:var(--dsw-alias-label-tertiary);font-size:11px;margin:10px 0 0;text-align:right}\n.dsh-codex-skeleton{display:grid;gap:9px;padding-top:10px}\n.dsh-codex-skeleton span{animation:dsh-codex-pulse 1.4s ease-in-out infinite;background:var(--dsw-alias-bg-layer-2);border-radius:5px;height:42px}\n.dsh-codex-skeleton span:nth-child(2){animation-delay:.12s}.dsh-codex-skeleton span:nth-child(3){animation-delay:.24s}\n.dsh-codex-sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0 0 0 0);white-space:nowrap}\n@keyframes dsh-codex-pulse{0%,100%{opacity:.55}50%{opacity:1}}\n@media(max-width:560px){.dsh-codex-row{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}}\n@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span{transition:none}.dsh-codex-skeleton span{animation:none}}\n`\n\nexport function installStyles(): () => void {\n if (document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`) !== null) return () => undefined\n const element = document.createElement('style')\n element.dataset.plugin = '@eddyskywalker/dsh-chatgpt-subscription'\n element.dataset.pluginCss = STYLE_ID\n element.textContent = CSS\n document.head.appendChild(element)\n return () => element.remove()\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { CodexSubscriptionSection } from './CodexSubscriptionSection.tsx'\nimport { dictionaries, NS, type LocaleKey } from './locales.ts'\nimport { installStyles } from './styles.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'dsh-chatgpt-subscription': LocaleKey\n }\n}\n\nexport const inject = ['slots', 'locale']\n\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, dictionaries), 'dsh-chatgpt-subscription: dictionaries')\n ctx.effect(() => installStyles(), 'dsh-chatgpt-subscription: styles')\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'codex-subscription',\n order: 45,\n label: 'Codex 订阅',\n locale: NS,\n }, CodexSubscriptionSection))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../src/compat.ts","../src/client/api.ts","../src/client/CodexSubscriptionSection.tsx","../src/client/locales.ts","../src/client/process-folding.ts","../src/client/styles.ts","../src/client/index.tsx"],"sourcesContent":["/**\n * Compatibility constants for the ChatGPT-backed Codex flow. The backend and\n * OAuth parameters are not a public third-party API contract, so every such\n * value is isolated here for review and rollback.\n */\nexport const CHATGPT_OAUTH_ISSUER = 'https://auth.openai.com' as const\nexport const CHATGPT_OAUTH_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann' as const\nexport const OAUTH_CALLBACK_HOST = 'localhost' as const\nexport const OAUTH_CALLBACK_PORT = 1455 as const\nexport const OAUTH_CALLBACK_PATH = '/auth/callback' as const\nexport const OAUTH_REDIRECT_URI = `http://${OAUTH_CALLBACK_HOST}:${OAUTH_CALLBACK_PORT}${OAUTH_CALLBACK_PATH}` as const\nexport const OAUTH_SCOPE = 'openid profile email offline_access' as const\nexport const OAUTH_ORIGINATOR = 'opencode' as const\nexport const OAUTH_LOGIN_TIMEOUT_MS = 5 * 60_000\nexport const TOKEN_REFRESH_MARGIN_MS = 60_000\nexport const ROUTE_PREFIX = '/api/dsh-chatgpt-subscription' as const\nexport const PLUGIN_VERSION = '0.1.0-alpha.0' as const\n\nexport const CODEX_API_BASE = 'https://chatgpt.com/backend-api/codex' as const\nexport const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses` as const\nexport const CODEX_USAGE_URL = 'https://chatgpt.com/backend-api/wham/usage' as const\nexport const CODEX_ORIGINATOR = 'opencode' as const\nexport const QUOTA_CACHE_MS = 60_000\nexport const QUOTA_MIN_UPSTREAM_INTERVAL_MS = 15_000\n\nexport const OAUTH_AUTHORIZE_URL = `${CHATGPT_OAUTH_ISSUER}/oauth/authorize` as const\nexport const OAUTH_TOKEN_URL = `${CHATGPT_OAUTH_ISSUER}/oauth/token` as const\n","import { ROUTE_PREFIX } from '../compat.ts'\nimport type {\n ApiEnvelope,\n LoginEventDto,\n LoginStartDto,\n PluginStatusDto,\n QuotaStatusDto,\n ConnectionTestDto,\n} from '../shared/contracts.ts'\n\nexport class SubscriptionApi {\n status(): Promise<PluginStatusDto> {\n return request<PluginStatusDto>(`${ROUTE_PREFIX}/status`)\n }\n\n startLogin(): Promise<LoginStartDto> {\n return post<LoginStartDto>(`${ROUTE_PREFIX}/login/start`, {})\n }\n\n cancelLogin(loginId: string): Promise<{ cancelled: boolean }> {\n return post(`${ROUTE_PREFIX}/login/cancel`, { loginId })\n }\n\n logout(): Promise<{ authenticated: false }> {\n return post(`${ROUTE_PREFIX}/logout`, {})\n }\n\n refresh(): Promise<PluginStatusDto> {\n return post(`${ROUTE_PREFIX}/token/refresh`, {})\n }\n\n refreshQuota(): Promise<QuotaStatusDto> {\n return post(`${ROUTE_PREFIX}/quota/refresh`, {})\n }\n\n testConnection(): Promise<ConnectionTestDto> {\n return post(`${ROUTE_PREFIX}/connection/test`, {})\n }\n\n events(loginId: string): EventSource {\n return new EventSource(`${ROUTE_PREFIX}/login/events?loginId=${encodeURIComponent(loginId)}`)\n }\n}\n\nasync function post<T>(url: string, body: Record<string, unknown>): Promise<T> {\n return request<T>(url, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n })\n}\n\nasync function request<T>(url: string, init?: RequestInit): Promise<T> {\n const response = await fetch(url, { ...init, credentials: 'same-origin' })\n const envelope = await response.json() as ApiEnvelope<T>\n if (!response.ok || !envelope.ok) {\n throw new Error(envelope.ok ? `Request failed (${response.status})` : envelope.error.message)\n }\n return envelope.value\n}\n\nexport function parseLoginEvent(event: MessageEvent<string>): LoginEventDto | null {\n try {\n const value = JSON.parse(event.data) as LoginEventDto\n return typeof value === 'object' && value !== null && typeof value.type === 'string' ? value : null\n } catch {\n return null\n }\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\nimport type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { PluginStatusDto, QuotaBucketDto, QuotaWindowDto } from '../shared/contracts.ts'\nimport { SubscriptionApi, parseLoginEvent } from './api.ts'\nimport { NS } from './locales.ts'\n\ntype Props = PropsRuntime<'settings.section'> & PropsLocale<typeof NS>\ntype BusyAction = 'login' | 'token' | 'quota' | 'test' | 'logout' | null\ntype Translate = Props['t']\n\nconst MODELS = ['gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.2']\n\nexport function CodexSubscriptionSection({ t }: Props): React.JSX.Element {\n const apiRef = useRef(new SubscriptionApi())\n const eventSourceRef = useRef<EventSource | null>(null)\n const [status, setStatus] = useState<PluginStatusDto | null>(null)\n const [busy, setBusy] = useState<BusyAction>(null)\n const [error, setError] = useState<string | null>(null)\n const [authUrl, setAuthUrl] = useState<string | null>(null)\n const [popupBlocked, setPopupBlocked] = useState(false)\n const [connection, setConnection] = useState<{ latencyMs: number; checkedAt: number } | null>(null)\n\n const load = useCallback(async (quiet = false) => {\n if (!quiet) setError(null)\n try {\n const next = await apiRef.current.status()\n setStatus(next)\n if (next.error !== undefined) setError(next.error.message)\n } catch (cause) {\n if (!quiet) setError(messageOf(cause))\n }\n }, [])\n\n useEffect(() => {\n void load()\n const refreshWhenVisible = (): void => {\n if (document.visibilityState === 'visible') void load(true)\n }\n document.addEventListener('visibilitychange', refreshWhenVisible)\n const timer = window.setInterval(refreshWhenVisible, 60_000)\n return () => {\n window.clearInterval(timer)\n document.removeEventListener('visibilitychange', refreshWhenVisible)\n eventSourceRef.current?.close()\n }\n }, [load])\n\n const watchLogin = useCallback((loginId: string) => {\n eventSourceRef.current?.close()\n const source = apiRef.current.events(loginId)\n eventSourceRef.current = source\n const finish = async (message?: string): Promise<void> => {\n source.close()\n eventSourceRef.current = null\n setBusy(null)\n setAuthUrl(null)\n if (message !== undefined) setError(message)\n // Preserve the terminal OAuth error while refreshing the account DTO.\n await load(true)\n }\n source.addEventListener('completed', (event) => {\n const parsed = parseLoginEvent(event as MessageEvent<string>)\n if (parsed?.type === 'completed') void finish()\n })\n source.addEventListener('cancelled', () => void finish())\n source.addEventListener('failed', (event) => {\n const parsed = parseLoginEvent(event as MessageEvent<string>)\n void finish(parsed?.type === 'failed' ? parsed.error.message : 'ChatGPT sign-in failed.')\n })\n }, [load])\n\n useEffect(() => {\n const loginId = status?.login.active ? status.login.loginId : null\n if (loginId !== null && loginId !== undefined && eventSourceRef.current === null) watchLogin(loginId)\n }, [status?.login.active, status?.login.loginId, watchLogin])\n\n const startLogin = async (): Promise<void> => {\n setBusy('login')\n setError(null)\n setPopupBlocked(false)\n const popup = window.open('about:blank', 'dsh-chatgpt-oauth', 'popup,width=560,height=760')\n try {\n const login = await apiRef.current.startLogin()\n setAuthUrl(login.authUrl)\n if (popup === null) setPopupBlocked(true)\n else popup.location.replace(login.authUrl)\n watchLogin(login.loginId)\n await load(true)\n } catch (cause) {\n popup?.close()\n setBusy(null)\n setError(messageOf(cause))\n }\n }\n\n const cancelLogin = async (): Promise<void> => {\n const loginId = status?.login.loginId\n if (loginId === null || loginId === undefined) return\n setBusy('login')\n try {\n await apiRef.current.cancelLogin(loginId)\n eventSourceRef.current?.close()\n eventSourceRef.current = null\n setAuthUrl(null)\n await load()\n } catch (cause) {\n setError(messageOf(cause))\n } finally {\n setBusy(null)\n }\n }\n\n const refreshToken = async (): Promise<void> => run('token', async () => {\n setStatus(await apiRef.current.refresh())\n })\n\n const refreshQuota = async (): Promise<void> => run('quota', async () => {\n const quota = await apiRef.current.refreshQuota()\n setStatus((current) => current === null ? current : { ...current, quota })\n })\n\n const testConnection = async (): Promise<void> => run('test', async () => {\n const result = await apiRef.current.testConnection()\n setConnection({ latencyMs: result.latencyMs, checkedAt: result.checkedAt })\n })\n\n const logout = async (): Promise<void> => run('logout', async () => {\n await apiRef.current.logout()\n eventSourceRef.current?.close()\n eventSourceRef.current = null\n setAuthUrl(null)\n setConnection(null)\n await load()\n })\n\n const run = async (action: Exclude<BusyAction, null>, task: () => Promise<void>): Promise<void> => {\n setBusy(action)\n setError(null)\n try {\n await task()\n } catch (cause) {\n setError(messageOf(cause))\n } finally {\n setBusy(null)\n }\n }\n\n const account = status?.account\n return <section className=\"dsh-codex-page\" aria-labelledby=\"dsh-codex-title\">\n <header>\n <h2 id=\"dsh-codex-title\" className=\"dsh-codex-title\">{t('title')}</h2>\n <p className=\"dsh-codex-intro\">{t('intro')}</p>\n </header>\n\n {error !== null ? <div className=\"dsh-codex-errorbar\" role=\"alert\">\n <span>{error}</span>\n {status === null ? <Button disabled={busy !== null} onClick={() => load()}>{t('retry')}</Button> : null}\n </div> : null}\n\n {status === null && error === null ? <Skeleton label={t('loading')} /> : <>\n <Section title={t('account')}>\n <InfoRow label={status?.authenticated ? t('signedIn') : t('signedOut')} value={account?.email ?? '—'} />\n {status?.authenticated ? <>\n <InfoRow label={t('plan')} value={account?.planType ?? t('unknown')} />\n <InfoRow label={t('accountId')} value={account?.accountIdSuffix ?? '—'} />\n <InfoRow label={t('expires')} value={formatDate(account?.tokenExpiresAt)} />\n </> : null}\n <InfoRow label={t('storage')} value={t('storageValue')} />\n <p className=\"dsh-codex-notice\">{t('securityNotice')}</p>\n {status?.login.active ? <p className=\"dsh-codex-muted\" role=\"status\">{t('pending')}</p> : null}\n {popupBlocked ? <p className=\"dsh-codex-error\">{t('popupBlocked')}</p> : null}\n {authUrl !== null ? <a className=\"dsh-codex-link\" href={authUrl} target=\"_blank\" rel=\"noreferrer\">{t('continueLogin')}</a> : null}\n <div className=\"dsh-codex-actions\">\n {status?.login.active\n ? <Button disabled={busy !== null} onClick={cancelLogin}>{t('cancel')}</Button>\n : <Button primary disabled={busy !== null} onClick={startLogin}>{status?.authenticated ? t('signInAgain') : t('signIn')}</Button>}\n {status?.authenticated ? <>\n <Button disabled={busy !== null} onClick={refreshToken}>{t('refreshToken')}</Button>\n <Button disabled={busy !== null} onClick={logout}>{t('signOut')}</Button>\n </> : null}\n </div>\n </Section>\n\n <Section title={t('connection')}>\n <InfoRow label={t('provider')} value=\"Codex(ChatGPT 订阅) · codex-chatgpt\" />\n <InfoRow label={t('connectionState')} value={connection === null ? t('untested') : t('connected')} />\n {connection !== null ? <InfoRow label={t('latency')} value={`${connection.latencyMs} ms · ${formatDate(connection.checkedAt)}`} /> : null}\n <div className=\"dsh-codex-models\" aria-label={t('models')}>\n {MODELS.map((model) => <code key={model}>{model}</code>)}\n </div>\n <div className=\"dsh-codex-actions\">\n <Button disabled={!status?.authenticated || busy !== null} onClick={testConnection}>{busy === 'test' ? t('testing') : t('testConnection')}</Button>\n </div>\n </Section>\n\n <Section title={t('quota')} aside={<Button disabled={!status?.authenticated || busy !== null} onClick={refreshQuota}>{busy === 'quota' ? t('refreshing') : t('refreshQuota')}</Button>}>\n <p className=\"dsh-codex-muted\">{t('quotaIntro')}</p>\n {status?.quota.state === 'signed-out' ? <p className=\"dsh-codex-empty\">{t('quotaSignedOut')}</p> : null}\n {status?.quota.buckets.map((bucket) => <QuotaBucket key={bucket.id} bucket={bucket} t={t} />)}\n {status?.quota.state === 'empty' ? <p className=\"dsh-codex-empty\">{t('noQuota')}</p> : null}\n {status?.quota.stale ? <p className=\"dsh-codex-warning\" role=\"status\">{t('stale')}</p> : null}\n {status?.quota.error ? <p className=\"dsh-codex-error\" role=\"alert\">{status.quota.error.message}</p> : null}\n {status?.quota.fetchedAt ? <p className=\"dsh-codex-timestamp\">{t('updated')}: {formatDate(status.quota.fetchedAt)}</p> : null}\n </Section>\n </>}\n\n <span className=\"dsh-codex-sr\" aria-live=\"polite\">{busy === null ? '' : busy}</span>\n </section>\n}\n\nfunction Section({ title, aside, children }: { title: string; aside?: React.ReactNode; children: React.ReactNode }): React.JSX.Element {\n return <section className=\"dsh-codex-group\">\n <div className=\"dsh-codex-grouphead\"><h3>{title}</h3>{aside}</div>\n {children}\n </section>\n}\n\nfunction Button({ primary = false, disabled, onClick, children }: { primary?: boolean; disabled?: boolean; onClick: () => void | Promise<void>; children: React.ReactNode }): React.JSX.Element {\n return <button className={`dsh-codex-button${primary ? ' dsh-codex-button-primary' : ''}`} type=\"button\" disabled={disabled} onClick={() => void onClick()}>{children}</button>\n}\n\nfunction InfoRow({ label, value }: { label: string; value: string }): React.JSX.Element {\n return <div className=\"dsh-codex-row\"><span className=\"dsh-codex-label\">{label}</span><span className=\"dsh-codex-value\">{value}</span></div>\n}\n\nfunction QuotaBucket({ bucket, t }: { bucket: QuotaBucketDto; t: Translate }): React.JSX.Element {\n return <article className=\"dsh-codex-quota-card\">\n <div className=\"dsh-codex-quota-title\"><strong>{bucket.name}</strong>{bucket.planType ? <span>{bucket.planType}</span> : null}</div>\n {bucket.primary ? <QuotaBar label={windowLabel(bucket.primary.windowDurationMins, t)} window={bucket.primary} t={t} /> : null}\n {bucket.secondary ? <QuotaBar label={windowLabel(bucket.secondary.windowDurationMins, t)} window={bucket.secondary} t={t} /> : null}\n </article>\n}\n\nexport function QuotaBar({ label, window, t }: { label: string; window: QuotaWindowDto; t: Translate }): React.JSX.Element {\n const percent = window.usedPercent\n const level = percent >= 95 ? 'danger' : percent >= 80 ? 'warning' : 'normal'\n const remaining = Math.max(0, 100 - percent)\n return <div className=\"dsh-codex-meter-wrap\">\n <div className=\"dsh-codex-meter-label\"><span>{label}</span><strong>{formatPercent(percent)}</strong></div>\n <div className={`dsh-codex-meter dsh-codex-meter-${level}`} role=\"progressbar\" aria-label={`${label}: ${formatPercent(percent)} ${t('used')}`} aria-valuemin={0} aria-valuemax={100} aria-valuenow={percent}>\n <span style={{ width: `${percent}%` }} />\n </div>\n <div className=\"dsh-codex-meter-meta\">\n <span>{percent >= 100 ? `${t('exhausted')} · ${formatPercent(remaining)} ${t('remaining')}` : `${formatPercent(percent)} ${t('used')} · ${formatPercent(remaining)} ${t('remaining')}`}</span>\n <span>{window.resetsAt === null ? '—' : `${t('resets')}: ${formatReset(window.resetsAt)}`}</span>\n </div>\n </div>\n}\n\nfunction Skeleton({ label }: { label: string }): React.JSX.Element {\n return <div className=\"dsh-codex-skeleton\" role=\"status\" aria-label={label}><span /><span /></div>\n}\n\nexport function windowLabel(minutes: number | null, t: Translate): string {\n if (minutes === null) return t('limitWindow')\n const [value, unit]: [number, Intl.NumberFormatOptions['unit']] = minutes >= 1440 && minutes % 1440 === 0\n ? [minutes / 1440, 'day']\n : minutes >= 60 && minutes % 60 === 0\n ? [minutes / 60, 'hour']\n : [Math.round(minutes), 'minute']\n return `${new Intl.NumberFormat(undefined, { style: 'unit', unit, unitDisplay: 'long' }).format(value)} ${t('limitWindow')}`\n}\n\nfunction formatPercent(value: number): string {\n return `${new Intl.NumberFormat(undefined, { maximumFractionDigits: 1 }).format(value)}%`\n}\n\nfunction formatDate(seconds: number | undefined): string {\n if (seconds === undefined) return '—'\n return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(seconds * 1000)\n}\n\nexport function formatReset(seconds: number): string {\n const absolute = formatDate(seconds)\n const diff = seconds * 1000 - Date.now()\n const abs = Math.abs(diff)\n const [amount, unit]: [number, Intl.RelativeTimeFormatUnit] = abs >= 86_400_000\n ? [Math.round(diff / 86_400_000), 'day']\n : abs >= 3_600_000\n ? [Math.round(diff / 3_600_000), 'hour']\n : [Math.round(diff / 60_000), 'minute']\n return `${absolute} (${new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' }).format(amount, unit)})`\n}\n\nfunction messageOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n","export const NS = 'dsh-chatgpt-subscription' as const\n\nexport const zh = {\n title: 'Codex 订阅',\n intro: '使用 ChatGPT 账号登录,在 DSH 中使用订阅可用的 Codex 模型。',\n account: '账号',\n signedOut: '尚未登录',\n signedIn: '已登录',\n plan: '套餐',\n accountId: '账号 ID',\n expires: '令牌到期',\n storage: '凭据存储',\n storageValue: 'Windows DPAPI(当前用户加密)',\n securityNotice: '令牌仅保存在 Host 端的 DPAPI 加密文件中,不会进入浏览器、settings.yaml 或日志。',\n signIn: '使用 ChatGPT 登录',\n signInAgain: '重新登录',\n cancel: '取消登录',\n signOut: '注销',\n refreshToken: '刷新凭据',\n pending: '请在浏览器中完成登录。',\n popupBlocked: '浏览器拦截了登录窗口,请使用下面的链接继续。',\n continueLogin: '打开 ChatGPT 登录页',\n loading: '正在读取状态…',\n connection: '连接',\n provider: 'Provider',\n connectionState: '连接状态',\n connected: '可用',\n untested: '尚未测试',\n testConnection: '测试连接',\n testing: '测试中…',\n latency: '最近延迟',\n models: '可用模型',\n quota: '用量与限额',\n quotaIntro: '数据来自 ChatGPT Codex 用量服务。页面可见时最多每 60 秒刷新一次。',\n refreshQuota: '刷新用量',\n refreshing: '刷新中…',\n noQuota: '当前套餐未返回可显示的限额窗口。',\n quotaSignedOut: '登录后可查看订阅限额。',\n stale: '显示的是上次成功获取的数据。',\n updated: '更新时间',\n primary: '主要窗口',\n secondary: '次要窗口',\n limitWindow: '额度',\n used: '已使用',\n remaining: '剩余',\n exhausted: '额度已用尽',\n resets: '重置',\n retry: '重试',\n unknown: '未知',\n} as const\n\nexport const en: Record<keyof typeof zh, string> = {\n title: 'Codex subscription',\n intro: 'Sign in with ChatGPT to use Codex models available to your subscription in DSH.',\n account: 'Account',\n signedOut: 'Not signed in',\n signedIn: 'Signed in',\n plan: 'Plan',\n accountId: 'Account ID',\n expires: 'Token expires',\n storage: 'Credential storage',\n storageValue: 'Windows DPAPI (current-user encrypted)',\n securityNotice: 'Tokens stay in a Host-side DPAPI-encrypted file and never enter the browser, settings.yaml, or logs.',\n signIn: 'Sign in with ChatGPT',\n signInAgain: 'Sign in again',\n cancel: 'Cancel sign-in',\n signOut: 'Sign out',\n refreshToken: 'Refresh credentials',\n pending: 'Complete sign-in in your browser.',\n popupBlocked: 'The sign-in window was blocked. Use the link below to continue.',\n continueLogin: 'Open ChatGPT sign-in',\n loading: 'Reading status…',\n connection: 'Connection',\n provider: 'Provider',\n connectionState: 'Connection status',\n connected: 'Available',\n untested: 'Not tested',\n testConnection: 'Test connection',\n testing: 'Testing…',\n latency: 'Last latency',\n models: 'Available models',\n quota: 'Usage and limits',\n quotaIntro: 'Data comes from the ChatGPT Codex usage service and refreshes at most once per minute while visible.',\n refreshQuota: 'Refresh usage',\n refreshing: 'Refreshing…',\n noQuota: 'Your plan did not return any displayable limit windows.',\n quotaSignedOut: 'Sign in to view subscription limits.',\n stale: 'Showing the last successfully fetched data.',\n updated: 'Updated',\n primary: 'Primary window',\n secondary: 'Secondary window',\n limitWindow: 'limit',\n used: 'used',\n remaining: 'remaining',\n exhausted: 'Quota exhausted',\n resets: 'Resets',\n retry: 'Retry',\n unknown: 'Unknown',\n}\n\nexport type LocaleKey = keyof typeof zh\nexport const dictionaries = { zh, en }\n","const ROW_CLASS = 'dsh-codex-process-row'\nconst GROUP_HEAD_CLASS = 'dsh-codex-process-group-head'\nconst GROUP_COLLAPSED_CLASS = 'dsh-codex-process-group-collapsed'\nconst GROUP_HIDDEN_CLASS = 'dsh-codex-process-group-hidden'\nconst USER_TOGGLED_ATTR = 'data-dsh-codex-process-user-toggled'\nconst TITLE_ATTR = 'data-dsh-codex-process-title'\nconst TITLE = 'Click to expand or collapse process details'\nconst DEFAULT_AUTO_COLLAPSE_MS = 2500\nconst MAX_PROCESS_LABELS_PER_ROW = 3\nconst MAX_SCAN_ROOTS_PER_FRAME = 80\nconst MAX_TEXT_SAMPLE = 20_000\nconst PROCESS_CANDIDATE_SELECTOR = 'article,section,li,div,p,h1,h2,h3,h4,h5,h6,[role=\"listitem\"]'\nconst PROCESS_PREFIX_PATTERN = '(?:上下文注入|Think|Search|Code|代码|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Web(?:\\\\s+Search)?|Tool|工具|思考)'\nconst COMMAND_PATTERN = /(?:Code|代码|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Tool|工具)/i\nconst SEARCH_PATTERN = /(?:Search|Web\\s+Search|搜索)/i\nconst PROCESS_PREFIX_RE = new RegExp(`^\\\\s*(?:[•●◦▪▫·#-]\\\\s*)?${PROCESS_PREFIX_PATTERN}\\\\s*(?:[·::-]|$)`, 'i')\nconst PROCESS_LINE_RE = new RegExp(`(?:^|\\\\n)\\\\s*(?:[•●◦▪▫·#-]\\\\s*)?${PROCESS_PREFIX_PATTERN}\\\\s*(?:[·::-]|$)`, 'gi')\n\nexport interface ProcessFoldingOptions {\n autoCollapseMs?: number\n}\n\ninterface GroupState {\n rows: HTMLElement[]\n click: (event: MouseEvent) => void\n keydown: (event: KeyboardEvent) => void\n timer: ReturnType<typeof setTimeout> | null\n}\n\ninterface PreviousGroupState {\n collapsed: boolean\n userToggled: boolean\n}\n\nexport function installProcessFolding(options: ProcessFoldingOptions = {}): () => void {\n if (typeof document === 'undefined') return () => undefined\n if (document.body === null) {\n let dispose: () => void = () => undefined\n let started = false\n const start = () => {\n if (started) return\n started = true\n dispose = installProcessFolding(options)\n }\n document.addEventListener('DOMContentLoaded', start, { once: true })\n return () => {\n document.removeEventListener('DOMContentLoaded', start)\n dispose()\n }\n }\n\n const autoCollapseMs = options.autoCollapseMs ?? DEFAULT_AUTO_COLLAPSE_MS\n const groups = new Map<HTMLElement, GroupState>()\n const pending = new Set<Element>()\n let frame: number | null = null\n\n const scheduleFlush = () => {\n if (frame !== null) return\n frame = requestAnimationFrame(() => {\n frame = null\n flush()\n })\n }\n\n const queue = (element: Element | null) => {\n if (element === null || !element.isConnected) return\n pending.add(element)\n scheduleFlush()\n }\n\n const scheduleAutoCollapse = (head: HTMLElement) => {\n const state = groups.get(head)\n if (state === undefined || head.hasAttribute(USER_TOGGLED_ATTR)) return\n if (state.timer !== null) clearTimeout(state.timer)\n state.timer = setTimeout(() => {\n state.timer = null\n if (head.isConnected && !head.hasAttribute(USER_TOGGLED_ATTR)) setGroupCollapsed(head, true)\n }, autoCollapseMs)\n }\n\n const syncGroup = (rows: HTMLElement[], previous: PreviousGroupState | undefined) => {\n const head = rows[0]\n const title = titleForProcessRows(rows)\n const click = (event: MouseEvent) => {\n if (isInteractiveTarget(event.target)) return\n markUserToggled(head)\n setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS))\n }\n const keydown = (event: KeyboardEvent) => {\n if (event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n markUserToggled(head)\n setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS))\n }\n\n groups.set(head, { rows, click, keydown, timer: null })\n for (const row of rows) row.classList.add(ROW_CLASS)\n head.classList.add(GROUP_HEAD_CLASS)\n if (!head.hasAttribute('tabindex')) head.tabIndex = 0\n head.setAttribute('aria-expanded', String(!(previous?.collapsed ?? false)))\n head.setAttribute(TITLE_ATTR, title)\n head.title ||= TITLE\n if (previous?.userToggled === true) head.setAttribute(USER_TOGGLED_ATTR, 'true')\n head.addEventListener('click', click)\n head.addEventListener('keydown', keydown)\n setGroupCollapsed(head, previous?.collapsed ?? false)\n scheduleAutoCollapse(head)\n }\n\n const rebuildParentGroups = (parent: Element) => {\n const previous = new Map<HTMLElement, PreviousGroupState>()\n for (const [head, state] of groups) {\n if (head.parentElement !== parent) continue\n previous.set(head, {\n collapsed: head.classList.contains(GROUP_COLLAPSED_CLASS),\n userToggled: head.hasAttribute(USER_TOGGLED_ATTR),\n })\n cleanupGroup(head, state)\n groups.delete(head)\n }\n\n let rows: HTMLElement[] = []\n const flushRows = () => {\n if (rows.length > 0) syncGroup(rows, previous.get(rows[0]))\n rows = []\n }\n\n for (const child of Array.from(parent.children)) {\n if (child instanceof HTMLElement && isProcessRow(child)) {\n rows.push(child)\n } else {\n flushRows()\n }\n }\n flushRows()\n }\n\n const flush = () => {\n const parents = new Set<Element>()\n let scanned = 0\n for (const root of Array.from(pending)) {\n pending.delete(root)\n if (!root.isConnected) continue\n for (const row of findProcessRows(root)) {\n if (row.parentElement !== null) parents.add(row.parentElement)\n }\n const grouped = nearestGroupHead(root)\n if (grouped !== null && grouped.parentElement !== null) parents.add(grouped.parentElement)\n scanned++\n if (scanned >= MAX_SCAN_ROOTS_PER_FRAME && pending.size > 0) {\n scheduleFlush()\n break\n }\n }\n for (const parent of parents) rebuildParentGroups(parent)\n }\n\n const observer = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type === 'characterData') {\n queue(nodeElement(mutation.target)?.closest(PROCESS_CANDIDATE_SELECTOR) ?? nodeElement(mutation.target))\n continue\n }\n for (const node of mutation.addedNodes) queue(nodeElement(node))\n }\n })\n observer.observe(document.body, { childList: true, characterData: true, subtree: true })\n queue(document.body)\n\n return () => {\n observer.disconnect()\n if (frame !== null) cancelAnimationFrame(frame)\n pending.clear()\n for (const [head, state] of groups) cleanupGroup(head, state)\n groups.clear()\n }\n}\n\nfunction cleanupGroup(head: HTMLElement, state: GroupState): void {\n if (state.timer !== null) clearTimeout(state.timer)\n head.removeEventListener('click', state.click)\n head.removeEventListener('keydown', state.keydown)\n for (const row of state.rows) row.classList.remove(ROW_CLASS, GROUP_HIDDEN_CLASS)\n head.classList.remove(GROUP_HEAD_CLASS, GROUP_COLLAPSED_CLASS)\n head.removeAttribute('aria-expanded')\n head.removeAttribute(USER_TOGGLED_ATTR)\n head.removeAttribute(TITLE_ATTR)\n if (head.title === TITLE) head.removeAttribute('title')\n}\n\nfunction findProcessRows(root: Element): HTMLElement[] {\n const rows: HTMLElement[] = []\n if (root instanceof HTMLElement && isProcessRow(root)) rows.push(root)\n for (const element of root.querySelectorAll(PROCESS_CANDIDATE_SELECTOR)) {\n if (element instanceof HTMLElement && isProcessRow(element)) rows.push(element)\n }\n return rows\n}\n\nfunction isProcessRow(element: HTMLElement): boolean {\n if (element.closest('.dsh-codex-page') !== null || shouldIgnore(element)) return false\n const raw = (element.textContent ?? '').slice(0, MAX_TEXT_SAMPLE)\n const normalized = raw.replace(/\\s+/g, ' ').trim()\n if (!PROCESS_PREFIX_RE.test(normalized)) return false\n const stats = processTextStats(raw)\n if (stats.processLabels === 0 || stats.processLabels > MAX_PROCESS_LABELS_PER_ROW) return false\n return !(element.children.length > 0 && stats.hasNonProcessLine)\n}\n\nfunction processTextStats(text: string): { processLabels: number; hasNonProcessLine: boolean } {\n PROCESS_LINE_RE.lastIndex = 0\n let processLabels = 0\n while (PROCESS_LINE_RE.exec(text) !== null) processLabels++\n const hasNonProcessLine = text.split(/\\r?\\n/)\n .map((line) => line.replace(/\\s+/g, ' ').trim())\n .some((line) => line !== '' && !PROCESS_PREFIX_RE.test(line))\n return { processLabels, hasNonProcessLine }\n}\n\nfunction setGroupCollapsed(head: HTMLElement, collapsed: boolean): void {\n const state = findCurrentGroupState(head)\n if (state === null) return\n head.classList.toggle(GROUP_COLLAPSED_CLASS, collapsed)\n head.setAttribute('aria-expanded', String(!collapsed))\n for (const row of state.rows.slice(1)) row.classList.toggle(GROUP_HIDDEN_CLASS, collapsed)\n}\n\nfunction findCurrentGroupState(head: HTMLElement): { rows: HTMLElement[] } | null {\n const rows: HTMLElement[] = [head]\n let sibling = head.nextElementSibling\n while (sibling instanceof HTMLElement && isProcessRow(sibling)) {\n rows.push(sibling)\n sibling = sibling.nextElementSibling\n }\n return rows.length > 0 ? { rows } : null\n}\n\nfunction markUserToggled(head: HTMLElement): void {\n head.setAttribute(USER_TOGGLED_ATTR, 'true')\n}\n\nfunction nearestGroupHead(element: Element): HTMLElement | null {\n const decorated = element.closest(`.${GROUP_HEAD_CLASS}`)\n return decorated instanceof HTMLElement ? decorated : null\n}\n\nfunction titleForProcessRows(rows: HTMLElement[]): string {\n const text = rows.map((row) => row.textContent ?? '').join('\\n')\n if (COMMAND_PATTERN.test(text)) return '运行了命令'\n if (SEARCH_PATTERN.test(text)) return '进行了搜索'\n return '思考过程'\n}\n\nfunction nodeElement(node: Node): Element | null {\n if (node instanceof Element) return node\n return node.parentElement\n}\n\nfunction shouldIgnore(element: HTMLElement): boolean {\n return element.closest('textarea,input,select,button,a,[contenteditable=\"true\"],script,style') !== null\n}\n\nfunction isInteractiveTarget(target: EventTarget | null): boolean {\n return target instanceof Element && target.closest('button,a,input,textarea,select,[role=\"button\"],[contenteditable=\"true\"]') !== null\n}\n","const STYLE_ID = '@eddyskywalker/dsh-chatgpt-subscription/main'\n\nconst CSS = `\n.dsh-codex-page{box-sizing:border-box;color:var(--dsw-alias-label-primary);display:flex;flex-direction:column;gap:20px;max-width:780px;min-width:0;padding:2px 0 30px}\n.dsh-codex-page *{box-sizing:border-box}\n.dsh-codex-title{font-size:15px;font-weight:650;line-height:1.4;margin:0 0 5px}\n.dsh-codex-intro,.dsh-codex-muted{color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1.55;margin:0}\n.dsh-codex-group{border-top:1px solid var(--dsw-alias-border-l2);min-width:0}\n.dsh-codex-grouphead{align-items:center;display:flex;gap:12px;justify-content:space-between;min-height:48px}\n.dsh-codex-grouphead h3{font-size:14px;font-weight:650;margin:0}\n.dsh-codex-row{align-items:center;border-bottom:1px solid var(--dsw-alias-border-l2);display:flex;gap:20px;justify-content:space-between;min-height:44px;padding:8px 0}\n.dsh-codex-label{color:var(--dsw-alias-label-secondary);font-size:13px;flex:0 0 auto}\n.dsh-codex-value{font-size:13px;min-width:0;overflow-wrap:anywhere;text-align:right}\n.dsh-codex-actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end;padding-top:12px}\n.dsh-codex-button{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:999px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;font-size:13px;line-height:1;padding:8px 13px;white-space:nowrap}\n.dsh-codex-button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\n.dsh-codex-button:focus-visible,.dsh-codex-link:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}\n.dsh-codex-button:disabled{cursor:default;opacity:.5}\n.dsh-codex-button-primary{background:var(--dsw-alias-button-info-fill,#397ee8);border-color:transparent;color:var(--dsw-alias-button-info-label,#fff)}\n.dsh-codex-notice{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55;margin:12px 0 0;padding:10px 12px}\n.dsh-codex-error,.dsh-codex-warning{font-size:12px;line-height:1.5;margin:8px 0 0}\n.dsh-codex-error{color:var(--dsw-alias-label-danger,#d94b4b)}\n.dsh-codex-warning{color:var(--dsw-alias-label-warning,#c77a18)}\n.dsh-codex-errorbar{align-items:center;background:color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 9%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-label-danger,#d94b4b) 28%,transparent);border-radius:7px;color:var(--dsw-alias-label-danger,#d94b4b);display:flex;font-size:13px;gap:12px;justify-content:space-between;padding:10px 12px}\n.dsh-codex-link{color:var(--dsw-alias-label-link,#3278d4);display:inline-block;font-size:13px;margin-top:8px}\n.dsh-codex-models{display:flex;flex-wrap:wrap;gap:6px;padding-top:12px}\n.dsh-codex-models code{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:5px;font-family:ui-monospace,SFMono-Regular,Consolas,monospace;font-size:11px;padding:4px 6px}\n.dsh-codex-quota-card{background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:8px;margin-top:12px;padding:12px}\n.dsh-codex-quota-title{align-items:center;display:flex;font-size:13px;gap:8px;justify-content:space-between}\n.dsh-codex-quota-title span{color:var(--dsw-alias-label-tertiary);font-size:11px;text-transform:uppercase}\n.dsh-codex-meter-wrap{margin-top:13px}\n.dsh-codex-meter-label,.dsh-codex-meter-meta{display:flex;gap:10px;justify-content:space-between}\n.dsh-codex-meter-label{font-size:12px;margin-bottom:6px}\n.dsh-codex-meter-meta{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.45;margin-top:6px}\n.dsh-codex-meter{background:var(--dsw-alias-bg-layer-1,rgba(127,127,127,.15));border-radius:999px;height:7px;overflow:hidden;width:100%}\n.dsh-codex-meter>span{background:var(--dsw-alias-button-info-fill,#397ee8);border-radius:inherit;display:block;height:100%;max-width:100%;min-width:0;transition:width .25s ease}\n.dsh-codex-meter-warning>span{background:var(--dsw-alias-label-warning,#d58a24)}\n.dsh-codex-meter-danger>span{background:var(--dsw-alias-label-danger,#d94b4b)}\n.dsh-codex-empty{border:1px dashed var(--dsw-alias-border-l2);border-radius:7px;color:var(--dsw-alias-label-tertiary);font-size:12px;margin:12px 0 0;padding:16px;text-align:center}\n.dsh-codex-timestamp{color:var(--dsw-alias-label-tertiary);font-size:11px;margin:10px 0 0;text-align:right}\n.dsh-codex-skeleton{display:grid;gap:9px;padding-top:10px}\n.dsh-codex-skeleton span{animation:dsh-codex-pulse 1.4s ease-in-out infinite;background:var(--dsw-alias-bg-layer-2);border-radius:5px;height:42px}\n.dsh-codex-skeleton span:nth-child(2){animation-delay:.12s}.dsh-codex-skeleton span:nth-child(3){animation-delay:.24s}\n.dsh-codex-sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0 0 0 0);white-space:nowrap}\n.dsh-codex-process-group-head{border-radius:6px;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}\n.dsh-codex-process-group-head:hover{background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,rgba(127,127,127,.18)) 72%,transparent)}\n.dsh-codex-process-group-head:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}\n.dsh-codex-process-group-head.dsh-codex-process-group-collapsed{align-items:center!important;color:transparent!important;display:flex!important;font-size:0!important;line-height:28px!important;max-height:28px!important;min-height:28px!important;overflow:hidden!important;opacity:.78}\n.dsh-codex-process-group-head.dsh-codex-process-group-collapsed>*{display:none!important}\n.dsh-codex-process-group-head.dsh-codex-process-group-collapsed::before{color:var(--dsw-alias-label-secondary);content:\"▸ \" attr(data-dsh-codex-process-title);display:block;font-size:13px;line-height:28px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.dsh-codex-process-group-hidden{display:none!important}\n@keyframes dsh-codex-pulse{0%,100%{opacity:.55}50%{opacity:1}}\n@media(max-width:560px){.dsh-codex-row{align-items:flex-start;flex-direction:column;gap:3px}.dsh-codex-value{text-align:left}.dsh-codex-actions{justify-content:flex-start}.dsh-codex-grouphead{align-items:flex-start;flex-direction:column;gap:0;padding:12px 0}.dsh-codex-meter-meta{align-items:flex-start;flex-direction:column;gap:2px}.dsh-codex-errorbar{align-items:flex-start;flex-direction:column}}\n@media(prefers-reduced-motion:reduce){.dsh-codex-meter>span,.dsh-codex-process-group-head{transition:none}.dsh-codex-skeleton span{animation:none}}\n`\n\nexport function installStyles(): () => void {\n if (document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`) !== null) return () => undefined\n const element = document.createElement('style')\n element.dataset.plugin = '@eddyskywalker/dsh-chatgpt-subscription'\n element.dataset.pluginCss = STYLE_ID\n element.textContent = CSS\n document.head.appendChild(element)\n return () => element.remove()\n}\n","import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\nimport { CodexSubscriptionSection } from './CodexSubscriptionSection.tsx'\nimport { dictionaries, NS, type LocaleKey } from './locales.ts'\nimport { installProcessFolding } from './process-folding.ts'\nimport { installStyles } from './styles.ts'\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n 'dsh-chatgpt-subscription': LocaleKey\n }\n}\n\nexport const inject = ['slots', 'locale']\n\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register(NS, dictionaries), 'dsh-chatgpt-subscription: dictionaries')\n ctx.effect(() => installStyles(), 'dsh-chatgpt-subscription: styles')\n ctx.effect(() => installProcessFolding(), 'dsh-chatgpt-subscription: process folding')\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section',\n id: 'codex-subscription',\n order: 45,\n label: 'Codex 订阅',\n locale: NS,\n }, CodexSubscriptionSection))\n}\n"],"mappings":"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"}
package/lib/index.js CHANGED
@@ -631,9 +631,10 @@ function hiddenSandboxControlToolNames(options) {
631
631
  const retryTools = recentSandboxRetryToolNames(options.messages);
632
632
  return new Set(options.tools?.filter((tool) => hasSandboxControls(tool.parameters) && !retryTools.has(tool.name)).map((tool) => tool.name) ?? []);
633
633
  }
634
- async function buildResponsesPayload(options, attachments) {
634
+ async function buildResponsesPayload(options, attachments, localRawImages = {}) {
635
635
  const sandboxRetryTools = recentSandboxRetryToolNames(options.messages);
636
- const instructions = [
636
+ const resolveLocalRawImages = supportsImageInput(options);
637
+ const instructionParts = [
637
638
  options.system?.trim(),
638
639
  ...options.messages.filter((message) => message.role === "system").map((message) => blocksToText(message.content).trim()),
639
640
  sandboxToolInstruction(options.tools, sandboxRetryTools),
@@ -642,6 +643,11 @@ async function buildResponsesPayload(options, attachments) {
642
643
  ].filter((value) => Boolean(value));
643
644
  const input = [];
644
645
  const knownToolCalls = /* @__PURE__ */ new Map();
646
+ const localImageStats = {
647
+ attempted: 0,
648
+ resolved: 0,
649
+ failed: 0
650
+ };
645
651
  for (const message of options.messages) {
646
652
  if (message.role === "system") continue;
647
653
  const replayItems = replayOutputItems(message);
@@ -649,7 +655,7 @@ async function buildResponsesPayload(options, attachments) {
649
655
  input.push(...replayItems);
650
656
  for (const item of replayItems) if (item.type === "function_call" && typeof item.call_id === "string") knownToolCalls.set(item.call_id, typeof item.name === "string" ? item.name : void 0);
651
657
  if (!replayItems.some((item) => item.type === "message")) {
652
- const content = await mapContent(message, attachments, options.signal);
658
+ const content = await mapContent(message, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
653
659
  if (content.length > 0) input.push({
654
660
  role: message.role,
655
661
  content
@@ -678,7 +684,7 @@ async function buildResponsesPayload(options, attachments) {
678
684
  });
679
685
  continue;
680
686
  }
681
- const content = await mapContent(message, attachments, options.signal);
687
+ const content = await mapContent(message, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
682
688
  if (content.length > 0) input.push({
683
689
  role: message.role,
684
690
  content
@@ -692,6 +698,7 @@ async function buildResponsesPayload(options, attachments) {
692
698
  store: false,
693
699
  include: ["reasoning.encrypted_content"]
694
700
  };
701
+ const instructions = [...instructionParts, localRawImageInstruction(localImageStats)].filter((value) => Boolean(value));
695
702
  if (instructions.length > 0) payload.instructions = instructions.join("\n\n");
696
703
  if (options.tools?.length) {
697
704
  payload.tools = options.tools.map((tool) => ({
@@ -713,6 +720,13 @@ function runCodeInstruction(tools) {
713
720
  if (!tools?.some((tool) => tool.name === "run_code")) return void 0;
714
721
  return "run_code compatibility rule: its code is parsed as strict JavaScript/TypeScript before execution. On Windows, do not embed PowerShell containing $, ${...}, backslashes, or here-strings in JavaScript template literals; String.raw does not disable ${...} interpolation. Prefer arrays of ordinary quoted strings joined with \"\\n\", escaping backslashes, or use a file-write tool for large scripts and then invoke pwsh.";
715
722
  }
723
+ function localRawImageInstruction(stats) {
724
+ if (stats.failed === 0) return void 0;
725
+ return "Image attachment rule: a user message contains a markdown image link to a local/raw session URL but no structured image attachment. That link is not accessible image bytes for the provider. Do not claim to see the image; ask the user to resend it as an actual image attachment if visual inspection is required.";
726
+ }
727
+ function supportsImageInput(options) {
728
+ return options.provider === "codex-chatgpt" && options.model.toLowerCase().startsWith("gpt-");
729
+ }
716
730
  function toolDescriptionForCodex(name, description) {
717
731
  if (name === "run_code") return `${description}\n\nCompatibility: code is strict JavaScript/TypeScript. When composing PowerShell, avoid JavaScript template literals containing $, \${...}, Windows backslashes, or PowerShell here-strings. Prefer ordinary quoted string arrays joined with "\\n", or write a script file with a dedicated file tool before invoking pwsh.`;
718
732
  if (isCommandTool(name)) return `${description}\n\n${commandToolCompatibilityText(name)}`;
@@ -819,10 +833,11 @@ function runCodeErrorOutput(output) {
819
833
  function isRunCodeParserError(output) {
820
834
  return /(?:Legacy octal escape is not permitted in strict mode|Unexpected token|Invalid or unexpected token|Unterminated template|Expected ['"]?\}['"]?)/i.test(output);
821
835
  }
822
- async function mapContent(message, attachments, signal) {
836
+ async function mapContent(message, attachments, signal, localRawImages, localImageStats, resolveLocalRawImages) {
823
837
  const result = [];
824
- for (const block of message.content) if (block.type === "text") result.push({
825
- type: message.role === "assistant" ? "output_text" : "input_text",
838
+ for (const block of message.content) if (block.type === "text") if (message.role === "user") result.push(...await mapUserText(block.text, attachments, signal, localRawImages, localImageStats, resolveLocalRawImages));
839
+ else result.push({
840
+ type: "output_text",
826
841
  text: block.text
827
842
  });
828
843
  else if (block.type === "image") {
@@ -834,9 +849,128 @@ async function mapContent(message, attachments, signal) {
834
849
  }
835
850
  return result;
836
851
  }
852
+ async function mapUserText(text, attachments, signal, localRawImages, localImageStats, resolveLocalRawImages) {
853
+ const links = markdownImageLinks(text);
854
+ if (links.length === 0) return [{
855
+ type: "input_text",
856
+ text
857
+ }];
858
+ if (!resolveLocalRawImages) {
859
+ localImageStats.failed += links.length;
860
+ return [{
861
+ type: "input_text",
862
+ text
863
+ }];
864
+ }
865
+ const result = [];
866
+ let cursor = 0;
867
+ for (const match of links) {
868
+ if (match.start > cursor) pushInputText(result, text.slice(cursor, match.start));
869
+ localImageStats.attempted++;
870
+ const image = await localRawImageDataUrl(match.url, localRawImages, attachments.imageLimits?.maxImageBytes, signal);
871
+ if (image === null) {
872
+ localImageStats.failed++;
873
+ pushInputText(result, text.slice(match.start, match.end));
874
+ } else {
875
+ localImageStats.resolved++;
876
+ result.push({
877
+ type: "input_image",
878
+ image_url: image
879
+ });
880
+ }
881
+ cursor = match.end;
882
+ }
883
+ if (cursor < text.length) pushInputText(result, text.slice(cursor));
884
+ return result.length > 0 ? result : [{
885
+ type: "input_text",
886
+ text
887
+ }];
888
+ }
889
+ function pushInputText(content, text) {
890
+ if (text === "") return;
891
+ const previous = content.at(-1);
892
+ if (previous?.type === "input_text" && typeof previous.text === "string") previous.text += text;
893
+ else content.push({
894
+ type: "input_text",
895
+ text
896
+ });
897
+ }
898
+ function markdownImageLinks(text) {
899
+ const links = [];
900
+ for (const match of text.matchAll(/!\[[^\]]*\]\(([^)\s]+)\)/gi)) {
901
+ const url = match[1];
902
+ if (match.index === void 0 || !isLocalRawImageReference(url)) continue;
903
+ links.push({
904
+ start: match.index,
905
+ end: match.index + match[0].length,
906
+ url
907
+ });
908
+ }
909
+ return links;
910
+ }
911
+ async function localRawImageDataUrl(rawUrl, options, maxBytes, signal) {
912
+ const url = localRawImageUrl(rawUrl, options.baseUrl);
913
+ if (url === null) return null;
914
+ let response;
915
+ try {
916
+ response = await (options.fetchFn ?? fetch)(url, {
917
+ signal,
918
+ redirect: "error"
919
+ });
920
+ } catch {
921
+ return null;
922
+ }
923
+ if (!response.ok) return null;
924
+ const contentLength = Number(response.headers.get("content-length") ?? NaN);
925
+ if (maxBytes !== void 0 && Number.isFinite(contentLength) && contentLength > maxBytes) return null;
926
+ let bytes;
927
+ try {
928
+ bytes = new Uint8Array(await response.arrayBuffer());
929
+ } catch {
930
+ return null;
931
+ }
932
+ if (maxBytes !== void 0 && bytes.byteLength > maxBytes) return null;
933
+ const mediaType = supportedImageMediaType(response.headers.get("content-type")) ?? sniffImageMediaType(bytes);
934
+ if (mediaType === null) return null;
935
+ return bytesToDataUrl(mediaType, bytes);
936
+ }
937
+ function localRawImageUrl(rawUrl, baseUrl) {
938
+ if (!isLocalRawImageReference(rawUrl)) return null;
939
+ try {
940
+ const url = rawUrl.startsWith("/") ? baseUrl === void 0 ? null : new URL(rawUrl, baseUrl) : new URL(rawUrl);
941
+ if (url === null || !isLoopbackHost(url.hostname)) return null;
942
+ return url.toString();
943
+ } catch {
944
+ return null;
945
+ }
946
+ }
947
+ function isLocalRawImageReference(url) {
948
+ return /(?:^|\/)raw\/sha256:[a-f0-9]{32,}/i.test(url);
949
+ }
950
+ function isLoopbackHost(hostname) {
951
+ return hostname === "127.0.0.1" || hostname === "localhost" || hostname === "[::1]" || hostname === "::1";
952
+ }
953
+ function supportedImageMediaType(value) {
954
+ const mediaType = value?.split(";", 1)[0]?.trim().toLowerCase();
955
+ if (mediaType === "image/png" || mediaType === "image/jpeg" || mediaType === "image/webp" || mediaType === "image/gif") return mediaType;
956
+ return null;
957
+ }
958
+ function sniffImageMediaType(bytes) {
959
+ if (bytes.length >= 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71 && bytes[4] === 13 && bytes[5] === 10 && bytes[6] === 26 && bytes[7] === 10) return "image/png";
960
+ if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
961
+ if (bytes.length >= 12 && ascii(bytes, 0, 4) === "RIFF" && ascii(bytes, 8, 12) === "WEBP") return "image/webp";
962
+ if (bytes.length >= 6 && (ascii(bytes, 0, 6) === "GIF87a" || ascii(bytes, 0, 6) === "GIF89a")) return "image/gif";
963
+ return null;
964
+ }
965
+ function ascii(bytes, start, end) {
966
+ return String.fromCharCode(...bytes.slice(start, end));
967
+ }
837
968
  async function imageDataUrl(ref, attachments, signal) {
838
969
  const stored = await attachments.readImage(ref, signal);
839
- return `data:${stored.ref.mediaType};base64,${Buffer.from(stored.data).toString("base64")}`;
970
+ return bytesToDataUrl(stored.ref.mediaType, stored.data);
971
+ }
972
+ function bytesToDataUrl(mediaType, data) {
973
+ return `data:${mediaType};base64,${Buffer.from(data).toString("base64")}`;
840
974
  }
841
975
  function blocksToText(blocks) {
842
976
  return blocks.map((block) => {
@@ -884,6 +1018,9 @@ function retryAfterMs(headers) {
884
1018
  }
885
1019
  //#endregion
886
1020
  //#region src/host/responses-client.ts
1021
+ const MAX_VISIBLE_REASONING_CHARS = 12e3;
1022
+ const REASONING_DELTA_FLUSH_CHARS = 768;
1023
+ const REASONING_TRUNCATED_NOTICE = "\n\n[Reasoning summary truncated to keep the DSH web UI responsive.]";
887
1024
  var ResponsesClient = class {
888
1025
  oauth;
889
1026
  attachments;
@@ -893,10 +1030,12 @@ var ResponsesClient = class {
893
1030
  this.oauth = oauth;
894
1031
  this.attachments = attachments;
895
1032
  this.fetchFn = options.fetchFn ?? fetch;
1033
+ this.localRawImages = options.localRawImages ?? {};
896
1034
  this.onGenerationFinished = options.onGenerationFinished ?? (() => void 0);
897
1035
  }
1036
+ localRawImages;
898
1037
  async *stream(options) {
899
- const payload = await buildResponsesPayload(options, this.attachments);
1038
+ const payload = await buildResponsesPayload(options, this.attachments, this.localRawImages);
900
1039
  const hiddenSandboxControls = hiddenSandboxControlToolNames(options);
901
1040
  const sessionId = stableSessionId(options.sessionId);
902
1041
  try {
@@ -948,6 +1087,8 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
948
1087
  let reasoningIndex = null;
949
1088
  let text = "";
950
1089
  let reasoning = "";
1090
+ let pendingReasoningDelta = "";
1091
+ let reasoningTruncated = false;
951
1092
  let terminal = null;
952
1093
  let usage = null;
953
1094
  let replayOutput = [];
@@ -1000,12 +1141,20 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
1000
1141
  blockType: "reasoning"
1001
1142
  };
1002
1143
  }
1003
- reasoning += delta;
1004
- if (delta) yield {
1005
- type: "reasoning-delta",
1006
- index: reasoningIndex,
1007
- text: delta
1008
- };
1144
+ const visibleDelta = visibleReasoningDelta(delta, reasoning.length, reasoningTruncated);
1145
+ reasoningTruncated ||= visibleDelta.truncated;
1146
+ if (visibleDelta.text !== "") {
1147
+ reasoning += visibleDelta.text;
1148
+ pendingReasoningDelta += visibleDelta.text;
1149
+ }
1150
+ if (pendingReasoningDelta.length >= REASONING_DELTA_FLUSH_CHARS) {
1151
+ yield {
1152
+ type: "reasoning-delta",
1153
+ index: reasoningIndex,
1154
+ text: pendingReasoningDelta
1155
+ };
1156
+ pendingReasoningDelta = "";
1157
+ }
1009
1158
  return;
1010
1159
  }
1011
1160
  if (type === "response.output_item.added" || type === "response.output_item.done") {
@@ -1101,14 +1250,24 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
1101
1250
  }
1102
1251
  if (signal?.aborted) throw signal.reason ?? new DOMException("Aborted", "AbortError");
1103
1252
  if (terminal === null) throw new LlmError("Codex stream ended before a terminal event.", "PROTOCOL_ERROR");
1104
- if (reasoningIndex !== null) yield {
1105
- type: "block-end",
1106
- index: reasoningIndex,
1107
- block: {
1108
- type: "reasoning",
1109
- text: reasoning
1253
+ if (reasoningIndex !== null) {
1254
+ if (pendingReasoningDelta !== "") {
1255
+ yield {
1256
+ type: "reasoning-delta",
1257
+ index: reasoningIndex,
1258
+ text: pendingReasoningDelta
1259
+ };
1260
+ pendingReasoningDelta = "";
1110
1261
  }
1111
- };
1262
+ yield {
1263
+ type: "block-end",
1264
+ index: reasoningIndex,
1265
+ block: {
1266
+ type: "reasoning",
1267
+ text: reasoning
1268
+ }
1269
+ };
1270
+ }
1112
1271
  if (textIndex !== null) yield {
1113
1272
  type: "block-end",
1114
1273
  index: textIndex,
@@ -1155,6 +1314,25 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
1155
1314
  replayState: { outputItems: replayOutput }
1156
1315
  };
1157
1316
  }
1317
+ function visibleReasoningDelta(delta, currentVisibleChars, alreadyTruncated) {
1318
+ if (delta === "" || alreadyTruncated) return {
1319
+ text: "",
1320
+ truncated: alreadyTruncated
1321
+ };
1322
+ const remaining = MAX_VISIBLE_REASONING_CHARS - currentVisibleChars;
1323
+ if (remaining <= 0) return {
1324
+ text: REASONING_TRUNCATED_NOTICE,
1325
+ truncated: true
1326
+ };
1327
+ if (delta.length <= remaining) return {
1328
+ text: delta,
1329
+ truncated: false
1330
+ };
1331
+ return {
1332
+ text: `${delta.slice(0, remaining)}${REASONING_TRUNCATED_NOTICE}`,
1333
+ truncated: true
1334
+ };
1335
+ }
1158
1336
  function mapUsage(value) {
1159
1337
  if (value === null) return null;
1160
1338
  const totalInput = number(value.input_tokens) ?? 0;
@@ -1769,7 +1947,10 @@ const inject = [
1769
1947
  function apply(ctx) {
1770
1948
  const oauth = new OAuthService(new WindowsDpapiTokenStore(), { logger: ctx.logger });
1771
1949
  const usage = new UsageService(oauth);
1772
- const adapter = new CodexChatGptAdapter(new ResponsesClient(oauth, ctx.attachments, { onGenerationFinished: () => usage.invalidate() }));
1950
+ const adapter = new CodexChatGptAdapter(new ResponsesClient(oauth, ctx.attachments, {
1951
+ localRawImages: { baseUrl: localWebServerBaseUrl(ctx.webServer.host, ctx.webServer.port) },
1952
+ onGenerationFinished: () => usage.invalidate()
1953
+ }));
1773
1954
  ctx.effect(() => {
1774
1955
  const disposeRoutes = registerRoutes(ctx, oauth, usage);
1775
1956
  const disposeAdapter = ctx.llm.registerAdapter([PROVIDER_ID], adapter);
@@ -1780,5 +1961,8 @@ function apply(ctx) {
1780
1961
  };
1781
1962
  }, "dsh-chatgpt-subscription: adapter, routes, and lifecycle");
1782
1963
  }
1964
+ function localWebServerBaseUrl(host, port) {
1965
+ return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${port}`;
1966
+ }
1783
1967
  //#endregion
1784
1968
  export { CodexChatGptAdapter, OAuthService, ResponsesClient, UsageService, apply, inject, mapCodexUsage, parseResponsesStream };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAG/D,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,0BAA0B,EAAE,SAAS,CAAA;KACtC;CACF;AAED,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAA;AAI/D,OAAO,QAAQ,kCAAkC,CAAC;IAChD,UAAU,kBAAkB;QAC1B,0BAA0B,EAAE,SAAS,CAAA;KACtC;CACF;AAED,eAAO,MAAM,MAAM,UAAsB,CAAA;AAEzC,wBAAgB,KAAK,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAW9C"}
@@ -0,0 +1,5 @@
1
+ export interface ProcessFoldingOptions {
2
+ autoCollapseMs?: number;
3
+ }
4
+ export declare function installProcessFolding(options?: ProcessFoldingOptions): () => void;
5
+ //# sourceMappingURL=process-folding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-folding.d.ts","sourceRoot":"","sources":["../../../src/client/process-folding.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAcD,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,qBAA0B,GAAG,MAAM,IAAI,CA8IrF"}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/client/styles.ts"],"names":[],"mappings":"AAiDA,wBAAgB,aAAa,IAAI,MAAM,IAAI,CAQ1C"}
1
+ {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/client/styles.ts"],"names":[],"mappings":"AAwDA,wBAAgB,aAAa,IAAI,MAAM,IAAI,CAQ1C"}
@@ -1,9 +1,11 @@
1
1
  import { type GenerateOptions, type StreamChunk } from '@deepseek-ai/dsh-llm';
2
2
  import { OAuthService } from './oauth-service.ts';
3
+ import { type LocalRawImageOptions } from './responses-mapper.ts';
3
4
  import type { AttachmentStore } from '@deepseek-ai/dsh-attachment';
4
5
  type FetchLike = typeof fetch;
5
6
  export interface ResponsesClientOptions {
6
7
  fetchFn?: FetchLike;
8
+ localRawImages?: LocalRawImageOptions;
7
9
  onGenerationFinished?: () => void;
8
10
  }
9
11
  export declare class ResponsesClient {
@@ -11,7 +13,8 @@ export declare class ResponsesClient {
11
13
  private readonly attachments;
12
14
  private readonly fetchFn;
13
15
  private readonly onGenerationFinished;
14
- constructor(oauth: OAuthService, attachments: Pick<AttachmentStore, 'readImage'>, options?: ResponsesClientOptions);
16
+ constructor(oauth: OAuthService, attachments: Pick<AttachmentStore, 'readImage'> & Partial<Pick<AttachmentStore, 'imageLimits'>>, options?: ResponsesClientOptions);
17
+ private readonly localRawImages;
15
18
  stream(options: GenerateOptions): AsyncIterable<StreamChunk>;
16
19
  private send;
17
20
  private request;
@@ -1 +1 @@
1
- {"version":3,"file":"responses-client.d.ts","sourceRoot":"","sources":["../../../src/host/responses-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,WAAW,EAEjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAGjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAElE,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AAE7B,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;CAClC;AAED,qBAAa,eAAe;IAKxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAL9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAY;gBAG9B,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,EAChE,OAAO,GAAE,sBAA2B;IAM/B,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC;YAYrD,IAAI;YAYJ,OAAO;CAsBtB;AAWD,wBAAuB,oBAAoB,CACzC,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,WAAW,EACpB,qBAAqB,GAAE,WAAW,CAAC,MAAM,CAAa,GACrD,aAAa,CAAC,WAAW,CAAC,CA2M5B"}
1
+ {"version":3,"file":"responses-client.d.ts","sourceRoot":"","sources":["../../../src/host/responses-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,WAAW,EAEjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAwD,KAAK,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAEvH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAElE,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AAK7B,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,cAAc,CAAC,EAAE,oBAAoB,CAAA;IACrC,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAA;CAClC;AAED,qBAAa,eAAe;IAKxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAL9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAW;IACnC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAY;gBAG9B,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC,EAChH,OAAO,GAAE,sBAA2B;IAOtC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IAE9C,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC;YAYrD,IAAI;YAYJ,OAAO;CAsBtB;AAWD,wBAAuB,oBAAoB,CACzC,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,WAAW,EACpB,qBAAqB,GAAE,WAAW,CAAC,MAAM,CAAa,GACrD,aAAa,CAAC,WAAW,CAAC,CAyN5B"}
@@ -6,6 +6,12 @@ export interface ResponsesPayload extends Record<string, unknown> {
6
6
  stream: true;
7
7
  store: false;
8
8
  }
9
+ type FetchLike = typeof fetch;
10
+ export interface LocalRawImageOptions {
11
+ baseUrl?: string;
12
+ fetchFn?: FetchLike;
13
+ }
9
14
  export declare function hiddenSandboxControlToolNames(options: GenerateOptions): Set<string>;
10
- export declare function buildResponsesPayload(options: GenerateOptions, attachments: Pick<AttachmentStore, 'readImage'>): Promise<ResponsesPayload>;
15
+ export declare function buildResponsesPayload(options: GenerateOptions, attachments: Pick<AttachmentStore, 'readImage'> & Partial<Pick<AttachmentStore, 'imageLimits'>>, localRawImages?: LocalRawImageOptions): Promise<ResponsesPayload>;
16
+ export {};
11
17
  //# sourceMappingURL=responses-mapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"responses-mapper.d.ts","sourceRoot":"","sources":["../../../src/host/responses-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,6BAA6B,CAAA;AACtF,OAAO,KAAK,EAAgB,eAAe,EAAW,MAAM,sBAAsB,CAAA;AAElF,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACrC,MAAM,EAAE,IAAI,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb;AAED,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAKnF;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAC9C,OAAO,CAAC,gBAAgB,CAAC,CAuF3B"}
1
+ {"version":3,"file":"responses-mapper.d.ts","sourceRoot":"","sources":["../../../src/host/responses-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAsC,MAAM,6BAA6B,CAAA;AACtG,OAAO,KAAK,EAAgB,eAAe,EAAW,MAAM,sBAAsB,CAAA;AAElF,MAAM,WAAW,gBAAiB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC/D,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACrC,MAAM,EAAE,IAAI,CAAA;IACZ,KAAK,EAAE,KAAK,CAAA;CACb;AAED,KAAK,SAAS,GAAG,OAAO,KAAK,CAAA;AAE7B,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB;AAQD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,eAAe,GAAG,GAAG,CAAC,MAAM,CAAC,CAKnF;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,eAAe,EACxB,WAAW,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC,EAC/F,cAAc,GAAE,oBAAyB,GACxC,OAAO,CAAC,gBAAgB,CAAC,CA6F3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAWlD,eAAO,MAAM,MAAM,UAAsC,CAAA;AAEzD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAiBxC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACrE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAWlD,eAAO,MAAM,MAAM,UAAsC,CAAA;AAEzD,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAkBxC;AAED,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAClF,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACrE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eddyskywalker/dsh-chatgpt-subscription",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "DSH provider plugin for Codex access through a ChatGPT subscription.",
5
5
  "author": {
6
6
  "name": "eddyskywalker",