cli-jaw 2.17.44 → 2.17.45

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 (219) hide show
  1. package/README.ja.md +5 -7
  2. package/README.ko.md +5 -7
  3. package/README.md +19 -7
  4. package/README.zh-CN.md +5 -7
  5. package/dist/bin/commands/dispatch.js +93 -18
  6. package/dist/bin/commands/dispatch.js.map +1 -1
  7. package/dist/bin/commands/doctor.js +0 -70
  8. package/dist/bin/commands/doctor.js.map +1 -1
  9. package/dist/bin/commands/provider.js +16 -28
  10. package/dist/bin/commands/provider.js.map +1 -1
  11. package/dist/bin/commands/slack.js +65 -2
  12. package/dist/bin/commands/slack.js.map +1 -1
  13. package/dist/bin/commands/tui/slash-command-runner.js +1 -1
  14. package/dist/bin/commands/tui/slash-command-runner.js.map +1 -1
  15. package/dist/bin/commands/tui/types.js +0 -4
  16. package/dist/bin/commands/tui/types.js.map +1 -1
  17. package/dist/scripts/fresh-install-smoke.js +1 -1
  18. package/dist/scripts/fresh-install-smoke.js.map +1 -1
  19. package/dist/server.js +5 -3
  20. package/dist/server.js.map +1 -1
  21. package/dist/src/agent/args.js +1 -176
  22. package/dist/src/agent/args.js.map +1 -1
  23. package/dist/src/agent/claude-runtime-pool.js +11 -7
  24. package/dist/src/agent/claude-runtime-pool.js.map +1 -1
  25. package/dist/src/agent/cli-helpers.js +1 -3
  26. package/dist/src/agent/cli-helpers.js.map +1 -1
  27. package/dist/src/agent/error-classifier.js +1 -1
  28. package/dist/src/agent/error-classifier.js.map +1 -1
  29. package/dist/src/agent/error-cooldown.js +1 -3
  30. package/dist/src/agent/error-cooldown.js.map +1 -1
  31. package/dist/src/agent/events/claude.js +4 -56
  32. package/dist/src/agent/events/claude.js.map +1 -1
  33. package/dist/src/agent/events/helpers.js +3 -5
  34. package/dist/src/agent/events/helpers.js.map +1 -1
  35. package/dist/src/agent/events/index.js +12 -18
  36. package/dist/src/agent/events/index.js.map +1 -1
  37. package/dist/src/agent/kiro-runtime.js +3 -16
  38. package/dist/src/agent/kiro-runtime.js.map +1 -1
  39. package/dist/src/agent/lifecycle-handler.js +17 -12
  40. package/dist/src/agent/lifecycle-handler.js.map +1 -1
  41. package/dist/src/agent/native-runtime-run.js +7 -2
  42. package/dist/src/agent/native-runtime-run.js.map +1 -1
  43. package/dist/src/agent/prompt-context.js +4 -5
  44. package/dist/src/agent/prompt-context.js.map +1 -1
  45. package/dist/src/agent/resume-classifier.js +0 -5
  46. package/dist/src/agent/resume-classifier.js.map +1 -1
  47. package/dist/src/agent/runtime/acp/cursor-session.js +21 -3
  48. package/dist/src/agent/runtime/acp/cursor-session.js.map +1 -1
  49. package/dist/src/agent/runtime-pool.js +127 -51
  50. package/dist/src/agent/runtime-pool.js.map +1 -1
  51. package/dist/src/agent/session-persistence.js +1 -6
  52. package/dist/src/agent/session-persistence.js.map +1 -1
  53. package/dist/src/agent/spawn/resume.js +3 -3
  54. package/dist/src/agent/spawn/resume.js.map +1 -1
  55. package/dist/src/agent/spawn.js +27 -96
  56. package/dist/src/agent/spawn.js.map +1 -1
  57. package/dist/src/cli/claude-models.js +1 -1
  58. package/dist/src/cli/claude-models.js.map +1 -1
  59. package/dist/src/cli/cli-status-worker.js +1 -8
  60. package/dist/src/cli/cli-status-worker.js.map +1 -1
  61. package/dist/src/cli/compact.js +2 -6
  62. package/dist/src/cli/compact.js.map +1 -1
  63. package/dist/src/cli/employee-handler.js +4 -0
  64. package/dist/src/cli/employee-handler.js.map +1 -1
  65. package/dist/src/cli/handlers-completions.js +1 -1
  66. package/dist/src/cli/handlers-completions.js.map +1 -1
  67. package/dist/src/cli/handlers-runtime.js +18 -8
  68. package/dist/src/cli/handlers-runtime.js.map +1 -1
  69. package/dist/src/cli/handlers.js +3 -31
  70. package/dist/src/cli/handlers.js.map +1 -1
  71. package/dist/src/cli/opencodex-models.js +0 -5
  72. package/dist/src/cli/opencodex-models.js.map +1 -1
  73. package/dist/src/cli/readiness.js +1 -20
  74. package/dist/src/cli/readiness.js.map +1 -1
  75. package/dist/src/cli/registry-live.js +1 -51
  76. package/dist/src/cli/registry-live.js.map +1 -1
  77. package/dist/src/cli/registry.js +0 -64
  78. package/dist/src/cli/registry.js.map +1 -1
  79. package/dist/src/core/chat-sessions.js +3 -2
  80. package/dist/src/core/chat-sessions.js.map +1 -1
  81. package/dist/src/core/cli-detection.js +2 -178
  82. package/dist/src/core/cli-detection.js.map +1 -1
  83. package/dist/src/core/compact.js +2 -4
  84. package/dist/src/core/compact.js.map +1 -1
  85. package/dist/src/core/config.js +5 -4
  86. package/dist/src/core/config.js.map +1 -1
  87. package/dist/src/core/runtime-settings.js +5 -20
  88. package/dist/src/core/runtime-settings.js.map +1 -1
  89. package/dist/src/core/session-ops.js +4 -6
  90. package/dist/src/core/session-ops.js.map +1 -1
  91. package/dist/src/core/windows-launch-spec.js +1 -1
  92. package/dist/src/http/full-access.js +42 -0
  93. package/dist/src/http/full-access.js.map +1 -0
  94. package/dist/src/manager/proxy.js +1 -0
  95. package/dist/src/manager/proxy.js.map +1 -1
  96. package/dist/src/messaging/send.js +30 -8
  97. package/dist/src/messaging/send.js.map +1 -1
  98. package/dist/src/orchestrator/dispatch-admission.js +424 -0
  99. package/dist/src/orchestrator/dispatch-admission.js.map +1 -0
  100. package/dist/src/orchestrator/distribute.js +63 -21
  101. package/dist/src/orchestrator/distribute.js.map +1 -1
  102. package/dist/src/orchestrator/gateway.js +6 -4
  103. package/dist/src/orchestrator/gateway.js.map +1 -1
  104. package/dist/src/orchestrator/worker-registry.js +8 -1
  105. package/dist/src/orchestrator/worker-registry.js.map +1 -1
  106. package/dist/src/prompt/builder.js +40 -16
  107. package/dist/src/prompt/builder.js.map +1 -1
  108. package/dist/src/prompt/templates/employee.md +4 -4
  109. package/dist/src/routes/messaging.js +34 -18
  110. package/dist/src/routes/messaging.js.map +1 -1
  111. package/dist/src/routes/orchestrate.js +139 -64
  112. package/dist/src/routes/orchestrate.js.map +1 -1
  113. package/dist/src/routes/settings.js +1 -30
  114. package/dist/src/routes/settings.js.map +1 -1
  115. package/dist/src/routes/slack-tools.js +6 -4
  116. package/dist/src/routes/slack-tools.js.map +1 -1
  117. package/dist/src/security/path-guards.js +15 -1
  118. package/dist/src/security/path-guards.js.map +1 -1
  119. package/dist/src/slack/search-quote.js +9 -5
  120. package/dist/src/slack/search-quote.js.map +1 -1
  121. package/dist/src/slack/send-handler.js +1 -25
  122. package/dist/src/slack/send-handler.js.map +1 -1
  123. package/dist/src/slack/slack-file.js +105 -53
  124. package/dist/src/slack/slack-file.js.map +1 -1
  125. package/dist/src/slack/tool-access.js +10 -2
  126. package/dist/src/slack/tool-access.js.map +1 -1
  127. package/dist/src/slack/tool-capabilities.js +16 -8
  128. package/dist/src/slack/tool-capabilities.js.map +1 -1
  129. package/dist/src/types/cli-engine.js +26 -3
  130. package/dist/src/types/cli-engine.js.map +1 -1
  131. package/dist/src/types/cli-events.js +1 -1
  132. package/dist/src/types/cli-events.js.map +1 -1
  133. package/dist/src/workflows/employee-boundary.js +9 -5
  134. package/dist/src/workflows/employee-boundary.js.map +1 -1
  135. package/dist/src/workflows/scope-sandbox.js +5 -2
  136. package/dist/src/workflows/scope-sandbox.js.map +1 -1
  137. package/package.json +2 -6
  138. package/public/dist/.vite/manifest.json +115 -115
  139. package/public/dist/assets/Agent-CKX93LQ8.js +1 -0
  140. package/public/dist/assets/Employees-BuFw6-fT.js +1 -0
  141. package/public/dist/assets/Heartbeat-BmkZshEU.js +1 -0
  142. package/public/dist/assets/Memory-DsK_yOCW.js +1 -0
  143. package/public/dist/assets/ModelProvider-L_hW6YWJ.js +1 -0
  144. package/public/dist/assets/agent-meta-CkRJlOmN.js +1 -0
  145. package/public/dist/assets/{app-9OQNfmqw.js → app-B_JTnXIY.js} +4 -4
  146. package/public/dist/assets/{bgtask-badge-BvxHqMGi.js → bgtask-badge-BLdI7Ara.js} +1 -1
  147. package/public/dist/assets/bgtask-badge-DOhTsE9l.js +1 -0
  148. package/public/dist/assets/cli-engine-NdU0lzs_.js +1 -0
  149. package/public/dist/assets/constants-DmRtjRj3.js +1 -0
  150. package/public/dist/assets/{employees-CkUqN4oh.js → employees-DGoVBWQd.js} +1 -1
  151. package/public/dist/assets/iframe-renderer-Dw5vTqFX.js +1 -0
  152. package/public/dist/assets/{iframe-renderer-C2gchtOj.js → iframe-renderer-mBjdW5ZV.js} +2 -2
  153. package/public/dist/assets/{manager-rb5X-4DJ.js → manager-iX7KosWI.js} +1 -1
  154. package/public/dist/assets/memory-DuHc2no-.js +1 -0
  155. package/public/dist/assets/{memory-BiWzpoBq.js → memory-Hq9y-GQB.js} +1 -1
  156. package/public/dist/assets/message-history-DT0VaJRd.js +1 -0
  157. package/public/dist/assets/{message-history-CuFefS02.js → message-history-H7G4apTo.js} +1 -1
  158. package/public/dist/assets/{provider-icons-Det0fC-4.js → provider-icons-Bge6teOj.js} +1 -1
  159. package/public/dist/assets/{render-DUGqq9Mu.js → render-OT0puqo3.js} +1 -1
  160. package/public/dist/assets/settings-BW8q_Rnq.js +1 -0
  161. package/public/dist/assets/{settings-DQ1fLygB.js → settings-DjCtFSpd.js} +3 -3
  162. package/public/dist/assets/{settings-BqUHavbH.js → settings-KIPNUOIV.js} +1 -1
  163. package/public/dist/assets/settings-core-CVO3_bn9.js +1 -0
  164. package/public/dist/assets/settings-core-DiStY7KC.js +2 -0
  165. package/public/dist/assets/{settings-embedding-BAKFrVLV.js → settings-embedding-DIqST-91.js} +1 -1
  166. package/public/dist/assets/{sidebar-CvGbp9x5.js → sidebar-DiS6dGEP.js} +3 -3
  167. package/public/dist/assets/{skills-abLMqY5_.js → skills-D_mbeyb3.js} +1 -1
  168. package/public/dist/assets/skills-NzM-geDj.js +1 -0
  169. package/public/dist/assets/slash-commands-DUk5bLQ1.js +1 -0
  170. package/public/dist/assets/{slash-commands-D8o9pqOS.js → slash-commands-PWDX9hXL.js} +1 -1
  171. package/public/dist/assets/{trace-drawer-C6RvkUAd.js → trace-drawer-DSn3xg8f.js} +1 -1
  172. package/public/dist/assets/{ui-Bxapl_Eu.js → ui-Dzebjyzl.js} +1 -1
  173. package/public/dist/assets/ui-TcZtZTFR.js +1 -0
  174. package/public/dist/index.html +1 -3
  175. package/public/dist/manager/index.html +1 -1
  176. package/public/dist/settings/index.html +1 -1
  177. package/public/index.html +0 -2
  178. package/public/js/constants.ts +1 -46
  179. package/public/js/features/employees.ts +1 -1
  180. package/public/js/features/retired-runtime-option.ts +2 -2
  181. package/public/js/features/settings-channel.ts +4 -2
  182. package/public/js/features/settings-cli-status-render.ts +2 -2
  183. package/public/js/features/settings-cli-status.ts +0 -2
  184. package/public/js/provider-icons.ts +1 -3
  185. package/public/manager/src/settings/pages/Heartbeat.tsx +2 -2
  186. package/public/manager/src/settings/pages/Memory.tsx +2 -2
  187. package/public/manager/src/settings/pages/ModelProvider.tsx +7 -4
  188. package/public/manager/src/settings/pages/components/agent/FlushAgentSection.tsx +2 -2
  189. package/public/manager/src/settings/pages/components/agent/RuntimeEmployeeRow.tsx +2 -2
  190. package/public/manager/src/settings/pages/components/agent/RuntimeHeader.tsx +2 -2
  191. package/public/manager/src/settings/pages/components/agent/agent-meta.ts +4 -35
  192. package/public/manager/src/settings/pages/components/employees-helpers.ts +0 -2
  193. package/public/manager/src/settings/pages/components/heartbeat-helpers.ts +0 -2
  194. package/scripts/bundle-sidecar.sh +0 -24
  195. package/scripts/check-electron-sidecar-no-jwc.cjs +12 -4
  196. package/scripts/fresh-install-smoke.ts +1 -1
  197. package/scripts/install.sh +0 -5
  198. package/scripts/retired-runtime-package-smoke.mjs +2 -12
  199. package/scripts/verify-fresh-install.sh +0 -14
  200. package/dist/src/agent/claude-e-runtime.js +0 -44
  201. package/dist/src/agent/claude-e-runtime.js.map +0 -1
  202. package/public/dist/assets/Agent-CNad_A6t.js +0 -1
  203. package/public/dist/assets/Employees-B6uviPeN.js +0 -1
  204. package/public/dist/assets/Heartbeat-C3S3d8xW.js +0 -1
  205. package/public/dist/assets/Memory-BgeIbQSr.js +0 -1
  206. package/public/dist/assets/ModelProvider-AnxBVYws.js +0 -1
  207. package/public/dist/assets/agent-meta-BWHASq1a.js +0 -1
  208. package/public/dist/assets/bgtask-badge-DeSZJGNN.js +0 -1
  209. package/public/dist/assets/cli-engine-Bw0QTAVX.js +0 -1
  210. package/public/dist/assets/constants-D8XAqfHk.js +0 -1
  211. package/public/dist/assets/iframe-renderer-DfvACXIn.js +0 -1
  212. package/public/dist/assets/memory-Ckp1Eq5a.js +0 -1
  213. package/public/dist/assets/message-history-Bv0l_t7O.js +0 -1
  214. package/public/dist/assets/settings-C81Kf9uX.js +0 -1
  215. package/public/dist/assets/settings-core-CzdXfoOK.js +0 -2
  216. package/public/dist/assets/settings-core-DO_5M7Lv.js +0 -1
  217. package/public/dist/assets/skills-DFpPmMUR.js +0 -1
  218. package/public/dist/assets/slash-commands-BU58xYih.js +0 -1
  219. package/public/dist/assets/ui-CUB4iwz3.js +0 -1
@@ -26,7 +26,7 @@ import slackSvg from '../assets/providers/slack.svg?raw';
26
26
  import telegramSvg from '../assets/providers/telegram.svg?raw';
27
27
  import opencodeSvg from '../assets/providers/opencode.svg?raw';
28
28
 
29
- export type ProviderSlug = 'ai-e' | 'claude' | 'openai' | 'gemini' | 'antigravity' | 'grok' | 'copilot' | 'cursor' | 'kiro-code' | 'codex' | 'codex-app' | 'opencode' | 'discord' | 'telegram' | 'slack';
29
+ export type ProviderSlug = 'claude' | 'openai' | 'gemini' | 'antigravity' | 'grok' | 'copilot' | 'cursor' | 'kiro-code' | 'codex' | 'codex-app' | 'opencode' | 'discord' | 'telegram' | 'slack';
30
30
 
31
31
  interface ProviderIcon {
32
32
  color: string;
@@ -37,7 +37,6 @@ interface ProviderIcon {
37
37
  const openaiColorSvg = openaiSvg.replace('fill="currentColor"', 'fill="#10A37F"');
38
38
 
39
39
  const PROVIDER_ICONS: Record<ProviderSlug, ProviderIcon> = {
40
- 'ai-e': { color: openaiColorSvg, mono: openaiSvg, label: 'AI-E' },
41
40
  claude: { color: claudeSvg, mono: claudeMonoSvg, label: 'Claude' },
42
41
  openai: { color: openaiColorSvg, mono: openaiSvg, label: 'OpenAI' },
43
42
  gemini: { color: geminiSvg, mono: geminiMonoSvg, label: 'Gemini' },
@@ -67,7 +66,6 @@ const PROVIDER_LABEL_ALIASES: Record<string, string> = {
67
66
 
68
67
  function resolveProviderSlug(slug: string): ProviderSlug | null {
69
68
  const normalized = slug.toLowerCase().replace(/[-_\s]/g, '');
70
- if (normalized === 'aie') return 'ai-e';
71
69
  if (normalized === 'claude' || normalized.startsWith('claude')) return 'claude';
72
70
  if (normalized === 'gemini' || normalized.startsWith('gemini')) return 'gemini';
73
71
  if (normalized === 'antigravity' || normalized === 'agy' || normalized === 'googleantigravity') return 'antigravity';
@@ -35,7 +35,7 @@ import {
35
35
  validateHHMM,
36
36
  validateInterval,
37
37
  } from './components/heartbeat-helpers';
38
- import { metaFor, selectableRuntimeOptions, isRetiredCliSelection } from './components/agent/agent-meta';
38
+ import { metaFor, selectableRuntimeOptions, isRetiredCliSelection, retiredRuntimeLabel } from './components/agent/agent-meta';
39
39
 
40
40
  // Re-export helpers (and types) that tests import from this module.
41
41
  export {
@@ -240,7 +240,7 @@ export default function Heartbeat({ port, client, dirty, registerSave }: Setting
240
240
  id="hb-target"
241
241
  label="Target"
242
242
  value={hbTarget}
243
- missingValueLabel={isRetiredCliSelection(hbTarget) ? 'JWC (retired)' : undefined}
243
+ missingValueLabel={isRetiredCliSelection(hbTarget) ? retiredRuntimeLabel(hbTarget) : undefined}
244
244
  error={isRetiredCliSelection(hbTarget) ? 'The saved target runtime is retired. Choose an available target.' : null}
245
245
  options={targetOptions}
246
246
  onChange={(next) => {
@@ -35,7 +35,7 @@ import {
35
35
  type MemoryBlock,
36
36
  type MemoryEntry,
37
37
  } from './components/memory-helpers';
38
- import { metaFor, selectableRuntimeOptions, isRetiredCliSelection } from './components/agent/agent-meta';
38
+ import { metaFor, selectableRuntimeOptions, isRetiredCliSelection, retiredRuntimeLabel } from './components/agent/agent-meta';
39
39
 
40
40
  // Re-export pure helpers for unit tests (Heartbeat pattern).
41
41
  export {
@@ -274,7 +274,7 @@ export default function Memory({ port, client, dirty, registerSave }: SettingsPa
274
274
  id="memory-cli"
275
275
  label="Flush CLI"
276
276
  value={cli}
277
- missingValueLabel={isRetiredCliSelection(cli) ? 'JWC (retired)' : undefined}
277
+ missingValueLabel={isRetiredCliSelection(cli) ? retiredRuntimeLabel(cli) : undefined}
278
278
  error={isRetiredCliSelection(cli) ? 'The saved runtime is retired. Choose an available runtime.' : null}
279
279
  options={cliOptions}
280
280
  onChange={(next) => {
@@ -14,7 +14,7 @@ import {
14
14
  type SnapshotState,
15
15
  } from './page-shell';
16
16
  import { PerCliRow, type PiRegistration } from './components/PerCliRow';
17
- import { metaFor, normalizeCliMetaRegistry, selectableRuntimeOptions, isRetiredCliSelection } from './components/agent/agent-meta';
17
+ import { metaFor, normalizeCliMetaRegistry, selectableRuntimeOptions, isRetiredCliSelection, retiredRuntimeLabel } from './components/agent/agent-meta';
18
18
  import type { CliMeta, PerCliEntry } from './components/agent/agent-meta';
19
19
  import type { PiSettingsView } from './components/pi-profile';
20
20
  import { expandPatch } from './path-utils';
@@ -40,8 +40,6 @@ export function orderModelCliKeys(keys: string[]): string[] {
40
40
  return selectableRuntimeOptions(keys).sort((a, b) => {
41
41
  if (a === 'pi') return -1;
42
42
  if (b === 'pi') return 1;
43
- if (a === 'ai-e') return b === 'pi' ? 1 : -1;
44
- if (b === 'ai-e') return a === 'pi' ? -1 : 1;
45
43
  return 0;
46
44
  });
47
45
  }
@@ -331,7 +329,12 @@ export default function ModelProvider({ port, client, dirty, registerSave }: Set
331
329
  <ChipListField
332
330
  id="model-fallbackOrder"
333
331
  label="Fallback order"
334
- error={fallback.some(isRetiredCliSelection) ? 'A saved JWC fallback is retired. Remove it before changing this order.' : null}
332
+ error={(() => {
333
+ const retired = fallback.find(isRetiredCliSelection);
334
+ if (!retired) return null;
335
+ const name = retiredRuntimeLabel(retired).replace(' (retired)', '');
336
+ return `A saved ${name} fallback is retired. Remove it before changing this order.`;
337
+ })()}
335
338
  disabled={saving || resetting}
336
339
  value={fallback}
337
340
  onChange={(next) => {
@@ -1,6 +1,6 @@
1
1
  import { SelectField } from '../../../fields';
2
2
  import { SettingsSection } from '../../page-shell';
3
- import { metaFor, selectableRuntimeOptions, isRetiredCliSelection, type CliMeta } from './agent-meta';
3
+ import { metaFor, selectableRuntimeOptions, isRetiredCliSelection, retiredRuntimeLabel, type CliMeta } from './agent-meta';
4
4
 
5
5
  type FlushAgentSectionProps = {
6
6
  activeCli: string;
@@ -46,7 +46,7 @@ export function FlushAgentSection({
46
46
  id="agent-flush-cli"
47
47
  label="Flush CLI"
48
48
  value={flushCli}
49
- missingValueLabel={isRetiredCliSelection(flushCli) ? 'JWC (retired)' : undefined}
49
+ missingValueLabel={isRetiredCliSelection(flushCli) ? retiredRuntimeLabel(flushCli) : undefined}
50
50
  error={isRetiredCliSelection(effectiveCli) ? 'The saved flush runtime is retired. Choose an available runtime.' : null}
51
51
  options={[
52
52
  { value: '', label: '(active CLI)' },
@@ -1,5 +1,5 @@
1
1
  import { SelectField, TextField } from '../../../fields';
2
- import { metaFor, optionList, selectableRuntimeOptions, isRetiredCliSelection, type CliMeta } from './agent-meta';
2
+ import { metaFor, optionList, selectableRuntimeOptions, isRetiredCliSelection, retiredRuntimeLabel, type CliMeta } from './agent-meta';
3
3
  import {
4
4
  isStaticEmployee,
5
5
  runtimeEmployeeError,
@@ -49,7 +49,7 @@ export function RuntimeEmployeeRow({
49
49
  id={`runtime-employee-${employee.id}-cli`}
50
50
  label="CLI"
51
51
  value={employee.cli}
52
- missingValueLabel={retired ? 'JWC (retired)' : undefined}
52
+ missingValueLabel={isRetiredCliSelection(employee.cli) ? retiredRuntimeLabel(employee.cli) : undefined}
53
53
  error={retired ? 'This saved runtime cannot execute. Choose an available runtime.' : null}
54
54
  disabled={locked}
55
55
  options={cliChoices.map((value) => ({ value, label: metaFor(value, cliMeta).label || value }))}
@@ -1,6 +1,6 @@
1
1
  import { SelectField, TextField } from '../../../fields';
2
2
  import { SettingsSection } from '../../page-shell';
3
- import { metaFor, orderRuntimeCliOptions, PRIMARY_CLIS, isRetiredCliSelection, type CliMeta } from './agent-meta';
3
+ import { metaFor, orderRuntimeCliOptions, PRIMARY_CLIS, isRetiredCliSelection, retiredRuntimeLabel, type CliMeta } from './agent-meta';
4
4
 
5
5
  type RuntimeHeaderProps = {
6
6
  cli: string;
@@ -53,7 +53,7 @@ export function RuntimeHeader({
53
53
  id="agent-cli"
54
54
  label="Active CLI"
55
55
  value={cli}
56
- missingValueLabel={retired ? 'JWC (retired)' : undefined}
56
+ missingValueLabel={isRetiredCliSelection(cli) ? retiredRuntimeLabel(cli) : undefined}
57
57
  error={retired ? 'This runtime is retired. Select an available runtime to continue.' : null}
58
58
  options={orderedCliOptions.map((value) => ({ value, label: metaFor(value, cliMeta).label || value }))}
59
59
  collapsedAfter={orderedPrimaryCliCount}
@@ -1,5 +1,5 @@
1
- import { isRetiredCliSelection } from '../../../../../../../src/types/cli-engine';
2
- export { isRetiredCliSelection };
1
+ import { isRetiredCliSelection, retiredRuntimeLabel } from '../../../../../../../src/types/cli-engine';
2
+ export { isRetiredCliSelection, retiredRuntimeLabel };
3
3
  import type { RuntimeTransport } from '../../../../../../../src/shared/runtime-contract';
4
4
 
5
5
  export type CliMeta = {
@@ -49,7 +49,7 @@ export type ActiveOverride = {
49
49
 
50
50
  const CODEX_MODELS: ReadonlyArray<string> = ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex-spark', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna'];
51
51
 
52
- export const PRIMARY_CLIS: ReadonlyArray<string> = ['pi', 'claude', 'claude-e', 'agy', 'codex', 'cursor', 'kiro-code', 'gemini'];
52
+ export const PRIMARY_CLIS: ReadonlyArray<string> = ['pi', 'claude', 'agy', 'codex', 'cursor', 'kiro-code', 'gemini'];
53
53
 
54
54
  export const CLI_META: Record<string, CliMeta> = {
55
55
  agy: {
@@ -75,29 +75,6 @@ export const CLI_META: Record<string, CliMeta> = {
75
75
  efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
76
76
  effortNote: 'Pi runs through --mode rpc. grok-composer-2.5-fast is the verified default; bare grok-composer-2.5 currently has no team access.',
77
77
  },
78
- 'ai-e': {
79
- label: 'AI-E',
80
- defaultProvider: 'claude',
81
- providers: ['claude', 'codex', 'gemini', 'grok', 'copilot', 'kiro'],
82
- models: ['opus', 'sonnet', 'haiku', ...CODEX_MODELS, 'gemini-3-flash-preview', 'grok-build', 'grok-composer-2.5-fast', 'gpt-5-mini'],
83
- efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
84
- modelsByProvider: {
85
- claude: ['claude-fable-5', 'claude-opus-5', 'claude-opus-4-8', 'opus', 'sonnet', 'haiku'],
86
- codex: CODEX_MODELS,
87
- gemini: ['gemini-3-flash-preview'],
88
- grok: ['grok-build', 'grok-composer-2.5-fast'],
89
- copilot: ['gpt-5-mini'],
90
- kiro: ['auto', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', 'claude-sonnet-5', 'claude-opus-5', 'claude-sonnet-4.6', 'deepseek-3.2', 'minimax-m2.5', 'glm-5', 'qwen3-coder-next'],
91
- },
92
- effortsByProvider: {
93
- claude: ['low', 'medium', 'high', 'xhigh', 'max'],
94
- codex: ['low', 'medium', 'high', 'xhigh'],
95
- gemini: [],
96
- grok: [],
97
- copilot: ['low', 'medium', 'high'],
98
- kiro: ['low', 'medium', 'high', 'xhigh'],
99
- },
100
- },
101
78
  claude: {
102
79
  label: 'Claude',
103
80
  // Aliases + pinned full IDs (hyphen form — Anthropic API rejects
@@ -132,14 +109,6 @@ export const CLI_META: Record<string, CliMeta> = {
132
109
  ],
133
110
  efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
134
111
  },
135
- 'claude-e': {
136
- label: 'Claude E',
137
- models: [
138
- 'opus', 'sonnet', 'haiku',
139
- 'claude-fable-5', 'claude-sonnet-5', 'claude-opus-5', 'claude-opus-4-8', 'claude-opus-4-7', 'claude-sonnet-4-6', 'claude-haiku-4-5',
140
- ],
141
- efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
142
- },
143
112
  codex: {
144
113
  label: 'Codex',
145
114
  models: CODEX_MODELS,
@@ -338,7 +307,7 @@ export function coerceEffortForModel(
338
307
  }
339
308
 
340
309
  export function metaFor(cli: string, registry?: Record<string, CliMeta> | null): CliMeta {
341
- if (isRetiredCliSelection(cli)) return { label: 'JWC (retired)', models: [], efforts: [] };
310
+ if (isRetiredCliSelection(cli)) return { label: retiredRuntimeLabel(cli), models: [], efforts: [] };
342
311
  return registry?.[cli] || CLI_META[cli] || { label: cli, models: [], efforts: [] };
343
312
  }
344
313
 
@@ -12,9 +12,7 @@ export type EmployeeRecord = {
12
12
  export const EMPLOYEE_KEYS = ['employees'] as const;
13
13
 
14
14
  export const DEFAULT_CLI_OPTIONS = [
15
- 'ai-e',
16
15
  'claude',
17
- 'claude-e',
18
16
  'codex',
19
17
  'codex-app',
20
18
  'copilot',
@@ -14,9 +14,7 @@ export type { HbJob, HbSchedule, HbScheduleEvery, HbScheduleCron };
14
14
  const INTERVAL_RE = /^\d+[smh]$/;
15
15
  const HHMM_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
16
16
  export const TARGET_FALLBACK = [
17
- 'ai-e',
18
17
  'claude',
19
- 'claude-e',
20
18
  'codex',
21
19
  'codex-app',
22
20
  'copilot',
@@ -103,9 +103,6 @@ const sourceHash = (base = project) => {
103
103
  else fail('Unsupported source entry');
104
104
  };
105
105
  for (const name of sourceNames(base)) walk(name);
106
- // Optional native executables are inputs too, never rebuilt by this script.
107
- for (const name of ['native/claude-e/target/release/jaw-claude-i', 'native/jaw-claude-i/target/release/jaw-claude-i'])
108
- if (exists(path.join(base, name))) walk(name);
109
106
  return hash.digest('hex');
110
107
  };
111
108
  const preflight = () => {
@@ -150,13 +147,6 @@ if (op === 'preflight') {
150
147
  recursive: true, dereference: false, verbatimSymlinks: true,
151
148
  filter: p => p !== path.join(project, 'public/dist'),
152
149
  });
153
- for (const name of ['native/claude-e/target/release/jaw-claude-i', 'native/jaw-claude-i/target/release/jaw-claude-i']) {
154
- if (!exists(path.join(project, name))) continue;
155
- fs.mkdirSync(path.dirname(path.join(build, 'source', name)), { recursive: true });
156
- fs.cpSync(path.join(project, name), path.join(build, 'source', name), {
157
- dereference: false, verbatimSymlinks: true,
158
- });
159
- }
160
150
  if (sourceHash() !== state.sourceSha256 || sourceHash(path.join(build, 'source')) !== state.sourceSha256)
161
151
  fail('Source changed during snapshot');
162
152
  } else {
@@ -396,20 +386,6 @@ echo "Verifying better-sqlite3 opens with bundled Node..."
396
386
  }
397
387
  }
398
388
 
399
- NATIVE_BIN="$SOURCE_ROOT/native/claude-e/target/release/jaw-claude-i"
400
- LEGACY_NATIVE_BIN="$SOURCE_ROOT/native/jaw-claude-i/target/release/jaw-claude-i"
401
- if [ -f "$NATIVE_BIN" ]; then
402
- echo "Copying jaw-claude-i..."
403
- cp "$NATIVE_BIN" "$SIDECAR_DIR/bin/jaw-claude-i"
404
- chmod +x "$SIDECAR_DIR/bin/jaw-claude-i"
405
- elif [ -f "$LEGACY_NATIVE_BIN" ]; then
406
- echo "Copying jaw-claude-i from legacy native path..."
407
- cp "$LEGACY_NATIVE_BIN" "$SIDECAR_DIR/bin/jaw-claude-i"
408
- chmod +x "$SIDECAR_DIR/bin/jaw-claude-i"
409
- else
410
- echo "WARN: jaw-claude-i not found, skipping (optional)"
411
- fi
412
-
413
389
  echo "Creating CLI shims..."
414
390
  if [[ "$PLATFORM" == "win32" ]]; then
415
391
  cat > "$SIDECAR_DIR/bin/jaw.cmd" << 'SHIM'
@@ -3,7 +3,8 @@ const { existsSync, readdirSync, readFileSync, readlinkSync, realpathSync, statS
3
3
  const { isAbsolute, join, relative, resolve, sep } = require('node:path');
4
4
 
5
5
  function retiredPackage(name) {
6
- return /^(?:jawcode|jwc|bun)$/.test(name)
6
+ return /^(?:jawcode|jwc|bun|claude-e|claude-exec)$/.test(name)
7
+ || name === '@bitkyc08/ai-e'
7
8
  || /^@(?:jawcode(?:-[^/]+)?|gajae(?:-[^/]+)?|oven)(?:\/|$)/.test(name);
8
9
  }
9
10
 
@@ -13,12 +14,19 @@ function retiredPayloadReason(file) {
13
14
  const parts = normalized.split('/');
14
15
  // Package names are meaningful only directly below node_modules. A normal
15
16
  // package may ship a Bun adapter (for example hono/dist/adapter/bun).
16
- if (parts.some((part, index) => part === 'node_modules' && retiredPackage(parts[index + 1] || ''))) {
17
+ const atNodeModules = (index) => {
18
+ if (parts[index] !== 'node_modules') return false;
19
+ const first = parts[index + 1] || '';
20
+ if (retiredPackage(first)) return true;
21
+ if (first.startsWith('@')) return retiredPackage(first + '/' + (parts[index + 2] || ''));
22
+ return false;
23
+ };
24
+ if (parts.some((_, index) => atNodeModules(index))) {
17
25
  return 'retired package or scope';
18
26
  }
19
27
  if (/(?:^|\/)electron\/sidecar\/jawcode(?:\/|$)/.test(normalized)) return 'retired vendored runtime';
20
- if (/^(?:bin\/)?(?:bun|jwc)(?:\.(?:cmd|ps1|exe|js))?$/.test(normalized)
21
- || /(?:^|\/)node_modules\/\.bin\/(?:bun|jwc)(?:\.(?:cmd|ps1|exe|js))?$/.test(normalized)) {
28
+ if (/^(?:bin\/)?(?:bun|jwc|jaw-claude-i|claude-e|claude-exec)(?:\.(?:cmd|ps1|exe|js))?$/.test(normalized)
29
+ || /(?:^|\/)node_modules\/\.bin\/(?:bun|jwc|jaw-claude-i|claude-e|claude-exec)(?:\.(?:cmd|ps1|exe|js))?$/.test(normalized)) {
22
30
  return 'retired runtime executable';
23
31
  }
24
32
  if (/(?:^|\/)src\/lib\/tui(?:\/|$)/.test(normalized)) return 'retired TUI assets';
@@ -179,7 +179,7 @@ async function main(): Promise<void> {
179
179
  if (!cliRes.ok) throw new Error(`/api/cli-status HTTP ${cliRes.status}`);
180
180
  const cliJson = (await cliRes.json()) as Record<string, unknown> | null;
181
181
  const keys = Object.keys(cliJson ?? {});
182
- const required: string[] = ['ai-e', 'claude', 'claude-e', 'codex', 'codex-app', 'copilot', 'cursor', 'kiro-code', 'grok', 'opencode'];
182
+ const required: string[] = ['claude', 'codex', 'codex-app', 'copilot', 'cursor', 'kiro-code', 'grok', 'opencode'];
183
183
  for (const k of required) {
184
184
  if (!keys.includes(k)) throw new Error(`missing cli key in status: ${k}`);
185
185
  }
@@ -489,11 +489,6 @@ install_cli_jaw() {
489
489
  unset CLI_JAW_REQUIRE_CLI_TOOLS 2>/dev/null || true
490
490
  unset npm_config_jaw_require_cli_tools 2>/dev/null || true
491
491
  fi
492
- if ! command -v cargo &>/dev/null; then
493
- export CLAUDE_E_SKIP_BUILD="${CLAUDE_E_SKIP_BUILD:-1}"
494
- warn "Rust Cargo not found — skipping optional claude-e native helper build"
495
- warn "Install Rust later and reinstall claude-e if you need the Claude E runtime"
496
- fi
497
492
  eval "$pkg_cmd"
498
493
 
499
494
  hash -r 2>/dev/null || true
@@ -25,16 +25,6 @@ export function checkPackedFiles(files, manifest) {
25
25
  export function checkDefaultInstall(manifest, lock, label = 'root') {
26
26
  assertRetiredManifestAbsent(manifest, `${label}/package.json`);
27
27
  assertRetiredManifestAbsent(lock, `${label}/package-lock.json`);
28
- // ai-e remains an on-demand provider, never a default installation.
29
- for (const pkg of [manifest, ...Object.values(lock.packages || {})]) {
30
- assert.notEqual(pkg.name, '@bitkyc08/ai-e', 'ai-e must not be installed by default');
31
- for (const field of ['dependencies', 'optionalDependencies']) {
32
- assert.equal(pkg[field]?.['@bitkyc08/ai-e'], undefined, 'ai-e must remain an on-demand provider');
33
- }
34
- }
35
- for (const file of Object.keys(lock.packages || {})) {
36
- assert.ok(!file.replaceAll('\\', '/').endsWith('node_modules/@bitkyc08/ai-e'), 'ai-e must not be in the default install tree');
37
- }
38
28
  }
39
29
 
40
30
  // Exercise the real entrypoint in an owned home. Any attempted child process,
@@ -119,7 +109,7 @@ function main() {
119
109
  checkDefaultInstall(manifest, read('package-lock.json'));
120
110
  checkDefaultInstall(read('electron/package.json'), read('electron/package-lock.json'), 'electron');
121
111
  if (args[0] === '--source-only') {
122
- console.log('[retired-runtime-package:source-only] PASS root/electron manifests and locks; ai-e remains on demand');
112
+ console.log('[retired-runtime-package:source-only] PASS root/electron manifests and locks');
123
113
  console.log('[retired-runtime-package:source-only] packed NOT RUN; CLI NOT RUN; staged NOT RUN');
124
114
  return;
125
115
  }
@@ -139,7 +129,7 @@ function main() {
139
129
  assert.equal(entries.length, 1, 'expected one npm package');
140
130
  checkPackedFiles(entries[0].files, manifest);
141
131
  checkRetiredCommand(join(repoRoot, 'dist/bin/cli-jaw.js'));
142
- console.log('[retired-runtime-package] PASS manifest, lock, packed files and retired CLI; ai-e remains on demand');
132
+ console.log('[retired-runtime-package] PASS manifest, lock, packed files and retired CLI');
143
133
  }
144
134
 
145
135
  if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) main();
@@ -32,18 +32,6 @@ run_version() {
32
32
  ok "$name works: $resolved"
33
33
  }
34
34
 
35
- run_optional_version() {
36
- local name="$1"
37
- if command -v "$name" >/dev/null 2>&1 && "$name" --version >/dev/null 2>&1; then
38
- ok "$name works: $(command -v "$name")"
39
- return 0
40
- fi
41
- if [ "${CLI_JAW_REQUIRE_OPTIONAL_RUNTIMES:-0}" = "1" ] || [ "${CLI_JAW_REQUIRE_OPTIONAL_RUNTIMES:-}" = "true" ]; then
42
- fail "$name optional runtime is missing or not runnable"
43
- fi
44
- ok "$name optional runtime not available; continuing"
45
- }
46
-
47
35
  path_contains() {
48
36
  local needle="$1"
49
37
  case ":${PATH:-}:" in
@@ -83,8 +71,6 @@ ok "node version is >=22: $(node --version)"
83
71
  run_version npm
84
72
  run_version jaw
85
73
  run_version cli-jaw
86
- run_optional_version ai-e
87
- run_optional_version claude-e
88
74
 
89
75
  if command -v npm >/dev/null 2>&1; then
90
76
  npm_prefix="$(npm prefix -g 2>/dev/null || true)"
@@ -1,44 +0,0 @@
1
- import { broadcast } from '../core/bus.js';
2
- export function isJawRuntimeEvent(raw) {
3
- return typeof raw === 'object' && raw !== null && raw['type'] === 'jaw_runtime';
4
- }
5
- export function handleJawRuntimeEvent(event, _agentLabel) {
6
- const eventName = String(event['event'] || '');
7
- const runId = String(event['run_id'] || '');
8
- const seq = Number(event['seq'] || 0);
9
- // Internal runtime traces — 'internal' keeps them off WS clients and the
10
- // SSE dual-emit path.
11
- switch (eventName) {
12
- case 'runtime_started':
13
- broadcast('agent:claude-e:runtime_started', { runId, seq, version: event['helperVersion'] }, 'internal');
14
- break;
15
- case 'claude_spawned':
16
- broadcast('agent:claude-e:spawned', { runId, pid: event['pid'] }, 'internal');
17
- break;
18
- case 'session_started':
19
- broadcast('agent:claude-e:session', { runId, sessionId: event['sessionId'], transcriptPath: event['transcriptPath'] }, 'internal');
20
- break;
21
- case 'prompt_injected':
22
- broadcast('agent:claude-e:prompt_injected', { runId }, 'internal');
23
- break;
24
- case 'stop_received':
25
- broadcast('agent:claude-e:stop', { runId, transcriptPath: event['transcriptPath'] }, 'internal');
26
- break;
27
- case 'stop_failure':
28
- broadcast('agent:claude-e:stop_failure', { runId, error: event['error'] }, 'internal');
29
- break;
30
- case 'interrupted':
31
- broadcast('agent:claude-e:interrupted', { runId, sessionId: event['sessionId'], resumable: event['resumable'] }, 'internal');
32
- break;
33
- case 'cleanup_started':
34
- case 'cleanup_done':
35
- broadcast('agent:claude-e:cleanup', { runId, event: eventName, escalated: event['escalated'] }, 'internal');
36
- break;
37
- case 'error':
38
- broadcast('agent:claude-e:error', { runId, message: event['message'], exitCode: event['exitCode'] }, 'internal');
39
- break;
40
- default:
41
- break;
42
- }
43
- }
44
- //# sourceMappingURL=claude-e-runtime.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-e-runtime.js","sourceRoot":"","sources":["../../../src/agent/claude-e-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC1C,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAK,GAA+B,CAAC,MAAM,CAAC,KAAK,aAAa,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAA8B,EAAE,WAAmB;IACrF,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAEtC,yEAAyE;IACzE,sBAAsB;IACtB,QAAQ,SAAS,EAAE,CAAC;QAChB,KAAK,iBAAiB;YAClB,SAAS,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,eAAe,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACzG,MAAM;QACV,KAAK,gBAAgB;YACjB,SAAS,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC9E,MAAM;QACV,KAAK,iBAAiB;YAClB,SAAS,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACnI,MAAM;QACV,KAAK,iBAAiB;YAClB,SAAS,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;YACnE,MAAM;QACV,KAAK,eAAe;YAChB,SAAS,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjG,MAAM;QACV,KAAK,cAAc;YACf,SAAS,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACvF,MAAM;QACV,KAAK,aAAa;YACd,SAAS,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC7H,MAAM;QACV,KAAK,iBAAiB,CAAC;QACvB,KAAK,cAAc;YACf,SAAS,CAAC,wBAAwB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YAC5G,MAAM;QACV,KAAK,OAAO;YACR,SAAS,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACjH,MAAM;QACV;YACI,MAAM;IACd,CAAC;AACL,CAAC"}
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./cli-engine-Bw0QTAVX.js";import{n}from"./settings-types-D3cd6SWy.js";import{t as r}from"./react-C_pPTFsM.js";import{t as i}from"./jsx-runtime-NZYk81nU.js";import{t as a}from"./settings-client-CmwRsVd1.js";import{t as o}from"./error-normalize-CL69Bl7z.js";import{a as s,i as c,n as l,r as u,t as d}from"./page-shell-BeGD0rRQ.js";import{i as f,s as p}from"./fields-mlGpofqQ.js";import{n as m,o as h,r as ee,s as g}from"./Permissions-DzNJCt8K.js";import{a as _,c as v,d as y,i as te,l as b,n as ne,o as x,r as re,s as ie,t as ae,u as S}from"./agent-meta-BWHASq1a.js";import{t as C}from"./path-utils-B6vBr0DD.js";var w=e(r(),1),oe=1e3,se=8e3,ce=9e4;function T(e,t){if(!e||!t)return!1;let n=e[t]?.probeState;return n?n===`checking`||n===`failing`:!1}function le(e){let t=oe*2**Math.min(Number.isFinite(e)&&e>0?Math.floor(e):0,8);return Math.min(Math.max(t,oe),se)}function ue(e){let{snapshot:t,cli:n,attempts:r,now:i,deadline:a}=e;if(!T(t,n))return{kind:`stop`};if(i>=a||r>=24)return{kind:`exhausted`};let o=t?.[n]?.nextRetryAt,s=typeof o==`number`&&o>i?o:i+le(r);return{kind:`wait`,delayMs:Math.max(Math.min(s,a)-i,0)}}var E=i();function de({cli:e,cliOptions:n,provider:r=``,providerOptions:i=[],model:a,modelOptions:o,effort:s,effortOptions:l,workingDir:u,workingDirError:d,cliMeta:m,onCliChange:h,onProviderChange:ee,onModelChange:g,onEffortChange:y,onWorkingDirChange:te}){let b=v(n),x=t(e),re=b.filter(e=>ne.includes(e)).length;return(0,E.jsx)(c,{title:`Agent runtime`,hint:`Active CLI, model, effort, and workspace used by this instance.`,children:(0,E.jsxs)(`div`,{className:`settings-agent-runtime-grid`,children:[(0,E.jsx)(f,{id:`agent-cli`,label:`Active CLI`,value:e,missingValueLabel:x?`JWC (retired)`:void 0,error:x?`This runtime is retired. Select an available runtime to continue.`:null,options:b.map(e=>({value:e,label:_(e,m).label||e})),collapsedAfter:re,onChange:h}),i.length>0?(0,E.jsx)(f,{id:`agent-${e}-provider`,label:`Provider`,value:r,options:i.map(e=>({value:e,label:e})),onChange:e=>ee?.(e)}):null,(0,E.jsx)(f,{id:`agent-model`,label:`Active model`,value:a,disabled:x,options:o.length>0?o:[{value:``,label:`(default)`}],onChange:g}),(0,E.jsx)(f,{id:`agent-effort`,label:`Effort`,value:s,options:[{value:``,label:`(default)`},...l.map(e=>({value:e,label:e}))],disabled:x||l.length===0,onChange:y}),(0,E.jsx)(p,{id:`agent-workingDir`,label:`Working directory`,value:u,error:d,placeholder:`/path/to/project`,onChange:te})]})})}var D=[{value:`auto`,label:`Auto (YOLO)`},{value:`safe`,label:`Safe`},{value:`custom`,label:`Custom allowlist`}];function fe({value:e,configuredValue:t,onChange:n}){let r=h(e),i=r.mode===`custom`?`custom`:r.mode===`safe`?`safe`:`auto`,a=r.mode===`custom`?r.tokens:[],o=r.mode===`custom`?`Editor draft: ${a.length} explicit token${a.length===1?``:`s`}`:null;return(0,E.jsxs)(c,{title:`Permissions`,hint:`Selecting a value changes the draft. Save applies it. Auto (YOLO) requests automatic approval or permission bypass. Behavior varies by runtime.`,children:[(0,E.jsx)(f,{id:`agent-permissions-mode`,label:`Change policy to`,value:i,options:D,onChange:e=>{n(e===`auto`?`auto`:e===`safe`?`safe`:a.length>0&&ee(a)?a:g(null))}}),o?(0,E.jsx)(`p`,{className:`settings-agent-note`,children:o}):null,(0,E.jsxs)(`p`,{className:`settings-agent-note`,id:`agent-configured-policy`,children:[`Configured policy: `,m(t)]})]})}function pe({activeCli:e,flushCli:n,flushModel:r,cliOptions:i,modelOptions:a,cliMeta:o,loading:s,error:l,onFlushCliChange:u,onFlushModelChange:d}){let p=n||e,m=p?_(p,o).label||p:`active`;return(0,E.jsx)(c,{title:`Flush Agent`,hint:`Separate summary agent used for context flush and compact work.`,children:(0,E.jsxs)(`details`,{className:`settings-agent-flush`,children:[(0,E.jsxs)(`summary`,{children:[(0,E.jsx)(`span`,{children:`Flush runtime`}),(0,E.jsxs)(`code`,{children:[m,r&&r!=="default"?` / ${r}`:``]})]}),s?(0,E.jsx)(`p`,{className:`settings-agent-note`,children:`Loading flush settings...`}):null,l?(0,E.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:l}):null,(0,E.jsxs)(`div`,{className:`settings-agent-runtime-grid`,children:[(0,E.jsx)(f,{id:`agent-flush-cli`,label:`Flush CLI`,value:n,missingValueLabel:t(n)?`JWC (retired)`:void 0,error:t(p)?`The saved flush runtime is retired. Choose an available runtime.`:null,options:[{value:``,label:`(active CLI)`},...y(i).map(e=>({value:e,label:_(e,o).label||e}))],onChange:u}),(0,E.jsx)(f,{id:`agent-flush-model`,label:`Flush model`,value:r,disabled:t(p),options:[{value:``,label:`(default)`},...a],onChange:d})]})]})})}function O(e){return e.source===`static`||e.id.startsWith(`static:`)}function me(){return`new:${Date.now().toString(36)}:${Math.random().toString(36).slice(2,8)}`}function he(e,t){let n=y(e)[0]||`claude`,r=t?.[n]?.models?.[0]||`default`;return{id:me(),name:`New Agent`,cli:n,model:r,role:``,status:`idle`,source:`db`}}function ge(e){return Array.isArray(e)?e.map(k).filter(Boolean):e.data.map(k).filter(Boolean)}function k(e){if(!e||typeof e!=`object`)return null;let t=e,n=typeof t.id==`string`?t.id:``,r=typeof t.name==`string`?t.name:``;if(!n||!r)return null;let i=t.source===`static`||n.startsWith(`static:`)?`static`:`db`,a={id:n,name:r,cli:typeof t.cli==`string`&&t.cli?t.cli:`claude`,model:typeof t.model==`string`&&t.model?t.model:`default`,role:typeof t.role==`string`?t.role:``,source:i};return typeof t.status==`string`&&(a.status=t.status),a}function A(e){return e.name.trim()?e.cli.trim()?e.model.trim()?null:`Model is required`:`CLI is required`:`Name is required`}function j(e){return e.some(e=>A(e)!==null)}function _e(e,t){return JSON.stringify(e.map(I))===JSON.stringify(t.map(I))}function M(e,t){let n=new Map(e.map(e=>[e.id,e])),r=new Set(t.map(e=>e.id)),i=[],a=[],o=[];for(let e of t){let t=n.get(e.id);if(!t||e.id.startsWith(`new:`)){i.push(e);continue}let r=P(t,e);Object.keys(r).length>0&&a.push({before:t,after:e,patch:r})}for(let t of e)!r.has(t.id)&&!O(t)&&o.push(t);return{added:i,updated:a,removed:o}}function N(e,t){let n=M(e,t);return{added:n.added.length,updated:n.updated.length,removed:n.removed.length}}async function ve(e,t,n){let r=M(t,n);for(let t of r.removed)await e.delete(`/api/employees/${encodeURIComponent(t.id)}`);for(let t of r.added)await e.post(`/api/employees`,F(t));for(let t of r.updated)await e.put(`/api/employees/${encodeURIComponent(t.after.id)}`,t.patch)}function P(e,t){if(O(t))return e.model===t.model?{}:{model:t.model};let n={};for(let r of[`name`,`cli`,`model`,`role`,`status`])(e[r]||``)!==(t[r]||``)&&(n[r]=t[r]||``);return n}function F(e){return{name:e.name.trim()||`New Agent`,cli:e.cli.trim()||`claude`,model:e.model.trim()||`default`,role:e.role.trim()}}function I(e){let t={id:e.id,name:e.name,cli:e.cli,model:e.model,role:e.role,source:e.source};return e.status!==void 0&&(t.status=e.status),t}function L({employee:e,index:n,cliOptions:r,cliMeta:i,onChange:a,onRemove:o}){let s=O(e),c=_(e.cli,i),l=ie(c.models,e.model),u=A(e),d=t(e.cli),m=y(Array.from(new Set([...r,e.cli,`claude`])).filter(Boolean));return(0,E.jsxs)(`fieldset`,{className:`settings-runtime-employee-row`,children:[(0,E.jsxs)(`legend`,{children:[e.name||`Employee ${n+1}`,s?(0,E.jsx)(`span`,{children:`static`}):null]}),(0,E.jsxs)(`div`,{className:`settings-runtime-employee-grid`,children:[(0,E.jsx)(p,{id:`runtime-employee-${e.id}-name`,label:`Name`,value:e.name,disabled:s,error:u===`Name is required`?u:null,onChange:e=>a({name:e})}),(0,E.jsx)(f,{id:`runtime-employee-${e.id}-cli`,label:`CLI`,value:e.cli,missingValueLabel:d?`JWC (retired)`:void 0,error:d?`This saved runtime cannot execute. Choose an available runtime.`:null,disabled:s,options:m.map(e=>({value:e,label:_(e,i).label||e})),onChange:e=>{a({cli:e,model:_(e,i).models[0]||`default`})}}),(0,E.jsx)(f,{id:`runtime-employee-${e.id}-model`,label:`Model`,value:e.model,disabled:d,options:l.length>0?l:[{value:`default`,label:`default`}],onChange:e=>a({model:e})}),(0,E.jsx)(p,{id:`runtime-employee-${e.id}-role`,label:`Role`,value:e.role,disabled:s,onChange:e=>a({role:e})})]}),(0,E.jsxs)(`div`,{className:`settings-runtime-employee-footer`,children:[(0,E.jsxs)(`span`,{children:[e.source,e.status?` / ${e.status}`:``]}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,disabled:s,onClick:o,"aria-label":`Remove employee ${e.name||n+1}`,children:`Remove`})]})]})}function ye({roster:e,original:t,cliOptions:n,cliMeta:r,loading:i,error:a,onRosterChange:o}){let s=N(t,e),l=j(e);function u(t,n){o(e.map((e,r)=>r===t?{...e,...n}:e))}function d(t){o(e.filter((e,n)=>n!==t))}return(0,E.jsxs)(c,{title:`Employees`,hint:`Runtime dispatch roster. Static employees keep their locked identity; database employees can be edited.`,children:[(0,E.jsxs)(`div`,{className:`settings-runtime-employee-summary`,children:[(0,E.jsxs)(`span`,{children:[`+`,s.added]}),(0,E.jsxs)(`span`,{children:[`~`,s.updated]}),(0,E.jsxs)(`span`,{children:[`-`,s.removed]}),l?(0,E.jsx)(`strong`,{children:`Fix invalid rows before saving.`}):null]}),i?(0,E.jsx)(`p`,{className:`settings-agent-note`,children:`Loading employees...`}):null,a?(0,E.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:a}):null,e.length===0?(0,E.jsx)(`p`,{className:`settings-empty`,children:`No runtime employees configured.`}):(0,E.jsx)(`div`,{className:`settings-runtime-employee-list`,children:e.map((e,t)=>(0,E.jsx)(L,{employee:e,index:t,cliOptions:n,cliMeta:r??null,onChange:e=>u(t,e),onRemove:()=>d(t)},e.id))}),(0,E.jsx)(`div`,{className:`settings-employee-footer-bar`,children:(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:()=>o([...e,he(n,r)]),children:`+ Add employee`})})]})}var R=new Set([`runtimeEmployees`,`flushCli`,`flushModel`]);function z(e){let t={},n=null,r=null;for(let[i,a]of Object.entries(e))i===`runtimeEmployees`?r=a:i===`flushCli`||i===`flushModel`?(n??={},n[i===`flushCli`?`cli`:`model`]=String(a??``)):R.has(i)||(t[i]=a);return{settingsBundle:t,flushPatch:n,runtimeEmployeesNext:r}}async function be(e){let{client:t,bundle:n,employeeDraft:r,employeeOriginal:i}=e;if(j(r))throw Error(`runtime employees: fix invalid rows before saving`);let{settingsBundle:a,flushPatch:o,runtimeEmployeesNext:s}=z(n),c=null;try{if(Object.keys(a).length>0){let e=await t.put(`/api/settings`,C(a));c=e&&typeof e==`object`&&`data`in e?e.data:e}}catch(e){throw Error(`settings save failed: ${e instanceof Error?e.message:String(e)}`)}try{o&&await t.put(`/api/memory-files/settings`,o)}catch(e){throw Error(`flush settings save failed: ${e instanceof Error?e.message:String(e)}`)}try{if(s){let e=i;try{let n=ge(await t.get(`/api/employees`)),r=new Set(i.map(e=>e.id)),a=new Set(s.map(e=>e.id));e=n.filter(e=>r.has(e.id)||a.has(e.id))}catch{}await ve(t,e,s)}}catch(e){throw Error(`runtime employees save failed: ${e instanceof Error?e.message:String(e)}`)}return c}function xe({status:e,exhausted:t=!1}){if(t)return(0,E.jsx)(`div`,{className:`settings-inline-notice`,role:`alert`,children:`상태 확인이 끝나지 않았습니다. 새로고침하거나 잠시 후 다시 확인하세요.`});if(!e)return null;let r=n(e);return r.kind===`checking`?(0,E.jsx)(`div`,{className:`settings-inline-notice`,role:`status`,"aria-live":`polite`,children:`상태 확인 중`}):r.kind===`unknown`?(0,E.jsx)(`div`,{className:`settings-inline-notice`,role:`alert`,children:r.message}):r.kind===`failing`?(0,E.jsxs)(`div`,{className:`settings-inline-notice`,role:`alert`,children:[`상태 확인 실패 (재시도 중)`,e.probeError?`: ${e.probeError}`:``]}):null}function B(e){if(!(e instanceof a)||e.status!==409)return null;try{return JSON.parse(e.detail).settings??null}catch{return null}}function Se({port:e,client:t,dirty:n,registerSave:r}){let{state:i,refresh:a,setData:c}=s(t,`/api/settings`),[f,p]=(0,w.useState)({cli:``,provider:``,model:``,effort:``,workingDir:``,permissions:`auto`}),[m,ee]=(0,w.useState)({}),[g,v]=(0,w.useState)({}),[ne,C]=(0,w.useState)(!0),[oe,se]=(0,w.useState)(null),[T,le]=(0,w.useState)([]),[D,O]=(0,w.useState)([]),[me,he]=(0,w.useState)(!0),[k,A]=(0,w.useState)(null),[M,N]=(0,w.useState)(null),[ve,P]=(0,w.useState)({}),[F,I]=(0,w.useState)(!1),[L,R]=(0,w.useState)(null),[z,Se]=(0,w.useState)(!1),[Ce,we]=(0,w.useState)(null),V=(0,w.useCallback)(async()=>{try{let e=await t.get(`/api/cli-registry`),n=e&&typeof e==`object`&&`data`in e?e.data:e;N(x(n))}catch{N(null)}},[t]),H=(0,w.useRef)(0),Te=(0,w.useRef)({}),[Ee,De]=(0,w.useState)(!1),U=(0,w.useCallback)(async e=>{try{let n=await t.get(`/api/cli-status`);if(e!==void 0&&e!==H.current)return;Te.current=n,P(n)}catch{if(e!==void 0&&e!==H.current)return;Te.current={},P({})}},[t]),W=(0,w.useCallback)(async()=>{C(!0),se(null);try{let e=await t.get(`/api/memory-files`),n={cli:e.cli||``,model:e.model||``};ee(n),v(n)}catch(e){se(e instanceof Error?e.message:String(e))}finally{C(!1)}},[t]),G=(0,w.useCallback)(async()=>{he(!0),A(null);try{let e=ge(await t.get(`/api/employees`));le(e),O(e)}catch(e){A(e instanceof Error?e.message:String(e))}finally{he(!1)}},[t]);(0,w.useEffect)(()=>{V(),U(),W(),G()},[V,U,G,W]),(0,w.useEffect)(()=>{if(!f.cli)return;let e=H.current+1;H.current=e,De(!1);let t=Date.now()+ce,n=0,r,i=()=>{if(e!==H.current)return;let a=ue({snapshot:Te.current,cli:f.cli,attempts:n,now:Date.now(),deadline:t});if(a.kind!==`stop`){if(a.kind===`exhausted`){De(!0);return}r=setTimeout(()=>{e===H.current&&(n+=1,U(e).then(()=>{e===H.current&&i()}))},a.delayMs)}};return i(),()=>{H.current=e+1,r!==void 0&&clearTimeout(r)}},[f.cli,U]),(0,w.useEffect)(()=>{if(i.kind!==`ready`)return;let e=Object.keys(i.data.perCli||{}),t=i.data.cli||e[0]||``,n=h(i.data.permissions),r=_(t,M);p({cli:t,provider:i.data.perCli?.[t]?.provider||r.defaultProvider||``,model:S(t,i.data.perCli,i.data.activeOverrides),effort:b(t,i.data.perCli,i.data.activeOverrides),workingDir:i.data.workingDir||``,permissions:n.mode===`custom`?n.tokens:n.mode===`safe`?`safe`:`auto`})},[M,i]),(0,w.useEffect)(()=>()=>{for(let e of Array.from(n.pending.keys()))(e===`cli`||e===`workingDir`||e===`permissions`||e===`runtimeEmployees`||e===`flushCli`||e===`flushModel`||e.startsWith(`activeOverrides.`))&&n.remove(e)},[n]);let K=(0,w.useCallback)((e,t)=>n.set(e,t),[n]),Oe=(0,w.useCallback)(async()=>{let e=n.saveBundle();if(Object.keys(e).length===0)return;let r=await be({client:t,bundle:e,employeeDraft:D,employeeOriginal:T});n.clear(),r&&c(r),await a(),await V(),await W(),await G()},[t,n,D,T,V,G,W,a,c]);(0,w.useEffect)(()=>{if(r)return r(Oe),()=>r(null)},[r,Oe]);let q=i.kind===`ready`?i.data:{},J=q.perCli||{},Y=q.activeOverrides||{},ke=(0,w.useMemo)(()=>{let e=y(Object.keys(J));return e.length?e:y(Object.keys(M||ae))},[J,M]),X=_(f.cli,M),Z=f.provider||X.defaultProvider||X.providers?.[0]||``,Ae=f.cli===`pi`,Q=!Ae&&(X.providers?.length??0)>0,je=ie(Q&&X.modelsByProvider?.[Z]||X.models,f.model),Me=Q?te(X,f.model,X.effortsByProvider?.[Z]||X.efforts,Z):te(X,f.model),Ne=f.workingDir.trim()?null:`Required`,Pe=(0,w.useCallback)(async e=>{I(!0),R(null);try{let n=await t.post(`/api/settings/runtime-default-migration`,{action:e}),r;r=`settings`in n&&n.settings?n.settings:`data`in n&&n.data?n.data:n,c(r)}catch(e){let t=B(e);if(t){c(t);return}R(o(e))}finally{I(!1)}},[t,c]),Fe=(0,w.useCallback)(async e=>{Se(!0),we(null);try{let n=await t.post(`/api/settings/multi-session-default-migration`,{action:e}),r;r=`settings`in n&&n.settings?n.settings:`data`in n&&n.data?n.data:n,c(r)}catch(e){let t=B(e);if(t){c(t);return}we(o(e))}finally{Se(!1)}},[t,c]);if(i.kind===`loading`)return(0,E.jsx)(l,{});if(i.kind===`offline`)return(0,E.jsx)(u,{port:e});if(i.kind===`error`)return(0,E.jsx)(d,{message:i.message});function Ie(){for(let e of Array.from(n.pending.keys()))e.startsWith(`activeOverrides.`)&&n.remove(e)}function $(e){p(e)}return(0,E.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),Oe()},children:[q.runtimeDefaultMigration?.state===`pending`?(0,E.jsxs)(`div`,{className:`settings-inline-notice`,role:`status`,children:[(0,E.jsx)(`strong`,{children:`기본 런타임 변경 안내`}),(0,E.jsx)(`p`,{children:`기존 선택은 유지됩니다. Codex App으로 전환하거나 현재 런타임을 계속 사용할 수 있습니다.`}),(0,E.jsxs)(`div`,{className:`settings-inline-actions`,children:[(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:F,onClick:()=>void Pe(`accept`),children:`Codex App 사용`}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-secondary`,disabled:F,onClick:()=>void Pe(`keep`),children:`현재 런타임 유지`})]}),L?(0,E.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:L}):null]}):null,q.multiSessionDefaultMigration?.state===`pending`?(0,E.jsxs)(`div`,{className:`settings-inline-notice`,role:`status`,children:[(0,E.jsx)(`strong`,{children:`다중 세션 안내`}),(0,E.jsx)(`p`,{children:`대화 세션을 여러 개 열 수 있습니다. 켜면 동시 실행도 2로 올라가서, 두 번째 세션이 첫 번째가 끝나기를 기다리지 않습니다. 지금 설정은 그대로 유지됩니다.`}),(0,E.jsxs)(`div`,{className:`settings-inline-actions`,children:[(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:z,onClick:()=>void Fe(`accept`),children:`다중 세션 켜기`}),(0,E.jsx)(`button`,{type:`button`,className:`settings-action settings-action-secondary`,disabled:z,onClick:()=>void Fe(`keep`),children:`지금 설정 유지`})]}),Ce?(0,E.jsx)(`span`,{className:`settings-field-error`,role:`alert`,children:Ce}):null]}):null,(0,E.jsxs)(`label`,{className:`settings-field settings-field-select`,htmlFor:`midrun-policy-select`,children:[(0,E.jsx)(`span`,{className:`settings-field-label`,children:`실행 중 메시지 처리 (mid-run policy)`}),(0,E.jsxs)(`select`,{id:`midrun-policy-select`,value:String(q.multiSession?.midRunPolicy||`steer`),onChange:e=>{let t=e.target.value;K(`multiSession.midRunPolicy`,{value:t,original:String(q.multiSession?.midRunPolicy||`steer`),valid:!0})},children:[(0,E.jsx)(`option`,{value:`steer`,children:`steer (기본) — 실행 중 지시 변경`}),(0,E.jsx)(`option`,{value:`followup`,children:`followup — 끝나면 순서대로 실행`}),(0,E.jsx)(`option`,{value:`collect`,children:`collect — 모아서 한 번에 실행`}),(0,E.jsx)(`option`,{value:`interrupt`,children:`interrupt — 현재 실행을 중단하고 즉시 실행`})]}),(0,E.jsx)(`span`,{className:`settings-field-hint`,children:`다중 세션이 켜져 있을 때 적용됩니다. codex-app은 같은 턴에 입력을 전달합니다. Cursor·Grok의 native 모드는 현재 요청의 취소와 정리가 끝난 뒤 같은 세션에 다시 요청합니다(cancel-reprompt). 그 외 런타임은 중단 후 새 실행으로 이어갑니다(kill-steer). 보존되는 맥락은 런타임에 따라 다릅니다. 끝난 뒤 실행하려면 followup을 선택하세요.`})]}),(0,E.jsx)(xe,{status:ve[f.cli],exhausted:Ee}),(0,E.jsx)(de,{cli:f.cli,cliOptions:ke,provider:Z,providerOptions:Ae?[]:X.providers||[],model:f.model,modelOptions:je,effort:f.effort,effortOptions:Me,workingDir:f.workingDir,workingDirError:Ne,cliMeta:M,onCliChange:e=>{let t=_(e,M),n={...f,cli:e,provider:J[e]?.provider||t.defaultProvider||``,model:S(e,J,Y),effort:b(e,J,Y)};Ie(),$(n),K(`cli`,{value:e,original:q.cli||``,valid:!0})},onProviderChange:e=>{let t=X.modelsByProvider?.[e]||[],n=X.effortsByProvider?.[e]||[],r=t.includes(f.model)?f.model:t[0]||``,i=re(X,r,f.effort,n,e);$({...f,provider:e,model:r,effort:i}),K(`perCli.${f.cli}.provider`,{value:e,original:J[f.cli]?.provider||X.defaultProvider||``,valid:!0}),K(`activeOverrides.${f.cli}.model`,{value:r,original:S(f.cli,J,Y),valid:r.trim().length>0}),K(`activeOverrides.${f.cli}.effort`,{value:i,original:b(f.cli,J,Y),valid:!0})},onModelChange:e=>{let t=re(X,e,f.effort,Q?X.effortsByProvider?.[Z]||X.efforts:void 0,Q?Z:void 0);$({...f,model:e,effort:t}),K(`activeOverrides.${f.cli}.model`,{value:e,original:S(f.cli,J,Y),valid:e.trim().length>0}),t!==f.effort&&K(`activeOverrides.${f.cli}.effort`,{value:t,original:b(f.cli,J,Y),valid:!0})},onEffortChange:e=>{$({...f,effort:e}),K(`activeOverrides.${f.cli}.effort`,{value:e,original:b(f.cli,J,Y),valid:!0})},onWorkingDirChange:e=>{$({...f,workingDir:e}),K(`workingDir`,{value:e,original:q.workingDir||``,valid:e.trim().length>0})}}),(0,E.jsx)(fe,{value:f.permissions,configuredValue:q.permissions,onChange:e=>{$({...f,permissions:e}),K(`permissions`,{value:e,original:q.permissions??`auto`,valid:e===`auto`||e.length>0})}}),(0,E.jsx)(pe,{activeCli:f.cli,flushCli:g.cli||``,flushModel:g.model||``,cliOptions:ke,cliMeta:M,modelOptions:ie(_(g.cli||f.cli,M).models,g.model||``),loading:ne,error:oe,onFlushCliChange:e=>{let t=e&&_(e,M).models[0]||``;v({cli:e,model:t}),K(`flushCli`,{value:e,original:m.cli||``,valid:!0}),K(`flushModel`,{value:t,original:m.model||``,valid:!0})},onFlushModelChange:e=>{v({...g,model:e}),K(`flushModel`,{value:e,original:m.model||``,valid:!0})}}),(0,E.jsx)(ye,{roster:D,original:T,cliOptions:ke,cliMeta:M,loading:me,error:k,onRosterChange:e=>{if(O(e),_e(e,T)){n.remove(`runtimeEmployees`);return}n.set(`runtimeEmployees`,{value:e,original:T,valid:!j(e)})}})]})}export{xe as CliProbeNotice,B as conflictSettingsFromError,Se as default,z as splitAgentSaveBundle};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./react-C_pPTFsM.js";import{t as n}from"./jsx-runtime-NZYk81nU.js";import{i as r}from"./page-shell-BeGD0rRQ.js";var i=e(t(),1),a=n(),o=[`employees`],s=[`ai-e`,`claude`,`claude-e`,`codex`,`codex-app`,`copilot`,`cursor`,`kiro-code`,`gemini`,`grok`,`opencode`],c=0;function l(){return c+=1,`emp_${Date.now().toString(36)}_${c}`}function u(){let e=globalThis.crypto;if(e&&typeof e.randomUUID==`function`)try{return e.randomUUID()}catch{}return l()}function d(e=u()){return{id:e,name:``,cli:`claude`,role:``,prompt:``,active:!0}}function f(e){if(!Array.isArray(e))return[];let t=[],n=0;for(let r of e){if(typeof r==`string`){n+=1,t.push({...d(`emp_legacy_${n}`),name:r});continue}if(!r||typeof r!=`object`)continue;let e=r,i=typeof e.name==`string`?e.name:``;if(!i&&!e.id)continue;n+=1;let a=typeof e.id==`string`&&e.id.trim()?e.id.trim():`emp_unknown_${n}`,o=typeof e.cli==`string`&&e.cli.trim()?e.cli.trim():`claude`,s=typeof e.role==`string`?e.role:``,c=typeof e.prompt==`string`?e.prompt:``,l=e.active!==!1;t.push({id:a,name:i,cli:o,role:s,prompt:c,active:l})}return t}function p(e){return e.name.trim()?e.cli.trim()?null:`CLI is required`:`Name is required`}function m(e){return e.some(e=>p(e)!==null)}function h(e){let t=new Map;for(let n of e){let e=n.name.trim().toLowerCase();e&&t.set(e,(t.get(e)??0)+1)}let n=new Set;for(let[e,r]of t)r>1&&n.add(e);return n}function g(e){return e.map(e=>{let t={id:e.id,name:e.name.trim(),cli:e.cli.trim()||`claude`,role:e.role.trim(),active:e.active};return e.prompt.trim()&&(t.prompt=e.prompt),t})}function _({registerSave:e}){return(0,i.useEffect)(()=>{if(e)return e(null),()=>e(null)},[e]),(0,a.jsx)(`form`,{className:`settings-page-form`,onSubmit:e=>e.preventDefault(),children:(0,a.jsx)(r,{title:`Employees`,hint:`Runtime employees are now managed from the Agent page.`,children:(0,a.jsx)(`p`,{className:`settings-section-hint`,children:`Open Runtime / Agent to edit dispatchable employees, static employee model overrides, and database-backed employees in one place.`})})})}export{s as DEFAULT_CLI_OPTIONS,o as EMPLOYEE_KEYS,_ as default,h as duplicateNameSet,p as employeeRowError,m as employeesHaveErrors,d as makeDefaultEmployee,u as newEmployeeId,f as normalizeEmployees,g as toPersistShape};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./cli-engine-Bw0QTAVX.js";import{t as n}from"./react-C_pPTFsM.js";import{t as r}from"./jsx-runtime-NZYk81nU.js";import{a as i,i as a,n as o,r as s,t as c}from"./page-shell-BeGD0rRQ.js";import{a as l,i as u,s as d}from"./fields-mlGpofqQ.js";import{a as f,d as p}from"./agent-meta-BWHASq1a.js";import{t as m}from"./path-utils-B6vBr0DD.js";var h=e(n(),1),g=r(),_=[{value:`every`,label:`every (interval)`},{value:`cron`,label:`cron expression`}];function v({job:e,index:t,bodyError:n,timeZoneError:r,onChange:i,onRemove:a}){let o=(0,h.useId)(),s=e.schedule.kind,c=e.schedule.timeZone??``;return(0,g.jsxs)(`fieldset`,{className:`settings-heartbeat-job`,"aria-label":`Heartbeat job ${t+1}${e.name?` (${e.name})`:``}`,children:[(0,g.jsx)(`legend`,{className:`settings-heartbeat-job-legend`,children:e.name||`Job ${t+1}`}),(0,g.jsx)(l,{id:`${o}-enabled`,label:`Enabled`,value:e.enabled,onChange:e=>i({enabled:e})}),(0,g.jsx)(d,{id:`${o}-name`,label:`Name`,value:e.name,placeholder:`Morning summary`,onChange:e=>i({name:e})}),(0,g.jsx)(u,{id:`${o}-kind`,label:`Schedule kind`,value:s,options:_,onChange:e=>{e===`every`&&s!==`every`?i({schedule:{kind:`every`,minutes:30,...c?{timeZone:c}:{}}}):e===`cron`&&s!==`cron`&&i({schedule:{kind:`cron`,cron:`0 9 * * *`,...c?{timeZone:c}:{}}})}}),s===`every`?(0,g.jsx)(d,{id:`${o}-minutes`,label:`Every (minutes)`,value:String(e.schedule.minutes??``),placeholder:`30`,error:n??null,onChange:e=>{let t=e.trim(),n=Number(t);i({schedule:{kind:`every`,minutes:Number.isFinite(n)?n:NaN,...c?{timeZone:c}:{}}})}}):(0,g.jsx)(d,{id:`${o}-cron`,label:`Cron expression`,value:e.schedule.cron??``,placeholder:`0 9 * * *`,error:n??null,onChange:e=>i({schedule:{kind:`cron`,cron:e,...c?{timeZone:c}:{}}})}),(0,g.jsx)(d,{id:`${o}-tz`,label:`Time zone (optional)`,value:c,placeholder:`Asia/Seoul`,error:r??null,onChange:t=>{let n=t.trim();i(s===`every`?{schedule:{kind:`every`,minutes:e.schedule.minutes,...n?{timeZone:n}:{}}}:{schedule:{kind:`cron`,cron:e.schedule.cron,...n?{timeZone:n}:{}}})}}),(0,g.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`${o}-prompt`,children:[(0,g.jsx)(`span`,{className:`settings-field-label`,children:`Prompt`}),(0,g.jsx)(`textarea`,{id:`${o}-prompt`,rows:3,value:e.prompt,placeholder:`What should this heartbeat do?`,onChange:e=>i({prompt:e.target.value})})]}),(0,g.jsx)(`div`,{className:`settings-heartbeat-job-footer`,children:(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:a,children:`Remove job`})})]})}var y=/^\d+[smh]$/,b=/^([01]\d|2[0-3]):[0-5]\d$/,x=[`ai-e`,`claude`,`claude-e`,`codex`,`codex-app`,`copilot`,`cursor`,`kiro-code`,`gemini`,`grok`,`opencode`],S=[`heartbeat.enabled`,`heartbeat.every`,`heartbeat.activeHours.start`,`heartbeat.activeHours.end`,`heartbeat.target`],C=[`heartbeat.jobs`,`heartbeat.md`];function w(e){return y.test(e.trim())}function T(e){return b.test(e.trim())}var E=0;function D(e=Date.now()){return{id:`hb_${e}_${E++}`,name:``,enabled:!0,schedule:{kind:`every`,minutes:30},prompt:``}}function O(e){return e.startsWith(`heartbeat.`)&&e!==`heartbeat.jobs`&&e!==`heartbeat.md`}function k(e,t){if(!e||typeof e!=`object`)return null;let n=e,r=typeof n.id==`string`&&n.id.trim()?n.id.trim():`hb_unknown_${t}`,i=typeof n.name==`string`?n.name:``,a=n.enabled!==!1,o=typeof n.prompt==`string`?n.prompt:``,s=n.schedule,c;if(s&&typeof s==`object`){let e=s;c=e.kind===`cron`&&typeof e.cron==`string`?{kind:`cron`,cron:e.cron,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}:{kind:`every`,minutes:typeof e.minutes==`number`?e.minutes:30,...typeof e.timeZone==`string`&&e.timeZone?{timeZone:e.timeZone}:{}}}else c={kind:`every`,minutes:30};return{id:r,name:i,enabled:a,schedule:c,prompt:o}}function A(e){if(!e||typeof e!=`object`)return[];let t=e.jobs;return Array.isArray(t)?t.map((e,t)=>k(e,t)).filter(e=>e!==null):[]}function j(e){if(e.kind===`every`){let t=e.minutes;return!Number.isFinite(t)||t<=0||!Number.isInteger(t)?`Minutes must be a positive integer`:null}let t=e.cron?.trim()??``;return t?t.split(/\s+/).length<5?`Cron must have at least 5 fields`:null:`Cron expression required`}function M(e){return e.some(e=>j(e.schedule)!==null)}function N({port:e,client:t,dirty:n,snapshot:r}){let[i,a]=(0,h.useState)([]),[o,l]=(0,h.useState)([]),[u,d]=(0,h.useState)(!1),[f,p]=(0,h.useState)(null);(0,h.useEffect)(()=>{if(r.kind!==`ready`)return;let e=A(r.data);a(e),l(e)},[r]),(0,h.useEffect)(()=>{n.set(`heartbeat.jobs`,{value:i,original:o,valid:!M(i)})},[i,o,n]),(0,h.useEffect)(()=>()=>{n.remove(`heartbeat.jobs`)},[n]);let m=(0,h.useCallback)(async()=>{if(M(i)){p(`Fix invalid schedules before saving.`);return}d(!0),p(null);try{let e=A(await t.put(`/api/heartbeat`,{jobs:i}));a(e),l(e),n.remove(`heartbeat.jobs`)}catch(e){p(e instanceof Error?e.message:String(e))}finally{d(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,g.jsx)(`p`,{className:`settings-section-hint`,children:`Loading jobs…`});if(r.kind===`offline`)return(0,g.jsx)(s,{port:e});if(r.kind===`error`)return(0,g.jsx)(c,{message:r.message});let _=n.pending.has(`heartbeat.jobs`),y=M(i);function b(e,t){a(n=>n.map((n,r)=>r===e?{...n,...t}:n))}function x(){a(e=>[...e,D()])}function S(e){a(t=>t.filter((t,n)=>n!==e))}return(0,g.jsxs)(g.Fragment,{children:[i.length===0?(0,g.jsx)(`p`,{className:`settings-section-hint`,children:`No jobs configured. Add one below.`}):(0,g.jsx)(`div`,{className:`settings-heartbeat-jobs-list`,children:i.map((e,t)=>(0,g.jsx)(v,{job:e,index:t,bodyError:j(e.schedule),onChange:e=>b(t,e),onRemove:()=>S(t)},e.id))}),(0,g.jsxs)(`div`,{className:`settings-heartbeat-jobs-footer`,children:[(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:x,children:`+ Add job`}),(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void m(),disabled:u||!_||y,children:u?`Saving…`:`Apply jobs`})]}),f?(0,g.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:f}):null]})}function P({port:e,client:t,dirty:n,snapshot:r}){let[i,a]=(0,h.useState)(``),[o,l]=(0,h.useState)(``),[u,d]=(0,h.useState)(!1),[f,p]=(0,h.useState)(null);(0,h.useEffect)(()=>{if(r.kind!==`ready`)return;let e=r.data.content??``;a(e),l(e)},[r]),(0,h.useEffect)(()=>{n.set(`heartbeat.md`,{value:i,original:o,valid:!0})},[i,o,n]),(0,h.useEffect)(()=>()=>{n.remove(`heartbeat.md`)},[n]);let m=(0,h.useCallback)(async()=>{d(!0),p(null);try{await t.put(`/api/heartbeat-md`,{content:i}),l(i),n.remove(`heartbeat.md`)}catch(e){p(e instanceof Error?e.message:String(e))}finally{d(!1)}},[t,n,i]);if(r.kind===`loading`)return(0,g.jsx)(`p`,{className:`settings-section-hint`,children:`Loading template…`});if(r.kind===`offline`)return(0,g.jsx)(s,{port:e});if(r.kind===`error`)return(0,g.jsx)(c,{message:r.message});let _=n.pending.has(`heartbeat.md`);return(0,g.jsxs)(g.Fragment,{children:[(0,g.jsxs)(`label`,{className:`settings-field settings-field-textarea`,htmlFor:`hb-md`,children:[(0,g.jsx)(`span`,{className:`settings-field-label`,children:`Template`}),(0,g.jsx)(`textarea`,{id:`hb-md`,rows:10,spellCheck:!1,value:i,onChange:e=>a(e.target.value),style:{fontFamily:`ui-monospace, monospace`}})]}),(0,g.jsx)(`div`,{className:`settings-heartbeat-md-footer`,children:(0,g.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,onClick:()=>void m(),disabled:u||!_,children:u?`Saving…`:`Save template`})}),f?(0,g.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:f}):null]})}function F({port:e,client:n,dirty:r,registerSave:_}){let v=i(n,`/api/settings`),y=i(n,`/api/heartbeat`),b=i(n,`/api/heartbeat-md`),[C,E]=(0,h.useState)(!1),[D,k]=(0,h.useState)(`30m`),[A,j]=(0,h.useState)(`08:00`),[M,F]=(0,h.useState)(`22:00`),[I,L]=(0,h.useState)(`all`);(0,h.useEffect)(()=>{if(v.state.kind!==`ready`)return;let e=v.state.data.heartbeat||{};E(!!e.enabled),k(typeof e.every==`string`?e.every:`30m`),j(e.activeHours?.start??`08:00`),F(e.activeHours?.end??`22:00`),L(typeof e.target==`string`?e.target:`all`)},[v.state]),(0,h.useEffect)(()=>()=>{for(let e of S)r.remove(e)},[r]);let R=(0,h.useMemo)(()=>v.state.kind===`ready`&&v.state.data.heartbeat||{},[v.state]),z=(0,h.useCallback)((e,t)=>r.set(e,t),[r]),B=(0,h.useRef)(0),V=(0,h.useCallback)(async()=>{let e=r.saveBundle(),t={};for(let[n,r]of Object.entries(e))O(n)&&(t[n]=r);if(Object.keys(t).length===0)return;let i=++B.current,a=m(t),o=await n.put(`/api/settings`,a);if(i!==B.current)return;let s=o&&typeof o==`object`&&`data`in o?o.data:o;for(let e of S)r.remove(e);v.setData(s);let c=s.heartbeat||{};E(!!c.enabled),k(typeof c.every==`string`?c.every:`30m`),j(c.activeHours?.start??`08:00`),F(c.activeHours?.end??`22:00`),L(typeof c.target==`string`?c.target:`all`),await v.refresh()},[n,r,v]);if((0,h.useEffect)(()=>{if(_)return _(V),()=>_(null)},[_,V]),v.state.kind===`loading`)return(0,g.jsx)(o,{});if(v.state.kind===`offline`)return(0,g.jsx)(s,{port:e});if(v.state.kind===`error`)return(0,g.jsx)(c,{message:v.state.message});let H=w(D)?null:"Use the form `<n>s|m|h`, e.g. `30m`",U=T(A)?null:`Use HH:MM (24h)`,W=T(M)?null:`Use HH:MM (24h)`,G=v.state.data.perCli||{},K=p(Object.keys(G)),q=[{value:`all`,label:`all (broadcast)`},...(K.length>0?K:[...x]).map(e=>({value:e,label:f(e).label||e}))];return!t(I)&&!q.some(e=>e.value===I)&&q.push({value:I,label:`${f(I).label||I} (legacy)`}),(0,g.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),V()},children:[(0,g.jsxs)(a,{title:`Heartbeat`,hint:`Background prompts the agent runs on a schedule.`,children:[(0,g.jsx)(l,{id:`hb-enabled`,label:`Heartbeat enabled`,value:C,onChange:e=>{E(e),z(`heartbeat.enabled`,{value:e,original:!!R.enabled,valid:!0})}}),(0,g.jsx)(d,{id:`hb-every`,label:`Default interval`,value:D,placeholder:`30m`,error:H,onChange:e=>{k(e),z(`heartbeat.every`,{value:e,original:R.every??`30m`,valid:w(e)})}}),(0,g.jsx)(d,{id:`hb-start`,label:`Active hours start`,value:A,placeholder:`08:00`,error:U,onChange:e=>{j(e),z(`heartbeat.activeHours.start`,{value:e,original:R.activeHours?.start??`08:00`,valid:T(e)})}}),(0,g.jsx)(d,{id:`hb-end`,label:`Active hours end`,value:M,placeholder:`22:00`,error:W,onChange:e=>{F(e),z(`heartbeat.activeHours.end`,{value:e,original:R.activeHours?.end??`22:00`,valid:T(e)})}}),(0,g.jsx)(u,{id:`hb-target`,label:`Target`,value:I,missingValueLabel:t(I)?`JWC (retired)`:void 0,error:t(I)?`The saved target runtime is retired. Choose an available target.`:null,options:q,onChange:e=>{L(e),z(`heartbeat.target`,{value:e,original:R.target??`all`,valid:!0})}})]}),(0,g.jsx)(a,{title:`Jobs`,hint:`Each job replaces the entire heartbeat.json on save. Concurrent edits from multiple browsers will overwrite — last write wins.`,children:(0,g.jsx)(N,{port:e,client:n,dirty:r,snapshot:y.state})}),(0,g.jsx)(a,{title:`Default heartbeat prompt template`,hint:`Markdown shown to the agent when a heartbeat fires without a job-specific prompt.`,children:(0,g.jsx)(P,{port:e,client:n,dirty:r,snapshot:b.state})})]})}export{C as PAGE_LOCAL_KEYS,S as SECTION_A_KEYS,x as TARGET_FALLBACK,F as default,O as isHeartbeatSettingsKey,j as jobScheduleBodyError,M as jobsHaveErrors,D as makeDefaultJob,A as normalizeJobsResponse,T as validateHHMM,w as validateInterval};
@@ -1 +0,0 @@
1
- import{r as e}from"./rolldown-runtime-hePW80VL.js";import{t}from"./cli-engine-Bw0QTAVX.js";import{t as n}from"./react-C_pPTFsM.js";import{t as r}from"./jsx-runtime-NZYk81nU.js";import{a as i,i as a,n as o,r as s,t as c}from"./page-shell-BeGD0rRQ.js";import{a as l,i as u,r as d}from"./fields-mlGpofqQ.js";import{a as f,d as ee}from"./agent-meta-BWHASq1a.js";import{t as p}from"./path-utils-B6vBr0DD.js";var m=e(n(),1),h=[`memory.enabled`,`memory.flushEvery`,`memory.cli`,`memory.retentionDays`,`memory.autoReflectAfterFlush`,`memory.flushLanguage`],g=[{value:`en`,label:`English (en)`},{value:`ko`,label:`한국어 (ko)`},{value:`ja`,label:`日本語 (ja)`},{value:`zh`,label:`中文 (zh)`}],_=50;function v(e){return h.includes(e)}function y(e){let t=b(e);if(!Array.isArray(t))return[];let n=[];for(let e of t){let t=x(e);t&&n.push(t)}return n}function b(e){if(!e||typeof e!=`object`)return e;let t=e;return Array.isArray(t)?t:`data`in t?t.data:e}function x(e){if(!e||typeof e!=`object`)return null;let t=e,n=typeof t.key==`string`?t.key:null;return n?{key:n,value:typeof t.value==`string`?t.value:``,source:typeof t.source==`string`?t.source:`manual`}:null}function S(e,t){return!Number.isFinite(e)||!Number.isInteger(e)||e<=0?`${t} must be a positive integer`:null}function C(e,t,n=50){let r=Math.max(0,Math.floor(t))*n,i=e.slice(r,r+n),a=Math.max(1,Math.ceil(e.length/n));return{slice:i,hasMore:r+n<e.length,pageCount:a}}function w(e,t=80){return e.length<=t?e:`${e.slice(0,t)}…`}var T=r();function E({row:e,onOpen:t}){return(0,T.jsxs)(`tr`,{className:`settings-memory-row`,children:[(0,T.jsx)(`td`,{className:`settings-memory-key`,children:(0,T.jsx)(`button`,{type:`button`,className:`settings-memory-link`,onClick:()=>t(e),"aria-label":`Open memory entry ${e.key}`,children:e.key})}),(0,T.jsx)(`td`,{className:`settings-memory-source`,children:e.source}),(0,T.jsx)(`td`,{className:`settings-memory-length`,children:e.value.length}),(0,T.jsx)(`td`,{className:`settings-memory-preview`,title:e.value,children:w(e.value)})]})}var D={busy:null,notice:null,error:null};function O({port:e,client:n,dirty:r,registerSave:_}){let b=i(n,`/api/settings`),x=i(n,`/api/memory`),[w,O]=(0,m.useState)(!0),[k,A]=(0,m.useState)(10),[j,M]=(0,m.useState)(``),[N,P]=(0,m.useState)(30),[F,I]=(0,m.useState)(!1),[te,L]=(0,m.useState)(`en`),[R,z]=(0,m.useState)(0),[B,V]=(0,m.useState)(null),[H,U]=(0,m.useState)(D);(0,m.useEffect)(()=>{if(b.state.kind!==`ready`)return;let e=b.state.data.memory||{};O(e.enabled!==!1),A(typeof e.flushEvery==`number`?e.flushEvery:10),M(typeof e.cli==`string`?e.cli:``),P(typeof e.retentionDays==`number`?e.retentionDays:30),I(!!e.autoReflectAfterFlush),L(typeof e.flushLanguage==`string`&&e.flushLanguage?e.flushLanguage:`en`)},[b.state]),(0,m.useEffect)(()=>()=>{for(let e of h)r.remove(e)},[r]),(0,m.useEffect)(()=>{if(!B)return;let e=e=>{e.key===`Escape`&&V(null)};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[B]);let W=(0,m.useCallback)((e,t)=>r.set(e,t),[r]),G=(0,m.useMemo)(()=>b.state.kind===`ready`&&b.state.data.memory||{},[b.state]),K=(0,m.useCallback)(async()=>{let e=r.saveBundle(),t={};for(let[n,r]of Object.entries(e))v(n)&&(t[n]=r);if(Object.keys(t).length===0)return;let i=p(t),a=await n.put(`/api/settings`,i),o=a&&typeof a==`object`&&`data`in a?a.data:a;for(let e of h)r.remove(e);b.setData(o);let s=o.memory||{};O(s.enabled!==!1),A(typeof s.flushEvery==`number`?s.flushEvery:10),M(typeof s.cli==`string`?s.cli:``),P(typeof s.retentionDays==`number`?s.retentionDays:30),I(!!s.autoReflectAfterFlush),L(typeof s.flushLanguage==`string`&&s.flushLanguage?s.flushLanguage:`en`),await b.refresh()},[n,r,b]);(0,m.useEffect)(()=>{if(_)return _(K),()=>_(null)},[_,K]);let q=(0,m.useCallback)(async()=>{U({busy:`flush`,notice:null,error:null});try{await n.post(`/api/jaw-memory/flush`,{}),U({busy:null,notice:`Memory flush queued. Browse refreshes when it completes.`,error:null}),await x.refresh()}catch(e){U({busy:null,notice:null,error:e instanceof Error?e.message:String(e)})}},[n,x]),J=(0,m.useCallback)(async()=>{U({busy:`reflect`,notice:null,error:null});try{await n.post(`/api/jaw-memory/reflect`,{}),U({busy:null,notice:`Reflect complete.`,error:null}),await x.refresh()}catch(e){U({busy:null,notice:null,error:e instanceof Error?e.message:String(e)})}},[n,x]),Y=(0,m.useCallback)(()=>{if(x.state.kind!==`ready`)return;let t=y(x.state.data),n=new Blob([JSON.stringify(t,null,2)],{type:`application/json`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`jaw-memory-${e}-${Date.now()}.json`,document.body.appendChild(i),i.click(),document.body.removeChild(i),URL.revokeObjectURL(r)},[x.state,e]);if(b.state.kind===`loading`)return(0,T.jsx)(o,{});if(b.state.kind===`offline`)return(0,T.jsx)(s,{port:e});if(b.state.kind===`error`)return(0,T.jsx)(c,{message:b.state.message});let X=S(k,`Flush every`),Z=S(N,`Retention days`),ne=b.state.data.perCli||{},Q=[{value:``,label:`(profile default)`},...ee(Object.keys(ne)).map(e=>({value:e,label:f(e).label||e}))];j&&!t(j)&&!Q.some(e=>e.value===j)&&Q.push({value:j,label:`${f(j).label||j} (legacy)`});let $=x.state.kind===`ready`?y(x.state.data):[],{slice:re,hasMore:ie,pageCount:ae}=C($,Math.min(R,Math.max(0,Math.ceil($.length/50)-1)));return(0,T.jsxs)(`form`,{className:`settings-page-form`,onSubmit:e=>{e.preventDefault(),K()},children:[(0,T.jsxs)(a,{title:`Memory engine`,hint:`Background memory flush and reflection cadence.`,children:[(0,T.jsx)(l,{id:`memory-enabled`,label:`Memory enabled`,value:w,onChange:e=>{O(e),W(`memory.enabled`,{value:e,original:G.enabled!==!1,valid:!0})}}),(0,T.jsx)(d,{id:`memory-flush-every`,label:`Flush every (sessions)`,value:k,min:1,error:X,onChange:e=>{A(e),W(`memory.flushEvery`,{value:e,original:typeof G.flushEvery==`number`?G.flushEvery:10,valid:S(e,`Flush every`)===null})}}),(0,T.jsx)(u,{id:`memory-cli`,label:`Flush CLI`,value:j,missingValueLabel:t(j)?`JWC (retired)`:void 0,error:t(j)?`The saved runtime is retired. Choose an available runtime.`:null,options:Q,onChange:e=>{M(e),W(`memory.cli`,{value:e,original:G.cli??``,valid:!0})}}),(0,T.jsx)(d,{id:`memory-retention`,label:`Retention days`,value:N,min:1,error:Z,onChange:e=>{P(e),W(`memory.retentionDays`,{value:e,original:typeof G.retentionDays==`number`?G.retentionDays:30,valid:S(e,`Retention days`)===null})}}),(0,T.jsx)(l,{id:`memory-auto-reflect`,label:`Auto-reflect after flush`,value:F,onChange:e=>{I(e),W(`memory.autoReflectAfterFlush`,{value:e,original:!!G.autoReflectAfterFlush,valid:!0})}}),(0,T.jsx)(u,{id:`memory-flush-language`,label:`Flush language`,value:te,options:[...g],onChange:e=>{L(e),W(`memory.flushLanguage`,{value:e,original:G.flushLanguage??`en`,valid:!0})}})]}),(0,T.jsx)(a,{title:`Stored entries`,hint:`Read-only browse of the key/value memory table (50/page).`,children:x.state.kind===`loading`?(0,T.jsx)(`p`,{className:`settings-section-hint`,children:`Loading entries…`}):x.state.kind===`offline`?(0,T.jsx)(s,{port:e}):x.state.kind===`error`?(0,T.jsx)(c,{message:x.state.message}):$.length===0?(0,T.jsx)(`p`,{className:`settings-section-hint`,children:`No memory entries yet.`}):(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(`table`,{className:`settings-memory-table`,children:[(0,T.jsx)(`thead`,{children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{scope:`col`,children:`Key`}),(0,T.jsx)(`th`,{scope:`col`,children:`Source`}),(0,T.jsx)(`th`,{scope:`col`,children:`Length`}),(0,T.jsx)(`th`,{scope:`col`,children:`Preview`})]})}),(0,T.jsx)(`tbody`,{children:re.map(e=>(0,T.jsx)(E,{row:e,onOpen:V},e.key))})]}),(0,T.jsxs)(`div`,{className:`settings-memory-pagination`,children:[(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,disabled:R===0,onClick:()=>z(e=>Math.max(0,e-1)),children:`Prev`}),(0,T.jsxs)(`span`,{className:`settings-memory-pageinfo`,children:[`Page `,R+1,` / `,ae]}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,disabled:!ie,onClick:()=>z(e=>e+1),children:`Next`})]})]})}),(0,T.jsxs)(a,{title:`Actions`,hint:`Flush runs async — the browse list refreshes when it finishes.`,children:[(0,T.jsxs)(`div`,{className:`settings-memory-actions`,children:[(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:H.busy!==null,onClick:()=>void q(),children:H.busy===`flush`?`Queuing…`:`Flush now`}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-save`,disabled:H.busy!==null,onClick:()=>void J(),children:H.busy===`reflect`?`Reflecting…`:`Reflect soul`}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,disabled:x.state.kind!==`ready`,onClick:Y,children:`Export memory`})]}),H.notice?(0,T.jsx)(`p`,{className:`settings-section-hint`,role:`status`,children:H.notice}):null,H.error?(0,T.jsx)(`p`,{className:`settings-field-error`,role:`alert`,children:H.error}):null]}),B?(0,T.jsx)(`div`,{className:`settings-memory-modal`,role:`dialog`,"aria-modal":`true`,"aria-label":`Memory entry ${B.key}`,onClick:e=>{e.target===e.currentTarget&&V(null)},children:(0,T.jsxs)(`div`,{className:`settings-memory-modal-card`,children:[(0,T.jsxs)(`header`,{className:`settings-memory-modal-header`,children:[(0,T.jsx)(`h3`,{children:B.key}),(0,T.jsx)(`button`,{type:`button`,className:`settings-action settings-action-discard`,onClick:()=>V(null),"aria-label":`Close memory entry`,children:`Close`})]}),(0,T.jsx)(`pre`,{className:`settings-memory-modal-body`,children:B.value})]})}):null]})}export{g as FLUSH_LANGUAGE_OPTIONS,_ as MEMORY_PAGE_SIZE,h as MEMORY_SECTION_A_KEYS,O as default,v as isMemorySettingsKey,y as normalizeMemoryRows,C as paginate,w as previewValue,S as validatePositiveInt};