@hienlh/ppm 0.20.5 → 0.20.6
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 +10 -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-Cmmozwer.js → accounts-settings-section-B-F7U-gq.js} +1 -1
- package/dist/web/assets/{ai-resource-editor-BlrWV3xU.js → ai-resource-editor-qRHwpktf.js} +1 -1
- package/dist/web/assets/{ai-settings-section-dDsgddSt.js → ai-settings-section-BePrVceb.js} +1 -1
- package/dist/web/assets/ai-settings-section-DSlsTrpf.js +1 -0
- package/dist/web/assets/{appearance-settings-section-DRxziHFt.js → appearance-settings-section-BMlkj9U2.js} +1 -1
- package/dist/web/assets/chat-tab-DmqV3MlC.js +15 -0
- package/dist/web/assets/{code-editor-DYkmDRRF.js → code-editor-C4CriX9c.js} +2 -2
- package/dist/web/assets/{conflict-editor-D9_sr59D.js → conflict-editor-LfQoRcK-.js} +1 -1
- package/dist/web/assets/{csv-preview-BMC8jnpF.js → csv-preview-BEYKn68B.js} +1 -1
- package/dist/web/assets/{database-viewer-Box3z5-Q.js → database-viewer-BL9R-ciJ.js} +1 -1
- package/dist/web/assets/{diff-viewer-B4PlZ1Dt.js → diff-viewer-D91SI_zb.js} +1 -1
- package/dist/web/assets/{explorer-body-SvWDS84f.js → explorer-body-ColVUjgk.js} +1 -1
- package/dist/web/assets/{explorer-window-content-DBHBTA7B.js → explorer-window-content-VSMJfZC2.js} +1 -1
- package/dist/web/assets/{extension-manager-section-BSt5I_H8.js → extension-manager-section-B-BRHGu1.js} +1 -1
- package/dist/web/assets/{extension-webview-DBGMUU97.js → extension-webview-DufzanN9.js} +1 -1
- package/dist/web/assets/{files-settings-section-0dwYLZou.js → files-settings-section-Do5YbTUK.js} +1 -1
- package/dist/web/assets/{general-settings-section-BgLy_6yj.js → general-settings-section-B-n_PYzs.js} +1 -1
- package/dist/web/assets/{git-log-panel-BkgmcWk1.js → git-log-panel-BQzOHgxG.js} +1 -1
- package/dist/web/assets/{glide-data-grid-CZVu-zCw.js → glide-data-grid-BUS44oLM.js} +1 -1
- package/dist/web/assets/{group-chat-tab-Cy9zIynj.js → group-chat-tab-CkHXqorZ.js} +1 -1
- package/dist/web/assets/{index-CuYtJ5xF.css → index-B9Wbjl0o.css} +1 -1
- package/dist/web/assets/{index-DYGLdCpe.js → index-Cx1meAwb.js} +4 -4
- package/dist/web/assets/{jira-watcher-section-DRQx632s.js → jira-watcher-section-BQ4hVqWo.js} +1 -1
- package/dist/web/assets/{keybindings-store-C2HZ1mT4.js → keybindings-store-yYx88hvw.js} +1 -1
- package/dist/web/assets/{keyboard-shortcuts-section-WiZSZ-Wr.js → keyboard-shortcuts-section-BZUYdXGx.js} +1 -1
- package/dist/web/assets/{markdown-renderer-BFYBVcZP.js → markdown-renderer-BA3C2L-a.js} +1 -1
- package/dist/web/assets/{markdown-renderer-CklcWnd6.js → markdown-renderer-CMFkajd7.js} +1 -1
- package/dist/web/assets/{mobile-explorer-sheet-D1OXw7op.js → mobile-explorer-sheet-gvO7a80O.js} +1 -1
- package/dist/web/assets/{notification-store-DyKshGRs.js → notification-store-CCh6a8RD.js} +1 -1
- package/dist/web/assets/{notifications-settings-section-BEQEjvan.js → notifications-settings-section-JQ3l-Qp-.js} +1 -1
- package/dist/web/assets/{pdf-preview-DmQazeeV.js → pdf-preview-B-JAU8JV.js} +1 -1
- package/dist/web/assets/{postgres-viewer-Cd_wXjkT.js → postgres-viewer-B--Y59n5.js} +1 -1
- package/dist/web/assets/{ppmbot-settings-section-PzCLPm8a.js → ppmbot-settings-section-D1SCOc0_.js} +1 -1
- package/dist/web/assets/{process-table-C2TdkJck.js → process-table-D9z7cEmb.js} +1 -1
- package/dist/web/assets/{proxy-settings-section-DsZ6KcHD.js → proxy-settings-section-y7VwH0Hf.js} +1 -1
- package/dist/web/assets/{query-audit-section-2eX9-6mO.js → query-audit-section-Ca_gRQ_s.js} +1 -1
- package/dist/web/assets/{remote-desktop-mobile-sheet-CMXSUcAN.js → remote-desktop-mobile-sheet-CdO2aMXl.js} +2 -2
- package/dist/web/assets/{remote-desktop-mobile-view-Bw6p5ikf.js → remote-desktop-mobile-view-CGQ8vSf1.js} +1 -1
- package/dist/web/assets/{remote-desktop-readiness-gate-W0lAhHq9.js → remote-desktop-readiness-gate-BmC3b05e.js} +1 -1
- package/dist/web/assets/{remote-desktop-window-content-P888YEqm.js → remote-desktop-window-content-Cdaoltdz.js} +1 -1
- package/dist/web/assets/{schedules-settings-section-C8YDAxlo.js → schedules-settings-section--0s10CfA.js} +1 -1
- package/dist/web/assets/{settings-body-B5v3_Tnb.js → settings-body-DEMqFm5z.js} +2 -2
- package/dist/web/assets/{settings-tab-CauShulf.js → settings-tab-Dh1FpBny.js} +1 -1
- package/dist/web/assets/{settings-window-content-BIosR7RY.js → settings-window-content-3KrQ6imZ.js} +1 -1
- package/dist/web/assets/{sql-query-editor-DMihDPnw.js → sql-query-editor-Clo90z8-.js} +1 -1
- package/dist/web/assets/{sqlite-viewer-jCIGt2GP.js → sqlite-viewer-C08QQR_L.js} +1 -1
- package/dist/web/assets/{system-monitor-body-IUamfS5w.js → system-monitor-body-30-TFH3a.js} +2 -2
- package/dist/web/assets/{system-monitor-tab-DaWeif4k.js → system-monitor-tab-ChIXfOWg.js} +1 -1
- package/dist/web/assets/{system-monitor-window-content-Bq3BS7Mg.js → system-monitor-window-content-C1Cd_pT7.js} +1 -1
- package/dist/web/assets/{tab-host-window-content-vfYLLIKU.js → tab-host-window-content-C6eG_Rf1.js} +1 -1
- package/dist/web/assets/{team-member-sheet-Be7OSGMT.js → team-member-sheet-BhatQbL1.js} +2 -2
- package/dist/web/assets/{team-member-window-content-D5cYZzBq.js → team-member-window-content-BN3luct-.js} +1 -1
- package/dist/web/assets/{terminal-tab-C89DQllY.js → terminal-tab-afylLiLY.js} +1 -1
- package/dist/web/assets/{tool-cards-CWotDH_2.js → tool-cards-Ct1QdT8c.js} +2 -2
- package/dist/web/assets/{use-accounts-data-lmmmG4ep.js → use-accounts-data-C0bvcMhi.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-0ziS4xlp.js → use-monaco-theme-cgPbRDUm.js} +1 -1
- package/dist/web/assets/{use-remote-desktop-display-choice-qBZ8ej7J.js → use-remote-desktop-display-choice-DSqF1Rgx.js} +1 -1
- package/dist/web/assets/use-websocket-BQssVSIR.js +1 -0
- package/dist/web/assets/{video-preview-B8xALVkh.js → video-preview-BTzstVhM.js} +1 -1
- package/dist/web/index.html +2 -2
- package/dist/web/sw.js +1 -1
- package/docs/architecture/ai-chat-and-providers.md +88 -0
- package/package.json +1 -1
- package/packages/vscode-compat/node_modules/.bin/tsc.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsc.exe +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.bunx +0 -0
- package/packages/vscode-compat/node_modules/.bin/tsserver.exe +0 -0
- package/schemas/ppm-config.schema.json +18 -1
- package/src/providers/claude-agent-sdk.ts +21 -13
- package/src/providers/cli-provider-base.ts +3 -1
- package/src/providers/codex-app-server/codex-history.ts +5 -3
- package/src/providers/codex-app-server/codex-provider.ts +16 -2
- package/src/providers/codex-app-server/codex-rollout-header.ts +2 -1
- package/src/providers/cursor-cli/cursor-history.ts +4 -2
- package/src/server/routes/settings.ts +15 -1
- package/src/server/ws/chat.ts +2 -2
- package/src/services/chat.service.ts +95 -2
- package/src/services/codex-native-memory.ts +66 -0
- package/src/services/edge-forwarder.ts +191 -191
- package/src/services/jsonl-transcript-parser.ts +2 -1
- package/src/services/provider-shared-context.ts +152 -0
- package/src/services/windows-process-tree.ts +351 -351
- package/src/shared/provider-context.ts +13 -0
- package/src/types/chat.ts +6 -0
- package/src/types/config.ts +29 -0
- package/src/web/components/chat/chat-history-bar.tsx +6 -3
- package/src/web/components/chat/chat-tab.tsx +7 -0
- package/src/web/components/settings/ai-settings-section.tsx +34 -5
- package/src/web/components/settings/codex-context-settings.tsx +100 -0
- package/src/web/hooks/use-chat.ts +71 -14
- package/src/web/hooks/use-websocket.ts +14 -7
- package/src/web/lib/api-settings.ts +3 -0
- package/src/web/lib/ws-client.ts +55 -4
- package/.release-bin/zip +0 -15
- package/.release-node-shim.sh +0 -11
- package/dist/web/assets/ai-settings-section-PaEh_o0w.js +0 -1
- package/dist/web/assets/chat-tab-MNuc18Os.js +0 -15
- package/dist/web/assets/use-websocket-DAvfbjxh.js +0 -1
package/src/web/lib/ws-client.ts
CHANGED
|
@@ -5,6 +5,12 @@ type MessageHandler = (data: MessageEvent) => void;
|
|
|
5
5
|
const MAX_RECONNECT_DELAY = 30_000;
|
|
6
6
|
const BASE_DELAY = 1_000;
|
|
7
7
|
|
|
8
|
+
export interface WsClientOptions {
|
|
9
|
+
/** Opt in only for protocols that regularly send heartbeat messages. */
|
|
10
|
+
idleTimeoutMs?: number;
|
|
11
|
+
onConnectionChange?: (connected: boolean) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
export class WsClient {
|
|
9
15
|
private ws: WebSocket | null = null;
|
|
10
16
|
private url: string;
|
|
@@ -15,14 +21,18 @@ export class WsClient {
|
|
|
15
21
|
/** Messages queued while WS is still CONNECTING — flushed on open */
|
|
16
22
|
private pendingMessages: (string | ArrayBuffer)[] = [];
|
|
17
23
|
private visibilityHandler: (() => void) | null = null;
|
|
24
|
+
private idleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
25
|
+
private lastReceivedAt = 0;
|
|
26
|
+
private connected = false;
|
|
18
27
|
|
|
19
|
-
constructor(url: string) {
|
|
28
|
+
constructor(url: string, private options: WsClientOptions = {}) {
|
|
20
29
|
this.url = url;
|
|
21
30
|
// Reconnect immediately when page becomes visible (e.g. iPad wake from sleep)
|
|
22
31
|
this.visibilityHandler = () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
const state = this.ws?.readyState;
|
|
33
|
+
const stale = !!this.options.idleTimeoutMs && Date.now() - this.lastReceivedAt >= this.options.idleTimeoutMs;
|
|
34
|
+
if (document.visibilityState === "visible" && !this.intentionalClose
|
|
35
|
+
&& (stale || (state !== WebSocket.OPEN && state !== WebSocket.CONNECTING))) {
|
|
26
36
|
this.reconnectAttempts = 0;
|
|
27
37
|
this.connect();
|
|
28
38
|
}
|
|
@@ -32,6 +42,8 @@ export class WsClient {
|
|
|
32
42
|
|
|
33
43
|
connect(): void {
|
|
34
44
|
this.intentionalClose = false;
|
|
45
|
+
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
|
|
46
|
+
this.reconnectTimer = null;
|
|
35
47
|
this.cleanup();
|
|
36
48
|
|
|
37
49
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
@@ -52,9 +64,13 @@ export class WsClient {
|
|
|
52
64
|
}
|
|
53
65
|
|
|
54
66
|
this.ws = new WebSocket(fullUrl);
|
|
67
|
+
this.lastReceivedAt = Date.now();
|
|
68
|
+
this.armIdleCheck();
|
|
55
69
|
|
|
56
70
|
this.ws.onopen = () => {
|
|
57
71
|
this.reconnectAttempts = 0;
|
|
72
|
+
this.lastReceivedAt = Date.now();
|
|
73
|
+
this.setConnected(true);
|
|
58
74
|
// Send "ready" handshake — triggers server to send status/connected.
|
|
59
75
|
// Through Cloudflare tunnels, the server's open-handler message may not
|
|
60
76
|
// arrive because the end-to-end data path isn't fully established yet.
|
|
@@ -71,12 +87,15 @@ export class WsClient {
|
|
|
71
87
|
};
|
|
72
88
|
|
|
73
89
|
this.ws.onmessage = (event) => {
|
|
90
|
+
this.lastReceivedAt = Date.now();
|
|
74
91
|
for (const handler of this.handlers) {
|
|
75
92
|
handler(event);
|
|
76
93
|
}
|
|
77
94
|
};
|
|
78
95
|
|
|
79
96
|
this.ws.onclose = () => {
|
|
97
|
+
this.clearIdleCheck();
|
|
98
|
+
this.setConnected(false);
|
|
80
99
|
if (!this.intentionalClose) {
|
|
81
100
|
this.scheduleReconnect();
|
|
82
101
|
}
|
|
@@ -125,6 +144,8 @@ export class WsClient {
|
|
|
125
144
|
}
|
|
126
145
|
|
|
127
146
|
private cleanup(): void {
|
|
147
|
+
this.clearIdleCheck();
|
|
148
|
+
this.setConnected(false);
|
|
128
149
|
if (this.ws) {
|
|
129
150
|
this.ws.onopen = null;
|
|
130
151
|
this.ws.onclose = null;
|
|
@@ -141,6 +162,7 @@ export class WsClient {
|
|
|
141
162
|
}
|
|
142
163
|
|
|
143
164
|
private scheduleReconnect(): void {
|
|
165
|
+
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
|
|
144
166
|
const delay = Math.min(
|
|
145
167
|
BASE_DELAY * Math.pow(2, this.reconnectAttempts),
|
|
146
168
|
MAX_RECONNECT_DELAY,
|
|
@@ -148,4 +170,33 @@ export class WsClient {
|
|
|
148
170
|
this.reconnectAttempts++;
|
|
149
171
|
this.reconnectTimer = setTimeout(() => this.connect(), delay);
|
|
150
172
|
}
|
|
173
|
+
|
|
174
|
+
private setConnected(connected: boolean): void {
|
|
175
|
+
if (this.connected === connected) return;
|
|
176
|
+
this.connected = connected;
|
|
177
|
+
this.options.onConnectionChange?.(connected);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private clearIdleCheck(): void {
|
|
181
|
+
if (this.idleTimer) clearTimeout(this.idleTimer);
|
|
182
|
+
this.idleTimer = null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private armIdleCheck(): void {
|
|
186
|
+
this.clearIdleCheck();
|
|
187
|
+
const timeout = this.options.idleTimeoutMs;
|
|
188
|
+
if (!timeout || timeout <= 0 || !Number.isFinite(timeout)) return;
|
|
189
|
+
const remaining = Math.max(0, timeout - (Date.now() - this.lastReceivedAt));
|
|
190
|
+
this.idleTimer = setTimeout(() => {
|
|
191
|
+
this.idleTimer = null;
|
|
192
|
+
if (this.intentionalClose) return;
|
|
193
|
+
if (Date.now() - this.lastReceivedAt >= timeout) {
|
|
194
|
+
// An OPEN socket can have a dead downstream without firing close/error.
|
|
195
|
+
// A fresh handshake lets the server replay the active turn or idle history.
|
|
196
|
+
this.connect();
|
|
197
|
+
} else {
|
|
198
|
+
this.armIdleCheck();
|
|
199
|
+
}
|
|
200
|
+
}, remaining);
|
|
201
|
+
}
|
|
151
202
|
}
|
package/.release-bin/zip
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
while [[ "$#" -gt 0 && "$1" == -* ]]; do shift; done
|
|
4
|
-
archive="$1"
|
|
5
|
-
root="$2"
|
|
6
|
-
python.exe - "$archive" "$root" <<'PY'
|
|
7
|
-
import os, sys, zipfile
|
|
8
|
-
archive, root = sys.argv[1:3]
|
|
9
|
-
base = os.path.dirname(root)
|
|
10
|
-
with zipfile.ZipFile(archive, "w", zipfile.ZIP_DEFLATED) as z:
|
|
11
|
-
for current, _, files in os.walk(root):
|
|
12
|
-
for filename in files:
|
|
13
|
-
path = os.path.join(current, filename)
|
|
14
|
-
z.write(path, os.path.relpath(path, base))
|
|
15
|
-
PY
|
package/.release-node-shim.sh
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{S as t,x as n}from"./vendor-markdown-Ls5AcU91.js";import{n as r}from"./api-client-CEYCBt_0.js";import{B as i,Dr as a,G as o,H as s,Ln as c,M as l,U as u,V as d,W as f,X as p,Xn as m,Y as h,cn as g}from"./index-DYGLdCpe.js";import{getAISettings as _,updateAISettings as v}from"./api-settings-D18Q4Ocp.js";var y=e(t(),1),b=n(),x=[{value:`low`,label:`Low`},{value:`medium`,label:`Medium`},{value:`high`,label:`High`},{value:`xhigh`,label:`Extra`},{value:`max`,label:`Max`}],S=[{value:`bypassPermissions`,label:`Bypass permissions (default)`},{value:`default`,label:`Ask before edits`},{value:`acceptEdits`,label:`Edit automatically`},{value:`plan`,label:`Plan mode`}],C={claude:`Claude`,cursor:`Cursor`,codex:`Codex`,gemini:`Gemini`};function w({compact:e}={}){let[t,n]=(0,y.useState)(null),[c,m]=(0,y.useState)(``),[w,E]=(0,y.useState)([]),[D,O]=(0,y.useState)(!1),[k,A]=(0,y.useState)(!1),[j,M]=(0,y.useState)(null),[N,P]=(0,y.useState)(0);(0,y.useEffect)(()=>{_().then(e=>{n(e),m(e.default_provider??`claude`)}).catch(e=>M(e.message))},[]),(0,y.useEffect)(()=>{c&&(O(!0),r.get(`/api/settings/ai/providers/${c}/models`).then(E).catch(()=>E([])).finally(()=>O(!1)))},[c]);let F=t?Object.keys(t.providers).filter(e=>e!==`mock`).map(e=>({id:e,name:C[e]??e})):[],I=t?.providers[c],L=I?.type===`agent-sdk`||!I?.type&&c===`claude`,R=async(e,r)=>{if(t){A(!0),M(null);try{n(await v({providers:{[c]:{[e]:r}}})),P(e=>e+1)}catch(e){M(e.message)}finally{A(!1)}}},z=e?`text-[11px]`:`text-sm`,B=e?`text-xs`:`text-sm`,V=e?`space-y-2`:`space-y-4`,H=e?`space-y-1.5`:`space-y-3`,U=e?`space-y-1`:`space-y-1.5`;if(!t)return(0,b.jsxs)(`div`,{className:H,children:[(0,b.jsx)(`h3`,{className:`${B} font-medium text-text-secondary`,children:`AI Settings`}),(0,b.jsx)(`p`,{className:`${z} text-text-subtle`,children:j?`Error: ${j}`:`Loading...`})]});let W=L?w:[{value:`__default__`,label:`Auto (default)`},...w];return(0,b.jsxs)(`div`,{className:V,children:[(0,b.jsx)(`h3`,{className:`${B} font-medium text-text-secondary`,children:`AI Settings`}),F.length>1&&(0,b.jsx)(`div`,{className:`flex gap-0.5 border-b border-border/50 -mx-1 px-1`,children:F.map(e=>(0,b.jsxs)(`button`,{onClick:()=>m(e.id),className:`flex items-center gap-1 px-2 py-1 text-[11px] rounded-t transition-colors ${c===e.id?`text-primary border-b-2 border-primary font-medium`:`text-text-subtle hover:text-text-secondary`}`,children:[(0,b.jsx)(l,{providerId:e.id}),(0,b.jsx)(`span`,{className:`capitalize`,children:e.name})]},e.id))}),(0,b.jsxs)(`div`,{className:H,children:[c===`codex`&&(0,b.jsxs)(`button`,{type:`button`,onClick:()=>g(`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:`${z} text-text-secondary`,children:`Codex accounts & login`}),(0,b.jsx)(a,{className:`size-3.5 text-text-subtle shrink-0`})]}),w.length>0&&(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-model`,className:e?z:void 0,children:`Model`}),(0,b.jsxs)(i,{value:L?I?.model??w[0]?.value:I?.model||`__default__`,onValueChange:e=>R(`model`,e===`__default__`?void 0:e),disabled:D,children:[(0,b.jsx)(u,{id:`ai-model`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(f,{placeholder:D?`Loading models...`:`Select model`})}),(0,b.jsx)(d,{className:`max-h-[300px]`,children:W.map(e=>(0,b.jsx)(s,{value:e.value,children:e.label},e.value))})]})]}),L&&(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-base-url`,className:e?z:void 0,children:`Base URL`}),(0,b.jsx)(p,{id:`ai-base-url`,type:`url`,defaultValue:I?.base_url??``,placeholder:`https://api.anthropic.com (default)`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{R(`base_url`,e.target.value.trim()||void 0)}},`baseurl-${c}-${N}`)]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-api-key`,className:e?z:void 0,children:`API Key / Token`}),(0,b.jsx)(p,{id:`ai-api-key`,type:`password`,defaultValue:I?.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(`••••`)||R(`api_key`,t||void 0)}},`apikey-${c}-${N}`),(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:U,children:[(0,b.jsx)(h,{htmlFor:`ai-effort`,className:e?z:void 0,children:`Effort`}),(0,b.jsxs)(i,{value:I?.effort??`high`,onValueChange:e=>R(`effort`,e),children:[(0,b.jsx)(u,{id:`ai-effort`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(f,{})}),(0,b.jsx)(d,{children:x.map(e=>(0,b.jsx)(s,{value:e.value,children:e.label},e.value))})]})]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-max-turns`,className:e?z:void 0,children:`Max Turns (1-500)`}),(0,b.jsx)(p,{id:`ai-max-turns`,type:`number`,min:1,max:500,defaultValue:I?.max_turns??100,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);isNaN(t)||R(`max_turns`,t)}},`turns-${c}-${N}`)]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-budget`,className:e?z:void 0,children:`Max Budget (USD)`}),(0,b.jsx)(p,{id:`ai-budget`,type:`number`,step:.1,min:.01,max:50,defaultValue:I?.max_budget_usd??``,placeholder:`No limit`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseFloat(e.target.value);R(`max_budget_usd`,isNaN(t)?void 0:t)}},`budget-${c}-${N}`)]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-thinking`,className:e?z:void 0,children:`Thinking Budget (tokens)`}),(0,b.jsx)(p,{id:`ai-thinking`,type:`number`,min:0,defaultValue:I?.thinking_budget_tokens??``,placeholder:`Adaptive (model decides)`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);R(`thinking_budget_tokens`,isNaN(t)?void 0:t)}},`thinking-${c}-${N}`)]}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(h,{htmlFor:`ai-agent-teams`,className:e?z: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)(o,{id:`ai-agent-teams`,checked:I?.agent_teams??!1,onCheckedChange:e=>R(`agent_teams`,e)})]}),I?.agent_teams&&(0,b.jsx)(T,{compact:e}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(h,{htmlFor:`ai-context-1m`,className:e?z: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)(o,{id:`ai-context-1m`,checked:I?.context_1m??!1,onCheckedChange:e=>R(`context_1m`,e)})]}),(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,b.jsxs)(`div`,{children:[(0,b.jsx)(h,{htmlFor:`ai-inherit-mcp`,className:e?z: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)(o,{id:`ai-inherit-mcp`,checked:I?.inherit_claude_mcp??!0,onCheckedChange:e=>R(`inherit_claude_mcp`,e)})]})]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-permission-mode`,className:e?z:void 0,children:`Default Permission Mode`}),(0,b.jsxs)(i,{value:I?.permission_mode??`bypassPermissions`,onValueChange:e=>R(`permission_mode`,e),children:[(0,b.jsx)(u,{id:`ai-permission-mode`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,b.jsx)(f,{})}),(0,b.jsx)(d,{children:S.map(e=>(0,b.jsx)(s,{value:e.value,children:e.label},e.value))})]})]}),(0,b.jsxs)(`div`,{className:U,children:[(0,b.jsx)(h,{htmlFor:`ai-system-prompt`,className:e?z:void 0,children:`Additional Instructions`}),(0,b.jsx)(`textarea`,{id:`ai-system-prompt`,rows:e?3:4,defaultValue:I?.system_prompt??``,placeholder:`Enter additional instructions for ${c}...`,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=>{R(`system_prompt`,e.target.value.trim()||void 0)}},`sysprompt-${c}-${N}`)]})]}),k&&(0,b.jsx)(`p`,{className:`text-xs text-text-subtle`,children:`Saving...`}),j&&(0,b.jsx)(`p`,{className:`text-xs text-error`,children:j})]})}function T({compact:e}){let[t,n]=(0,y.useState)([]),[i,a]=(0,y.useState)(!1),[o,s]=(0,y.useState)(null),l=(0,y.useCallback)(async()=>{a(!0);try{n(await r.get(`/api/teams`)??[])}catch{}a(!1)},[]);(0,y.useEffect)(()=>{l()},[l]);let u=async e=>{try{await r.del(`/api/teams/${encodeURIComponent(e)}`),n(t=>t.filter(t=>t.name!==e)),s(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)(h,{className:e?`text-[11px]`:void 0,children:[`Teams (`,t.length,`)`]}),(0,b.jsx)(`button`,{onClick:l,className:`text-text-subtle hover:text-foreground p-1`,"aria-label":`Refresh teams`,children:(0,b.jsx)(m,{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()}`:``]})]}),o===e.name?(0,b.jsxs)(`div`,{className:`flex gap-1 shrink-0 ml-2`,children:[(0,b.jsx)(`button`,{onClick:()=>u(e.name),className:`px-2 py-1 bg-error text-white rounded text-[10px]`,children:`Delete`}),(0,b.jsx)(`button`,{onClick:()=>s(null),className:`px-2 py-1 bg-panel-2 text-text rounded text-[10px]`,children:`Cancel`})]}):(0,b.jsx)(`button`,{onClick:()=>s(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)(c,{className:`size-3.5`})})]},e.name))]})}export{w as t};
|