@hienlh/ppm 0.22.1 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/cli-reference.md +4 -4
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/{accounts-settings-section-D3BylchP.js → accounts-settings-section-CLEAA_Jc.js} +1 -1
- package/dist/web/assets/{ai-resource-editor-BLPcnhTM.js → ai-resource-editor-C4ecid2g.js} +1 -1
- package/dist/web/assets/ai-settings-section-BOwGdiyH.js +1 -0
- package/dist/web/assets/ai-settings-section-Cqz13gRt.js +1 -0
- package/dist/web/assets/{api-client-C1ZwRL4Y.js → api-client-Jn3njtNw.js} +1 -1
- package/dist/web/assets/api-client-rSFnnCj4.js +1 -0
- package/dist/web/assets/{api-settings-_7Q-ULxp.js → api-settings-BxijvPBR.js} +1 -1
- package/dist/web/assets/{api-themes-DRAERo4Q.js → api-themes-CSUarkzD.js} +1 -1
- package/dist/web/assets/{appearance-settings-section-CiMdk3sb.js → appearance-settings-section-DbA8L-Vz.js} +1 -1
- package/dist/web/assets/{audio-preview-DsYvgKqj.js → audio-preview-CxJd8wRV.js} +1 -1
- package/dist/web/assets/{branch-review-tab-B1pFjlKM.js → branch-review-tab-CMTa2uSR.js} +1 -1
- package/dist/web/assets/chat-tab-BpdgqjSL.js +15 -0
- package/dist/web/assets/{code-editor-BJhOEsnZ.js → code-editor-B7y7-5KE.js} +3 -3
- package/dist/web/assets/{codex-daily-guard-CaCQJ4r_.js → codex-daily-guard-ChDPiXDx.js} +1 -1
- package/dist/web/assets/{conflict-editor-B7u_p49h.js → conflict-editor-Axs9Ad7A.js} +1 -1
- package/dist/web/assets/{csv-preview-CttjJU1e.js → csv-preview-DTUAW2HW.js} +1 -1
- package/dist/web/assets/{database-viewer-Ca4HxIfx.js → database-viewer-qXDiWeXj.js} +1 -1
- package/dist/web/assets/{diff-viewer-9-XjLIwa.js → diff-viewer-BtLiSpqe.js} +1 -1
- package/dist/web/assets/{docx-preview-CXuk-emm.js → docx-preview-Dxvy6h13.js} +1 -1
- package/dist/web/assets/{editor-language-service-D0DuEOs_.js → editor-language-service-D75GuLXP.js} +1 -1
- package/dist/web/assets/{explorer-body-VdCBqcZu.js → explorer-body-xg1-MhlW.js} +1 -1
- package/dist/web/assets/{explorer-window-content-BIsbl7Th.js → explorer-window-content-BeQocW3i.js} +1 -1
- package/dist/web/assets/{extension-manager-section-HkY7geS5.js → extension-manager-section-Bm2v3P-n.js} +1 -1
- package/dist/web/assets/{extension-webview-DZG8YHX9.js → extension-webview-CzxrAHyL.js} +1 -1
- package/dist/web/assets/{file-icons-BXdvggK2.js → file-icons-wS-OmEVu.js} +1 -1
- package/dist/web/assets/{file-store-ojgMXgAw.js → file-store-Ds3qJ4hC.js} +1 -1
- package/dist/web/assets/{files-settings-section-qnRtkX05.js → files-settings-section-Bd-_GeZU.js} +1 -1
- package/dist/web/assets/{format-file-meta-C77h04cZ.js → format-file-meta-PPi3ptkm.js} +1 -1
- package/dist/web/assets/{general-settings-section-BAFSZmCE.js → general-settings-section-CfNPHQUk.js} +1 -1
- package/dist/web/assets/{git-log-panel-2sGpfEla.js → git-log-panel-CtGxPzH6.js} +1 -1
- package/dist/web/assets/{git-repo-store-88Z8v-pF.js → git-repo-store-BCEPfUGT.js} +1 -1
- package/dist/web/assets/{glide-data-grid-f0hyITiF.js → glide-data-grid-iSo2vP0q.js} +1 -1
- package/dist/web/assets/{group-chat-tab-Ck6sk7yY.js → group-chat-tab-D1lx0zz-.js} +1 -1
- package/dist/web/assets/{image-preview-CzCc4_Do.js → image-preview-DeGD0HJu.js} +1 -1
- package/dist/web/assets/{index-CEZVxM4G.js → index-CN0G8uYY.js} +5 -5
- package/dist/web/assets/{jira-watcher-section-CeLmhvu1.js → jira-watcher-section-kyifZPTv.js} +1 -1
- package/dist/web/assets/keybindings-store-L5vV8DEJ.js +1 -0
- package/dist/web/assets/{keyboard-shortcuts-section-PVz6kuh2.js → keyboard-shortcuts-section-D2uJq4x9.js} +1 -1
- package/dist/web/assets/{markdown-renderer-C140Ijk0.js → markdown-renderer-BX1Q00sC.js} +1 -1
- package/dist/web/assets/markdown-renderer-CLUux0vA.js +1 -0
- package/dist/web/assets/{media-url-yfqHpPz0.js → media-url-DKK0YHxL.js} +1 -1
- package/dist/web/assets/{mobile-explorer-sheet-CUG_owdf.js → mobile-explorer-sheet-BHQDzpwK.js} +1 -1
- package/dist/web/assets/notification-store-BHgSy-ci.js +1 -0
- package/dist/web/assets/panel-store-D20Zuf3i.js +1 -0
- package/dist/web/assets/{pdf-preview-CmBI6E7d.js → pdf-preview-DAcfhfGm.js} +1 -1
- package/dist/web/assets/{postgres-viewer-8ZAqEALv.js → postgres-viewer-DPRsmgP5.js} +1 -1
- package/dist/web/assets/{ppmbot-settings-section-Cji-Mil-.js → ppmbot-settings-section-B5N1jHgm.js} +1 -1
- package/dist/web/assets/{problems-panel-a6_hrWvl.js → problems-panel-D_wZ4_Qg.js} +1 -1
- package/dist/web/assets/{process-table-CiIqlOIK.js → process-table-DahflyQn.js} +1 -1
- package/dist/web/assets/{project-framework-store-B70Q3dNM.js → project-framework-store-ViZgce6y.js} +1 -1
- package/dist/web/assets/{project-store-B87hLRSk.js → project-store-hNvwfqX3.js} +1 -1
- package/dist/web/assets/{proxy-settings-section-BjI4IFgp.js → proxy-settings-section-CLg_nlxn.js} +1 -1
- package/dist/web/assets/{query-audit-section-By6qyqdB.js → query-audit-section-BrfSo0s_.js} +1 -1
- package/dist/web/assets/{remote-desktop-clipboard-notice-eXYvwgx7.js → remote-desktop-clipboard-notice-Fi6cieGM.js} +1 -1
- package/dist/web/assets/{remote-desktop-mobile-sheet-Doh-fci-.js → remote-desktop-mobile-sheet-lLZ-oK73.js} +2 -2
- package/dist/web/assets/{remote-desktop-mobile-view-Dt8Akc3p.js → remote-desktop-mobile-view-j3v-4rYa.js} +1 -1
- package/dist/web/assets/{remote-desktop-readiness-gate-t83fqbID.js → remote-desktop-readiness-gate-CeLvcX_w.js} +1 -1
- package/dist/web/assets/{remote-desktop-window-content-CguhZMmx.js → remote-desktop-window-content-lwbkLsTC.js} +1 -1
- package/dist/web/assets/{run-in-terminal-CdefEe_R.js → run-in-terminal-D7W4IKb9.js} +1 -1
- package/dist/web/assets/{schedules-settings-section-BVkpW5ms.js → schedules-settings-section-C8OS0o80.js} +1 -1
- package/dist/web/assets/{send-to-chat-F207yH3u.js → send-to-chat-DNKhmHbi.js} +1 -1
- package/dist/web/assets/{settings-body-CoIxYAh6.js → settings-body-DgN22Z0W.js} +2 -2
- package/dist/web/assets/{settings-store-krC6bc79.js → settings-store-CsVSVgLp.js} +2 -2
- package/dist/web/assets/{settings-tab-7DKVUTbM.js → settings-tab-ChOs94iB.js} +1 -1
- package/dist/web/assets/{settings-window-content-3_39TeX-.js → settings-window-content-BnKMmg2a.js} +1 -1
- package/dist/web/assets/{sql-query-editor-CQB7Yp7U.js → sql-query-editor-BJZIIQsm.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-Bd7rjr1D.js → sqlite-viewer--cMeCZum.js} +1 -1
- package/dist/web/assets/{system-monitor-body-DsRXeMyU.js → system-monitor-body-CXiIrn0N.js} +2 -2
- package/dist/web/assets/system-monitor-tab-BJKrTSl0.js +1 -0
- package/dist/web/assets/{system-monitor-window-content-ClPo4-El.js → system-monitor-window-content-Dy9fZJE3.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-d2TAD4PU.js → tab-host-window-content-BezqrAwC.js} +1 -1
- package/dist/web/assets/{tab-store-OJa1GPCq.js → tab-store-krAuHQ6_.js} +1 -1
- package/dist/web/assets/{team-member-sheet-7d2Qp-ie.js → team-member-sheet-CVM2QC3H.js} +2 -2
- package/dist/web/assets/{team-member-window-content-Bctg2gmg.js → team-member-window-content-D4RYKplm.js} +1 -1
- package/dist/web/assets/{terminal-tab-0HQic25V.js → terminal-tab-jikhQLct.js} +1 -1
- package/dist/web/assets/{tool-cards-CmLLRACd.js → tool-cards-D5jCQvqn.js} +2 -2
- package/dist/web/assets/{use-blob-url-CPtCcY3i.js → use-blob-url-DMGlPCQD.js} +1 -1
- package/dist/web/assets/{use-inline-blame-sDMjcz1-.js → use-inline-blame-BF8Y1KfV.js} +1 -1
- package/dist/web/assets/{use-lsp-CBgID-EU.js → use-lsp-Bx4oVtlk.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-gvhJ_jZh.js → use-monaco-theme-DHczXLMb.js} +1 -1
- package/dist/web/assets/{use-websocket-C9wlRliB.js → use-websocket-BWZkbleJ.js} +1 -1
- package/dist/web/assets/{video-preview-CSDK5j6H.js → video-preview-D191TvX9.js} +1 -1
- package/dist/web/assets/{window-pip-registry-yD6esSju.js → window-pip-registry-D1oXq-Dq.js} +1 -1
- package/dist/web/assets/ws-auth-BG-cdrQ8.js +1 -0
- package/dist/web/index.html +13 -13
- package/dist/web/sw.js +1 -1
- package/docs/architecture/workspace-and-ui.md +13 -0
- package/package.json +1 -1
- package/src/cli/commands/init.ts +1 -0
- package/src/providers/codex-app-server/codex-history.ts +26 -7
- package/src/providers/codex-app-server/codex-provider.ts +6 -4
- package/src/server/routes/chat.ts +1 -1
- package/src/server/routes/settings.ts +11 -5
- package/src/services/config.service.ts +2 -0
- package/src/types/chat.ts +1 -1
- package/src/types/config.ts +12 -1
- package/src/web/components/chat/chat-tab.tsx +162 -38
- package/src/web/components/chat/message-input.tsx +24 -0
- package/src/web/components/chat/model-thinking-selector.tsx +25 -5
- package/src/web/components/chat/new-chat-provider-gate.tsx +68 -0
- package/src/web/components/layout/editor-panel.tsx +1 -1
- package/src/web/components/layout/reparenting-tab.tsx +4 -2
- package/src/web/components/layout/tab-bar.tsx +1 -1
- package/src/web/components/settings/ai-settings-section.tsx +36 -0
- package/src/web/hooks/use-draft.ts +25 -4
- package/src/web/hooks/use-usage.ts +6 -4
- package/src/web/lib/api-client.ts +7 -1
- package/src/web/lib/api-settings.ts +1 -0
- package/src/web/lib/new-chat-provider.ts +8 -0
- package/src/web/stores/panel-store.ts +46 -3
- package/dist/web/assets/ai-settings-section-BtR7rF-T.js +0 -1
- package/dist/web/assets/ai-settings-section-r9JctHNM.js +0 -1
- package/dist/web/assets/api-client-pQL53cDQ.js +0 -1
- package/dist/web/assets/chat-tab-DZagX06m.js +0 -15
- package/dist/web/assets/keybindings-store-C_3ChOEf.js +0 -1
- package/dist/web/assets/markdown-renderer-Dz7-DYUg.js +0 -1
- package/dist/web/assets/notification-store-6vib1ISy.js +0 -1
- package/dist/web/assets/panel-store-CboGJAwh.js +0 -1
- package/dist/web/assets/system-monitor-tab-DdSZgux3.js +0 -1
- package/dist/web/assets/ws-auth-CEYVQ8NH.js +0 -1
|
@@ -26,8 +26,9 @@ interface UseUsageReturn {
|
|
|
26
26
|
* `sessionId` scopes the reported account to this session's binding. Without it the header
|
|
27
27
|
* shows whichever account ran last across every open session, which is wrong for all but one.
|
|
28
28
|
*/
|
|
29
|
-
export function useUsage(projectName: string, providerId = "claude", sessionId?: string): UseUsageReturn {
|
|
30
|
-
const
|
|
29
|
+
export function useUsage(projectName: string, providerId = "claude", sessionId?: string, pickedAccountId?: string): UseUsageReturn {
|
|
30
|
+
const previewAccountId = providerId === "codex" && !sessionId ? pickedAccountId : undefined;
|
|
31
|
+
const scope = JSON.stringify([projectName, providerId, sessionId, previewAccountId]);
|
|
31
32
|
const [snapshot, setSnapshot] = useState<{ scope: string; usage: UsageInfo; fetchedAt: string | null } | null>(null);
|
|
32
33
|
const [usageLoading, setUsageLoading] = useState(false);
|
|
33
34
|
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
@@ -39,11 +40,12 @@ export function useUsage(projectName: string, providerId = "claude", sessionId?:
|
|
|
39
40
|
setUsageLoading(true);
|
|
40
41
|
const qs = forceRefresh ? "&refresh=1" : "";
|
|
41
42
|
const sessionQs = sessionId ? `&session=${encodeURIComponent(sessionId)}` : "";
|
|
43
|
+
const accountQs = previewAccountId ? `&accountId=${encodeURIComponent(previewAccountId)}` : "";
|
|
42
44
|
// Via api.get, not raw fetch: the toolbar's loading state is gated on this
|
|
43
45
|
// settling, and a raw fetch has no timeout to stop it stalling forever.
|
|
44
46
|
return api
|
|
45
47
|
.get<(UsageInfo & { lastFetchedAt?: string }) | null>(
|
|
46
|
-
`${projectUrl(projectName)}/chat/usage?providerId=${providerId}${sessionQs}${qs}`,
|
|
48
|
+
`${projectUrl(projectName)}/chat/usage?providerId=${providerId}${sessionQs}${accountQs}${qs}`,
|
|
47
49
|
)
|
|
48
50
|
.then((data) => {
|
|
49
51
|
if (request !== requestRef.current) return;
|
|
@@ -55,7 +57,7 @@ export function useUsage(projectName: string, providerId = "claude", sessionId?:
|
|
|
55
57
|
.finally(() => {
|
|
56
58
|
if (request === requestRef.current) setUsageLoading(false);
|
|
57
59
|
});
|
|
58
|
-
}, [projectName, providerId, sessionId, scope]);
|
|
60
|
+
}, [projectName, providerId, sessionId, previewAccountId, scope]);
|
|
59
61
|
|
|
60
62
|
// Read cache on mount + auto-read every POLL_INTERVAL
|
|
61
63
|
useEffect(() => {
|
|
@@ -122,11 +122,17 @@ export class ApiClient {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
/**
|
|
126
|
+
* No default timeout, unlike `get`: a POST is not idempotent, so cutting one off
|
|
127
|
+
* mid-flight can leave the server having done the work with nobody to tell. A
|
|
128
|
+
* caller that would rather fail loudly than wait passes its own `signal`.
|
|
129
|
+
*/
|
|
130
|
+
async post<T>(path: string, body?: unknown, options?: { signal?: AbortSignal }): Promise<T> {
|
|
126
131
|
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
127
132
|
method: "POST",
|
|
128
133
|
headers: this.headers(),
|
|
129
134
|
body: body != null ? JSON.stringify(body) : undefined,
|
|
135
|
+
signal: options?.signal,
|
|
130
136
|
});
|
|
131
137
|
return this.handleResponse<T>(res);
|
|
132
138
|
}
|
|
@@ -212,6 +212,7 @@ export interface AIProviderSettings {
|
|
|
212
212
|
|
|
213
213
|
export interface AISettings {
|
|
214
214
|
default_provider: string;
|
|
215
|
+
new_chat_provider_mode?: "default" | "follow-focus";
|
|
215
216
|
share_provider_context?: boolean;
|
|
216
217
|
providers: Record<string, AIProviderSettings>;
|
|
217
218
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AISettings } from "./api-settings";
|
|
2
|
+
|
|
3
|
+
/** The source is captured when the tab opens, before another panel can gain focus. */
|
|
4
|
+
export function resolveNewChatProvider(settings: AISettings, focusedProvider?: string): string {
|
|
5
|
+
return settings.new_chat_provider_mode === "follow-focus" && focusedProvider
|
|
6
|
+
? focusedProvider
|
|
7
|
+
: settings.default_provider || "claude";
|
|
8
|
+
}
|
|
@@ -89,6 +89,8 @@ export interface PanelStore {
|
|
|
89
89
|
grid: string[][];
|
|
90
90
|
focusedPanelId: string;
|
|
91
91
|
currentProject: string | null;
|
|
92
|
+
/** Session-local focus memory, isolated by project; non-chat tabs do not clear it. */
|
|
93
|
+
lastFocusedChatProviders: Record<string, string>;
|
|
92
94
|
|
|
93
95
|
/** Keep-alive: per-project grid snapshots (for hidden workspaces) */
|
|
94
96
|
projectGrids: Record<string, string[][]>;
|
|
@@ -106,7 +108,7 @@ export interface PanelStore {
|
|
|
106
108
|
reloadProject: (projectName: string) => void;
|
|
107
109
|
|
|
108
110
|
// Panel focus
|
|
109
|
-
setFocusedPanel: (panelId: string) => void;
|
|
111
|
+
setFocusedPanel: (panelId: string, rememberChat?: boolean) => void;
|
|
110
112
|
|
|
111
113
|
// Tab operations (operate on focused panel by default)
|
|
112
114
|
openTab: (tab: Omit<Tab, "id">, panelId?: string) => string;
|
|
@@ -210,6 +212,7 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
210
212
|
return {
|
|
211
213
|
...defaultLayout(),
|
|
212
214
|
currentProject: null,
|
|
215
|
+
lastFocusedChatProviders: {},
|
|
213
216
|
projectGrids: {},
|
|
214
217
|
projectFocused: {},
|
|
215
218
|
dock: { visible: false, height: 30 },
|
|
@@ -459,10 +462,13 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
459
462
|
get().switchProject(projectName);
|
|
460
463
|
},
|
|
461
464
|
|
|
462
|
-
setFocusedPanel: (panelId) => {
|
|
465
|
+
setFocusedPanel: (panelId, rememberChat = true) => {
|
|
463
466
|
// Focus drives where the next tab opens, so it must stay on a real, on-grid panel.
|
|
464
467
|
if (isWindowPanelId(panelId)) return;
|
|
465
|
-
|
|
468
|
+
const panel = get().panels[panelId];
|
|
469
|
+
if (!panel) return;
|
|
470
|
+
set({ focusedPanelId: panelId });
|
|
471
|
+
if (rememberChat) rememberChatProvider(panel.tabs.find((t) => t.id === panel.activeTabId));
|
|
466
472
|
},
|
|
467
473
|
|
|
468
474
|
openTab: (tabDef, panelId?) => {
|
|
@@ -474,6 +480,15 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
474
480
|
const panel = get().panels[pid];
|
|
475
481
|
if (!panel) return "";
|
|
476
482
|
|
|
483
|
+
if (tabDef.type === "chat" && !tabDef.metadata?.sessionId && !tabDef.metadata?.providerId) {
|
|
484
|
+
const project = tabDef.projectId ?? (tabDef.metadata?.projectName as string | undefined) ?? get().currentProject;
|
|
485
|
+
tabDef = { ...tabDef, metadata: {
|
|
486
|
+
...tabDef.metadata,
|
|
487
|
+
providerPending: true,
|
|
488
|
+
focusedProviderOnOpen: project ? get().lastFocusedChatProviders[project] : undefined,
|
|
489
|
+
} };
|
|
490
|
+
}
|
|
491
|
+
|
|
477
492
|
// Terminal: compute next available index if not provided
|
|
478
493
|
if (tabDef.type === "terminal" && !tabDef.metadata?.terminalIndex) {
|
|
479
494
|
const allTabs = Object.values(get().panels).flatMap((p) => p.tabs);
|
|
@@ -499,6 +514,7 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
499
514
|
for (const p of Object.values(get().panels)) {
|
|
500
515
|
const existing = p.tabs.find((t) => t.type === "chat" && t.metadata?.sessionId === sid);
|
|
501
516
|
if (existing) {
|
|
517
|
+
rememberChatProvider(existing);
|
|
502
518
|
set((s) => ({
|
|
503
519
|
focusedPanelId: focusAfterActivate(p.id),
|
|
504
520
|
panels: {
|
|
@@ -664,6 +680,7 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
664
680
|
setActiveTab: (tabId, panelId?) => {
|
|
665
681
|
const panel = panelId ? get().panels[panelId] : findPanel(tabId);
|
|
666
682
|
if (!panel) return;
|
|
683
|
+
rememberChatProvider(panel.tabs.find((t) => t.id === tabId));
|
|
667
684
|
const pid = panel.id;
|
|
668
685
|
set((s) => {
|
|
669
686
|
const p = s.panels[pid]!;
|
|
@@ -862,3 +879,29 @@ export const usePanelStore = create<PanelStore>()((set, get) => {
|
|
|
862
879
|
isMobile: () => typeof window !== "undefined" && window.innerWidth < 768,
|
|
863
880
|
};
|
|
864
881
|
});
|
|
882
|
+
|
|
883
|
+
// Observe activation as well as a provider change in the focused composer. Updates
|
|
884
|
+
// from background chats must never replace the user's most recent focus choice.
|
|
885
|
+
function rememberChatProvider(tab: Tab | undefined) {
|
|
886
|
+
const state = usePanelStore.getState();
|
|
887
|
+
if (tab?.type !== "chat" || tab.metadata?.providerPending) return;
|
|
888
|
+
const project = tab.projectId ?? (tab.metadata?.projectName as string | undefined) ?? state.currentProject;
|
|
889
|
+
const provider = (tab.metadata?.providerId as string | undefined) ?? "claude";
|
|
890
|
+
if (!project || state.lastFocusedChatProviders[project] === provider) return;
|
|
891
|
+
usePanelStore.setState({ lastFocusedChatProviders: {
|
|
892
|
+
...state.lastFocusedChatProviders, [project]: provider,
|
|
893
|
+
} });
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
usePanelStore.subscribe((state, previous) => {
|
|
897
|
+
const panel = state.panels[state.focusedPanelId];
|
|
898
|
+
const tab = panel?.tabs.find((t) => t.id === panel.activeTabId);
|
|
899
|
+
// A panel's chrome can change the destination for new tabs without focusing
|
|
900
|
+
// its chat. Actual body/tab focus is recorded explicitly by the actions above.
|
|
901
|
+
const oldPanel = previous.panels[state.focusedPanelId];
|
|
902
|
+
const oldTab = oldPanel?.tabs.find((t) => t.id === oldPanel.activeTabId);
|
|
903
|
+
if (tab?.id === oldTab?.id
|
|
904
|
+
&& tab?.metadata?.providerId === oldTab?.metadata?.providerId
|
|
905
|
+
&& state.currentProject === previous.currentProject) return;
|
|
906
|
+
rememberChatProvider(tab);
|
|
907
|
+
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import"./icons-DQjqk0lJ.js";import"./api-client-C1ZwRL4Y.js";import"./portal-container-context-BarKmT4S.js";import"./panel-store-CboGJAwh.js";import"./window-store-UC1jJeLM.js";import"./tab-store-OJa1GPCq.js";import"./use-is-mobile-TkcwP1Gx.js";import"./input-C7Q8FxeL.js";import{t as e}from"./ai-settings-section-r9JctHNM.js";export{e as AISettingsSection};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{C as t,S as n}from"./vendor-markdown-CuWCHIVb.js";import{Qn as r,ct as i,wr as a}from"./icons-DQjqk0lJ.js";import{n as o}from"./api-client-C1ZwRL4Y.js";import{t as s}from"./input-C7Q8FxeL.js";import{G as c,J as l,K as u,W as d,Y as f,fn as p,q as m,rn as h,rt as g}from"./index-CEZVxM4G.js";import{getAISettings as _,updateAISettings as v}from"./api-settings-_7Q-ULxp.js";var y=e(t(),1),b=n(),x=[128e3,272e3,4e5,512e3,872e3,1e6],S=[1e5,2e5,23e4,35e4,45e4,75e4,9e5];function C({id:e,label:t,value:n,presets:r,disabled:i,compact:a,onChange:o}){let[c,l]=(0,y.useState)(!!n&&!r.includes(Number(n))),u=a?`text-[11px]`:`text-sm`;return(0,b.jsxs)(`div`,{className:`space-y-1`,children:[(0,b.jsx)(g,{htmlFor:e,className:u,children:t}),(0,b.jsxs)(`select`,{id:e,value:c?`custom`:n||`default`,disabled:i,"aria-describedby":`codex-context-help`,className:`w-full min-h-11 sm:min-h-0 rounded-md border border-input bg-background px-3 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50 ${a?`h-7`:`h-9`} ${u}`,onChange:e=>{let t=e.target.value;l(t===`custom`),t!==`custom`&&o(t===`default`?``:t)},children:[(0,b.jsx)(`option`,{value:`default`,children:`Codex default`}),r.map(e=>(0,b.jsxs)(`option`,{value:String(e),children:[e===1e6?`1M`:`${e/1e3}K`,` tokens`]},e)),(0,b.jsx)(`option`,{value:`custom`,children:`Custom...`})]}),c&&(0,b.jsx)(s,{id:`${e}-custom`,"aria-label":`Custom ${t.toLowerCase()}`,type:`number`,min:1,step:1,required:!0,value:n,disabled:i,placeholder:`Enter tokens`,"aria-describedby":`codex-context-help`,className:`min-h-11 sm:min-h-0 ${a?`h-7 text-[11px]`:``}`,onChange:e=>o(e.target.value)})]})}function w({config:e,compact:t,saving:n,onSave:r}){let[i,a]=(0,y.useState)(String(e?.model_context_window??``)),[o,s]=(0,y.useState)(String(e?.model_auto_compact_token_limit??``)),[c,l]=(0,y.useState)(null),u=t?`text-[11px]`:`text-sm`,d=t?`text-[9px]`:`text-[11px]`;async function f(e){e.preventDefault();let t=i.trim()?Number(i):null,n=o.trim()?Number(o):null;if([t,n].some(e=>e!==null&&(!Number.isSafeInteger(e)||e<=0))){l(`Enter positive whole numbers of tokens, or leave blank for Codex defaults.`);return}if(t!==null&&n!==null&&n>t){l(`Auto-compact threshold must not exceed the context window.`);return}l(null),await r({model_context_window:t,model_auto_compact_token_limit:n})}return(0,b.jsxs)(`form`,{onSubmit:f,className:`space-y-2 rounded-md border border-border p-3`,children:[(0,b.jsxs)(`div`,{className:`grid grid-cols-1 gap-3 sm:grid-cols-2`,children:[(0,b.jsx)(C,{id:`codex-context-window`,label:`Context window (tokens)`,value:i,presets:x,disabled:n,compact:t,onChange:e=>{a(e),l(null)}}),(0,b.jsx)(C,{id:`codex-compact-threshold`,label:`Auto-compact threshold (tokens)`,value:o,presets:S,disabled:n,compact:t,onChange:e=>{s(e),l(null)}})]}),(0,b.jsx)(`p`,{id:`codex-context-help`,className:`${d} text-muted-foreground`,children:`Choose Codex default to use Codex configuration and model defaults, or Custom to enter a value. Presets are shortcuts, not a list of limits supported by your model; increasing these values does not unlock a larger context window. Applies to new sessions and sessions resumed after a PPM restart.`}),c&&(0,b.jsx)(`p`,{role:`alert`,className:`${u} text-error`,children:c}),(0,b.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,b.jsx)(`a`,{href:`https://learn.chatgpt.com/docs/config-file/config-reference`,target:`_blank`,rel:`noreferrer`,className:`${d} text-primary underline`,children:`Codex context documentation`}),(0,b.jsx)(`button`,{type:`submit`,disabled:n,className:`min-h-11 sm:min-h-0 rounded-md border border-border px-3 py-1.5 hover:bg-surface-elevated disabled:opacity-50 ${u}`,children:n?`Saving...`:`Save context settings`})]})]})}var T=[{value:`low`,label:`Low`},{value:`medium`,label:`Medium`},{value:`high`,label:`High`},{value:`xhigh`,label:`Extra`},{value:`max`,label:`Max`}],E=[{value:`bypassPermissions`,label:`Bypass permissions (default)`},{value:`default`,label:`Ask before edits`},{value:`acceptEdits`,label:`Edit automatically`},{value:`plan`,label:`Plan mode`}],D={claude:`Claude`,cursor:`Cursor`,codex:`Codex`,gemini:`Gemini`};function O({compact:e}={}){let[t,n]=(0,y.useState)(null),[r,a]=(0,y.useState)(``),[x,S]=(0,y.useState)([]),[C,O]=(0,y.useState)(!1),[A,j]=(0,y.useState)(!1),[M,N]=(0,y.useState)(null),[P,F]=(0,y.useState)(0);(0,y.useEffect)(()=>{_().then(e=>{n(e),a(e.default_provider??`claude`)}).catch(e=>N(e.message))},[]),(0,y.useEffect)(()=>{r&&(O(!0),o.get(`/api/settings/ai/providers/${r}/models`).then(S).catch(()=>S([])).finally(()=>O(!1)))},[r]);let I=t?Object.keys(t.providers).filter(e=>e!==`mock`).map(e=>({id:e,name:D[e]??e})):[],L=t?.providers[r],R=L?.type===`agent-sdk`||!L?.type&&r===`claude`,z=async e=>{if(!t)return!1;j(!0),N(null);try{return n(await v(e)),F(e=>e+1),!0}catch(e){return N(e.message),!1}finally{j(!1)}},B=(e,t)=>z({providers:{[r]:{[e]:t}}}),V=e?`text-[11px]`:`text-sm`,H=e?`text-xs`:`text-sm`,U=e?`space-y-2`:`space-y-4`,W=e?`space-y-1.5`:`space-y-3`,G=e?`space-y-1`:`space-y-1.5`;if(!t)return(0,b.jsxs)(`div`,{className:W,children:[(0,b.jsx)(`h3`,{className:`${H} font-medium text-text-secondary`,children:`AI Settings`}),(0,b.jsx)(`p`,{className:`${V} text-text-subtle`,children:M?`Error: ${M}`:`Loading...`})]});let K=R?x:[{value:`__default__`,label:`Auto (default)`},...x];return(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(`h3`,{className:`${H} font-medium text-text-secondary`,children:`AI Settings`}),(0,b.jsxs)(`div`,{className:`flex items-start justify-between gap-3 rounded-md border border-border p-3`,children:[(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-share-provider-context`,className:e?V:void 0,children:`Share rules and memory between providers`}),(0,b.jsx)(`p`,{id:`ai-share-provider-context-description`,className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Share project rules and memory, plus global instruction files, across providers. Applies from the next project-chat message. Turning off keeps context already sent.`})]}),(0,b.jsx)(f,{id:`ai-share-provider-context`,"aria-describedby":`ai-share-provider-context-description`,checked:t.share_provider_context??!0,disabled:A,onCheckedChange:e=>z({share_provider_context:e})})]}),I.length>1&&(0,b.jsx)(`div`,{className:`flex gap-0.5 border-b border-border/50 -mx-1 px-1`,children:I.map(e=>(0,b.jsxs)(`button`,{onClick:()=>a(e.id),className:`flex items-center gap-1 px-2 py-1 text-[11px] rounded-t transition-colors ${r===e.id?`text-primary border-b-2 border-primary font-medium`:`text-text-subtle hover:text-text-secondary`}`,children:[(0,b.jsx)(p,{providerId:e.id}),(0,b.jsx)(`span`,{className:`capitalize`,children:e.name})]},e.id))}),(0,b.jsxs)(`div`,{className:W,children:[r===`codex`&&(0,b.jsxs)(`button`,{type:`button`,onClick:()=>h(`accounts`),className:`w-full flex items-center justify-between gap-2 rounded-md border border-border px-2.5 py-2 text-left cursor-pointer hover:bg-surface-elevated transition-colors`,children:[(0,b.jsx)(`span`,{className:`${V} text-text-secondary`,children:`Codex accounts & login`}),(0,b.jsx)(i,{className:`size-3.5 text-text-subtle shrink-0`})]}),x.length>0&&(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-model`,className:e?V:void 0,children:`Model`}),(0,b.jsxs)(d,{value:R?L?.model??x[0]?.value:L?.model||`__default__`,onValueChange:e=>B(`model`,e===`__default__`?void 0:e),disabled:C,children:[(0,b.jsx)(m,{id:`ai-model`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(l,{placeholder:C?`Loading models...`:`Select model`})}),(0,b.jsx)(c,{className:`max-h-[300px]`,children:K.map(e=>(0,b.jsx)(u,{value:e.value,children:e.label},e.value))})]})]}),r===`codex`&&(0,b.jsx)(w,{config:L,compact:e,saving:A,onSave:e=>z({providers:{codex:e}})},JSON.stringify([L?.model_context_window,L?.model_auto_compact_token_limit])),R&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-base-url`,className:e?V:void 0,children:`Base URL`}),(0,b.jsx)(s,{id:`ai-base-url`,type:`url`,defaultValue:L?.base_url??``,placeholder:`https://api.anthropic.com (default)`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{B(`base_url`,e.target.value.trim()||void 0)}},`baseurl-${r}-${P}`)]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-api-key`,className:e?V:void 0,children:`API Key / Token`}),(0,b.jsx)(s,{id:`ai-api-key`,type:`password`,defaultValue:L?.api_key??``,placeholder:`sk-ant-... (optional, overrides accounts)`,className:e?`h-7 text-[11px] font-mono`:`font-mono`,onBlur:e=>{let t=e.target.value.trim();t.startsWith(`••••`)||B(`api_key`,t||void 0)}},`apikey-${r}-${P}`),(0,b.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Direct API key or OAuth token. Leave empty to use connected accounts.`})]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-effort`,className:e?V:void 0,children:`Effort`}),(0,b.jsxs)(d,{value:L?.effort??`high`,onValueChange:e=>B(`effort`,e),children:[(0,b.jsx)(m,{id:`ai-effort`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(l,{})}),(0,b.jsx)(c,{children:T.map(e=>(0,b.jsx)(u,{value:e.value,children:e.label},e.value))})]})]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-max-turns`,className:e?V:void 0,children:`Max Turns (1-500)`}),(0,b.jsx)(s,{id:`ai-max-turns`,type:`number`,min:1,max:500,defaultValue:L?.max_turns??100,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);isNaN(t)||B(`max_turns`,t)}},`turns-${r}-${P}`)]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-budget`,className:e?V:void 0,children:`Max Budget (USD)`}),(0,b.jsx)(s,{id:`ai-budget`,type:`number`,step:.1,min:.01,max:50,defaultValue:L?.max_budget_usd??``,placeholder:`No limit`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseFloat(e.target.value);B(`max_budget_usd`,isNaN(t)?void 0:t)}},`budget-${r}-${P}`)]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-thinking`,className:e?V:void 0,children:`Thinking Budget (tokens)`}),(0,b.jsx)(s,{id:`ai-thinking`,type:`number`,min:0,defaultValue:L?.thinking_budget_tokens??``,placeholder:`Adaptive (model decides)`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);B(`thinking_budget_tokens`,isNaN(t)?void 0:t)}},`thinking-${r}-${P}`)]}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(g,{htmlFor:`ai-agent-teams`,className:e?V:void 0,children:`Agent Teams`}),(0,b.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Experimental. Enables multi-agent collaboration with shared tasks and messaging. Uses ~7x more tokens.`})]}),(0,b.jsx)(f,{id:`ai-agent-teams`,checked:L?.agent_teams??!1,onCheckedChange:e=>B(`agent_teams`,e)})]}),L?.agent_teams&&(0,b.jsx)(k,{compact:e}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(g,{htmlFor:`ai-context-1m`,className:e?V:void 0,children:`1M Context Window`}),(0,b.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Requires an entitled account (Max/Team/Enterprise) and an Opus 4 / Sonnet 4 model. Other accounts will error.`})]}),(0,b.jsx)(f,{id:`ai-context-1m`,checked:L?.context_1m??!1,onCheckedChange:e=>B(`context_1m`,e)})]}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(g,{htmlFor:`ai-inherit-mcp`,className:e?V:void 0,children:`Inherit Claude Code MCP`}),(0,b.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Auto-load MCP servers from Claude Code's ~/.claude.json (global + per-project). Your own MCP servers override inherited ones.`})]}),(0,b.jsx)(f,{id:`ai-inherit-mcp`,checked:L?.inherit_claude_mcp??!0,onCheckedChange:e=>B(`inherit_claude_mcp`,e)})]})]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-permission-mode`,className:e?V:void 0,children:`Default Permission Mode`}),(0,b.jsxs)(d,{value:L?.permission_mode??`bypassPermissions`,onValueChange:e=>B(`permission_mode`,e),children:[(0,b.jsx)(m,{id:`ai-permission-mode`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(l,{})}),(0,b.jsx)(c,{children:E.map(e=>(0,b.jsx)(u,{value:e.value,children:e.label},e.value))})]})]}),(0,b.jsxs)(`div`,{className:G,children:[(0,b.jsx)(g,{htmlFor:`ai-system-prompt`,className:e?V:void 0,children:`Additional Instructions`}),(0,b.jsx)(`textarea`,{id:`ai-system-prompt`,rows:e?3:4,defaultValue:L?.system_prompt??``,placeholder:`Enter additional instructions for ${r}...`,className:`w-full rounded-md border border-input bg-background px-3 py-2 ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${e?`text-[11px]`:`text-sm`}`,onBlur:e=>{B(`system_prompt`,e.target.value.trim()||void 0)}},`sysprompt-${r}-${P}`)]})]}),A&&(0,b.jsx)(`p`,{className:`text-xs text-text-subtle`,children:`Saving...`}),M&&(0,b.jsx)(`p`,{className:`text-xs text-error`,children:M})]})}function k({compact:e}){let[t,n]=(0,y.useState)([]),[i,s]=(0,y.useState)(!1),[c,l]=(0,y.useState)(null),u=(0,y.useCallback)(async()=>{s(!0);try{n(await o.get(`/api/teams`)??[])}catch{}s(!1)},[]);(0,y.useEffect)(()=>{u()},[u]);let d=async e=>{try{await o.del(`/api/teams/${encodeURIComponent(e)}`),n(t=>t.filter(t=>t.name!==e)),l(null)}catch{}};return t.length===0&&!i?null:(0,b.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,b.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,b.jsxs)(g,{className:e?`text-[11px]`:void 0,children:[`Teams (`,t.length,`)`]}),(0,b.jsx)(`button`,{onClick:u,className:`text-text-subtle hover:text-foreground p-1`,"aria-label":`Refresh teams`,children:(0,b.jsx)(r,{className:`size-3 ${i?`animate-spin`:``}`})})]}),t.map(e=>(0,b.jsxs)(`div`,{className:`flex items-center justify-between p-2 rounded bg-surface-elevated text-xs`,children:[(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`div`,{className:`font-medium truncate`,children:e.name}),e.description&&(0,b.jsx)(`div`,{className:`text-text-subtle truncate`,children:e.description}),(0,b.jsxs)(`div`,{className:`text-text-subtle`,children:[e.members?.length??e.memberCount??0,` members`,e.createdAt?` · ${new Date(e.createdAt).toLocaleDateString()}`:``]})]}),c===e.name?(0,b.jsxs)(`div`,{className:`flex gap-1 shrink-0 ml-2`,children:[(0,b.jsx)(`button`,{onClick:()=>d(e.name),className:`px-2 py-1 bg-error text-white rounded text-[10px]`,children:`Delete`}),(0,b.jsx)(`button`,{onClick:()=>l(null),className:`px-2 py-1 bg-panel-2 text-text rounded text-[10px]`,children:`Cancel`})]}):(0,b.jsx)(`button`,{onClick:()=>l(e.name),className:`shrink-0 text-text-subtle hover:text-error p-1 ml-2`,"aria-label":`Delete team ${e.name}`,children:(0,b.jsx)(a,{className:`size-3.5`})})]},e.name))]})}export{O as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./vendor-markdown-CuWCHIVb.js";import"./vendor-ui-DmZ-Mb-H.js";import{i as e,n as t}from"./api-client-C1ZwRL4Y.js";export{t as api,e as projectUrl};
|