@eddyskywalker/dsh-chatgpt-subscription 0.1.0-alpha.0 → 0.1.1

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,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1 - 2026-08-16
4
+
5
+ - 新增执行过程详情与思考过程的可折叠展示机制(Collapsible process detail folding)。
6
+ - 增强客户端与服务端 Responses 过程解析及 UI 交互。
7
+
8
+ ## 0.1.0 - 2026-08-16
9
+
10
+ - 首个正式版本发布。
11
+ - 完善客户端 UI 样式体系与 `@eddyskywalker` 命名空间配置。
12
+ - 增强命令执行工具与无状态安全重试机制。
13
+
3
14
  ## 0.1.0-alpha.0 - 2026-08-14
4
15
 
5
16
  - 新增 DSH Host/Client 双端插件与一级“Codex 订阅”设置入口。
package/lib/client.js CHANGED
@@ -592,6 +592,213 @@ 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 = 1;
605
+ const MAX_SCAN_ROOTS_PER_FRAME = 80;
606
+ const MAX_TEXT_SAMPLE = 2e4;
607
+ const PROCESS_CANDIDATE_SELECTOR = "article,section,li,div,p,[role=\"listitem\"]";
608
+ const PROCESS_PREFIX_PATTERN = "(?:上下文注入|Think|Search|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Web(?:\\s+Search)?|Tool|工具|思考)";
609
+ const COMMAND_PATTERN = /(?: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" || document.body === null) return () => void 0;
615
+ const autoCollapseMs = options.autoCollapseMs ?? DEFAULT_AUTO_COLLAPSE_MS;
616
+ const groups = /* @__PURE__ */ new Map();
617
+ const pending = /* @__PURE__ */ new Set();
618
+ let frame = null;
619
+ const scheduleFlush = () => {
620
+ if (frame !== null) return;
621
+ frame = requestAnimationFrame(() => {
622
+ frame = null;
623
+ flush();
624
+ });
625
+ };
626
+ const queue = (element) => {
627
+ if (element === null || !element.isConnected) return;
628
+ pending.add(element);
629
+ scheduleFlush();
630
+ };
631
+ const scheduleAutoCollapse = (head) => {
632
+ const state = groups.get(head);
633
+ if (state === void 0 || head.hasAttribute(USER_TOGGLED_ATTR)) return;
634
+ if (state.timer !== null) clearTimeout(state.timer);
635
+ state.timer = setTimeout(() => {
636
+ state.timer = null;
637
+ if (head.isConnected && !head.hasAttribute(USER_TOGGLED_ATTR)) setGroupCollapsed(head, true);
638
+ }, autoCollapseMs);
639
+ };
640
+ const syncGroup = (rows, previous) => {
641
+ const head = rows[0];
642
+ const title = titleForProcessRows(rows);
643
+ const click = (event) => {
644
+ if (isInteractiveTarget(event.target)) return;
645
+ markUserToggled(head);
646
+ setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS));
647
+ };
648
+ const keydown = (event) => {
649
+ if (event.key !== "Enter" && event.key !== " ") return;
650
+ event.preventDefault();
651
+ markUserToggled(head);
652
+ setGroupCollapsed(head, !head.classList.contains(GROUP_COLLAPSED_CLASS));
653
+ };
654
+ groups.set(head, {
655
+ rows,
656
+ click,
657
+ keydown,
658
+ timer: null
659
+ });
660
+ for (const row of rows) row.classList.add(ROW_CLASS);
661
+ head.classList.add(GROUP_HEAD_CLASS);
662
+ if (!head.hasAttribute("tabindex")) head.tabIndex = 0;
663
+ head.setAttribute("aria-expanded", String(!(previous?.collapsed ?? false)));
664
+ head.setAttribute(TITLE_ATTR, title);
665
+ head.title ||= TITLE;
666
+ if (previous?.userToggled === true) head.setAttribute(USER_TOGGLED_ATTR, "true");
667
+ head.addEventListener("click", click);
668
+ head.addEventListener("keydown", keydown);
669
+ setGroupCollapsed(head, previous?.collapsed ?? false);
670
+ scheduleAutoCollapse(head);
671
+ };
672
+ const rebuildParentGroups = (parent) => {
673
+ const previous = /* @__PURE__ */ new Map();
674
+ for (const [head, state] of groups) {
675
+ if (head.parentElement !== parent) continue;
676
+ previous.set(head, {
677
+ collapsed: head.classList.contains(GROUP_COLLAPSED_CLASS),
678
+ userToggled: head.hasAttribute(USER_TOGGLED_ATTR)
679
+ });
680
+ cleanupGroup(head, state);
681
+ groups.delete(head);
682
+ }
683
+ let rows = [];
684
+ const flushRows = () => {
685
+ if (rows.length > 0) syncGroup(rows, previous.get(rows[0]));
686
+ rows = [];
687
+ };
688
+ for (const child of Array.from(parent.children)) if (child instanceof HTMLElement && isProcessRow(child)) rows.push(child);
689
+ else flushRows();
690
+ flushRows();
691
+ };
692
+ const flush = () => {
693
+ const parents = /* @__PURE__ */ new Set();
694
+ let scanned = 0;
695
+ for (const root of Array.from(pending)) {
696
+ pending.delete(root);
697
+ if (!root.isConnected) continue;
698
+ for (const row of findProcessRows(root)) if (row.parentElement !== null) parents.add(row.parentElement);
699
+ const grouped = nearestGroupHead(root);
700
+ if (grouped !== null && grouped.parentElement !== null) parents.add(grouped.parentElement);
701
+ scanned++;
702
+ if (scanned >= MAX_SCAN_ROOTS_PER_FRAME && pending.size > 0) {
703
+ scheduleFlush();
704
+ break;
705
+ }
706
+ }
707
+ for (const parent of parents) rebuildParentGroups(parent);
708
+ };
709
+ const observer = new MutationObserver((mutations) => {
710
+ for (const mutation of mutations) {
711
+ if (mutation.type === "characterData") {
712
+ queue(nodeElement(mutation.target)?.closest(PROCESS_CANDIDATE_SELECTOR) ?? nodeElement(mutation.target));
713
+ continue;
714
+ }
715
+ for (const node of mutation.addedNodes) queue(nodeElement(node));
716
+ }
717
+ });
718
+ observer.observe(document.body, {
719
+ childList: true,
720
+ characterData: true,
721
+ subtree: true
722
+ });
723
+ queue(document.body);
724
+ return () => {
725
+ observer.disconnect();
726
+ if (frame !== null) cancelAnimationFrame(frame);
727
+ pending.clear();
728
+ for (const [head, state] of groups) cleanupGroup(head, state);
729
+ groups.clear();
730
+ };
731
+ }
732
+ function cleanupGroup(head, state) {
733
+ if (state.timer !== null) clearTimeout(state.timer);
734
+ head.removeEventListener("click", state.click);
735
+ head.removeEventListener("keydown", state.keydown);
736
+ for (const row of state.rows) row.classList.remove(ROW_CLASS, GROUP_HIDDEN_CLASS);
737
+ head.classList.remove(GROUP_HEAD_CLASS, GROUP_COLLAPSED_CLASS);
738
+ head.removeAttribute("aria-expanded");
739
+ head.removeAttribute(USER_TOGGLED_ATTR);
740
+ head.removeAttribute(TITLE_ATTR);
741
+ if (head.title === TITLE) head.removeAttribute("title");
742
+ }
743
+ function findProcessRows(root) {
744
+ const rows = [];
745
+ if (root instanceof HTMLElement && isProcessRow(root)) rows.push(root);
746
+ for (const element of root.querySelectorAll(PROCESS_CANDIDATE_SELECTOR)) if (element instanceof HTMLElement && isProcessRow(element)) rows.push(element);
747
+ return rows;
748
+ }
749
+ function isProcessRow(element) {
750
+ if (element.closest(".dsh-codex-page") !== null || shouldIgnore(element)) return false;
751
+ const raw = (element.textContent ?? "").slice(0, MAX_TEXT_SAMPLE);
752
+ const normalized = raw.replace(/\s+/g, " ").trim();
753
+ if (!PROCESS_PREFIX_RE.test(normalized)) return false;
754
+ return processLabelCount(raw) <= MAX_PROCESS_LABELS_PER_ROW;
755
+ }
756
+ function processLabelCount(text) {
757
+ PROCESS_LINE_RE.lastIndex = 0;
758
+ let count = 0;
759
+ while (PROCESS_LINE_RE.exec(text) !== null) count++;
760
+ return count;
761
+ }
762
+ function setGroupCollapsed(head, collapsed) {
763
+ const state = findCurrentGroupState(head);
764
+ if (state === null) return;
765
+ head.classList.toggle(GROUP_COLLAPSED_CLASS, collapsed);
766
+ head.setAttribute("aria-expanded", String(!collapsed));
767
+ for (const row of state.rows.slice(1)) row.classList.toggle(GROUP_HIDDEN_CLASS, collapsed);
768
+ }
769
+ function findCurrentGroupState(head) {
770
+ const rows = [head];
771
+ let sibling = head.nextElementSibling;
772
+ while (sibling instanceof HTMLElement && isProcessRow(sibling)) {
773
+ rows.push(sibling);
774
+ sibling = sibling.nextElementSibling;
775
+ }
776
+ return rows.length > 0 ? { rows } : null;
777
+ }
778
+ function markUserToggled(head) {
779
+ head.setAttribute(USER_TOGGLED_ATTR, "true");
780
+ }
781
+ function nearestGroupHead(element) {
782
+ const decorated = element.closest(`.${GROUP_HEAD_CLASS}`);
783
+ return decorated instanceof HTMLElement ? decorated : null;
784
+ }
785
+ function titleForProcessRows(rows) {
786
+ const text = rows.map((row) => row.textContent ?? "").join("\n");
787
+ if (COMMAND_PATTERN.test(text)) return "运行了命令";
788
+ if (SEARCH_PATTERN.test(text)) return "进行了搜索";
789
+ return "思考过程";
790
+ }
791
+ function nodeElement(node) {
792
+ if (node instanceof Element) return node;
793
+ return node.parentElement;
794
+ }
795
+ function shouldIgnore(element) {
796
+ return element.closest("textarea,input,select,button,a,[contenteditable=\"true\"],script,style") !== null;
797
+ }
798
+ function isInteractiveTarget(target) {
799
+ return target instanceof Element && target.closest("button,a,input,textarea,select,[role=\"button\"],[contenteditable=\"true\"]") !== null;
800
+ }
801
+ //#endregion
595
802
  //#region src/client/styles.ts
596
803
  const STYLE_ID = "@eddyskywalker/dsh-chatgpt-subscription/main";
597
804
  const CSS = `
@@ -636,9 +843,16 @@ window.__ModuleLoader__.load({
636
843
  .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
844
  .dsh-codex-skeleton span:nth-child(2){animation-delay:.12s}.dsh-codex-skeleton span:nth-child(3){animation-delay:.24s}
638
845
  .dsh-codex-sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0 0 0 0);white-space:nowrap}
846
+ .dsh-codex-process-group-head{border-radius:6px;cursor:pointer;transition:background-color .15s ease,opacity .15s ease}
847
+ .dsh-codex-process-group-head:hover{background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,rgba(127,127,127,.18)) 72%,transparent)}
848
+ .dsh-codex-process-group-head:focus-visible{outline:2px solid var(--dsw-alias-button-info-fill,#397ee8);outline-offset:2px}
849
+ .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}
850
+ .dsh-codex-process-group-head.dsh-codex-process-group-collapsed>*{display:none!important}
851
+ .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}
852
+ .dsh-codex-process-group-hidden{display:none!important}
639
853
  @keyframes dsh-codex-pulse{0%,100%{opacity:.55}50%{opacity:1}}
640
854
  @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}}
855
+ @media(prefers-reduced-motion:reduce){.dsh-codex-meter>span,.dsh-codex-process-group-head{transition:none}.dsh-codex-skeleton span{animation:none}}
642
856
  `;
643
857
  function installStyles() {
644
858
  if (document.querySelector(`style[data-plugin-css="${STYLE_ID}"]`) !== null) return () => void 0;
@@ -655,6 +869,7 @@ window.__ModuleLoader__.load({
655
869
  function apply(ctx) {
656
870
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-chatgpt-subscription: dictionaries");
657
871
  ctx.effect(() => installStyles(), "dsh-chatgpt-subscription: styles");
872
+ ctx.effect(() => installProcessFolding(), "dsh-chatgpt-subscription: process folding");
658
873
  ctx.slots.inject("settings.section", () => ctx.slots.register({
659
874
  name: "settings.section",
660
875
  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 = 1\nconst MAX_SCAN_ROOTS_PER_FRAME = 80\nconst MAX_TEXT_SAMPLE = 20_000\nconst PROCESS_CANDIDATE_SELECTOR = 'article,section,li,div,p,[role=\"listitem\"]'\nconst PROCESS_PREFIX_PATTERN = '(?:上下文注入|Think|Search|Pwsh|PowerShell|Bash|Shell|Read|Glob|Grep|Web(?:\\\\s+Search)?|Tool|工具|思考)'\nconst COMMAND_PATTERN = /(?: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' || document.body === null) return () => undefined\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 return processLabelCount(raw) <= MAX_PROCESS_LABELS_PER_ROW\n}\n\nfunction processLabelCount(text: string): number {\n PROCESS_LINE_RE.lastIndex = 0\n let count = 0\n while (PROCESS_LINE_RE.exec(text) !== null) count++\n return count\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,16 +631,23 @@ 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),
641
+ commandToolInstruction(options.tools),
640
642
  runCodeInstruction(options.tools)
641
643
  ].filter((value) => Boolean(value));
642
644
  const input = [];
643
645
  const knownToolCalls = /* @__PURE__ */ new Map();
646
+ const localImageStats = {
647
+ attempted: 0,
648
+ resolved: 0,
649
+ failed: 0
650
+ };
644
651
  for (const message of options.messages) {
645
652
  if (message.role === "system") continue;
646
653
  const replayItems = replayOutputItems(message);
@@ -648,7 +655,7 @@ async function buildResponsesPayload(options, attachments) {
648
655
  input.push(...replayItems);
649
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);
650
657
  if (!replayItems.some((item) => item.type === "message")) {
651
- const content = await mapContent(message, attachments, options.signal);
658
+ const content = await mapContent(message, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
652
659
  if (content.length > 0) input.push({
653
660
  role: message.role,
654
661
  content
@@ -677,7 +684,7 @@ async function buildResponsesPayload(options, attachments) {
677
684
  });
678
685
  continue;
679
686
  }
680
- const content = await mapContent(message, attachments, options.signal);
687
+ const content = await mapContent(message, attachments, options.signal, localRawImages, localImageStats, resolveLocalRawImages);
681
688
  if (content.length > 0) input.push({
682
689
  role: message.role,
683
690
  content
@@ -691,6 +698,7 @@ async function buildResponsesPayload(options, attachments) {
691
698
  store: false,
692
699
  include: ["reasoning.encrypted_content"]
693
700
  };
701
+ const instructions = [...instructionParts, localRawImageInstruction(localImageStats)].filter((value) => Boolean(value));
694
702
  if (instructions.length > 0) payload.instructions = instructions.join("\n\n");
695
703
  if (options.tools?.length) {
696
704
  payload.tools = options.tools.map((tool) => ({
@@ -712,9 +720,26 @@ function runCodeInstruction(tools) {
712
720
  if (!tools?.some((tool) => tool.name === "run_code")) return void 0;
713
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.";
714
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
+ }
715
730
  function toolDescriptionForCodex(name, description) {
716
- if (name !== "run_code") return description;
717
- 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.`;
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.`;
732
+ if (isCommandTool(name)) return `${description}\n\n${commandToolCompatibilityText(name)}`;
733
+ return description;
734
+ }
735
+ function commandToolInstruction(tools) {
736
+ const names = tools?.filter((tool) => isCommandTool(tool.name)).map((tool) => tool.name);
737
+ if (!names?.length) return void 0;
738
+ return `Command tool compatibility rule (${[...new Set(names)].join(", ")}): each command call runs in a fresh process, so do not rely on cd, aliases, functions, or variables from previous calls; set workdir when the tool supports it. On Windows/pwsh, keep commands in native PowerShell syntax and native Windows paths. For deletion or move operations, first resolve and verify exact absolute target paths, then operate on those literal paths only; avoid dynamically deleting paths built from $HOME, wildcards, command substitution, or another shell's output. Treat [auto-mode hard deny] and similar policy denials as non-retriable; choose a safer non-destructive inspection or report the limitation instead of repeating the same command or adding sandbox escalation. If downloads fail with TLS credential or connection-closed errors, treat that as an environment/network failure and use local sources or report the limitation instead of cycling through equivalent download commands.`;
739
+ }
740
+ function commandToolCompatibilityText(name) {
741
+ const shell = name.toLowerCase();
742
+ return `Compatibility: command execution is stateless between calls.${shell === "pwsh" || shell.includes("powershell") ? " Use native PowerShell syntax and native Windows paths; prefer workdir over cd because every call starts a fresh process." : " Prefer workdir over cd because every call starts a fresh process."} For destructive operations, verify exact absolute targets first and use literal paths; policy hard-deny results require a safer command shape, not sandbox escalation.`;
718
743
  }
719
744
  function sandboxToolInstruction(tools, sandboxRetryTools) {
720
745
  if (!tools?.some((tool) => hasSandboxControls(tool.parameters))) return void 0;
@@ -723,7 +748,8 @@ function sandboxToolInstruction(tools, sandboxRetryTools) {
723
748
  }
724
749
  function toolParametersForCodex(toolName, parameters, allowSandboxRetry) {
725
750
  const hideSandboxControls = !allowSandboxRetry && hasSandboxControls(parameters);
726
- if (!hideSandboxControls && toolName !== "run_code") return parameters;
751
+ const augmentCommandTool = isCommandTool(toolName);
752
+ if (!hideSandboxControls && toolName !== "run_code" && !augmentCommandTool) return parameters;
727
753
  const cloned = structuredClone(parameters);
728
754
  const properties = record$2(cloned.properties);
729
755
  if (properties !== null && hideSandboxControls) {
@@ -739,8 +765,27 @@ function toolParametersForCodex(toolName, parameters, allowSandboxRetry) {
739
765
  code.description = current ? `${current}\n\n${compatibility}` : compatibility;
740
766
  }
741
767
  }
768
+ if (augmentCommandTool && properties !== null) {
769
+ appendPropertyDescription(properties.command, "Single command for a fresh process; do not rely on state from earlier calls.");
770
+ appendPropertyDescription(properties.workdir, "Use a native absolute working directory instead of embedding cd in the command.");
771
+ appendPropertyDescription(properties.timeoutMs, "Positive finite timeout in milliseconds for bounded commands.");
772
+ appendPropertyDescription(properties.run_in_background, "Use only for long-running servers or watchers whose output will be checked later.");
773
+ appendPropertyDescription(properties.sandbox_permissions, "Only set when retrying the exact previous sandbox-denied call; it does not bypass hard-deny policy results.");
774
+ appendPropertyDescription(properties.justification, "Required only for an allowed sandbox retry; explain why the wider access is needed.");
775
+ }
742
776
  return cloned;
743
777
  }
778
+ function appendPropertyDescription(value, addition) {
779
+ const property = record$2(value);
780
+ if (property === null) return;
781
+ const current = typeof property.description === "string" ? property.description.trim() : "";
782
+ if (current.includes(addition)) return;
783
+ property.description = current ? `${current}\n\n${addition}` : addition;
784
+ }
785
+ function isCommandTool(name) {
786
+ const normalized = name.toLowerCase();
787
+ return normalized === "pwsh" || normalized === "powershell" || normalized === "bash" || normalized === "shell";
788
+ }
744
789
  function hasSandboxControls(parameters) {
745
790
  const properties = record$2(parameters.properties);
746
791
  return properties !== null && ("sandbox_permissions" in properties || "justification" in properties);
@@ -788,10 +833,11 @@ function runCodeErrorOutput(output) {
788
833
  function isRunCodeParserError(output) {
789
834
  return /(?:Legacy octal escape is not permitted in strict mode|Unexpected token|Invalid or unexpected token|Unterminated template|Expected ['"]?\}['"]?)/i.test(output);
790
835
  }
791
- async function mapContent(message, attachments, signal) {
836
+ async function mapContent(message, attachments, signal, localRawImages, localImageStats, resolveLocalRawImages) {
792
837
  const result = [];
793
- for (const block of message.content) if (block.type === "text") result.push({
794
- 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",
795
841
  text: block.text
796
842
  });
797
843
  else if (block.type === "image") {
@@ -803,9 +849,128 @@ async function mapContent(message, attachments, signal) {
803
849
  }
804
850
  return result;
805
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
+ }
806
968
  async function imageDataUrl(ref, attachments, signal) {
807
969
  const stored = await attachments.readImage(ref, signal);
808
- 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")}`;
809
974
  }
810
975
  function blocksToText(blocks) {
811
976
  return blocks.map((block) => {
@@ -853,6 +1018,9 @@ function retryAfterMs(headers) {
853
1018
  }
854
1019
  //#endregion
855
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.]";
856
1024
  var ResponsesClient = class {
857
1025
  oauth;
858
1026
  attachments;
@@ -862,10 +1030,12 @@ var ResponsesClient = class {
862
1030
  this.oauth = oauth;
863
1031
  this.attachments = attachments;
864
1032
  this.fetchFn = options.fetchFn ?? fetch;
1033
+ this.localRawImages = options.localRawImages ?? {};
865
1034
  this.onGenerationFinished = options.onGenerationFinished ?? (() => void 0);
866
1035
  }
1036
+ localRawImages;
867
1037
  async *stream(options) {
868
- const payload = await buildResponsesPayload(options, this.attachments);
1038
+ const payload = await buildResponsesPayload(options, this.attachments, this.localRawImages);
869
1039
  const hiddenSandboxControls = hiddenSandboxControlToolNames(options);
870
1040
  const sessionId = stableSessionId(options.sessionId);
871
1041
  try {
@@ -917,6 +1087,8 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
917
1087
  let reasoningIndex = null;
918
1088
  let text = "";
919
1089
  let reasoning = "";
1090
+ let pendingReasoningDelta = "";
1091
+ let reasoningTruncated = false;
920
1092
  let terminal = null;
921
1093
  let usage = null;
922
1094
  let replayOutput = [];
@@ -969,12 +1141,20 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
969
1141
  blockType: "reasoning"
970
1142
  };
971
1143
  }
972
- reasoning += delta;
973
- if (delta) yield {
974
- type: "reasoning-delta",
975
- index: reasoningIndex,
976
- text: delta
977
- };
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
+ }
978
1158
  return;
979
1159
  }
980
1160
  if (type === "response.output_item.added" || type === "response.output_item.done") {
@@ -1070,14 +1250,24 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
1070
1250
  }
1071
1251
  if (signal?.aborted) throw signal.reason ?? new DOMException("Aborted", "AbortError");
1072
1252
  if (terminal === null) throw new LlmError("Codex stream ended before a terminal event.", "PROTOCOL_ERROR");
1073
- if (reasoningIndex !== null) yield {
1074
- type: "block-end",
1075
- index: reasoningIndex,
1076
- block: {
1077
- type: "reasoning",
1078
- text: reasoning
1253
+ if (reasoningIndex !== null) {
1254
+ if (pendingReasoningDelta !== "") {
1255
+ yield {
1256
+ type: "reasoning-delta",
1257
+ index: reasoningIndex,
1258
+ text: pendingReasoningDelta
1259
+ };
1260
+ pendingReasoningDelta = "";
1079
1261
  }
1080
- };
1262
+ yield {
1263
+ type: "block-end",
1264
+ index: reasoningIndex,
1265
+ block: {
1266
+ type: "reasoning",
1267
+ text: reasoning
1268
+ }
1269
+ };
1270
+ }
1081
1271
  if (textIndex !== null) yield {
1082
1272
  type: "block-end",
1083
1273
  index: textIndex,
@@ -1124,6 +1314,25 @@ async function* parseResponsesStream(response, signal, hiddenSandboxControls = /
1124
1314
  replayState: { outputItems: replayOutput }
1125
1315
  };
1126
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
+ }
1127
1336
  function mapUsage(value) {
1128
1337
  if (value === null) return null;
1129
1338
  const totalInput = number(value.input_tokens) ?? 0;
@@ -1738,7 +1947,10 @@ const inject = [
1738
1947
  function apply(ctx) {
1739
1948
  const oauth = new OAuthService(new WindowsDpapiTokenStore(), { logger: ctx.logger });
1740
1949
  const usage = new UsageService(oauth);
1741
- 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
+ }));
1742
1954
  ctx.effect(() => {
1743
1955
  const disposeRoutes = registerRoutes(ctx, oauth, usage);
1744
1956
  const disposeAdapter = ctx.llm.registerAdapter([PROVIDER_ID], adapter);
@@ -1749,5 +1961,8 @@ function apply(ctx) {
1749
1961
  };
1750
1962
  }, "dsh-chatgpt-subscription: adapter, routes, and lifecycle");
1751
1963
  }
1964
+ function localWebServerBaseUrl(host, port) {
1965
+ return `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${port}`;
1966
+ }
1752
1967
  //#endregion
1753
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,CAgIrF"}
@@ -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,CAsF3B"}
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-alpha.0",
3
+ "version": "0.1.1",
4
4
  "description": "DSH provider plugin for Codex access through a ChatGPT subscription.",
5
5
  "author": {
6
6
  "name": "eddyskywalker",
@@ -26,7 +26,7 @@
26
26
  "type": "module",
27
27
  "publishConfig": {
28
28
  "access": "public",
29
- "tag": "next"
29
+ "tag": "latest"
30
30
  },
31
31
  "main": "lib/index.js",
32
32
  "types": "lib/types/index.d.ts",