cli-jaw 2.2.2 → 2.2.3

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.
Files changed (240) hide show
  1. package/README.ja.md +13 -9
  2. package/README.ko.md +5 -5
  3. package/README.md +7 -6
  4. package/README.zh-CN.md +5 -5
  5. package/dist/bin/commands/goal.js +14 -1
  6. package/dist/bin/commands/goal.js.map +1 -1
  7. package/dist/src/agent/agy-bootstrap.js +104 -0
  8. package/dist/src/agent/agy-bootstrap.js.map +1 -0
  9. package/dist/src/agent/agy-capabilities.js +103 -0
  10. package/dist/src/agent/agy-capabilities.js.map +1 -0
  11. package/dist/src/agent/agy-transcript-watcher.js +11 -0
  12. package/dist/src/agent/agy-transcript-watcher.js.map +1 -1
  13. package/dist/src/agent/args.js +32 -13
  14. package/dist/src/agent/args.js.map +1 -1
  15. package/dist/src/agent/events/claude.js +8 -4
  16. package/dist/src/agent/events/claude.js.map +1 -1
  17. package/dist/src/agent/events/helpers.js +13 -0
  18. package/dist/src/agent/events/helpers.js.map +1 -1
  19. package/dist/src/agent/events/index.js +24 -4
  20. package/dist/src/agent/events/index.js.map +1 -1
  21. package/dist/src/agent/lifecycle-handler.js +25 -4
  22. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  23. package/dist/src/agent/spawn/queue.js +11 -5
  24. package/dist/src/agent/spawn/queue.js.map +1 -1
  25. package/dist/src/agent/spawn.js +49 -13
  26. package/dist/src/agent/spawn.js.map +1 -1
  27. package/dist/src/browser/web-ai/ax-snapshot.js +131 -8
  28. package/dist/src/browser/web-ai/ax-snapshot.js.map +1 -1
  29. package/dist/src/browser/web-ai/candidate-reconcile.js +61 -0
  30. package/dist/src/browser/web-ai/candidate-reconcile.js.map +1 -0
  31. package/dist/src/browser/web-ai/capability-probe.js +92 -0
  32. package/dist/src/browser/web-ai/capability-probe.js.map +1 -0
  33. package/dist/src/browser/web-ai/chatgpt-archive.js +90 -0
  34. package/dist/src/browser/web-ai/chatgpt-archive.js.map +1 -0
  35. package/dist/src/browser/web-ai/chatgpt-attachments.js +70 -3
  36. package/dist/src/browser/web-ai/chatgpt-attachments.js.map +1 -1
  37. package/dist/src/browser/web-ai/chatgpt-composer.js +97 -11
  38. package/dist/src/browser/web-ai/chatgpt-composer.js.map +1 -1
  39. package/dist/src/browser/web-ai/chatgpt-deep-research-report.js +63 -0
  40. package/dist/src/browser/web-ai/chatgpt-deep-research-report.js.map +1 -0
  41. package/dist/src/browser/web-ai/chatgpt-deep-research.js +76 -13
  42. package/dist/src/browser/web-ai/chatgpt-deep-research.js.map +1 -1
  43. package/dist/src/browser/web-ai/chatgpt-files.js +328 -0
  44. package/dist/src/browser/web-ai/chatgpt-files.js.map +1 -0
  45. package/dist/src/browser/web-ai/chatgpt-images.js +281 -0
  46. package/dist/src/browser/web-ai/chatgpt-images.js.map +1 -0
  47. package/dist/src/browser/web-ai/chatgpt-model.js +35 -14
  48. package/dist/src/browser/web-ai/chatgpt-model.js.map +1 -1
  49. package/dist/src/browser/web-ai/chatgpt-multi-turn.js +28 -4
  50. package/dist/src/browser/web-ai/chatgpt-multi-turn.js.map +1 -1
  51. package/dist/src/browser/web-ai/chatgpt-project-sources.js +191 -0
  52. package/dist/src/browser/web-ai/chatgpt-project-sources.js.map +1 -0
  53. package/dist/src/browser/web-ai/chatgpt-response-dom.js +64 -0
  54. package/dist/src/browser/web-ai/chatgpt-response-dom.js.map +1 -0
  55. package/dist/src/browser/web-ai/chatgpt-response-observer.js +170 -0
  56. package/dist/src/browser/web-ai/chatgpt-response-observer.js.map +1 -0
  57. package/dist/src/browser/web-ai/chatgpt-response.js +99 -60
  58. package/dist/src/browser/web-ai/chatgpt-response.js.map +1 -1
  59. package/dist/src/browser/web-ai/chatgpt-tools.js +48 -1
  60. package/dist/src/browser/web-ai/chatgpt-tools.js.map +1 -1
  61. package/dist/src/browser/web-ai/chatgpt-upload-surface.js +202 -0
  62. package/dist/src/browser/web-ai/chatgpt-upload-surface.js.map +1 -0
  63. package/dist/src/browser/web-ai/chatgpt.js +93 -12
  64. package/dist/src/browser/web-ai/chatgpt.js.map +1 -1
  65. package/dist/src/browser/web-ai/code-artifact.js +32 -10
  66. package/dist/src/browser/web-ai/code-artifact.js.map +1 -1
  67. package/dist/src/browser/web-ai/code-mode.js +40 -4
  68. package/dist/src/browser/web-ai/code-mode.js.map +1 -1
  69. package/dist/src/browser/web-ai/contract-audit.js +7 -22
  70. package/dist/src/browser/web-ai/contract-audit.js.map +1 -1
  71. package/dist/src/browser/web-ai/control-summary.js +43 -0
  72. package/dist/src/browser/web-ai/control-summary.js.map +1 -0
  73. package/dist/src/browser/web-ai/copy-markdown.js +10 -0
  74. package/dist/src/browser/web-ai/copy-markdown.js.map +1 -1
  75. package/dist/src/browser/web-ai/diagnostics.js +7 -0
  76. package/dist/src/browser/web-ai/diagnostics.js.map +1 -1
  77. package/dist/src/browser/web-ai/errors.js +17 -0
  78. package/dist/src/browser/web-ai/errors.js.map +1 -1
  79. package/dist/src/browser/web-ai/gemini-capabilities.js +46 -0
  80. package/dist/src/browser/web-ai/gemini-capabilities.js.map +1 -0
  81. package/dist/src/browser/web-ai/gemini-live.js +6 -0
  82. package/dist/src/browser/web-ai/gemini-live.js.map +1 -1
  83. package/dist/src/browser/web-ai/gemini-model.js +41 -0
  84. package/dist/src/browser/web-ai/gemini-model.js.map +1 -1
  85. package/dist/src/browser/web-ai/grok-capabilities.js +41 -0
  86. package/dist/src/browser/web-ai/grok-capabilities.js.map +1 -0
  87. package/dist/src/browser/web-ai/grok-live.js +5 -0
  88. package/dist/src/browser/web-ai/grok-live.js.map +1 -1
  89. package/dist/src/browser/web-ai/grok-model.js +38 -0
  90. package/dist/src/browser/web-ai/grok-model.js.map +1 -1
  91. package/dist/src/browser/web-ai/index.js +10 -0
  92. package/dist/src/browser/web-ai/index.js.map +1 -1
  93. package/dist/src/browser/web-ai/navigation-ready.js +123 -0
  94. package/dist/src/browser/web-ai/navigation-ready.js.map +1 -0
  95. package/dist/src/browser/web-ai/observation-bundle.js +26 -1
  96. package/dist/src/browser/web-ai/observation-bundle.js.map +1 -1
  97. package/dist/src/browser/web-ai/provider-adapter.js.map +1 -1
  98. package/dist/src/browser/web-ai/session-artifacts.js +156 -0
  99. package/dist/src/browser/web-ai/session-artifacts.js.map +1 -0
  100. package/dist/src/browser/web-ai/session-doctor.js +101 -0
  101. package/dist/src/browser/web-ai/session-doctor.js.map +1 -0
  102. package/dist/src/browser/web-ai/session-store.js +94 -17
  103. package/dist/src/browser/web-ai/session-store.js.map +1 -1
  104. package/dist/src/browser/web-ai/session.js +73 -0
  105. package/dist/src/browser/web-ai/session.js.map +1 -1
  106. package/dist/src/browser/web-ai/tab-inspect.js +143 -0
  107. package/dist/src/browser/web-ai/tab-inspect.js.map +1 -0
  108. package/dist/src/browser/web-ai/tab-lease-store.js +114 -4
  109. package/dist/src/browser/web-ai/tab-lease-store.js.map +1 -1
  110. package/dist/src/browser/web-ai/tier-timeout.js +58 -0
  111. package/dist/src/browser/web-ai/tier-timeout.js.map +1 -0
  112. package/dist/src/browser/web-ai/vendor-editor-contract.js +6 -3
  113. package/dist/src/browser/web-ai/vendor-editor-contract.js.map +1 -1
  114. package/dist/src/browser/web-ai/watcher-lock.js +125 -0
  115. package/dist/src/browser/web-ai/watcher-lock.js.map +1 -0
  116. package/dist/src/browser/web-ai/watcher.js +23 -4
  117. package/dist/src/browser/web-ai/watcher.js.map +1 -1
  118. package/dist/src/cli/handlers-workflows.js +14 -3
  119. package/dist/src/cli/handlers-workflows.js.map +1 -1
  120. package/dist/src/core/cli-detection.js +2 -3
  121. package/dist/src/core/cli-detection.js.map +1 -1
  122. package/dist/src/core/settings-merge.js +2 -2
  123. package/dist/src/core/settings-merge.js.map +1 -1
  124. package/dist/src/goal/heartbeat.js +13 -7
  125. package/dist/src/goal/heartbeat.js.map +1 -1
  126. package/dist/src/goal/pause-gate.js +22 -0
  127. package/dist/src/goal/pause-gate.js.map +1 -0
  128. package/dist/src/goal/store.js +5 -0
  129. package/dist/src/goal/store.js.map +1 -1
  130. package/dist/src/manager/lifecycle.js +2 -1
  131. package/dist/src/manager/lifecycle.js.map +1 -1
  132. package/dist/src/manager/preview-origin-proxy.js +36 -6
  133. package/dist/src/manager/preview-origin-proxy.js.map +1 -1
  134. package/dist/src/manager/proxy.js +25 -4
  135. package/dist/src/manager/proxy.js.map +1 -1
  136. package/dist/src/manager/registry.js +36 -3
  137. package/dist/src/manager/registry.js.map +1 -1
  138. package/dist/src/manager/routes/runtime-monitor.js +2 -0
  139. package/dist/src/manager/routes/runtime-monitor.js.map +1 -1
  140. package/dist/src/manager/routes/telegram-hub.js +120 -0
  141. package/dist/src/manager/routes/telegram-hub.js.map +1 -0
  142. package/dist/src/manager/server.js +4 -0
  143. package/dist/src/manager/server.js.map +1 -1
  144. package/dist/src/manager/telegram-hub/hub-bot.js +409 -0
  145. package/dist/src/manager/telegram-hub/hub-bot.js.map +1 -0
  146. package/dist/src/manager/telegram-hub/routing-store.js +24 -0
  147. package/dist/src/manager/telegram-hub/routing-store.js.map +1 -0
  148. package/dist/src/manager/telegram-hub/types.js +5 -0
  149. package/dist/src/manager/telegram-hub/types.js.map +1 -0
  150. package/dist/src/messaging/thread-target.js +21 -0
  151. package/dist/src/messaging/thread-target.js.map +1 -0
  152. package/dist/src/orchestrator/gateway.js +10 -7
  153. package/dist/src/orchestrator/gateway.js.map +1 -1
  154. package/dist/src/orchestrator/pipeline.js +19 -0
  155. package/dist/src/orchestrator/pipeline.js.map +1 -1
  156. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  157. package/dist/src/routes/command.js +58 -2
  158. package/dist/src/routes/command.js.map +1 -1
  159. package/dist/src/routes/goal.js +6 -3
  160. package/dist/src/routes/goal.js.map +1 -1
  161. package/dist/src/routes/messaging.js +7 -2
  162. package/dist/src/routes/messaging.js.map +1 -1
  163. package/dist/src/routes/orchestrate.js +2 -0
  164. package/dist/src/routes/orchestrate.js.map +1 -1
  165. package/dist/src/telegram/bot.js +59 -4
  166. package/dist/src/telegram/bot.js.map +1 -1
  167. package/dist/src/telegram/forwarder.js +4 -1
  168. package/dist/src/telegram/forwarder.js.map +1 -1
  169. package/dist/src/telegram/hub-callback.js +21 -0
  170. package/dist/src/telegram/hub-callback.js.map +1 -0
  171. package/dist/src/telegram/rich-message.js +20 -0
  172. package/dist/src/telegram/rich-message.js.map +1 -0
  173. package/dist/src/telegram/telegram-file.js +4 -3
  174. package/dist/src/telegram/telegram-file.js.map +1 -1
  175. package/dist/src/workflows/status.js +14 -4
  176. package/dist/src/workflows/status.js.map +1 -1
  177. package/package.json +5 -5
  178. package/public/dist/assets/{Agent-wJtedbz4.js → Agent-Ci12HWhE.js} +1 -1
  179. package/public/dist/assets/{Heartbeat-CjgQ-0p8.js → Heartbeat-D-Rfp094.js} +1 -1
  180. package/public/dist/assets/{Memory-6o-wyhAT.js → Memory-VH4ZJCMW.js} +1 -1
  181. package/public/dist/assets/ModelProvider-_tUCghOF.js +1 -0
  182. package/public/dist/assets/TelegramHub-CuJoPPib.js +1 -0
  183. package/public/dist/assets/{agent-meta-g8UDRdWA.js → agent-meta-DqBTGRRQ.js} +1 -1
  184. package/public/dist/assets/{app-CLrfEHAk.js → app-DaORcAyD.js} +4 -4
  185. package/public/dist/assets/bgtask-badge-B3HLOZae.js +1 -0
  186. package/public/dist/assets/{bgtask-badge-xWbw-l-0.js → bgtask-badge-BtUXEe1T.js} +1 -1
  187. package/public/dist/assets/constants-DkJ3E63Y.js +1 -0
  188. package/public/dist/assets/{employees-C5GPj3d3.js → employees-CZSyvJbx.js} +1 -1
  189. package/public/dist/assets/manager-D3waO_XX.css +1 -0
  190. package/public/dist/assets/manager-DB5qTw1A.js +13 -0
  191. package/public/dist/assets/memory-BEruUlfu.js +1 -0
  192. package/public/dist/assets/{memory-CcnjBuo-.js → memory-cWI_Htbn.js} +1 -1
  193. package/public/dist/assets/message-history-DU1V9ZAW.js +142 -0
  194. package/public/dist/assets/message-history-tjkyOp_K.js +1 -0
  195. package/public/dist/assets/{render-C2g_qvCg.js → render-Bp8eyqCf.js} +1 -1
  196. package/public/dist/assets/settings-B-GgyJZI.js +1 -0
  197. package/public/dist/assets/{settings-DxClXVD0.js → settings-DLkP7qRV.js} +1 -1
  198. package/public/dist/assets/{settings-core-CSUV4-QG.js → settings-core-B5XRRNcX.js} +1 -1
  199. package/public/dist/assets/settings-core-Cw1av-Ox.js +1 -0
  200. package/public/dist/assets/{sidebar-CJz_SnMW.js → sidebar-CsogFOse.js} +3 -3
  201. package/public/dist/assets/skills-CLcoop6W.js +1 -0
  202. package/public/dist/assets/{skills-PKg2h1N4.js → skills-Dmf4v9rj.js} +1 -1
  203. package/public/dist/assets/slash-commands-DY6-hzq6.js +1 -0
  204. package/public/dist/assets/{slash-commands-FMOOfedZ.js → slash-commands-vcf7FuPD.js} +1 -1
  205. package/public/dist/assets/{trace-drawer-BoU1ucw7.js → trace-drawer-DuQQ0SNq.js} +1 -1
  206. package/public/dist/assets/{ui-BX-IfLze.js → ui-BKYuBdZE.js} +1 -1
  207. package/public/dist/assets/ui-CqlGwgUo.js +1 -0
  208. package/public/dist/index.html +1 -1
  209. package/public/dist/manager/index.html +2 -2
  210. package/public/js/constants.ts +2 -3
  211. package/public/js/features/process-block.ts +61 -9
  212. package/public/manager/src/code/code-composer.css +1 -0
  213. package/public/manager/src/code/code.css +7 -2
  214. package/public/manager/src/dashboard-settings/DashboardSettingsSidebar.tsx +6 -2
  215. package/public/manager/src/dashboard-settings/DashboardSettingsWorkspace.tsx +91 -2
  216. package/public/manager/src/goal-status/GoalPabcdStatusPanel.tsx +9 -1
  217. package/public/manager/src/goal-status/goal-pabcd-status-client.ts +9 -0
  218. package/public/manager/src/settings/SettingsShell.tsx +1 -0
  219. package/public/manager/src/settings/SettingsSidebar.tsx +1 -0
  220. package/public/manager/src/settings/pages/TelegramHub.tsx +179 -0
  221. package/public/manager/src/settings/pages/components/PerCliRow.tsx +23 -13
  222. package/public/manager/src/settings/pages/components/agent/agent-meta.ts +3 -1
  223. package/public/manager/src/settings/types.ts +1 -0
  224. package/public/manager/src/settings-shell.css +11 -0
  225. package/public/sw.js +1 -1
  226. package/scripts/bundle-sidecar.sh +6 -1
  227. package/public/dist/assets/ModelProvider-CNu6WOjM.js +0 -1
  228. package/public/dist/assets/bgtask-badge-4OjtCvDq.js +0 -1
  229. package/public/dist/assets/constants-CCiCctGV.js +0 -1
  230. package/public/dist/assets/manager-Ceg2x8D0.js +0 -13
  231. package/public/dist/assets/manager-CwAlpgV7.css +0 -1
  232. package/public/dist/assets/memory-B1beDKbo.js +0 -1
  233. package/public/dist/assets/message-history-BSWJwi__.js +0 -142
  234. package/public/dist/assets/message-history-CzaziSe8.js +0 -1
  235. package/public/dist/assets/settings-Dst1mUjn.js +0 -1
  236. package/public/dist/assets/settings-core-BW5mtFPE.js +0 -1
  237. package/public/dist/assets/skills-B2io6S_4.js +0 -1
  238. package/public/dist/assets/slash-commands-D1IS00Eg.js +0 -1
  239. package/public/dist/assets/ui-C-al0etg.js +0 -1
  240. /package/public/dist/assets/{TerminalPanel-B7WRXPsE.js → TerminalPanel-DSCJeGjp.js} +0 -0
@@ -48,6 +48,8 @@ export function GoalPabcdStatusPanel() {
48
48
  const gateEvidence = useMemo(() => snapshot?.pabcd.gate.evidence.slice(0, 5) ?? [], [snapshot]);
49
49
  const goalEvidence = snapshot?.goal?.lastCheckpoint?.evidencePaths.slice(0, 5) ?? [];
50
50
  const goalStatus = snapshot?.goal?.status ?? 'idle';
51
+ const pauseGate = snapshot?.goal?.pauseGate;
52
+ const goalStatusLabel = pauseGate?.armed ? 'pause gate' : goalStatus;
51
53
  const evidenceFreshness = snapshot?.goal?.evidenceFreshness ?? 'missing';
52
54
 
53
55
  return (
@@ -60,7 +62,7 @@ export function GoalPabcdStatusPanel() {
60
62
  <span className="code-goal-status-meta">{gateLine(snapshot)}</span>
61
63
  </button>
62
64
  <div className="code-goal-status-pills" aria-live="polite">
63
- <span className={statusClass(goalStatus)}>{goalStatus}</span>
65
+ <span className={pauseGate?.armed ? 'is-pending' : statusClass(goalStatus)}>{goalStatusLabel}</span>
64
66
  <span className={statusClass(snapshot?.pabcd.gate.status)}>{snapshot?.pabcd.gate.status ?? 'pending'}</span>
65
67
  <span className={statusClass(evidenceFreshness)}>{evidenceFreshness}</span>
66
68
  </div>
@@ -88,6 +90,12 @@ export function GoalPabcdStatusPanel() {
88
90
  <span>Next action</span>
89
91
  <code>{snapshot.goal?.lastCheckpoint?.nextAction || 'No checkpoint next action'}</code>
90
92
  </div>
93
+ {snapshot.goal?.pauseGate.armed && (
94
+ <div className="code-goal-status-detail-row">
95
+ <span>Pause gate</span>
96
+ <code>{snapshot.goal.pauseGate.nextAction || 'Pending audited pause decision'}</code>
97
+ </div>
98
+ )}
91
99
  <div className="code-goal-status-detail-row">
92
100
  <span>Repository</span>
93
101
  <code>{snapshot.goal?.repoRoot || snapshot.pabcd.projectDirs[0] || 'unknown'}</code>
@@ -3,6 +3,14 @@ export type PabcdGateStatus = 'idle' | 'pending' | 'pass' | 'fail';
3
3
  export type GoalStatusKind = 'active' | 'paused' | 'blocked' | 'complete' | 'cancelled';
4
4
  export type PabcdStateName = 'IDLE' | 'I' | 'P' | 'A' | 'B' | 'C' | 'D';
5
5
 
6
+ export interface GoalPauseGateSummary {
7
+ armed: boolean;
8
+ attempts: number;
9
+ requiredAttempts: number;
10
+ reason: 'pause_gate_pending' | null;
11
+ nextAction: string | null;
12
+ }
13
+
6
14
  export interface GoalCheckpointSummary {
7
15
  summary: string;
8
16
  nextAction: string;
@@ -20,6 +28,7 @@ export interface GoalStatusSummary {
20
28
  updatedAt: string;
21
29
  checkpointCount: number;
22
30
  lastCheckpoint: GoalCheckpointSummary | null;
31
+ pauseGate: GoalPauseGateSummary;
23
32
  evidenceFreshness: GoalEvidenceFreshness;
24
33
  evidenceAgeMs: number | null;
25
34
  }
@@ -43,6 +43,7 @@ const PAGE_REGISTRY: Record<
43
43
  mcp: lazy(() => import('./pages/Mcp')),
44
44
  browser: lazy(() => import('./pages/Browser')),
45
45
  'dashboard-meta': lazy(() => import('./pages/DashboardMeta')),
46
+ 'telegram-hub': lazy(() => import('./pages/TelegramHub')),
46
47
  'advanced-export': lazy(() => import('./pages/AdvancedExport')),
47
48
  };
48
49
 
@@ -19,6 +19,7 @@ const CATEGORIES: SidebarEntry[] = [
19
19
  { id: 'display', label: 'Display', group: 'identity' },
20
20
  { id: 'channels-telegram', label: 'Channels — Telegram', group: 'channels' },
21
21
  { id: 'channels-discord', label: 'Channels — Discord', group: 'channels' },
22
+ { id: 'telegram-hub', label: 'Telegram Hub', group: 'channels' },
22
23
  { id: 'heartbeat', label: 'Heartbeat & schedules', group: 'automation' },
23
24
  { id: 'memory', label: 'Memory', group: 'automation' },
24
25
  { id: 'mcp', label: 'MCP servers', group: 'mcp' },
@@ -0,0 +1,179 @@
1
+ // Telegram Hub — manager-level settings page (P3).
2
+ //
3
+ // Talks to `/api/dashboard/telegram-hub` on the MANAGER itself (NOT the per-instance
4
+ // `/i/{port}` proxy). Mirrors DashboardMeta.tsx's managerClient pattern — the injected
5
+ // instance `client` would 404 on this manager-side route.
6
+
7
+ import { useCallback, useEffect, useState } from 'react';
8
+ import type { SettingsPageProps } from '../types';
9
+ import { ToggleField, SecretField, TextField } from '../fields';
10
+ import { SettingsSection, PageError, PageLoading, usePageSnapshot } from './page-shell';
11
+
12
+ // Local mirror of MANAGED_INSTANCE_PORT_FROM/TO (src/manager/constants.ts). The frontend
13
+ // bundle must not import server modules; the backend validates the real range authoritatively.
14
+ const PORT_MIN = 3457;
15
+ const PORT_MAX = 3506;
16
+
17
+ type Route = { chatId: string; threadId: string; port: number; label?: string; enabled: boolean; systemPrompt?: string; model?: string };
18
+ type HubConfig = { enabled: boolean; hasToken: boolean; chatId: string; defaultPort: number; routes: Route[] };
19
+ type HubRuntime = { state: 'stopped' | 'starting' | 'polling' | 'error'; chatId?: string; error?: string };
20
+ type HubResponse = { ok: boolean; config: HubConfig; runtime?: HubRuntime };
21
+
22
+ type ManagerClient = {
23
+ get<T>(path: string): Promise<T>;
24
+ put<T>(path: string, body: unknown): Promise<T>;
25
+ delete<T>(path: string): Promise<T>;
26
+ };
27
+
28
+ function defaultManagerClient(): ManagerClient {
29
+ return {
30
+ async get<T>(path: string): Promise<T> {
31
+ const res = await fetch(path);
32
+ if (!res.ok) throw new Error(`GET ${path} → ${res.status}`);
33
+ return (await res.json()) as T;
34
+ },
35
+ async put<T>(path: string, body: unknown): Promise<T> {
36
+ const res = await fetch(path, {
37
+ method: 'PUT',
38
+ headers: { 'content-type': 'application/json' },
39
+ body: JSON.stringify(body),
40
+ });
41
+ if (!res.ok) throw new Error(`PUT ${path} → ${res.status}`);
42
+ return (await res.json()) as T;
43
+ },
44
+ async delete<T>(path: string): Promise<T> {
45
+ const res = await fetch(path, { method: 'DELETE' });
46
+ if (!res.ok) throw new Error(`DELETE ${path} → ${res.status}`);
47
+ return (await res.json()) as T;
48
+ },
49
+ };
50
+ }
51
+
52
+ const HUB_KEYS = ['hub.enabled', 'hub.token', 'hub.chatId', 'hub.defaultPort'] as const;
53
+
54
+ export type TelegramHubProps = SettingsPageProps & {
55
+ /** Tests inject a stub client; production uses fetch. */
56
+ managerClient?: ManagerClient;
57
+ };
58
+
59
+ export default function TelegramHub({ port, client, dirty, registerSave, managerClient }: TelegramHubProps) {
60
+ // Reuse page-shell's snapshot only for parity (loading/error scaffolding); the real load
61
+ // runs through managerClient below, because `client` hits /i/{port} and 404s here.
62
+ const { state } = usePageSnapshot<HubResponse>(client, '__telegram_hub_unused__', [port]);
63
+ void state;
64
+
65
+ const [config, setConfig] = useState<HubConfig | null>(null);
66
+ const [runtime, setRuntime] = useState<HubRuntime | null>(null);
67
+ const [loadError, setLoadError] = useState<string | null>(null);
68
+ const [enabled, setEnabled] = useState(false);
69
+ const [token, setToken] = useState(''); // blank ⇒ keep stored token
70
+ const [chatId, setChatId] = useState('');
71
+ const [defaultPort, setDefaultPort] = useState(PORT_MIN);
72
+ const mClient = managerClient || defaultManagerClient();
73
+
74
+ const load = useCallback(async () => {
75
+ setLoadError(null);
76
+ try {
77
+ const res = await mClient.get<HubResponse>('/api/dashboard/telegram-hub');
78
+ setConfig(res.config);
79
+ setRuntime(res.runtime || null);
80
+ setEnabled(res.config.enabled);
81
+ setChatId(res.config.chatId);
82
+ setDefaultPort(res.config.defaultPort);
83
+ setToken('');
84
+ } catch (err) {
85
+ setLoadError(err instanceof Error ? err.message : String(err));
86
+ }
87
+ }, [mClient]);
88
+
89
+ useEffect(() => { void load(); /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [port]);
90
+ useEffect(() => () => { for (const k of HUB_KEYS) dirty.remove(k); }, [dirty]);
91
+
92
+ const onSave = useCallback(async () => {
93
+ const body: Record<string, unknown> = { enabled, chatId: chatId.trim(), defaultPort };
94
+ if (token.trim()) body['token'] = token.trim(); // omit ⇒ keep stored token
95
+ const res = await mClient.put<HubResponse>('/api/dashboard/telegram-hub', body);
96
+ setConfig(res.config);
97
+ setRuntime(res.runtime || null);
98
+ setToken('');
99
+ for (const k of HUB_KEYS) dirty.remove(k);
100
+ }, [enabled, chatId, defaultPort, token, mClient, dirty]);
101
+
102
+ useEffect(() => {
103
+ if (!registerSave) return;
104
+ registerSave(onSave);
105
+ return () => registerSave(null);
106
+ }, [registerSave, onSave]);
107
+
108
+ const removeRoute = useCallback(async (r: Route) => {
109
+ try {
110
+ await mClient.delete(
111
+ `/api/dashboard/telegram-hub/routes/${encodeURIComponent(r.chatId)}/${encodeURIComponent(r.threadId)}`,
112
+ );
113
+ } catch (err) {
114
+ setLoadError(err instanceof Error ? err.message : String(err));
115
+ }
116
+ await load();
117
+ }, [mClient, load]);
118
+
119
+ if (loadError) return <PageError message={loadError} />;
120
+ if (!config) return <PageLoading label="Loading Telegram hub…" />;
121
+
122
+ return (
123
+ <form className="settings-page-form settings-form" onSubmit={(e) => { e.preventDefault(); void onSave(); }}>
124
+ <SettingsSection title="Telegram hub" hint="One dashboard-owned bot routes Telegram chat topics to instances 3457–3506.">
125
+ <ToggleField
126
+ id="hub-enabled" label="Enable hub" value={enabled}
127
+ onChange={(next) => { setEnabled(next); dirty.set('hub.enabled', { value: next, original: config.enabled, valid: true }); }}
128
+ />
129
+ <SecretField
130
+ id="hub-token" label="Bot token" value={token}
131
+ placeholder={config.hasToken ? '•••• (saved)' : 'paste bot token'}
132
+ onChange={(next) => { setToken(next); dirty.set('hub.token', { value: next, original: '', valid: true }); }}
133
+ />
134
+ <TextField
135
+ id="hub-chat-id" label="Hub chat ID" value={chatId} placeholder="823… or -100…"
136
+ onChange={(next) => { setChatId(next); dirty.set('hub.chatId', { value: next, original: config.chatId, valid: true }); }}
137
+ />
138
+ {runtime ? (
139
+ <p className="settings-help">
140
+ Runtime: {runtime.state}{runtime.chatId ? ` · ${runtime.chatId}` : ''}{runtime.error ? ` · ${runtime.error}` : ''}
141
+ </p>
142
+ ) : null}
143
+ <label className="settings-field" htmlFor="hub-default-port">
144
+ <span className="settings-field-label">Default port</span>
145
+ <input
146
+ id="hub-default-port" type="number" min={PORT_MIN} max={PORT_MAX} value={defaultPort}
147
+ onChange={(e) => {
148
+ const next = Number(e.target.value);
149
+ setDefaultPort(next);
150
+ dirty.set('hub.defaultPort', { value: next, original: config.defaultPort, valid: next >= PORT_MIN && next <= PORT_MAX });
151
+ }}
152
+ />
153
+ </label>
154
+ </SettingsSection>
155
+
156
+ <SettingsSection title="Topic routes" hint="(chatId, threadId) → instance port. Bind in a bot private topic or group topic with /setthread <port>.">
157
+ {config.routes.length === 0 ? (
158
+ <p className="settings-empty">No routes yet.</p>
159
+ ) : (
160
+ <table className="settings-table">
161
+ <thead><tr><th>Thread</th><th>Port</th><th>Label</th><th>Model</th><th>Prompt</th><th>On</th><th /></tr></thead>
162
+ <tbody>
163
+ {config.routes.map((r) => (
164
+ <tr key={`${r.chatId}:${r.threadId}`}>
165
+ <td>{r.threadId}</td><td>{r.port}</td><td>{r.label || '—'}</td>
166
+ <td>{r.model || '—'}</td><td>{r.systemPrompt ? '✓' : '—'}</td>
167
+ <td>{r.enabled ? '✓' : '—'}</td>
168
+ <td><button type="button" onClick={() => void removeRoute(r)}>Delete</button></td>
169
+ </tr>
170
+ ))}
171
+ </tbody>
172
+ </table>
173
+ )}
174
+ </SettingsSection>
175
+ </form>
176
+ );
177
+ }
178
+
179
+ export const __test__ = { defaultManagerClient };
@@ -100,6 +100,9 @@ export function PerCliRow({ cli, meta, original, value, setValue, setEntry, clie
100
100
  placeholder={modelOptions[0] ?? 'model id'}
101
101
  />
102
102
  )}
103
+ {meta.modelNote ? (
104
+ <p className="settings-percli-note">{meta.modelNote}</p>
105
+ ) : null}
103
106
  {modelOptions.length > 0 ? (
104
107
  <datalist id={modelDatalistId}>
105
108
  {modelOptions.map((m) => (
@@ -109,19 +112,26 @@ export function PerCliRow({ cli, meta, original, value, setValue, setEntry, clie
109
112
  ) : null}
110
113
  </div>
111
114
  {effortOptions.length > 0 ? (
112
- <SelectField
113
- id={`percli-${cli}-effort`}
114
- label="Effort"
115
- value={value.effort ?? ''}
116
- options={[
117
- { value: '', label: '(default)' },
118
- ...effortOptions.map((e) => ({ value: e, label: e })),
119
- ]}
120
- onChange={(next) => {
121
- setValue({ ...value, effort: next });
122
- setEntry(`perCli.${cli}.effort`, entryFor(next, original.effort ?? ''));
123
- }}
124
- />
115
+ <div className="settings-percli-effort">
116
+ <SelectField
117
+ id={`percli-${cli}-effort`}
118
+ label="Effort"
119
+ value={value.effort ?? ''}
120
+ options={[
121
+ { value: '', label: '(default)' },
122
+ ...effortOptions.map((e) => ({ value: e, label: e })),
123
+ ]}
124
+ onChange={(next) => {
125
+ setValue({ ...value, effort: next });
126
+ setEntry(`perCli.${cli}.effort`, entryFor(next, original.effort ?? ''));
127
+ }}
128
+ />
129
+ {meta.effortNote ? (
130
+ <p className="settings-percli-note">{meta.effortNote}</p>
131
+ ) : null}
132
+ </div>
133
+ ) : meta.effortNote ? (
134
+ <p className="settings-percli-note settings-percli-note--effort">{meta.effortNote}</p>
125
135
  ) : null}
126
136
  <ToggleField
127
137
  id={`percli-${cli}-fastmode`}
@@ -7,6 +7,7 @@ export type CliMeta = {
7
7
  modelsByProvider?: Record<string, ReadonlyArray<string>>;
8
8
  effortsByProvider?: Record<string, ReadonlyArray<string>>;
9
9
  effortNote?: string;
10
+ modelNote?: string;
10
11
  };
11
12
 
12
13
  export type PerCliEntry = {
@@ -32,7 +33,8 @@ export const CLI_META: Record<string, CliMeta> = {
32
33
  label: 'Antigravity',
33
34
  models: ['gemini-3.5-flash'],
34
35
  efforts: [],
35
- effortNote: 'AGY print mode uses the current AGY-selected model; switch models in native AGY UI, no --model/--effort flags in agy 1.0.0',
36
+ modelNote: 'AGY model override is version-dependent. Current observed AGY 1.0.12 supports --model; cli-jaw probes the installed binary and emits this field only when supported. Leave empty to use native AGY selection.',
37
+ effortNote: 'AGY has no separate effort flag.',
36
38
  },
37
39
  pi: {
38
40
  label: 'Pi',
@@ -17,6 +17,7 @@ export type SettingsCategoryId =
17
17
  | 'mcp'
18
18
  | 'browser'
19
19
  | 'dashboard-meta'
20
+ | 'telegram-hub'
20
21
  | 'advanced-export';
21
22
 
22
23
  export type SettingsCategoryGroup =
@@ -417,6 +417,17 @@
417
417
  align-items: end;
418
418
  }
419
419
 
420
+ .settings-percli-note {
421
+ margin: 4px 0 0;
422
+ color: var(--text-secondary);
423
+ font-size: 11px;
424
+ line-height: 1.35;
425
+ }
426
+
427
+ .settings-percli-note--effort {
428
+ margin-bottom: 2px;
429
+ }
430
+
420
431
  .settings-overrides-table {
421
432
  width: 100%;
422
433
  border-collapse: collapse;
package/public/sw.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // ── CLI-JAW Service Worker ──
2
2
  // Three-tier fetch: navigate→network-first, hashed→cache-first, static→stale-while-revalidate
3
3
 
4
- const CACHE_NAME = 'clijaw-v2';
4
+ const CACHE_NAME = 'clijaw-v3-dev-20260626';
5
5
  const STATIC_ASSETS = [
6
6
  // Only pre-cache immutable/semi-static assets — NOT '/' (HTML is dynamic)
7
7
  '/css/variables.css',
@@ -121,11 +121,16 @@ echo "Verifying better-sqlite3 opens with bundled Node..."
121
121
  echo "Cleaning up Node extract..."
122
122
  rm -rf "/tmp/${NODE_PKG}" /tmp/node-sidecar.zip 2>/dev/null || true
123
123
 
124
- NATIVE_BIN="$PROJECT_ROOT/native/jaw-claude-i/target/release/jaw-claude-i"
124
+ NATIVE_BIN="$PROJECT_ROOT/native/claude-e/target/release/jaw-claude-i"
125
+ LEGACY_NATIVE_BIN="$PROJECT_ROOT/native/jaw-claude-i/target/release/jaw-claude-i"
125
126
  if [ -f "$NATIVE_BIN" ]; then
126
127
  echo "Copying jaw-claude-i..."
127
128
  cp "$NATIVE_BIN" "$SIDECAR_DIR/bin/jaw-claude-i"
128
129
  chmod +x "$SIDECAR_DIR/bin/jaw-claude-i"
130
+ elif [ -f "$LEGACY_NATIVE_BIN" ]; then
131
+ echo "Copying jaw-claude-i from legacy native path..."
132
+ cp "$LEGACY_NATIVE_BIN" "$SIDECAR_DIR/bin/jaw-claude-i"
133
+ chmod +x "$SIDECAR_DIR/bin/jaw-claude-i"
129
134
  else
130
135
  echo "WARN: jaw-claude-i not found, skipping (optional)"
131
136
  fi
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-XQCOJYun.js";import{n as t,t as n}from"./jsx-runtime-B3ZGMGGg.js";import{a as r,i,n as a,r as o,t as s}from"./page-shell-BeAyKBJW.js";import{a as c,i as l,n as u,r as d,s as f}from"./fields-MeoSVgIK.js";import{n as p}from"./agent-meta-g8UDRdWA.js";import{t as m}from"./path-utils-DX1HplvB.js";var h=e(t(),1),g=n(),_=[`basic`,`openai`,`anthropic`,`vertex`];function v(e){return e===`anthropic`?`https://api.anthropic.com/v1/messages`:e===`vertex`?`https://LOCATION-aiplatform.googleapis.com/v1`:`http://127.0.0.1:18645/v1`}function y({client:e,pi:t,provider:n,model:r,onClose:i,onRegistered:a}){let o=(0,h.useMemo)(()=>t?.profiles?.find(e=>e.id===n)||t?.profiles?.[0],[t,n]),[s,c]=(0,h.useState)(o?.mode||`basic`),[u,d]=(0,h.useState)(o?.id||n||`progrok`),[p,m]=(0,h.useState)(o?.endpoint||v(s)),[y,b]=(0,h.useState)(r||o?.model||`grok-composer-2.5-fast`),[x,S]=(0,h.useState)(``),[C,w]=(0,h.useState)(!1),[T,E]=(0,h.useState)(null);(0,h.useEffect)(()=>{m(e=>e||v(s))},[s]);let D=async()=>{w(!0),E(null);try{let t=await e.post(`/api/pi/profiles/register`,{id:u,label:u,mode:s,endpoint:p,model:y,apiKey:x});a({provider:u,model:y,models:t.models||[],pi:t.settings?.pi}),i()}catch(e){E(e instanceof Error?e.message:String(e))}finally{w(!1)}};return(0,g.jsx)(`div`,{className:`settings-memory-modal`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`pi-profile-title`,children:(0,g.jsxs)(`div`,{className:`settings-memory-modal-card`,children:[(0,g.jsxs)(`header`,{className:`settings-memory-modal-header`,children:[(0,g.jsx)(`h3`,{id:`pi-profile-title`,children:`Pi Settings`}),(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:i,children:`Close`})]}),(0,g.jsxs)(`div`,{className:`settings-page-form`,children:[(0,g.jsx)(l,{id:`pi-profile-mode`,label:`Mode`,value:s,options:_.map(e=>({value:e,label:e})),onChange:e=>c(e)}),(0,g.jsx)(f,{id:`pi-profile-id`,label:`Provider`,value:u,onChange:d,placeholder:`progrok`}),(0,g.jsx)(f,{id:`pi-profile-endpoint`,label:`Endpoint`,value:p,onChange:m,placeholder:v(s)}),(0,g.jsx)(f,{id:`pi-profile-model`,label:`Model`,value:y,onChange:b,placeholder:`grok-composer-2.5-fast`}),(0,g.jsx)(f,{id:`pi-profile-key`,label:`API Key`,value:x,onChange:S,placeholder:o?.apiKeySet?`set (${o.apiKeyLast4||`****`})`:`empty for local proxy`}),(0,g.jsx)(`p`,{className:`settings-empty`,children:`Default: grok-composer-2.5-fast. Bare grok-composer-2.5 currently has no verified team access.`}),T?(0,g.jsx)(`p`,{className:`settings-field-error`,children:T}):null,(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:C,onClick:()=>void D(),children:C?`Registering...`:`Register`})]})]})})}function b(e,t,n=``){let r=new Set;n&&r.add(n);for(let n of e?.discoveredModels?.[t]||[])r.add(n);let i=e?.profiles?.find(e=>e.id===t);return i?.model&&r.add(i.model),[...r]}function x(e,t=``){let n=new Set;t&&n.add(t);for(let t of e?.profiles||[])n.add(t.id);return[...n]}function S(e,t,n=!0){return{value:e,original:t,valid:n}}function C({cli:e,meta:t,original:n,value:r,setValue:i,setEntry:a,client:o,pi:s,setPi:u}){let d=`percli-${e}-models`,p=e===`pi`,[m,_]=(0,h.useState)(!1),v=r.provider||t.defaultProvider||t.providers?.[0]||`claude`,C=p?b(s,v,r.model||``):[],w=!p&&(t.providers?.length??0)>0,T=p?C:w?t.modelsByProvider?.[v]??t.models:t.models,E=w?t.effortsByProvider?.[v]??t.efforts:t.efforts;return(0,g.jsxs)(`div`,{className:`settings-percli-row`,"data-cli":e,children:[(0,g.jsx)(`h3`,{className:`settings-percli-title`,children:t.label}),(0,g.jsxs)(`div`,{className:`settings-percli-grid`,children:[p&&x(s,v).length?(0,g.jsx)(l,{id:`percli-${e}-provider`,label:`Provider`,value:v,options:x(s,v).map(e=>({value:e,label:e})),onChange:t=>{let o=b(s,t),c=o.includes(r.model||``)?r.model||``:o[0]||``;i({...r,provider:t,model:c}),a(`perCli.${e}.provider`,S(t,n.provider??`progrok`)),a(`perCli.${e}.model`,S(c,n.model??``))}}):w?(0,g.jsx)(l,{id:`percli-${e}-provider`,label:`Provider`,value:v,options:(t.providers??[]).map(e=>({value:e,label:e})),onChange:o=>{let s=t.modelsByProvider?.[o]??[],c=t.effortsByProvider?.[o]??[],l=s.includes(r.model||``)?r.model||``:s[0]||``,u=c.includes(r.effort||``)&&r.effort||``;i({...r,provider:o,model:l,effort:u}),a(`perCli.${e}.provider`,S(o,n.provider??t.defaultProvider??`claude`)),a(`perCli.${e}.model`,S(l,n.model??``)),a(`perCli.${e}.effort`,S(u,n.effort??``))}}):null,(0,g.jsxs)(`div`,{className:`settings-percli-model`,children:[p&&T.length>0?(0,g.jsx)(l,{id:`percli-${e}-model`,label:`Model`,value:r.model??T[0]??``,options:T.map(e=>({value:e,label:e})),onChange:t=>{i({...r,model:t}),a(`perCli.${e}.model`,S(t,n.model??``))}}):(0,g.jsx)(f,{id:`percli-${e}-model`,label:`Model`,value:r.model??``,onChange:t=>{i({...r,model:t}),a(`perCli.${e}.model`,S(t,n.model??``))},placeholder:T[0]??`model id`}),T.length>0?(0,g.jsx)(`datalist`,{id:d,children:T.map(e=>(0,g.jsx)(`option`,{value:e},e))}):null]}),E.length>0?(0,g.jsx)(l,{id:`percli-${e}-effort`,label:`Effort`,value:r.effort??``,options:[{value:``,label:`(default)`},...E.map(e=>({value:e,label:e}))],onChange:t=>{i({...r,effort:t}),a(`perCli.${e}.effort`,S(t,n.effort??``))}}):null,(0,g.jsx)(c,{id:`percli-${e}-fastmode`,label:`Fast mode`,value:!!r.fastMode,onChange:t=>{i({...r,fastMode:t}),a(`perCli.${e}.fastMode`,S(t,!!n.fastMode))}}),p&&o?(0,g.jsx)(`button`,{type:`button`,className:`settings-action`,onClick:()=>_(!0),children:`Settings`}):null]}),p&&o&&m?(0,g.jsx)(y,{client:o,pi:s,provider:v,model:r.model||`grok-composer-2.5-fast`,onClose:()=>_(!1),onRegistered:({provider:t,model:o,pi:s})=>{s&&u&&u(s),i({...r,provider:t,model:o}),a(`perCli.${e}.provider`,S(t,n.provider??`progrok`)),a(`perCli.${e}.model`,S(o,n.model??``))}}):null]})}function w(e){return[...e].sort((e,t)=>e===`pi`?-1:t===`pi`?1:e===`ai-e`?t===`pi`?1:-1:t===`ai-e`?e===`pi`?-1:1:0)}function T(e){let t=new Set;for(let n of Object.keys(e.activeOverrides||{}))t.add(n);for(let n of Object.keys(e.perCli||{}))t.add(n);let n={};for(let e of t)n[e]={model:``,effort:``};return{activeOverrides:n}}function E({port:e,client:t,dirty:n,registerSave:c}){let{state:l,refresh:f,setData:_}=r(t,`/api/settings`),[v,y]=(0,h.useState)({}),[b,x]=(0,h.useState)(void 0),[S,E]=(0,h.useState)([]),[D,O]=(0,h.useState)({}),[k,A]=(0,h.useState)(!1),[j,M]=(0,h.useState)(null);(0,h.useEffect)(()=>{if(l.kind!==`ready`)return;y({...l.data.perCli||{}}),x(l.data.pi),E([...l.data.fallbackOrder||[]]);let e=l.data.perCli?.codex||{},t={};typeof e.contextWindowSize==`number`&&(t.contextWindowSize=e.contextWindowSize),typeof e.contextWindowCompactLimit==`number`&&(t.contextWindowCompactLimit=e.contextWindowCompactLimit),O(t)},[l]),(0,h.useEffect)(()=>()=>{for(let e of Array.from(n.pending.keys()))(e===`fallbackOrder`||e.startsWith(`perCli.`))&&n.remove(e)},[n]);let N=(0,h.useCallback)((e,t)=>n.set(e,t),[n]),P=(0,h.useCallback)(async()=>{let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=m(e),i=await t.put(`/api/settings`,r),a=i&&typeof i==`object`&&`data`in i?i.data:i;n.clear(),_(a),y({...a.perCli||{}}),E([...a.fallbackOrder||[]]),await f()},[t,n,f,_]);(0,h.useEffect)(()=>{if(c)return c(P),()=>c(null)},[c,P]);let F=(0,h.useCallback)(async()=>{if(l.kind===`ready`&&window.confirm(`Reset all active overrides?`)){A(!0),M(null);try{let e=T(l.data),n=await t.put(`/api/settings`,e);_(n&&typeof n==`object`&&`data`in n?n.data:n),await f()}catch(e){M(e instanceof Error?e.message:String(e))}finally{A(!1)}}},[t,f,_,l]);if(l.kind===`loading`)return(0,g.jsx)(a,{});if(l.kind===`offline`)return(0,g.jsx)(o,{port:e});if(l.kind===`error`)return(0,g.jsx)(s,{message:l.message});let I=l.data,L=I.perCli||{},R=w(Object.keys(L)),z=L.codex||{},B=I.activeOverrides||{},V=Object.entries(B);return(0,g.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),P()},children:[(0,g.jsx)(i,{title:`Model defaults`,hint:`Per-CLI defaults applied when no active override is set on the Agent page.`,children:R.length===0?(0,g.jsx)(`p`,{className:`settings-empty`,children:`No CLIs registered for this instance.`}):R.map(e=>(0,g.jsx)(C,{cli:e,meta:p(e),original:L[e]||{},value:v[e]||L[e]||{},setValue:t=>y({...v,[e]:t}),setEntry:N,client:t,pi:b,setPi:x},e))}),L.codex?(0,g.jsxs)(i,{title:`Codex context window`,hint:`Codex-only sliders. Other CLIs ignore these values.`,children:[(0,g.jsx)(d,{id:`model-codex-ctx`,label:`Context window size`,value:D.contextWindowSize??(typeof z.contextWindowSize==`number`?z.contextWindowSize:1e6),min:0,step:1e4,onChange:e=>{O({...D,contextWindowSize:e}),N(`perCli.codex.contextWindowSize`,{value:e,original:z.contextWindowSize??1e6,valid:Number.isFinite(e)&&e>=0})}}),(0,g.jsx)(d,{id:`model-codex-compact`,label:`Compact limit`,value:D.contextWindowCompactLimit??(typeof z.contextWindowCompactLimit==`number`?z.contextWindowCompactLimit:9e5),min:0,step:1e4,onChange:e=>{O({...D,contextWindowCompactLimit:e}),N(`perCli.codex.contextWindowCompactLimit`,{value:e,original:z.contextWindowCompactLimit??9e5,valid:Number.isFinite(e)&&e>=0})}})]}):null,(0,g.jsx)(i,{title:`Fallback order`,hint:`Order of CLIs used when the active CLI fails. Press Enter to add a chip; Backspace to remove the last.`,children:(0,g.jsx)(u,{id:`model-fallbackOrder`,label:`Fallback order`,value:S,onChange:e=>{E(e),N(`fallbackOrder`,{value:e,original:I.fallbackOrder||[],valid:!0})},placeholder:`cli name`})}),(0,g.jsxs)(i,{title:`Active overrides`,hint:`Per-session overrides applied on top of per-CLI defaults.`,children:[V.length===0?(0,g.jsx)(`p`,{className:`settings-empty`,children:`No active overrides.`}):(0,g.jsxs)(`table`,{className:`settings-overrides-table`,children:[(0,g.jsx)(`thead`,{children:(0,g.jsxs)(`tr`,{children:[(0,g.jsx)(`th`,{scope:`col`,children:`CLI`}),(0,g.jsx)(`th`,{scope:`col`,children:`Model`}),(0,g.jsx)(`th`,{scope:`col`,children:`Effort`})]})}),(0,g.jsx)(`tbody`,{children:V.map(([e,t])=>(0,g.jsxs)(`tr`,{children:[(0,g.jsx)(`td`,{children:e}),(0,g.jsx)(`td`,{children:(0,g.jsx)(`code`,{children:t?.model||`—`})}),(0,g.jsx)(`td`,{children:(0,g.jsx)(`code`,{children:t?.effort||`—`})})]},e))})]}),(0,g.jsxs)(`div`,{className:`settings-overrides-actions`,children:[(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:()=>void F(),disabled:k||V.length===0,children:k?`Resetting…`:`Reset overrides`}),j?(0,g.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:j}):null]})]})]})}export{T as buildResetOverridesPatch,E as default,w as orderModelCliKeys};
@@ -1 +0,0 @@
1
- import{r as e,t}from"./bgtask-badge-xWbw-l-0.js";export{t as applyBgtaskUpdate,e as refreshBgtaskBadge};
@@ -1 +0,0 @@
1
- import{n as e}from"./api-tVoG39dL.js";var t={agy:{label:`Antigravity`,efforts:[],effortNote:`Change at TUI`,modelNote:`Change at TUI`,models:[]},"ai-e":{label:`AI-E`,defaultProvider:`claude`,providers:[`claude`,`codex`,`gemini`,`grok`,`copilot`,`kiro`],efforts:[`low`,`medium`,`high`,`xhigh`,`max`],models:[`opus`,`sonnet`,`haiku`,`gpt-5.5`,`gpt-5.4`,`gpt-5.4-mini`,`gemini-3-flash-preview`,`grok-build`,`grok-composer-2.5-fast`,`gpt-5-mini`],modelsByProvider:{claude:[`claude-fable-5`,`claude-opus-4-8`,`opus`,`sonnet`,`haiku`],codex:[`gpt-5.5`,`gpt-5.4`,`gpt-5.4-mini`],gemini:[`gemini-3-flash-preview`],grok:[`grok-build`,`grok-composer-2.5-fast`],copilot:[`gpt-5-mini`],kiro:[`auto`,`claude-sonnet-4.6`,`deepseek-3.2`,`minimax-m2.5`,`glm-5`,`qwen3-coder-next`]},effortsByProvider:{claude:[`low`,`medium`,`high`,`xhigh`,`max`],codex:[`low`,`medium`,`high`,`xhigh`],gemini:[],grok:[],copilot:[`low`,`medium`,`high`],kiro:[]}},claude:{label:`Claude`,efforts:[`low`,`medium`,`high`,`xhigh`,`max`],models:[`opus`,`sonnet`,`sonnet[1m]`,`haiku`,`claude-fable-5`,`claude-fable-5[1m]`,`claude-opus-4-8`,`claude-opus-4-8[1m]`,`claude-opus-4-7`,`claude-opus-4-7[1m]`,`claude-opus-4-6`,`claude-opus-4-6[1m]`,`claude-sonnet-4-6`,`claude-sonnet-4-6[1m]`,`claude-haiku-4-5`]},"claude-e":{label:`Claude E`,efforts:[`low`,`medium`,`high`,`xhigh`,`max`],models:[`opus`,`sonnet`,`haiku`,`claude-fable-5`,`claude-opus-4-8`,`claude-opus-4-7`,`claude-sonnet-4-6`,`claude-haiku-4-5`]},codex:{label:`Codex`,efforts:[`low`,`medium`,`high`,`xhigh`],models:[`gpt-5.5`,`gpt-5.4`,`gpt-5.3-codex`,`gpt-5.3-codex-spark`,`gpt-5.2-codex`,`gpt-5.1-codex-max`,`gpt-5.1-codex-mini`]},"codex-app":{label:`Codex App`,efforts:[`low`,`medium`,`high`,`xhigh`],models:[`gpt-5.5`,`gpt-5.4`,`gpt-5.4-mini`,`gpt-5.3-codex`,`gpt-5.3-codex-spark`]},cursor:{label:`Cursor`,efforts:[`none`,`none-fast`,`low`,`low-fast`,`medium`,`medium-fast`,`high`,`high-fast`,`xhigh`,`xhigh-fast`,`max`,`max-fast`],effortNote:`Cursor effort resolves to model IDs; cli-jaw never passes --effort`,models:`auto,composer-2.5,composer-2,gpt-5.5,gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.3-codex,gpt-5.2,gpt-5.2-codex,gpt-5.1-codex-max,gpt-5.1-codex-mini,gpt-5.1,claude-fable-5,claude-fable-5-thinking,claude-opus-4-8,claude-opus-4-8-thinking,claude-opus-4-7,claude-opus-4-7-thinking,claude-4.6-opus,claude-4.6-sonnet,claude-4.5-opus-high,claude-4.5-sonnet,claude-4-sonnet,gemini-3.1-pro,gemini-3-flash,gemini-3.5-flash,grok-4.3,grok-build-0.1,gpt-5-mini,kimi-k2.5`.split(`,`)},"kiro-code":{label:`Kiro`,efforts:[],effortNote:`Kiro CLI has no separate effort flag`,models:[`auto`,`claude-fable-5`,`claude-opus-4.8`,`claude-opus-4.7`,`claude-opus-4.6`,`claude-sonnet-4.6`,`claude-opus-4.5`,`claude-sonnet-4.5`,`claude-sonnet-4`,`claude-haiku-4.5`,`deepseek-3.2`,`minimax-m2.5`,`minimax-m2.1`,`glm-5`,`qwen3-coder-next`]},gemini:{label:`Gemini`,efforts:[],models:[`gemini-3.0-pro-preview`,`gemini-3.1-pro-preview`,`gemini-2.5-pro`,`gemini-3-flash-preview`,`gemini-2.5-flash`]},grok:{label:`Grok`,efforts:[],effortNote:`unsupported by grok-build/composer; do not pass --effort`,models:[`grok-build`,`grok-composer-2.5-fast`]},opencode:{label:`OpenCode`,efforts:[`minimal`,`low`,`high`,`max`],models:[`opencode-go/glm-5.1`,`opencode-go/kimi-k2.6`,`opencode-go/mimo-v2.5-pro`,`opencode-go/mimo-v2.5`,`opencode-go/minimax-m2.7`,`opencode-go/qwen3.6-plus`,`opencode-go/deepseek-v4-pro`,`opencode-go/deepseek-v4-flash`]},copilot:{label:`Copilot`,efforts:[`low`,`medium`,`high`],effortNote:`-> ~/.copilot/config.json`,models:[`gpt-5.5`,`claude-fable-5`,`claude-opus-4.8`,`claude-sonnet-4.6`,`claude-haiku-4.5`,`gpt-5.4`,`gpt-5.3-codex`,`gpt-5.2-codex`,`gpt-5.1-codex`,`gpt-4.1`,`gpt-5-mini`,`gemini-3-pro-preview`]}};function n(e){let t={};for(let[n,r]of Object.entries(e))t[n]=Array.isArray(r?.models)?[...r.models]:[];return t}function r(e){let t={};for(let[n,r]of Object.entries(e||{})){if(!r||typeof r!=`object`)continue;let e=r,i={label:e.label||n,efforts:Array.isArray(e.efforts)?[...e.efforts]:[],models:Array.isArray(e.models)?[...e.models]:[]};typeof e.effortNote==`string`&&e.effortNote.trim()&&(i.effortNote=e.effortNote),typeof e.modelNote==`string`&&e.modelNote.trim()&&(i.modelNote=e.modelNote),typeof e.defaultProvider==`string`&&(i.defaultProvider=e.defaultProvider),Array.isArray(e.providers)&&(i.providers=[...e.providers]),e.modelsByProvider&&typeof e.modelsByProvider==`object`&&(i.modelsByProvider=Object.fromEntries(Object.entries(e.modelsByProvider).filter(e=>Array.isArray(e[1])).map(([e,t])=>[e,[...t]]))),e.effortsByProvider&&typeof e.effortsByProvider==`object`&&(i.effortsByProvider=Object.fromEntries(Object.entries(e.effortsByProvider).filter(e=>Array.isArray(e[1])).map(([e,t])=>[e,[...t]]))),t[n]=i}return t}var i=r(t),a=Object.keys(i),o=n(i);function s(e){let t=r(e);return Object.keys(t).length?(i=t,a=Object.keys(t),o=n(t),!0):!1}async function c(){try{let t=await e(`/api/cli-registry`);if(!t||!s(t))throw Error(`invalid registry`)}catch(e){console.warn(`[cli-registry] fallback:`,e.message),s(t)}return i}function l(){return a}function u(e){return i[e]||null}var d=[`pi`,`claude`,`claude-e`,`agy`,`codex`,`cursor`,`kiro-code`,`gemini`],f=[{value:`frontend`,labelKey:`role.label.frontend`,label:`Frontend`,prompt:`Frontend employee — UI/UX, CSS, components`,skill:`dev-frontend`},{value:`backend`,labelKey:`role.label.backend`,label:`Backend`,prompt:`Backend employee — API, DB, server logic`,skill:`dev-backend`},{value:`data`,labelKey:`role.label.data`,label:`Data`,prompt:`Data employee — data pipeline, analysis, ML`,skill:`dev-data`},{value:`docs`,labelKey:`role.label.docs`,label:`Docs`,prompt:`Docs employee — documentation, README, API docs`,skill:`documentation`},{value:`security`,labelKey:`role.label.security`,label:`Security`,prompt:`Security reviewer — auth, secrets, injection, destructive-command, sandbox, and data exposure risks`,skill:`dev-security`},{value:`testing`,labelKey:`role.label.testing`,label:`Testing`,prompt:`Testing reviewer — unit, integration, regression, smoke, and edge-case coverage`,skill:`dev-testing`},{value:`custom`,labelKey:`role.label.custom`,label:`Custom...`,prompt:``,skill:null}];export{u as a,l as i,d as n,c as o,f as r,o as t};