glimmervoid 0.45.1-next.84 → 0.45.1-next.92

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 (65) hide show
  1. package/dist/bin/glimmervoid.js +3 -3
  2. package/dist/chunks/config-store-CaMEG7BR.js +1 -0
  3. package/dist/chunks/{config-store-B_YyKZoA.js → config-store-SeN0w6cD.js} +3 -2
  4. package/dist/chunks/{main-fsAN0sGp.js → main-BQubti_L.js} +9 -9
  5. package/dist/chunks/{pair-cli-BVJ0urnX.js → pair-cli-DojX0sOi.js} +2 -2
  6. package/dist/chunks/{remote-config-BV-hN-g0.js → remote-config-BQ0ggoxv.js} +1 -1
  7. package/dist/chunks/{settings-cli-RlxgyF0l.js → settings-cli-DP_NIdxV.js} +2 -2
  8. package/dist/chunks/{settings-readout-core-CdP-M1yc.js → settings-readout-core-C1uJhry6.js} +1 -1
  9. package/dist/client/assets/{benchmark-panel-C2oKUk5L.js → benchmark-panel-QHCgNiK0.js} +1 -1
  10. package/dist/client/assets/benchmark-panel-QHCgNiK0.js.br +0 -0
  11. package/dist/client/assets/dialogs-BAjecPOu.js +84 -0
  12. package/dist/client/assets/dialogs-BAjecPOu.js.br +0 -0
  13. package/dist/client/assets/{hooks-panel-B2NHVpb2.js → hooks-panel-Qos_hq6w.js} +1 -1
  14. package/dist/client/assets/hooks-panel-Qos_hq6w.js.br +0 -0
  15. package/dist/client/assets/index-CHUWzO2K.js +84 -0
  16. package/dist/client/assets/index-CHUWzO2K.js.br +0 -0
  17. package/dist/client/assets/index-aMk1lj4J.css +2 -0
  18. package/dist/client/assets/index-aMk1lj4J.css.br +0 -0
  19. package/dist/client/assets/{issues-panel-BlEKlbiI.js → issues-panel-DDBZNwE5.js} +1 -1
  20. package/dist/client/assets/issues-panel-DDBZNwE5.js.br +0 -0
  21. package/dist/client/assets/plan-face-DY-Ksq04.js +3 -0
  22. package/dist/client/assets/plan-face-DY-Ksq04.js.br +0 -0
  23. package/dist/client/assets/{pr-scope-tabs-DfkU4ceg.js → pr-scope-tabs-BAGYBTZu.js} +1 -1
  24. package/dist/client/assets/pr-scope-tabs-BAGYBTZu.js.br +0 -0
  25. package/dist/client/assets/radar-panel-BatuXdn3.js +1 -0
  26. package/dist/client/assets/radar-panel-BatuXdn3.js.br +0 -0
  27. package/dist/client/assets/review-queue-panel-DfGl9NlH.js +10 -0
  28. package/dist/client/assets/review-queue-panel-DfGl9NlH.js.br +0 -0
  29. package/dist/client/assets/settings-panel-BDqHINpW.js +4 -0
  30. package/dist/client/assets/settings-panel-BDqHINpW.js.br +0 -0
  31. package/dist/client/assets/trace-panel-DmkAgGHD.js +2 -0
  32. package/dist/client/assets/trace-panel-DmkAgGHD.js.br +0 -0
  33. package/dist/client/assets/usage-panel-cJRZ58CR.js +1 -0
  34. package/dist/client/assets/usage-panel-cJRZ58CR.js.br +0 -0
  35. package/dist/client/assets/visions-panel-H1kY_WQz.js +1 -0
  36. package/dist/client/assets/visions-panel-H1kY_WQz.js.br +0 -0
  37. package/dist/client/index.html +2 -2
  38. package/dist/client/index.html.br +0 -0
  39. package/dist/server/index.js +1 -1
  40. package/package.json +1 -1
  41. package/dist/chunks/config-store-ZjZY9CST.js +0 -1
  42. package/dist/client/assets/benchmark-panel-C2oKUk5L.js.br +0 -0
  43. package/dist/client/assets/dialogs-CqgEBcOx.js +0 -74
  44. package/dist/client/assets/dialogs-CqgEBcOx.js.br +0 -0
  45. package/dist/client/assets/hooks-panel-B2NHVpb2.js.br +0 -0
  46. package/dist/client/assets/index-C1GQzJGW.css +0 -2
  47. package/dist/client/assets/index-C1GQzJGW.css.br +0 -0
  48. package/dist/client/assets/index-cLVH9cFO.js +0 -84
  49. package/dist/client/assets/index-cLVH9cFO.js.br +0 -0
  50. package/dist/client/assets/issues-panel-BlEKlbiI.js.br +0 -0
  51. package/dist/client/assets/plan-face-CH3EXmuY.js +0 -3
  52. package/dist/client/assets/plan-face-CH3EXmuY.js.br +0 -0
  53. package/dist/client/assets/pr-scope-tabs-DfkU4ceg.js.br +0 -0
  54. package/dist/client/assets/radar-panel-BKrDgHtr.js +0 -1
  55. package/dist/client/assets/radar-panel-BKrDgHtr.js.br +0 -0
  56. package/dist/client/assets/review-queue-panel-B_hO04nL.js +0 -10
  57. package/dist/client/assets/review-queue-panel-B_hO04nL.js.br +0 -0
  58. package/dist/client/assets/settings-panel-C30TQ6rn.js +0 -4
  59. package/dist/client/assets/settings-panel-C30TQ6rn.js.br +0 -0
  60. package/dist/client/assets/trace-panel-DKSQRXZ5.js +0 -2
  61. package/dist/client/assets/trace-panel-DKSQRXZ5.js.br +0 -0
  62. package/dist/client/assets/usage-panel-D0e0A37f.js +0 -1
  63. package/dist/client/assets/usage-panel-D0e0A37f.js.br +0 -0
  64. package/dist/client/assets/visions-panel-BZ7Ye61H.js +0 -1
  65. package/dist/client/assets/visions-panel-BZ7Ye61H.js.br +0 -0
@@ -65,7 +65,7 @@ var OWN_SUBCOMMAND_RUNNERS = [
65
65
  return 0;
66
66
  }],
67
67
  ["pair", async (subcommandArgs) => {
68
- const { runPairCli } = await import("../chunks/pair-cli-BVJ0urnX.js");
68
+ const { runPairCli } = await import("../chunks/pair-cli-DojX0sOi.js");
69
69
  return runPairCli(subcommandArgs);
70
70
  }],
71
71
  ["agent", async (subcommandArgs) => {
@@ -73,7 +73,7 @@ var OWN_SUBCOMMAND_RUNNERS = [
73
73
  return runAgentSetupCli(subcommandArgs);
74
74
  }],
75
75
  ["settings", async (subcommandArgs) => {
76
- const { runSettingsCli } = await import("../chunks/settings-cli-RlxgyF0l.js");
76
+ const { runSettingsCli } = await import("../chunks/settings-cli-DP_NIdxV.js");
77
77
  return runSettingsCli(subcommandArgs);
78
78
  }],
79
79
  ["visions", async (subcommandArgs) => {
@@ -158,7 +158,7 @@ async function readDeclaredCustomAgents() {
158
158
  declared: [],
159
159
  error: null
160
160
  };
161
- const { loadConfigFile } = await import("../chunks/config-store-ZjZY9CST.js");
161
+ const { loadConfigFile } = await import("../chunks/config-store-CaMEG7BR.js");
162
162
  try {
163
163
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
164
164
  if (!loaded.config) return {
@@ -0,0 +1 @@
1
+ export { c as loadConfigFile } from "./config-store-SeN0w6cD.js";
@@ -3509,6 +3509,7 @@ var DEFAULT_CONFIG = {
3509
3509
  var DEFAULT_CONFIG_BY_KEY = DEFAULT_CONFIG;
3510
3510
  var ABORT_CONFIG_SAVE = "abort-config-save";
3511
3511
  var CONFIG_DIR_MODE = 448;
3512
+ var CONFIG_RELOAD_DEBOUNCE_MS = 500;
3512
3513
  function glimmervoidHomeDir() {
3513
3514
  return glimmervoidHomeDir$1(os.homedir(), process.env);
3514
3515
  }
@@ -3969,7 +3970,7 @@ function createConfigStore({ settingsDefaults, readTelemetryInstallId, isExperim
3969
3970
  config.hooks = Array.isArray(newConfig.hooks) ? newConfig.hooks : [];
3970
3971
  if (newConfig.port != null && newConfig.port !== config.port) console.log(`[settings] Port changed to ${newConfig.port} - restart required to take effect`);
3971
3972
  }
3972
- function watchForChanges(callback) {
3973
+ function watchForChanges(callback, { reloadDebounceMs = CONFIG_RELOAD_DEBOUNCE_MS } = {}) {
3973
3974
  let reloadTimer = null;
3974
3975
  let watcher = null;
3975
3976
  function handleConfigChange(err, data) {
@@ -4005,7 +4006,7 @@ function createConfigStore({ settingsDefaults, readTelemetryInstallId, isExperim
4005
4006
  if (reloadTimer) clearTimeoutFn(reloadTimer);
4006
4007
  reloadTimer = setTimeoutFn(() => {
4007
4008
  fs.readFile(configPath, "utf8", handleConfigChange);
4008
- }, 500);
4009
+ }, reloadDebounceMs);
4009
4010
  });
4010
4011
  console.log("[config] Watching config.json for changes");
4011
4012
  } catch (watchErr) {
@@ -22,13 +22,13 @@ import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.j
22
22
  import { a as readPageTitle, i as filesAfterRetention, n as decideShownKind, o as shownMimeForFilename, r as describeOverCap, t as SHOWN_SNIFF_BYTES } from "./shown-files-core-Bkuessu6.js";
23
23
  import { n as shellQuote } from "./hook-command-core-qTNK-xMF.js";
24
24
  import { C as parseCgroupBytes, S as memoryReserveBytes, T as parseMemAvailableBytes, _ as createSpawnGate, a as jsonStateLoadError, b as cgroupLimitBytes, c as loadedJsonValue, d as writeJsonAtomicSync, f as writeTextAtomic, g as createSerialQueue, h as createMemoryAdmission, i as createJsonStateWriter, m as createKeyedSerialQueue, n as appendJsonLines, o as loadJsonStateFile, p as writeTextAtomicSync, r as createJsonStateStore, s as loadJsonStateFileSync, t as appendJsonLine, u as writeJsonAtomic, v as isQueueAdmissionTimeout, w as parseCgroupV2Path, x as headroomFromReadings, y as cgroupAncestorPaths } from "./json-file-BjFK_eSH.js";
25
- import { $ as resolveProjectToken, B as buildAiGenerationEvents, G as claudeAccountUuidOf, H as buildExceptionProperties, I as FIRST_RUN_NOTICE, J as decideRemoteTelemetryState, K as codexUserIdOf, L as TELEMETRY_BATCH_URL, Q as parsePosthogReleaseId, R as TELEMETRY_FLAGS_URL, S as validateSettingsBlock, U as buildPersonProperties, V as buildBrowserExceptionProperties, W as classifySessionExit, X as exceptionFingerprint, Y as decideTelemetryConsent, Z as nodeMajorVersion, _ as isRtkBinaryName, a as ensureProjectIds, at as matchedPrefix, b as mergeSettingsBlock, ct as sessionIdFromBranch, dt as canonicalizePath, ft as comparableDirectoryPath, g as installTargetPath, h as findEscapingArchiveMember, i as createConfigStore, it as DEFAULT_BRANCH_GC_PREFIXES, lt as usablePrefixes, m as decideRtkInstall, n as DEFAULT_CONFIG, nt as stableConfigKey, o as generateProjectId, ot as planBranchGc, p as assetForPlatform, pt as isSameDirectoryPath, q as decideIsDevInstall, s as glimmervoidHomeDir$1, st as planWorktreeGc, t as ABORT_CONFIG_SAVE, ut as worktreeIntegrationTips, v as verifyDigest, x as settingsBlockSpecFor, z as adapterBucket } from "./config-store-B_YyKZoA.js";
25
+ import { $ as resolveProjectToken, B as buildAiGenerationEvents, G as claudeAccountUuidOf, H as buildExceptionProperties, I as FIRST_RUN_NOTICE, J as decideRemoteTelemetryState, K as codexUserIdOf, L as TELEMETRY_BATCH_URL, Q as parsePosthogReleaseId, R as TELEMETRY_FLAGS_URL, S as validateSettingsBlock, U as buildPersonProperties, V as buildBrowserExceptionProperties, W as classifySessionExit, X as exceptionFingerprint, Y as decideTelemetryConsent, Z as nodeMajorVersion, _ as isRtkBinaryName, a as ensureProjectIds, at as matchedPrefix, b as mergeSettingsBlock, ct as sessionIdFromBranch, dt as canonicalizePath, ft as comparableDirectoryPath, g as installTargetPath, h as findEscapingArchiveMember, i as createConfigStore, it as DEFAULT_BRANCH_GC_PREFIXES, lt as usablePrefixes, m as decideRtkInstall, n as DEFAULT_CONFIG, nt as stableConfigKey, o as generateProjectId, ot as planBranchGc, p as assetForPlatform, pt as isSameDirectoryPath, q as decideIsDevInstall, s as glimmervoidHomeDir$1, st as planWorktreeGc, t as ABORT_CONFIG_SAVE, ut as worktreeIntegrationTips, v as verifyDigest, x as settingsBlockSpecFor, z as adapterBucket } from "./config-store-SeN0w6cD.js";
26
26
  import { a as DEEP_HISTORY_SCROLLBACK_LINES, c as DashboardTelemetryReport, d as TELEMETRY_EVENT_SCHEMAS, i as HookEnvelope, o as parseDataAttach, p as TelemetryState, r as HTTP_URL_RE, s as parseDataClientMessage, u as PendingCrashReport } from "./build-channel-DNz_uA_k.js";
27
27
  import { A as decideFileRead, B as shouldEvaluateDespiteIoFailures, C as pickNewestPublished, D as codexRootCandidates, E as codexHomes, F as isUsageFile, H as splitLines$1, I as passOutcome, L as projectDirCandidates, M as expandTilde, N as grokHomes, O as codexSessionIdFromPath, P as grokRootCandidates, R as resolveProjectsDirs, S as parseResolvedSha, T as codexFallbackRoots, U as claudeCode, V as shouldPersistWarehouse, _ as isCheckFresh, a as describeAgentResolvability, b as parseRegistryDeprecation, c as isKnownAgentId, d as resolveAdapter, f as setCustomAgents, g as decideUpdateStatus, h as decideInstallFlavor, i as customAgentFingerprint, j as dedupeCodexFiles, k as continuationDelayMs, l as listAgentIds, m as readHostCodexVersion, n as cachedAgentResolvability, o as getAdapter, p as codex, r as commandFor, s as hookProfileOf, t as DEFAULT_AGENT_ID, u as resetCommandCache, v as normalizeSha, w as shortSha$1, x as parseRegistryLatest, y as normalizeUpdateChannel, z as scopedClaudeRoots } from "./adapters-D8q7K0IN.js";
28
28
  import { t as HOOK_TOOLS } from "./hook-tools-Dl7-r2Eb.js";
29
29
  import { a as formatSshPublicKey, c as orderAgentSockets, i as commitSigningShimText, l as parseSshPublicKey, n as NO_AGENT_HOLDS_KEY, o as isForwardedAgentDirName, r as agentListsKey, s as isSignableGitObject, t as COMMIT_SIGNING_SHIM_NAME } from "./ssh-signing-core-CRhVVWNW.js";
30
- import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-BV-hN-g0.js";
31
- import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-CdP-M1yc.js";
30
+ import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-BQ0ggoxv.js";
31
+ import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-C1uJhry6.js";
32
32
  import { _ as escapeMarkup, g as createLaneLog, n as createVisionsSetup } from "./visions-setup-VMMyqOpl.js";
33
33
  import { t as getRtkPath } from "./rtk-resolver-C_IReILP.js";
34
34
  import { createRequire } from "node:module";
@@ -39650,7 +39650,7 @@ async function forwardedSocketsIn(searchRoot, ownerUid) {
39650
39650
  const socketPaths = (await Promise.all(agentDirs.map(async (agentDir) => (await readEntryNames(agentDir)).map((entryName) => path.join(agentDir, entryName))))).flat();
39651
39651
  return (await Promise.all(socketPaths.map((socketPath) => ownedSocketAt(socketPath, ownerUid)))).filter((candidate) => candidate !== null);
39652
39652
  }
39653
- function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSearchRoots(), ownerUid = process.getuid?.() ?? null, agentWaitMs = FORWARDED_AGENT_RECONNECT_WAIT_MS } = {}) {
39653
+ function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSearchRoots(), ownerUid = process.getuid?.() ?? null, agentWaitMs = FORWARDED_AGENT_RECONNECT_WAIT_MS, agentRescanIntervalMs = AGENT_RESCAN_INTERVAL_MS } = {}) {
39654
39654
  async function agentHolds(socketPath, publicKey) {
39655
39655
  const listing = await execFileAsync("ssh-add", ["-L"], {
39656
39656
  env: {
@@ -39675,7 +39675,7 @@ function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSea
39675
39675
  const agentEnv = await agentEnvFor(publicKey);
39676
39676
  if (agentEnv || Date.now() >= deadlineMs) return agentEnv;
39677
39677
  await new Promise((resolve) => {
39678
- setTimeout(resolve, AGENT_RESCAN_INTERVAL_MS);
39678
+ setTimeout(resolve, agentRescanIntervalMs);
39679
39679
  });
39680
39680
  return agentEnvBefore(publicKey, deadlineMs);
39681
39681
  }
@@ -44835,7 +44835,7 @@ async function pruneTraceFiles({ traceDirectory, now = Date.now(), isBoundSessio
44835
44835
  isRetainedId: isBoundSessionId
44836
44836
  })).length;
44837
44837
  }
44838
- function createTraceWiring({ configPath = null, logger = console, debug = false, nowFn = Date.now, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn } = {}) {
44838
+ function createTraceWiring({ configPath = null, logger = console, debug = false, nowFn = Date.now, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, maxRememberedSubagents = 512 } = {}) {
44839
44839
  const traceDirectory = configSiblingPath(configPath, "traces");
44840
44840
  const emitter = new EventEmitter();
44841
44841
  const bindingByGlimmervoidSessionId = /* @__PURE__ */ new Map();
@@ -45043,7 +45043,7 @@ function createTraceWiring({ configPath = null, logger = console, debug = false,
45043
45043
  didFallbackToTranscriptEnd: resume.didFallbackToTranscriptEnd,
45044
45044
  scannedBytes: traceTail.scannedBytes,
45045
45045
  committedOffsetByTranscriptPath: checkpoint ? checkpoint.offsetByTranscriptPath : {},
45046
- subagentPathsWithoutOffset: subagentPathsWithoutOffset.slice(-512),
45046
+ subagentPathsWithoutOffset: subagentPathsWithoutOffset.slice(-maxRememberedSubagents),
45047
45047
  subagentOffsetByPath
45048
45048
  };
45049
45049
  }
@@ -45377,7 +45377,7 @@ function createTraceWiring({ configPath = null, logger = console, debug = false,
45377
45377
  committedOffset = readEnd;
45378
45378
  isSkippingOversizedLine = true;
45379
45379
  }
45380
- binding.subagentOffsetByPath = withCommittedOffset(binding.subagentOffsetByPath, subagentPath, committedOffset, { maxRemembered: 512 });
45380
+ binding.subagentOffsetByPath = withCommittedOffset(binding.subagentOffsetByPath, subagentPath, committedOffset, { maxRemembered: maxRememberedSubagents });
45381
45381
  binding.subagentPathsWithoutOffset.delete(subagentPath);
45382
45382
  } catch (error) {
45383
45383
  laneLog.warn("subagent transcript read failed", { error: errorMessage(error) });
@@ -58106,7 +58106,7 @@ function createBackend(httpServer, options = {}) {
58106
58106
  stopConfigWatch = configStore.watchForChanges((newConfig) => {
58107
58107
  applyConfigReload(newConfig);
58108
58108
  broadcastSettings?.();
58109
- });
58109
+ }, { reloadDebounceMs: options.configReloadDebounceMs });
58110
58110
  updateCheck.start();
58111
58111
  return {
58112
58112
  shutdown,
@@ -1,6 +1,6 @@
1
1
  import { r as errorMessage } from "./text-DoirglWV.js";
2
- import { l as resolveConfigPath } from "./config-store-B_YyKZoA.js";
3
- import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-BV-hN-g0.js";
2
+ import { l as resolveConfigPath } from "./config-store-SeN0w6cD.js";
3
+ import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-BQ0ggoxv.js";
4
4
  import fs from "node:fs";
5
5
  //#region server/text-format.ts
6
6
  function trimIso(iso) {
@@ -3,7 +3,7 @@ import { n as equalsIgnoringCaseOnWindows } from "./paths-Bu4eH1Yd.js";
3
3
  import { n as isRecord } from "./coerce-NSst8oRP.js";
4
4
  import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.js";
5
5
  import { a as jsonStateLoadError, d as writeJsonAtomicSync, l as sleepSync, s as loadJsonStateFileSync, u as writeJsonAtomic } from "./json-file-BjFK_eSH.js";
6
- import { dt as canonicalizePath, s as glimmervoidHomeDir } from "./config-store-B_YyKZoA.js";
6
+ import { dt as canonicalizePath, s as glimmervoidHomeDir } from "./config-store-SeN0w6cD.js";
7
7
  import fs from "node:fs";
8
8
  import path from "node:path";
9
9
  import crypto from "node:crypto";
@@ -4,8 +4,8 @@ import { f as AgentSettingsReply } from "./session-BF6eF7dw.js";
4
4
  import { r as BrowserConfig } from "./config-BYsrGS5K.js";
5
5
  import { n as isRecord } from "./coerce-NSst8oRP.js";
6
6
  import { t as renderTable } from "./ascii-figure-core-pDAwtlKO.js";
7
- import { A as setValueAtPath, F as SETTINGS_REGISTRY, N as valueAtPath, O as parsePosthogProjectSelection, T as deleteValueAtPath, c as loadConfigFile, d as validateConfig, et as ENV_SECRET_BINDINGS, f as isSettingAvailable, k as scoreSettingsSearch, r as IS_EXPERIMENTAL_BUILD, rt as withEnvSecrets, tt as readEnvSecrets, u as saveConfigFileOnce, w as cloneValue } from "./config-store-B_YyKZoA.js";
8
- import { a as fail, c as listSettings, d as renderSectionTables, f as requireConfigFileSetting, g as valueText, h as succeed, i as describeSetting, l as readSetting, m as settingsRequestForServer, n as configFileViewOf, o as fitColumn, p as sectionOf, r as defaultText, s as getSetting, t as availableSettings } from "./settings-readout-core-CdP-M1yc.js";
7
+ import { A as setValueAtPath, F as SETTINGS_REGISTRY, N as valueAtPath, O as parsePosthogProjectSelection, T as deleteValueAtPath, c as loadConfigFile, d as validateConfig, et as ENV_SECRET_BINDINGS, f as isSettingAvailable, k as scoreSettingsSearch, r as IS_EXPERIMENTAL_BUILD, rt as withEnvSecrets, tt as readEnvSecrets, u as saveConfigFileOnce, w as cloneValue } from "./config-store-SeN0w6cD.js";
8
+ import { a as fail, c as listSettings, d as renderSectionTables, f as requireConfigFileSetting, g as valueText, h as succeed, i as describeSetting, l as readSetting, m as settingsRequestForServer, n as configFileViewOf, o as fitColumn, p as sectionOf, r as defaultText, s as getSetting, t as availableSettings } from "./settings-readout-core-C1uJhry6.js";
9
9
  import fs from "node:fs";
10
10
  import os from "node:os";
11
11
  import { parseArgs } from "node:util";
@@ -1,6 +1,6 @@
1
1
  import { p as AgentSettingsRequest } from "./session-BF6eF7dw.js";
2
2
  import { t as renderTable } from "./ascii-figure-core-pDAwtlKO.js";
3
- import { C as SETTINGS_INDEX, D as hasScaledUnit, E as displayText, F as SETTINGS_REGISTRY, M as settingsOf, N as valueAtPath, P as FILE_ONLY_GROUPS, f as isSettingAvailable, j as settingsGroupOf, tt as readEnvSecrets, w as cloneValue } from "./config-store-B_YyKZoA.js";
3
+ import { C as SETTINGS_INDEX, D as hasScaledUnit, E as displayText, F as SETTINGS_REGISTRY, M as settingsOf, N as valueAtPath, P as FILE_ONLY_GROUPS, f as isSettingAvailable, j as settingsGroupOf, tt as readEnvSecrets, w as cloneValue } from "./config-store-SeN0w6cD.js";
4
4
  import { parseArgs } from "node:util";
5
5
  //#region server/core/settings-readout-core.ts
6
6
  var VALUE_COLUMN_WIDTH = 40;
@@ -1 +1 @@
1
- import{n as e,o as t,r as n}from"./dom-helpers-B98sy9ep.js";import{H as r,U as i,W as a}from"./index-cLVH9cFO.js";var o={mine:`Mine`,run:`Run`,cancel:`Cancel`},s=null;function c(e){return e===null?`n/a`:`${Math.round(e*100)}%`}function l(e){if(e===null)return`n/a`;let t=Math.round(e*100);return t>0?`+${t}`:String(t)}function u(e,n,r){let a=t(`button`,`bench-action-button`,o[n]);return a.type=`button`,a.disabled=r,a.addEventListener(`click`,()=>i(e.id,n)),a}function d(e,t){let n=e.inFlight;if(!n||n.suiteId!==t.id)return``;let r=n.caseId?`case ${n.caseId}, `:``;return`Cell ${n.cellIndex+1} of ${n.cellCount}: ${r}arm ${n.armId}, trial ${n.trial}, ${n.phase}.`}function f(e){let n=t(`td`,`bench-score`,c(e?.recall??null));return e&&e.invalid>0&&(n.title=`${e.invalid} invalid or failed cell(s)`),e&&e.degraded>0&&(n.dataset.degraded=`true`),n}function p(e){let n=e.armIds.filter(t=>t!==e.baselineArm),r=t(`table`,`bench-table`),i=t(`tr`);i.append(t(`th`,null,`Case`),...e.armIds.map(n=>t(`th`,null,n===e.baselineArm?`${n} (baseline)`:n))),i.append(...n.map(e=>t(`th`,null,`${e} vs baseline`))),r.append(i);for(let i of e.rows){let a=t(`tr`);a.append(t(`td`,`bench-case`,i.caseId),...e.armIds.map(e=>f(i.arms[e]))),a.append(...n.map(e=>t(`td`,`bench-delta`,l(i.deltaVsBaseline[e]??null)))),r.append(a)}let a=[...new Set(e.armIds.flatMap(t=>Object.keys(e.totals[t]?.recallByTag??{})))].sort(),o=t(`tr`,`bench-total`);o.append(t(`td`,`bench-case`,`Paired recall`),...e.armIds.map(t=>f(e.totals[t]))),r.append(o);for(let n of a){let i=t(`tr`,`bench-total`);i.append(t(`td`,`bench-case`,`Recall, ${n}`),...e.armIds.map(r=>t(`td`,`bench-score`,c(e.totals[r]?.recallByTag[n]??null)))),r.append(i)}return r}function m(e,i){let{isServerConnected:a,pendingActionBySuite:o,outcomeBySuite:s}=r(),c=t(`div`,`bench-suite`),l=e.inFlight?.suiteId===i.id,f=!!e.inFlight&&!l,m=o.has(i.id)||!a,h=t(`div`,`bench-summary`);h.append(t(`span`,`bench-suite-title`,i.title),n(`bench`,i.caseCount===1?`case`:`cases`,String(i.caseCount)),n(`bench`,i.candidateCount===1?`candidate`:`candidates`,String(i.candidateCount)),n(`bench`,`arms`,String(i.armIds.length))),c.append(h);let g=t(`div`,`bench-controls`),_=e.configured===!0&&i.error===null;g.append(u(i,`mine`,!_||m||l),u(i,`run`,!_||m||l||f||i.caseCount===0),u(i,`cancel`,m||!l));let v=t(`span`,`bench-status`,(a?``:`Not connected to the server. Reconnecting.`)||d(e,i)||s.get(i.id)||``);if(v.setAttribute(`role`,`status`),g.append(v),c.append(g),i.error)return c.append(t(`p`,`bench-error`,i.error)),c;let y=i.latestReport;return y?(c.append(t(`p`,`bench-run-line`,`Latest run ${y.runId}: ${y.status}. Only cases every arm scored count toward paired recall.`)),y.rows.length>0&&c.append(p(y)),c):(c.append(t(`p`,`bench-empty`,i.caseCount===0?`Move approved candidates into the cases folder, then choose Run.`:`No run yet.`)),c)}function h(){if(!s)return;s.textContent=``;let{status:n}=r(),i=e(`bench`,`Benchmarks`,`Suites from the benchmarks folder of the Glimmervoid home, one run at a time.`);if(s.append(i),!n)s.append(t(`p`,`bench-empty`,`Waiting for the server.`));else if(!n.configured)s.append(t(`p`,`bench-empty`,n.reason||`Benchmarks are off.`));else if(n.suites.length===0)s.append(t(`p`,`bench-empty`,`No suites yet. Create a folder holding suite.json under benchmarks in the Glimmervoid home.`));else for(let e of n.suites)s.append(m(n,e))}function g(e){s||(s=t(`div`,`bench-content`),e.append(s),a(h),h())}var _={mount:g};export{_ as view};
1
+ import{n as e,o as t,r as n}from"./dom-helpers-B98sy9ep.js";import{J as r,K as i,q as a}from"./index-CHUWzO2K.js";var o={mine:`Mine`,run:`Run`,cancel:`Cancel`},s=null;function c(e){return e===null?`n/a`:`${Math.round(e*100)}%`}function l(e){if(e===null)return`n/a`;let t=Math.round(e*100);return t>0?`+${t}`:String(t)}function u(e,n,r){let i=t(`button`,`bench-action-button`,o[n]);return i.type=`button`,i.disabled=r,i.addEventListener(`click`,()=>a(e.id,n)),i}function d(e,t){let n=e.inFlight;if(!n||n.suiteId!==t.id)return``;let r=n.caseId?`case ${n.caseId}, `:``;return`Cell ${n.cellIndex+1} of ${n.cellCount}: ${r}arm ${n.armId}, trial ${n.trial}, ${n.phase}.`}function f(e){let n=t(`td`,`bench-score`,c(e?.recall??null));return e&&e.invalid>0&&(n.title=`${e.invalid} invalid or failed cell(s)`),e&&e.degraded>0&&(n.dataset.degraded=`true`),n}function p(e){let n=e.armIds.filter(t=>t!==e.baselineArm),r=t(`table`,`bench-table`),i=t(`tr`);i.append(t(`th`,null,`Case`),...e.armIds.map(n=>t(`th`,null,n===e.baselineArm?`${n} (baseline)`:n))),i.append(...n.map(e=>t(`th`,null,`${e} vs baseline`))),r.append(i);for(let i of e.rows){let a=t(`tr`);a.append(t(`td`,`bench-case`,i.caseId),...e.armIds.map(e=>f(i.arms[e]))),a.append(...n.map(e=>t(`td`,`bench-delta`,l(i.deltaVsBaseline[e]??null)))),r.append(a)}let a=[...new Set(e.armIds.flatMap(t=>Object.keys(e.totals[t]?.recallByTag??{})))].sort(),o=t(`tr`,`bench-total`);o.append(t(`td`,`bench-case`,`Paired recall`),...e.armIds.map(t=>f(e.totals[t]))),r.append(o);for(let n of a){let i=t(`tr`,`bench-total`);i.append(t(`td`,`bench-case`,`Recall, ${n}`),...e.armIds.map(r=>t(`td`,`bench-score`,c(e.totals[r]?.recallByTag[n]??null)))),r.append(i)}return r}function m(e,r){let{isServerConnected:a,pendingActionBySuite:o,outcomeBySuite:s}=i(),c=t(`div`,`bench-suite`),l=e.inFlight?.suiteId===r.id,f=!!e.inFlight&&!l,m=o.has(r.id)||!a,h=t(`div`,`bench-summary`);h.append(t(`span`,`bench-suite-title`,r.title),n(`bench`,r.caseCount===1?`case`:`cases`,String(r.caseCount)),n(`bench`,r.candidateCount===1?`candidate`:`candidates`,String(r.candidateCount)),n(`bench`,`arms`,String(r.armIds.length))),c.append(h);let g=t(`div`,`bench-controls`),_=e.configured===!0&&r.error===null;g.append(u(r,`mine`,!_||m||l),u(r,`run`,!_||m||l||f||r.caseCount===0),u(r,`cancel`,m||!l));let v=t(`span`,`bench-status`,(a?``:`Not connected to the server. Reconnecting.`)||d(e,r)||s.get(r.id)||``);if(v.setAttribute(`role`,`status`),g.append(v),c.append(g),r.error)return c.append(t(`p`,`bench-error`,r.error)),c;let y=r.latestReport;return y?(c.append(t(`p`,`bench-run-line`,`Latest run ${y.runId}: ${y.status}. Only cases every arm scored count toward paired recall.`)),y.rows.length>0&&c.append(p(y)),c):(c.append(t(`p`,`bench-empty`,r.caseCount===0?`Move approved candidates into the cases folder, then choose Run.`:`No run yet.`)),c)}function h(){if(!s)return;s.textContent=``;let{status:n}=i(),r=e(`bench`,`Benchmarks`,`Suites from the benchmarks folder of the Glimmervoid home, one run at a time.`);if(s.append(r),!n)s.append(t(`p`,`bench-empty`,`Waiting for the server.`));else if(!n.configured)s.append(t(`p`,`bench-empty`,n.reason||`Benchmarks are off.`));else if(n.suites.length===0)s.append(t(`p`,`bench-empty`,`No suites yet. Create a folder holding suite.json under benchmarks in the Glimmervoid home.`));else for(let e of n.suites)s.append(m(n,e))}function g(e){s||(s=t(`div`,`bench-content`),e.append(s),r(h),h())}var _={mount:g};export{_ as view};
@@ -0,0 +1,84 @@
1
+ import{H as e,Mt as t,Nt as n,dt as r,ft as i,h as a,m as o,o as s,ut as c}from"./dom-helpers-B98sy9ep.js";import{u as l}from"./control-ws-C8SS9PPx.js";import{i as u,n as d}from"./poll-ago-DdlzkUaM.js";import{i as f,s as p,t as m}from"./action-status-DmJCv-Ib.js";import{n as h,r as g,t as _}from"./modal-5t7_5VCF.js";import{_r as v,ar as y,br as b,cr as x,gr as S,mr as C,or as w,sr as T,tn as E,vr as D,yr as O}from"./index-CHUWzO2K.js";var ee=`<h2 class="dialog-title" id="add-session-title">Add Session</h2>
2
+ <fieldset class="dialog-mode-controls" aria-label="Session kind">
3
+ <button type="button" class="dialog-mode-button" id="add-session-single-mode" aria-pressed="true">Single repo</button>
4
+ <button type="button" class="dialog-mode-button" id="add-session-workspace-mode" aria-pressed="false">Workspace</button>
5
+ </fieldset>
6
+ <p class="dialog-mode-hint">Workspace runs one session across several repos.</p>
7
+ <label class="dialog-label" id="add-session-picker-label">
8
+ Pick a project:
9
+ <select class="dialog-input project-picker" id="add-session-picker">
10
+ <option value="" disabled selected>Scanning...</option>
11
+ </select>
12
+ </label>
13
+ <fieldset class="dialog-workspace-list" id="add-session-workspace-list" aria-label="Workspace repositories" hidden></fieldset>
14
+ <div class="dialog-repo-roots" id="add-session-repo-roots" hidden>
15
+ <p class="dialog-repo-roots-title" id="add-session-repo-roots-title">No repository roots yet</p>
16
+ <p class="dialog-repo-roots-desc">Add the folder that holds your git checkouts. Its repos show up right here.</p>
17
+ </div>
18
+ <label class="dialog-label" id="add-session-agent-label" hidden>
19
+ Agent
20
+ <select class="dialog-input" id="add-session-agent"></select>
21
+ </label>
22
+ <label class="dialog-label" id="add-session-environment-label" hidden>
23
+ Environment
24
+ <select class="dialog-input" id="add-session-environment"></select>
25
+ <span class="dialog-hint" id="add-session-environment-hint" hidden></span>
26
+ </label>
27
+ <div class="dialog-label" id="add-session-agent-login" hidden>
28
+ <span class="dialog-hint" id="add-session-agent-login-text"></span>
29
+ <button type="button" class="btn-dialog btn-dialog-cancel" id="add-session-agent-connect">Connect</button>
30
+ </div>
31
+ <button type="button" class="dialog-advanced-toggle" id="add-session-advanced-toggle" aria-controls="add-session-advanced">Run in a folder outside your repository roots</button>
32
+ <div class="dialog-advanced-panel" id="add-session-advanced" hidden>
33
+ <label class="dialog-label">
34
+ Name
35
+ <input type="text" class="dialog-input" id="add-session-name" placeholder="my-project" autocomplete="off" spellcheck="false">
36
+ </label>
37
+ <label class="dialog-label" id="add-session-path-label">
38
+ Path
39
+ <input type="text" class="dialog-input" id="add-session-path" placeholder="Full path to the project folder" autocomplete="off" spellcheck="false">
40
+ </label>
41
+ </div>
42
+ <div class="dialog-sane-yolo-row">
43
+ <label class="dialog-label dialog-checkbox-label" id="add-session-skip-perms-label">
44
+ <input type="checkbox" class="dialog-checkbox" id="add-session-skip-perms">
45
+ <span>Sane YOLO mode</span>
46
+ </label>
47
+ <a class="dialog-help-link" id="add-session-sane-yolo-help" href="#settings/machine-guardrails/sane-yolo" aria-label="What Sane YOLO mode does" title="What Sane YOLO mode does">?</a>
48
+ </div>
49
+ <p class="dialog-hint dialog-hint-warning" id="add-session-sane-yolo-unavailable" hidden>Sane YOLO cannot protect this session here, so this mode skips permission prompts unprotected.</p>
50
+ <div class="dialog-safety-row">
51
+ <button type="button" class="dialog-advanced-toggle" id="add-session-safety-toggle" aria-controls="add-session-safety" aria-expanded="false">Safety overrides</button>
52
+ <span class="dialog-safety-status" id="add-session-safety-status">guardrails on</span>
53
+ </div>
54
+ <div class="dialog-advanced-panel" id="add-session-safety" hidden>
55
+ <label class="dialog-label dialog-checkbox-label" id="add-session-unguarded-label">
56
+ <input type="checkbox" class="dialog-checkbox" id="add-session-unguarded">
57
+ <span>Run without guardrails</span>
58
+ <span class="dialog-hint">Claude Code sessions run with guardrails that block writes to credentials and Glimmervoid's own state and hide credentials and other agents' settings. Turn this on only for work the guardrails cannot serve.</span>
59
+ </label>
60
+ </div>
61
+ <div class="dialog-error" id="add-session-error"></div>
62
+ <div class="dialog-actions">
63
+ <button type="button" class="btn-dialog btn-dialog-cancel" id="add-session-cancel">Cancel</button>
64
+ <button type="button" class="btn-dialog btn-dialog-confirm" id="add-session-confirm">Add</button>
65
+ </div>
66
+ `,k=`<h2 class="dialog-title" id="agent-connect-title">Connect</h2>
67
+ <p class="dialog-hint" id="agent-connect-intro"></p>
68
+ <p class="dialog-label" id="agent-connect-state" role="status"></p>
69
+ <div class="dialog-label" id="agent-connect-steps" hidden>
70
+ <span>1. Open <a class="dialog-link" id="agent-connect-link" href="about:blank" target="_blank" rel="noopener noreferrer">the sign-in page</a> and sign in.</span>
71
+ <span id="agent-connect-code-row" hidden>2. Enter this code there: <code id="agent-connect-code"></code></span>
72
+ <label class="dialog-label" id="agent-connect-paste-label" hidden>
73
+ 2. Paste the code the page shows
74
+ <input type="text" class="dialog-input" id="agent-connect-paste" autocomplete="off" spellcheck="false">
75
+ </label>
76
+ </div>
77
+ <div class="dialog-error" id="agent-connect-error"></div>
78
+ <div class="dialog-actions">
79
+ <button type="button" class="btn-dialog btn-dialog-cancel" id="agent-connect-close">Close</button>
80
+ <button type="button" class="btn-dialog btn-dialog-cancel" id="agent-connect-stop" hidden>Stop sign-in</button>
81
+ <button type="button" class="btn-dialog btn-dialog-confirm" id="agent-connect-submit" hidden>Submit code</button>
82
+ <button type="button" class="btn-dialog btn-dialog-confirm" id="agent-connect-start">Start sign-in</button>
83
+ </div>
84
+ `;function A(e,{value:t,disabled:n=!1,selected:r=!1}={}){let i=s(`option`,null,e);return t!=null&&(i.value=t),n&&(i.disabled=!0),r&&(i.selected=!0),i}function te(e){return typeof e!=`object`||!e?!1:`saneYoloAvailable`in e&&e.saneYoloAvailable===!0}function ne(e){if(typeof e!=`object`||!e||!(`coderEnvironments`in e))return[];let n=t.safeParse(e.coderEnvironments);return n.success&&n.data?n.data:[]}function re(e){let t=Object.entries(e.parameters).map(([e,t])=>`${e}=${t}`).join(`, `);return[`Template ${e.template}.`,t?`Parameters: ${t}.`:``,e.hourlyCostUsd===null?``:`Costs $${e.hourlyCostUsd.toFixed(2)} an hour.`,`Stops after ${e.idleStopMinutes} idle minutes.`].filter(Boolean).join(` `)}var j=Object.freeze({"claude-code":`Claude Code`,codex:`Codex`});function ie(e){let t=n.safeParse(e);return t.success?t.data:null}function M(e,t){let n=j[t];return e?e.state===`signed-in`&&e.source===`host`?`${n} uses the login already on this machine.`:e.state===`signed-in`?`${n} uses the login Glimmervoid connected.`:e.state===`connecting`?e.reason??`${n} sign-in is waiting for you.`:e.state===`failed`?e.reason??`${n} sign-in failed.`:`${n} has no login on this machine, so remote ${n} sessions cannot sign in.`:`Checking whether ${n} is signed in.`}function N(){l(`get-agent-logins`,{},{timeoutMs:m}).then(e=>{e.type===`agent-logins`&&O(e.logins)}).catch(()=>{})}function ae(e){let t=j[e],{dialog:n,close:r}=g();n.innerHTML=k,_(n,`agent-connect-title`),o(n,`#agent-connect-title`).textContent=`Connect ${t}`,o(n,`#agent-connect-intro`).textContent=`Glimmervoid signs ${t} in for its own remote sessions and keeps that login in its own folder, apart from any login you already have on this machine. The sign-in runs here and is never recorded.`;let i=o(n,`#agent-connect-state`),s=o(n,`#agent-connect-steps`),c=a(n,`#agent-connect-link`,`a`),u=o(n,`#agent-connect-code-row`),d=o(n,`#agent-connect-code`),f=o(n,`#agent-connect-paste-label`),h=a(n,`#agent-connect-paste`,`input`),v=o(n,`#agent-connect-error`),y=a(n,`#agent-connect-close`,`button`),x=a(n,`#agent-connect-stop`,`button`),S=a(n,`#agent-connect-submit`,`button`),C=a(n,`#agent-connect-start`,`button`);function w(){if(!n.isConnected){E();return}let t=D(e),r=t?.state===`connecting`;i.textContent=M(t,e),C.hidden=r,x.hidden=!r;let a=r?t.verificationUrl:null;s.hidden=a===null,c.href=a??``,c.textContent=a??``,u.hidden=!t?.userCode,d.textContent=t?.userCode??``;let o=r&&t.needsPastedCode;f.hidden=!o,S.hidden=!o}async function T(t,n,r){r.disabled=!0,v.textContent=``;try{let r=await l(t,{agent:e,...n},{timeoutMs:m});if(r.type!==`agent-logins`)return;O(r.logins),r.error&&(v.textContent=r.error)}catch(e){v.textContent=`The server did not answer (${p(e,m)}).`}finally{r.disabled=!1}}C.addEventListener(`click`,()=>{T(`agent-connect`,{action:`start`},C)}),x.addEventListener(`click`,()=>{T(`agent-connect`,{action:`cancel`},x)}),S.addEventListener(`click`,()=>{let e=h.value;h.value=``,T(`agent-connect-code`,{code:e},S)}),h.addEventListener(`keydown`,e=>{e.key===`Enter`&&(e.preventDefault(),S.click())}),y.addEventListener(`click`,r);let E=b(w);w(),N()}function oe(){let{dialog:e,close:t,actions:r,btnCancel:i}=h({title:`Set up a remote host`}),a=s(`p`,`dialog-hint`,`The setup session runs outside the guardrails so it can use your ssh keys. It runs commands on the remote host over ssh and asks before each one. Glimmervoid deletes its working folder when the session ends.`),o=s(`p`,`dialog-label`,`Agent`),c=s(`div`,`hooks-type-row`);c.setAttribute(`role`,`radiogroup`);let u=f(),d=s(`button`,`btn-dialog btn-dialog-confirm`,`Start setup`);d.type=`button`,i.type=`button`,i.addEventListener(`click`,t),r.append(d),e.append(a,o,c,u.element,r);let g=null,_=!1;function v(){if(!e.isConnected){y();return}let t=n.options.filter(e=>D(e)?.state===`signed-in`);(g===null||!t.includes(g))&&(g=t[0]??null),c.replaceChildren(...t.map(e=>{let t=s(`label`,`settings-view-toggle hooks-choice`),n=s(`input`,`settings-view-checkbox`);return n.type=`radio`,n.name=`remote-setup-agent`,n.checked=e===g,n.addEventListener(`change`,()=>{g=e}),t.append(n,s(`span`,null,j[e])),t})),t.length===0&&c.append(s(`span`,``,`Sign in to Claude Code or Codex on this machine first.`)),d.disabled=_||g===null}d.addEventListener(`click`,async()=>{if(g!==null){_=!0,d.disabled=!0,u.show(`busy`,`Starting the setup session.`);try{let e=await l(`start-remote-setup`,{agent:g},{timeoutMs:m});if(e.type===`start-remote-setup-result`&&e.ok){t();return}u.show(`error`,e.type===`start-remote-setup-result`&&e.error?e.error:`The setup session did not start.`)}catch(e){u.show(`error`,`The server did not answer (${p(e,m)}).`)}finally{_=!1,v()}}});let y=b(v);v(),N()}function se(){let{dialog:e,close:t}=g();e.innerHTML=ee,_(e,`add-session-title`);let n=a(e,`#add-session-picker`,`select`),r=o(e,`#add-session-picker-label`),i=o(e,`#add-session-workspace-list`),c=a(e,`#add-session-single-mode`,`button`),u=a(e,`#add-session-workspace-mode`,`button`),d=o(e,`#add-session-agent-label`),h=a(e,`#add-session-agent`,`select`),O=o(e,`#add-session-environment-label`),k=a(e,`#add-session-environment`,`select`),j=o(e,`#add-session-environment-hint`),oe=o(e,`#add-session-agent-login`),se=o(e,`#add-session-agent-login-text`),ce=a(e,`#add-session-agent-connect`,`button`),P=o(e,`#add-session-repo-roots`),le=o(e,`#add-session-repo-roots-title`),F=a(e,`#add-session-advanced-toggle`,`button`),I=o(e,`#add-session-advanced`),L=a(e,`#add-session-name`,`input`),R=a(e,`#add-session-path`,`input`),ue=o(e,`#add-session-path-label`),z=a(e,`#add-session-skip-perms`,`input`),B=a(e,`#add-session-unguarded`,`input`),de=a(e,`#add-session-sane-yolo-help`,`a`),fe=o(e,`#add-session-sane-yolo-unavailable`),pe=a(e,`#add-session-safety-toggle`,`button`),me=o(e,`#add-session-safety`),he=o(e,`#add-session-safety-status`),V=o(e,`#add-session-error`),ge=a(e,`#add-session-cancel`,`button`),H=a(e,`#add-session-confirm`,`button`),U=!1,_e=[],W=null;function G(e){U=e,c.setAttribute(`aria-pressed`,String(!e)),u.setAttribute(`aria-pressed`,String(e)),r.hidden=e,i.hidden=!e,F.hidden=e,F.setAttribute(`aria-expanded`,String(e)),I.hidden=!e,ue.hidden=e,e&&requestAnimationFrame(()=>L.focus())}c.addEventListener(`click`,()=>G(!1)),u.addEventListener(`click`,()=>G(!0)),F.setAttribute(`aria-expanded`,`false`),F.addEventListener(`click`,()=>{let e=I.hidden;I.hidden=!e,F.setAttribute(`aria-expanded`,String(e)),e&&requestAnimationFrame(()=>L.focus())}),de.addEventListener(`click`,()=>t()),pe.addEventListener(`click`,()=>{let e=me.hidden;me.hidden=!e,pe.setAttribute(`aria-expanded`,String(e))}),B.addEventListener(`change`,()=>{he.textContent=B.checked?`guardrails off`:`guardrails on`});let ve=y({onAdded:J});P.append(ve.element);let K=f(`dialog-hint`),q=s(`button`,`btn-dialog btn-dialog-cancel`,`Scan again`);q.type=`button`,q.hidden=!0,q.addEventListener(`click`,()=>{J()});let ye=s(`div`,`flex items-center gap-2`);ye.append(K.element,q),P.before(ye);function be(e){n.textContent=``,n.appendChild(A(`Scan failed`,{disabled:!0,selected:!0})),i.textContent=``,K.show(`error`,`The project scan failed: ${e}`),q.hidden=!1,q.disabled=!1}function xe(e){let t=e.type===`repo-roots-scanned`;le.textContent=t&&e.directories.length>0?`No projects in your repository roots yet`:`No repository roots yet`,ve.setSuggestions(t?e.suggestions??[]:[]),P.hidden=!1}function J(){return q.disabled=!0,K.show(`busy`,`Scanning your repository roots`),l(`scan-repo-roots`,{includeSuggestions:!0},{timeoutMs:m}).then(e=>{if(e.type===`repo-roots-scanned`&&e.error){be(e.error);return}K.clear(),q.hidden=!0,n.textContent=``,i.textContent=``,P.hidden=!0,n.appendChild(A(`-- Select a project --`,{value:``,disabled:!0,selected:!0}));let t=!1,r=e.type===`repo-roots-scanned`?e.directories:[];for(let e of r){if(e.projects.length===0)continue;let r=s(`optgroup`);r.label=e.root;for(let n of e.projects){let e=S(n.name),a=e>0?`${n.name} (${e} open)`:n.name;r.appendChild(A(a,{value:JSON.stringify({name:n.name,path:n.path})})),i.appendChild(E(n.name,n.path)),t=!0}n.appendChild(r)}t||(n.textContent=``,n.appendChild(A(`No projects yet`,{disabled:!0,selected:!0})),i.textContent=`No projects yet.`,xe(e))}).catch(e=>{be(p(e,m))})}J(),n.addEventListener(`change`,()=>{try{let e=JSON.parse(n.value);L.value=v(e.name),R.value=e.path}catch{}});let Y=w,X=!1;function Z(e){let t=s(`p`,`dialog-hint dialog-hint-warning`,e);return t.setAttribute(`role`,`status`),V.before(t),t}function Se(e){X=!0,H.disabled=!0,Z(e).id=`add-session-agent-guidance`}l(`list-agents`,{},{timeoutMs:m}).then(e=>{let t=T(e);t.canSpawn||Se(t.guidance);let n=x(e.type===`agents-listed`?e.agents:[]);if(Y=n.selectedId,n.show){h.textContent=``;for(let e of n.options)h.appendChild(A(e.label,{value:e.id,selected:e.id===n.selectedId}));d.hidden=!1}}).catch(e=>{Z(`Could not load the agent list (${p(e,m)}), so the session uses the default agent.`)}),h.addEventListener(`change`,()=>{Y=h.value,Q()});function Q(){if(!e.isConnected){Ce();return}let t=ie(Y),n=t?D(t):null;oe.hidden=W===null||t===null||n===null||n.state===`signed-in`,se.textContent=t?M(n,t):``}ce.addEventListener(`click`,()=>{let e=ie(Y);e&&ae(e)});let Ce=b(Q);N();let we=!1,Te=!1;z.addEventListener(`change`,()=>{we=!0});function $(){let e=Te&&W===null;fe.hidden=e,!we&&(z.checked=e)}l(`get-settings`,{},{timeoutMs:m}).then(e=>{e.type===`settings-error`?(Z(`Could not load your settings (${e.message}). Check Sane YOLO mode yourself.`),$()):(Ee(ne(e.settings)),Te=te(e.settings),$())}).catch(e=>{Z(`Could not load your settings (${p(e,m)}). Check Sane YOLO mode yourself.`),$()});function Ee(e){if(e.length!==0){_e=e,k.textContent=``,k.appendChild(A(`Local`,{value:``,selected:!0}));for(let t of e)k.appendChild(A(t.name,{value:t.name}));O.hidden=!1}}k.addEventListener(`change`,()=>{W=_e.find(e=>e.name===k.value)??null,u.hidden=W!==null,j.hidden=W===null,j.textContent=W?re(W):``,Q(),$(),W!==null&&U&&G(!1)}),L.addEventListener(`input`,()=>{n.selectedIndex=0}),R.addEventListener(`input`,()=>{n.selectedIndex=0});function De(){if(X)return;let e=L.value.trim(),t=R.value.trim();if(U){let t=[...i.querySelectorAll(`input:checked`)].map(e=>e.value);if(!e||t.length<2){V.textContent=`Enter a name and select at least two repositories.`;return}let n={name:v(e),path:t[0],repos:t,dangerouslySkipPermissions:z.checked,saneYolo:z.checked,unguarded:B.checked};Y&&Y!==`claude-code`&&(n.agent=Y),Oe(n);return}if(!e||!t){V.textContent=`Both fields are required. Select a project or use Advanced options.`;return}let n={name:v(e),path:t,dangerouslySkipPermissions:z.checked,saneYolo:z.checked,unguarded:B.checked};Y&&Y!==`claude-code`&&(n.agent=Y),W&&(n.environment=W.name),Oe(n)}function Oe(e){H.disabled=!0,V.textContent=``,l(`add-session`,e,{timeoutMs:m}).then(e=>{e.type===`add-session-result`&&e.ok?t():V.textContent=C(e)}).catch(e=>{V.textContent=`The session was not added: ${p(e,m)}`}).finally(()=>{H.disabled=X})}ge.addEventListener(`click`,t),H.addEventListener(`click`,De),L.addEventListener(`keydown`,e=>{e.key===`Enter`&&(U&&De(),U||R.focus())}),R.addEventListener(`keydown`,e=>{e.key===`Enter`&&De()}),requestAnimationFrame(()=>n.focus())}function ce({issueId:e,issueTitle:t,format:n,content:r,message:i,error:a}){let{dialog:o,close:c,actions:l,btnCancel:u}=h({title:`Investigation report`,dialogClass:`dialog dialog-report`,cancelLabel:`Close`}),d=s(`div`,`dialog-report-meta`,t||e||``),f=null;if(n===`html`&&!a&&!i){let e=s(`iframe`,`dialog-report-frame`);e.setAttribute(`sandbox`,``),e.srcdoc=r||``,f=e}f||=s(`pre`,a?`dialog-report-body dialog-report-error`:`dialog-report-body`,a||i||r||``),o.append(d,f,l),u.addEventListener(`click`,c),requestAnimationFrame(()=>u.focus())}function P({issueTitle:t,projectLabel:n,onOpenReport:a}){let{dialog:o,close:l,actions:f,btnCancel:p}=h({title:`Investigation`,dialogClass:`dialog dialog-report`,cancelLabel:`Close`}),m=s(`div`,`dialog-report-meta`,n?`${n}: ${t}`:t),g=s(`p`,`dialog-trail-status`),_=s(`p`,`dialog-trail-summary`),v=s(`ol`,`dialog-trail-steps`),y=s(`p`,`dialog-trail-empty`,`No tool calls yet; the session is reading the issue.`),b=s(`button`,`btn-dialog btn-dialog-cancel`,`Open report`);b.type=`button`,b.hidden=!0,b.addEventListener(`click`,()=>{l(),a()}),f.prepend(b),o.append(m,g,_,v,y,f),p.addEventListener(`click`,l),requestAnimationFrame(()=>p.focus());let x=null,S=``;function C(t){let n=v.scrollHeight-v.scrollTop-v.clientHeight<24,r=c(t);if(S!==r){v.textContent=``;for(let n of i(t.steps)){let r=s(`li`,`dialog-trail-step dialog-trail-${n.kind}`),i=n.kind===`note`?n.text:`${n.stepCount} ${n.stepCount===1?`step`:`steps`}`;r.append(s(`span`,`dialog-trail-at`,e(t.startedAt,n.at)),s(`span`,`dialog-trail-detail`,i)),v.append(r)}S=r}y.hidden=t.steps.length>0||!t.inFlight,v.hidden=t.steps.length===0,n&&(v.scrollTop=v.scrollHeight)}function w(e){g.textContent=r(e,d(e.startedAt))}function T(){x&&(w(x),g.dataset.tone=x.inFlight?`live`:`done`,_.textContent=x.summaryLine,_.hidden=!x.summaryLine,b.hidden=x.inFlight||!x.verdict,C(x))}let E=u(()=>{o.isConnected?x?.inFlight&&w(x):E()});return{update(e){x=e,T()},isOpen:()=>o.isConnected,close:()=>{E(),l()}}}export{D as agentLoginOf,M as agentLoginSummary,se as createAddSessionDialog,P as createInvestigationDialog,ce as createRadarReportDialog,b as onAgentLoginsChanged,ae as openAgentConnectDialog,oe as openRemoteSetupDialog};
@@ -1 +1 @@
1
- import{_ as e,a as t,f as n,l as r,m as i,n as a,r as o,u as s}from"./zod-BRLv4KqJ.js";import{C as c,n as l,o as u,p as ee,r as d,u as f}from"./dom-helpers-B98sy9ep.js";import{u as p}from"./control-ws-C8SS9PPx.js";import{i as m,s as h,t as g}from"./action-status-DmJCv-Ib.js";import{a as _}from"./modal-5t7_5VCF.js";import{Bt as v,Rt as y,zt as b}from"./index-cLVH9cFO.js";var te=n(i(),e());s({glimmervoidId:i().min(1),event:i().min(1),token:i().nullable().optional(),payload:te}),s({id:i().min(1),name:i().min(1),event:i().min(1),matcher:i().optional(),type:a([`command`,`http`]),command:i().optional(),url:i().optional(),timeout:r().int().positive().optional(),enabled:t(),projects:o(i()).optional()}).passthrough();var ne=`Claude Code hooks injected into every session Glimmervoid spawns.`,re=`Loading hooks`,ie=`No hooks yet. A hook runs a command, or calls a URL, when a Claude Code event fires in a Glimmervoid session. Start from one of these, or add your own.`,ae=`Start from`,oe=`Filter by name, event or command`,se=`Nothing matches that filter.`,ce=`Preview`,le=`The entry this becomes in the per-session settings file.`,ue=`Duplicate`,de=`Discard changes`,fe=`Close the editor and lose the unsaved changes?`,pe=`Esc cancels. Ctrl+Enter saves.`,me=4,he=`A change reaches a session at its next start or restart. Claude Code sessions only; Codex and Grok sessions do not read this file.`,ge=`Glimmervoid's own hooks`,_e=`Always present, read-only. Status detection depends on them.`,ve=`Your hooks`,ye=`New hook`,be=`Edit hook`,xe=`Saved to config.json.`,x=`All projects`,Se=`This event takes no matcher.`,Ce=`Blank uses Claude Code's default for the event.`,we=Object.freeze([{value:`command`,label:`Command`,hint:`Run a shell command. It receives the event JSON on stdin.`},{value:`http`,label:`HTTP`,hint:`POST the event JSON to a URL.`}]),Te=Object.freeze([{id:`lint`,label:`Lint after edits`,summary:`PostToolUse on Edit|Write`,draft:{name:`Lint after edits`,event:`PostToolUse`,matcher:`Edit|Write`,type:`command`,command:`npx biome check --write "$(jq -r .tool_input.file_path)"`}},{id:`notify`,label:`Notify on Stop`,summary:`Stop, command`,draft:{name:`Notify on Stop`,event:`Stop`,matcher:``,type:`command`,command:`command -v notify-send >/dev/null 2>&1 && notify-send "Claude finished a turn" || { command -v osascript >/dev/null 2>&1 && osascript -e 'display notification "Claude finished a turn" with title "Claude Code"'; }`}},{id:`guard`,label:`Guard destructive Bash`,summary:`PreToolUse on Bash, exit 2 blocks`,draft:{name:`Guard destructive Bash`,event:`PreToolUse`,matcher:`Bash`,type:`command`,command:`jq -r .tool_input.command | grep -Eq "rm -rf|git push --force" && exit 2 || exit 0`}},{id:`log`,label:`Log every prompt`,summary:`UserPromptSubmit, appends JSON`,draft:{name:`Log every prompt`,event:`UserPromptSubmit`,matcher:``,type:`command`,command:`cat >> ~/.claude/prompts.jsonl`}}]),Ee=Object.freeze({hooks:[],builtin:[],events:[]});function De(e){return!e||typeof e.error==`string`}function Oe(e){return!e||typeof e.error!=`string`?``:e.error}function S(e,t){let n=e?.[t];return Array.isArray(n)?n:Ee[t]}var C=e=>S(e,`hooks`),w=e=>S(e,`builtin`),T=e=>S(e,`events`);function E(e){let t=e?.limits?.maxTimeoutSec;return typeof t==`number`&&Number.isInteger(t)&&t>0?t:600}function ke(e){let t=C(e),n=t.filter(e=>e.enabled!==!1).length;return[{label:`yours`,value:String(t.length),tone:null},{label:`enabled`,value:String(n),tone:t.length>0&&n===0?`warn`:null},{label:`built in`,value:String(w(e).length),tone:null}]}function Ae(e,t){let n=new Map(t.map((e,t)=>[e.name,t])),r=e=>n.get(e.event)??t.length;return[...e].sort((e,t)=>{let n=r(e)-r(t);return n===0?String(e.name).localeCompare(String(t.name)):n})}function je(e,t){let n=String(t||``).trim().toLowerCase();return n?e.filter(e=>[e.name,e.event,e.matcher,e.command,e.url].some(e=>typeof e==`string`&&e.toLowerCase().includes(n))):e}function Me(e){return e.length>=me}function Ne(e){let t=[];for(let n of e){let e=t[t.length-1];e&&e.event===n.event?e.hooks.push(n):t.push({event:n.event,hooks:[n]})}return t}function Pe(e){let t=e.type===`http`?{type:`http`,url:e.url||``}:{type:`command`,command:e.command||``};Number.isInteger(e.timeout)&&Number(e.timeout)>0&&(t.timeout=e.timeout);let n=e.matcher?{matcher:e.matcher,hooks:[t]}:{hooks:[t]};return JSON.stringify({hooks:{[e.event]:[n]}},null,2)}function Fe(e){return`${e} copy`}function D(e,t){return e.find(e=>e.name===t)||null}function O(e,t){let n=D(e,t);return n?n.matcher?`Matches ${n.matcher}. Blank matches every ${n.name}.`:Se:``}function Ie(e){return e.type===`http`?e.url||``:e.command||``}function Le(e){let t=we.find(t=>t.value===e);return t?t.label:String(e||``)}function Re(e){return!Number.isInteger(e.timeout)||Number(e.timeout)<=0?``:`${e.timeout}s timeout`}function ze(e,t){let n=Array.isArray(e.projects)?e.projects:[];return n.length===0?x:n.map(e=>{let n=t.find(t=>t.id===e);return n?n.name:e}).join(`, `)}function Be(e){return e.matcher?`${e.event} / ${e.matcher}`:e.event}function Ve(e){return Be(e)}function He(e,t){let n=Array.isArray(e.projects)?e.projects:[],r=new Set(t.map(e=>e.id));return n.filter(e=>!r.has(e))}function k(e){let t=e[0];return{id:null,name:``,event:t?t.name:``,matcher:``,type:`command`,command:``,url:``,timeout:``,enabled:!0,projects:[]}}function A(e){return{id:e.id??null,name:e.name||``,event:e.event||``,matcher:e.matcher||``,type:e.type===`http`?`http`:`command`,command:e.command||``,url:e.url||``,timeout:Number.isInteger(e.timeout)?String(e.timeout):``,enabled:e.enabled!==!1,projects:Array.isArray(e.projects)?[...e.projects]:[]}}function Ue(e,t,n=600){if(!e.name.trim())return`Give the hook a name.`;let r=D(t,e.event);if(!r)return`Pick an event.`;if(e.matcher.trim()&&!r.matcher)return`${r.name} takes no matcher.`;if(e.type===`http`&&r.http===!1)return`${r.name} does not support HTTP hooks.`;if(e.type===`command`&&!e.command.trim())return`Enter the command to run.`;if(e.type===`http`&&!/^https?:\/\/\S+$/i.test(e.url.trim()))return`Enter a URL starting with http:// or https://.`;if(e.timeout.trim()!==``){let t=Number(e.timeout);if(!Number.isInteger(t)||t<1||t>n)return`Timeout must be a whole number of seconds from 1 to ${n}.`}return null}function j(e){let t={name:e.name.trim(),event:e.event,type:e.type,enabled:e.enabled!==!1};return e.id&&(t.id=e.id),e.matcher.trim()&&(t.matcher=e.matcher.trim()),e.type===`command`&&(t.command=e.command.trim()),e.type===`http`&&(t.url=e.url.trim()),e.timeout.trim()!==``&&(t.timeout=Number(e.timeout)),e.projects.length>0&&(t.projects=[...e.projects]),t}function We(e,t){let n={...k(t),...e.draft};return D(t,n.event)||(n.event=k(t).event),n}function Ge(e,t){return JSON.stringify(j(e))!==JSON.stringify(t)}function Ke(e){return{...e,enabled:e.enabled===!1}}function qe(e){return`Delete the hook "${e.name}"? Sessions already running keep it until they restart.`}var M=y(),N=null,P=null,F=null,I=null,L=null,R=null,z=!1,B=``,V=new Set,H=new Set,U=new Map,W=!1,G=(e,t)=>l(`hooks`,e,t);function K(e,t,n){let r=u(`p`,e,t);return n&&(r.dataset.tone=n),r}function q(e,t,n,r){let i=u(`button`,e,t);return i.type=`button`,r&&i.setAttribute(`aria-label`,r),i.addEventListener(`click`,n),i}async function Je(e,t){try{let n=await p(e,t,{timeoutMs:g});if((n.type===`save-hook-result`||n.type===`delete-hook-result`)&&n.ok)return null;let r=e===`save-hook`?`Could not save the hook.`:`Could not delete the hook.`;return`error`in n&&typeof n.error==`string`&&n.error?n.error:r}catch(e){return h(e,g)}}async function Ye(e,t,n,r){H.add(e),U.set(e,{tone:`busy`,text:r}),$({force:!0});let i=await Je(t,n);H.delete(e),i&&U.set(e,{tone:`error`,text:i}),i||U.delete(e),$({force:!0}),b()}function J(e,t,n){let r=u(`label`,`hooks-field`);return r.append(u(`span`,`hooks-field-label`,e),t),n&&r.append(u(`span`,`hooks-field-hint`,n)),r}function Y(e,t,n){let r=u(`input`,`settings-view-input`);return r.type=`text`,r.value=e,r.autocomplete=`off`,r.spellcheck=!1,t&&(r.placeholder=t),r.addEventListener(`input`,()=>n(r.value)),r}function Xe(e,t){let n=u(`textarea`,`settings-view-input hooks-command`);return n.rows=3,n.value=e,n.spellcheck=!1,n.addEventListener(`input`,()=>t(n.value)),n}function Ze(e,t,n){let r=u(`select`,`settings-view-input hooks-select`);for(let n of t){let t=u(`option`,null,n.name);t.value=n.name,t.title=n.description,n.name===e.event&&(t.selected=!0),r.append(t)}return r.addEventListener(`change`,()=>n(r.value)),r}function Qe(e,t){let n=u(`div`,`hooks-type-row`);n.setAttribute(`role`,`radiogroup`);for(let r of we){let i=u(`label`,`settings-view-toggle hooks-choice`),a=u(`input`,`settings-view-checkbox`);a.type=`radio`,a.name=`hooks-type`,a.value=r.value,a.checked=e.type===r.value,a.title=r.hint,a.addEventListener(`change`,()=>{a.checked&&t(r.value)}),i.append(a,u(`span`,null,r.label)),n.append(i)}return n}function $e(e,t){let n=u(`div`,`hooks-projects`);if(t.length===0)return n.append(u(`span`,`hooks-field-hint`,x)),n;let r=u(`label`,`settings-view-project-choice hooks-choice`),i=u(`input`,`settings-view-checkbox`);i.type=`checkbox`,i.checked=e.projects.length===0,r.append(i,u(`span`,null,x)),n.append(r);let a=[];for(let r of t){let t=u(`label`,`settings-view-project-choice hooks-choice`),o=u(`input`,`settings-view-checkbox`);o.type=`checkbox`,o.value=r.id,o.checked=e.projects.includes(r.id),o.addEventListener(`change`,()=>{e.projects=a.filter(e=>e.checked).map(e=>e.value),i.checked=e.projects.length===0}),a.push(o),t.append(o,u(`span`,null,r.name)),r.agent!==`claude-code`&&(t.append(u(`span`,`hooks-choice-note`,r.agent)),t.title=`Not a Claude Code project: this hook will not reach its sessions.`),n.append(t)}return i.addEventListener(`change`,()=>{if(!i.checked)i.checked=e.projects.length===0;else{for(let e of a)e.checked=!1;e.projects=[]}}),n}function et(e){let t=u(`div`,`hooks-templates`);t.append(u(`span`,`hooks-templates-label`,ae));for(let n of Te){let r=q(`hooks-chip`,n.label,()=>Z(null,We(n,e)));r.title=n.summary,t.append(r)}return t}function X(e){L&&(e?L.show(`error`,e):L.clear())}function tt(e){let t=T(M.report),n=ee(M.report),r=G(e.id?be:ye,xe);r.classList.add(`hooks-editor`);let i=u(`form`,`hooks-form`);i.addEventListener(`submit`,e=>{e.preventDefault(),rt()}),i.addEventListener(`keydown`,e=>{e.key===`Escape`?(e.preventDefault(),nt()):e.key===`Enter`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),rt())}),e.id||i.append(et(t));let a=u(`span`,`hooks-field-hint`,O(t,e.event)),o=Y(e.matcher,``,t=>{e.matcher=t}),s=J(`Command`,Xe(e.command,t=>{e.command=t}),`Runs through the shell with the event JSON on stdin. Exit 2 blocks the action where the event allows it.`),c=J(`URL`,Y(e.url,`http://127.0.0.1:8080/hook`,t=>{e.url=t}),`Claude Code POSTs the event JSON to it.`),l=()=>{s.hidden=e.type!==`command`,c.hidden=e.type!==`http`};l();let d=J(`Matcher`,o,null);d.append(a);let f=()=>{let n=t.find(t=>t.name===e.event);a.textContent=O(t,e.event),o.disabled=!!n&&!n.matcher,o.disabled&&(o.value=``,e.matcher=``)};f();let p=u(`input`,`settings-view-input hooks-timeout`);p.type=`number`,p.inputMode=`numeric`,p.min=`1`,p.max=String(E(M.report)),p.value=e.timeout,p.addEventListener(`input`,()=>{e.timeout=p.value});let h=u(`label`,`settings-view-toggle hooks-choice`),g=u(`input`,`settings-view-checkbox`);g.type=`checkbox`,g.checked=e.enabled,g.addEventListener(`change`,()=>{e.enabled=g.checked}),h.append(g,u(`span`,null,`Enabled`)),i.append(J(`Name`,Y(e.name,`Lint after edits`,t=>{e.name=t}),null),J(`Event`,Ze(e,t,t=>{e.event=t,f()}),null),d,J(`Type`,Qe(e,t=>{e.type=t,l()}),null),s,c,J(`Timeout (seconds)`,p,Ce),J(`Projects`,$e(e,n),null),J(``,h,null)),L=m(`hooks-editor-status`);let _=u(`div`,`hooks-editor-footer`),v=u(`span`,`hooks-editor-shortcut`,pe),y=q(`btn-dialog btn-dialog-cancel`,`Cancel`,nt),b=u(`button`,`btn-dialog btn-dialog-confirm`,e.id?`Save changes`:`Add hook`);return b.type=`submit`,R=b,_.append(L.element,v,y,b),i.append(_),r.append(i),r}function Z(e,t=null){P=t||(e?A(e):k(T(M.report))),F=j(e?A(e):k(T(M.report))),I=tt(P),$({force:!0}),I.scrollIntoView({block:`nearest`});let n=I.querySelector(`input[type=text]`);n instanceof HTMLInputElement&&n.focus()}function Q(){P=null,F=null,I=null,L=null,R=null,z=!1,W=!0,$({force:!0})}function nt(){!P||!F||!Ge(P,F)?Q():_({title:de,message:fe,confirmLabel:`Discard`,danger:!0,onConfirm:Q})}async function rt(){if(!P||z)return;let e=Ue(P,T(M.report),E(M.report));if(e){X(e);return}let t=L,n=R;z=!0,t?.show(`busy`,`Saving the hook.`),n&&(n.disabled=!0);let r=await Je(`save-hook`,{hook:j(P)});z=!1,n&&(n.disabled=!1),t===L&&(r?X(r):(Q(),b()))}function it(e){let t=u(`details`,`hooks-preview`);t.open=V.has(e.id),t.addEventListener(`toggle`,()=>{t.open?V.add(e.id):V.delete(e.id)});let n=u(`summary`,`hooks-preview-summary`,ce);n.title=le;let r=u(`pre`,`hooks-preview-code`,Pe(e));return t.append(n,r),t}function at(e,{grouped:t=!1}={}){let n=ee(M.report),r=u(`article`,`hooks-row`);r.setAttribute(`aria-label`,e.name),e.enabled===!1&&(r.dataset.state=`off`);let i=u(`div`,`hooks-row-main`),a=u(`div`,`hooks-row-head`);a.append(u(`span`,`hooks-row-name`,e.name));let o=t?e.matcher||``:Be(e);o&&a.append(u(`span`,`hooks-row-event`,o));let s=u(`code`,`hooks-row-target`,Ie(e));s.title=Ie(e);let c=u(`p`,`hooks-row-meta`,[Le(e.type),Re(e),ze(e,n)].filter(Boolean).join(` / `));i.append(a,s,c);let l=He(e,n);l.length>0&&i.append(K(`hooks-row-meta`,`Scoped to a project no longer in config: ${l.join(`, `)}`,`warn`)),i.append(it(e));let d=U.get(e.id);if(d){let e=m(`hooks-row-status`);e.show(d.tone,d.text),i.append(e.element)}let f=u(`div`,`hooks-row-actions`),p=u(`label`,`settings-view-toggle hooks-choice`),h=u(`input`,`settings-view-checkbox`);h.type=`checkbox`,h.checked=e.enabled!==!1,h.disabled=H.has(e.id),h.setAttribute(`aria-label`,`${e.name} enabled`),h.addEventListener(`change`,()=>{Ye(e.id,`save-hook`,{hook:Ke(e)},h.checked?`Turning the hook on.`:`Turning the hook off.`)}),p.append(h,u(`span`,null,`On`));let g=q(`hooks-btn`,`Edit`,()=>Z(e),`Edit ${e.name}`),v=q(`hooks-btn`,ue,()=>{let t=A({...e,name:Fe(e.name)});t.id=null,Z(null,t)},`Duplicate ${e.name}`),y=q(`hooks-btn hooks-btn-danger`,`Delete`,()=>{_({title:`Delete hook`,message:qe(e),confirmLabel:`Delete`,danger:!0,onConfirm:()=>{Ye(e.id,`delete-hook`,{id:e.id},`Deleting the hook.`)}})},`Delete ${e.name}`);return y.disabled=H.has(e.id),f.append(p,g,v,y),r.append(i,f),r}function ot(e){let t=u(`article`,`hooks-row hooks-row-builtin`),n=u(`div`,`hooks-row-main`);return n.append(u(`span`,`hooks-row-event`,Ve(e)),u(`p`,`hooks-row-meta`,e.purpose)),t.append(n),t}function st(){let e=G(`Hooks`,ne),t=u(`div`,`hooks-stats`);for(let e of ke(M.report))t.append(d(`hooks`,e.label,e.value,e.tone));return e.append(t,K(`hooks-meta`,he)),e}function ct(){let e=u(`input`,`settings-view-input hooks-filter`);return e.type=`search`,e.value=B,e.placeholder=oe,e.setAttribute(`aria-label`,oe),e.addEventListener(`input`,()=>{B=e.value;let t=N?.querySelector(`.hooks-list-yours`);t&&t.replaceWith(ut())}),e}function lt(){let e=u(`div`,`hooks-empty-state`);return e.append(K(`hooks-empty`,ie),et(T(M.report))),e}function ut(){let e=u(`div`,`hooks-list-yours`),t=C(M.report);if(t.length===0)return e.append(lt()),e;let n=je(Ae(t,T(M.report)),B);if(n.length===0)return e.append(K(`hooks-empty`,se)),e;for(let t of Ne(n)){let n=u(`div`,`hooks-group`);n.append(u(`h3`,`hooks-group-title`,t.event));let r=u(`div`,`hooks-list`);for(let e of t.hooks)r.append(at(e,{grouped:!0}));n.append(r),e.append(n)}return e}function dt(){let e=G(ve,null),t=q(`hooks-btn hooks-btn-add`,`+ New hook`,()=>Z(null));t.disabled=!!P;let n=e.querySelector(`.hooks-section-head`);return n&&n.append(t),Me(C(M.report))&&e.append(ct()),e.append(ut()),e}function ft(){let e=u(`details`,`hooks-builtin`),t=u(`summary`,`hooks-builtin-summary`);t.append(u(`span`,`hooks-section-title`,`${ge} (${w(M.report).length})`),u(`span`,`hooks-section-hint`,_e));let n=u(`div`,`hooks-list`);for(let e of w(M.report))n.append(ot(e));return e.append(t,n),e}function pt(){let e=u(`div`,`hooks-content`);return M.report?De(M.report)?(e.append(K(`hooks-warning`,Oe(M.report))),e):(e.append(st()),I&&e.append(I),e.append(dt(),ft()),e):(e.append(M.hasReportSendFailed?K(`hooks-warning`,c):K(`hooks-empty`,re)),e)}function $({force:e=!1}={}){if(!N||!e&&f(N)||(M=y(),N.replaceChildren(pt()),!W))return;W=!1;let t=N.querySelector(`.hooks-btn-add`);t instanceof HTMLButtonElement&&t.focus()}function mt(e){N||(N=u(`div`,`hooks-panel`),e.append(N),v(()=>$()),$({force:!0}))}function ht(e){e===`shown`&&$({force:!0}),b()}var gt={mount:mt,refresh:ht};export{gt as view};
1
+ import{_ as e,a as t,f as n,l as r,m as i,n as a,r as o,u as s}from"./zod-BRLv4KqJ.js";import{C as c,n as l,o as u,p as ee,r as d,u as f}from"./dom-helpers-B98sy9ep.js";import{u as p}from"./control-ws-C8SS9PPx.js";import{i as m,s as h,t as g}from"./action-status-DmJCv-Ib.js";import{a as _}from"./modal-5t7_5VCF.js";import{Ht as v,Ut as y,Wt as b}from"./index-CHUWzO2K.js";var te=n(i(),e());s({glimmervoidId:i().min(1),event:i().min(1),token:i().nullable().optional(),payload:te}),s({id:i().min(1),name:i().min(1),event:i().min(1),matcher:i().optional(),type:a([`command`,`http`]),command:i().optional(),url:i().optional(),timeout:r().int().positive().optional(),enabled:t(),projects:o(i()).optional()}).passthrough();var ne=`Claude Code hooks injected into every session Glimmervoid spawns.`,re=`Loading hooks`,ie=`No hooks yet. A hook runs a command, or calls a URL, when a Claude Code event fires in a Glimmervoid session. Start from one of these, or add your own.`,ae=`Start from`,oe=`Filter by name, event or command`,se=`Nothing matches that filter.`,ce=`Preview`,le=`The entry this becomes in the per-session settings file.`,ue=`Duplicate`,de=`Discard changes`,fe=`Close the editor and lose the unsaved changes?`,pe=`Esc cancels. Ctrl+Enter saves.`,me=4,he=`A change reaches a session at its next start or restart. Claude Code sessions only; Codex and Grok sessions do not read this file.`,ge=`Glimmervoid's own hooks`,_e=`Always present, read-only. Status detection depends on them.`,ve=`Your hooks`,ye=`New hook`,be=`Edit hook`,xe=`Saved to config.json.`,x=`All projects`,Se=`This event takes no matcher.`,Ce=`Blank uses Claude Code's default for the event.`,we=Object.freeze([{value:`command`,label:`Command`,hint:`Run a shell command. It receives the event JSON on stdin.`},{value:`http`,label:`HTTP`,hint:`POST the event JSON to a URL.`}]),Te=Object.freeze([{id:`lint`,label:`Lint after edits`,summary:`PostToolUse on Edit|Write`,draft:{name:`Lint after edits`,event:`PostToolUse`,matcher:`Edit|Write`,type:`command`,command:`npx biome check --write "$(jq -r .tool_input.file_path)"`}},{id:`notify`,label:`Notify on Stop`,summary:`Stop, command`,draft:{name:`Notify on Stop`,event:`Stop`,matcher:``,type:`command`,command:`command -v notify-send >/dev/null 2>&1 && notify-send "Claude finished a turn" || { command -v osascript >/dev/null 2>&1 && osascript -e 'display notification "Claude finished a turn" with title "Claude Code"'; }`}},{id:`guard`,label:`Guard destructive Bash`,summary:`PreToolUse on Bash, exit 2 blocks`,draft:{name:`Guard destructive Bash`,event:`PreToolUse`,matcher:`Bash`,type:`command`,command:`jq -r .tool_input.command | grep -Eq "rm -rf|git push --force" && exit 2 || exit 0`}},{id:`log`,label:`Log every prompt`,summary:`UserPromptSubmit, appends JSON`,draft:{name:`Log every prompt`,event:`UserPromptSubmit`,matcher:``,type:`command`,command:`cat >> ~/.claude/prompts.jsonl`}}]),Ee=Object.freeze({hooks:[],builtin:[],events:[]});function De(e){return!e||typeof e.error==`string`}function Oe(e){return!e||typeof e.error!=`string`?``:e.error}function S(e,t){let n=e?.[t];return Array.isArray(n)?n:Ee[t]}var C=e=>S(e,`hooks`),w=e=>S(e,`builtin`),T=e=>S(e,`events`);function E(e){let t=e?.limits?.maxTimeoutSec;return typeof t==`number`&&Number.isInteger(t)&&t>0?t:600}function ke(e){let t=C(e),n=t.filter(e=>e.enabled!==!1).length;return[{label:`yours`,value:String(t.length),tone:null},{label:`enabled`,value:String(n),tone:t.length>0&&n===0?`warn`:null},{label:`built in`,value:String(w(e).length),tone:null}]}function Ae(e,t){let n=new Map(t.map((e,t)=>[e.name,t])),r=e=>n.get(e.event)??t.length;return[...e].sort((e,t)=>{let n=r(e)-r(t);return n===0?String(e.name).localeCompare(String(t.name)):n})}function je(e,t){let n=String(t||``).trim().toLowerCase();return n?e.filter(e=>[e.name,e.event,e.matcher,e.command,e.url].some(e=>typeof e==`string`&&e.toLowerCase().includes(n))):e}function Me(e){return e.length>=me}function Ne(e){let t=[];for(let n of e){let e=t[t.length-1];e&&e.event===n.event?e.hooks.push(n):t.push({event:n.event,hooks:[n]})}return t}function Pe(e){let t=e.type===`http`?{type:`http`,url:e.url||``}:{type:`command`,command:e.command||``};Number.isInteger(e.timeout)&&Number(e.timeout)>0&&(t.timeout=e.timeout);let n=e.matcher?{matcher:e.matcher,hooks:[t]}:{hooks:[t]};return JSON.stringify({hooks:{[e.event]:[n]}},null,2)}function Fe(e){return`${e} copy`}function D(e,t){return e.find(e=>e.name===t)||null}function O(e,t){let n=D(e,t);return n?n.matcher?`Matches ${n.matcher}. Blank matches every ${n.name}.`:Se:``}function Ie(e){return e.type===`http`?e.url||``:e.command||``}function Le(e){let t=we.find(t=>t.value===e);return t?t.label:String(e||``)}function Re(e){return!Number.isInteger(e.timeout)||Number(e.timeout)<=0?``:`${e.timeout}s timeout`}function ze(e,t){let n=Array.isArray(e.projects)?e.projects:[];return n.length===0?x:n.map(e=>{let n=t.find(t=>t.id===e);return n?n.name:e}).join(`, `)}function Be(e){return e.matcher?`${e.event} / ${e.matcher}`:e.event}function Ve(e){return Be(e)}function He(e,t){let n=Array.isArray(e.projects)?e.projects:[],r=new Set(t.map(e=>e.id));return n.filter(e=>!r.has(e))}function k(e){let t=e[0];return{id:null,name:``,event:t?t.name:``,matcher:``,type:`command`,command:``,url:``,timeout:``,enabled:!0,projects:[]}}function A(e){return{id:e.id??null,name:e.name||``,event:e.event||``,matcher:e.matcher||``,type:e.type===`http`?`http`:`command`,command:e.command||``,url:e.url||``,timeout:Number.isInteger(e.timeout)?String(e.timeout):``,enabled:e.enabled!==!1,projects:Array.isArray(e.projects)?[...e.projects]:[]}}function Ue(e,t,n=600){if(!e.name.trim())return`Give the hook a name.`;let r=D(t,e.event);if(!r)return`Pick an event.`;if(e.matcher.trim()&&!r.matcher)return`${r.name} takes no matcher.`;if(e.type===`http`&&r.http===!1)return`${r.name} does not support HTTP hooks.`;if(e.type===`command`&&!e.command.trim())return`Enter the command to run.`;if(e.type===`http`&&!/^https?:\/\/\S+$/i.test(e.url.trim()))return`Enter a URL starting with http:// or https://.`;if(e.timeout.trim()!==``){let t=Number(e.timeout);if(!Number.isInteger(t)||t<1||t>n)return`Timeout must be a whole number of seconds from 1 to ${n}.`}return null}function j(e){let t={name:e.name.trim(),event:e.event,type:e.type,enabled:e.enabled!==!1};return e.id&&(t.id=e.id),e.matcher.trim()&&(t.matcher=e.matcher.trim()),e.type===`command`&&(t.command=e.command.trim()),e.type===`http`&&(t.url=e.url.trim()),e.timeout.trim()!==``&&(t.timeout=Number(e.timeout)),e.projects.length>0&&(t.projects=[...e.projects]),t}function We(e,t){let n={...k(t),...e.draft};return D(t,n.event)||(n.event=k(t).event),n}function Ge(e,t){return JSON.stringify(j(e))!==JSON.stringify(t)}function Ke(e){return{...e,enabled:e.enabled===!1}}function qe(e){return`Delete the hook "${e.name}"? Sessions already running keep it until they restart.`}var M=v(),N=null,P=null,F=null,I=null,L=null,R=null,z=!1,B=``,V=new Set,H=new Set,U=new Map,W=!1,G=(e,t)=>l(`hooks`,e,t);function K(e,t,n){let r=u(`p`,e,t);return n&&(r.dataset.tone=n),r}function q(e,t,n,r){let i=u(`button`,e,t);return i.type=`button`,r&&i.setAttribute(`aria-label`,r),i.addEventListener(`click`,n),i}async function Je(e,t){try{let n=await p(e,t,{timeoutMs:g});if((n.type===`save-hook-result`||n.type===`delete-hook-result`)&&n.ok)return null;let r=e===`save-hook`?`Could not save the hook.`:`Could not delete the hook.`;return`error`in n&&typeof n.error==`string`&&n.error?n.error:r}catch(e){return h(e,g)}}async function Ye(e,t,n,r){H.add(e),U.set(e,{tone:`busy`,text:r}),$({force:!0});let i=await Je(t,n);H.delete(e),i&&U.set(e,{tone:`error`,text:i}),i||U.delete(e),$({force:!0}),y()}function J(e,t,n){let r=u(`label`,`hooks-field`);return r.append(u(`span`,`hooks-field-label`,e),t),n&&r.append(u(`span`,`hooks-field-hint`,n)),r}function Y(e,t,n){let r=u(`input`,`settings-view-input`);return r.type=`text`,r.value=e,r.autocomplete=`off`,r.spellcheck=!1,t&&(r.placeholder=t),r.addEventListener(`input`,()=>n(r.value)),r}function Xe(e,t){let n=u(`textarea`,`settings-view-input hooks-command`);return n.rows=3,n.value=e,n.spellcheck=!1,n.addEventListener(`input`,()=>t(n.value)),n}function Ze(e,t,n){let r=u(`select`,`settings-view-input hooks-select`);for(let n of t){let t=u(`option`,null,n.name);t.value=n.name,t.title=n.description,n.name===e.event&&(t.selected=!0),r.append(t)}return r.addEventListener(`change`,()=>n(r.value)),r}function Qe(e,t){let n=u(`div`,`hooks-type-row`);n.setAttribute(`role`,`radiogroup`);for(let r of we){let i=u(`label`,`settings-view-toggle hooks-choice`),a=u(`input`,`settings-view-checkbox`);a.type=`radio`,a.name=`hooks-type`,a.value=r.value,a.checked=e.type===r.value,a.title=r.hint,a.addEventListener(`change`,()=>{a.checked&&t(r.value)}),i.append(a,u(`span`,null,r.label)),n.append(i)}return n}function $e(e,t){let n=u(`div`,`hooks-projects`);if(t.length===0)return n.append(u(`span`,`hooks-field-hint`,x)),n;let r=u(`label`,`settings-view-project-choice hooks-choice`),i=u(`input`,`settings-view-checkbox`);i.type=`checkbox`,i.checked=e.projects.length===0,r.append(i,u(`span`,null,x)),n.append(r);let a=[];for(let r of t){let t=u(`label`,`settings-view-project-choice hooks-choice`),o=u(`input`,`settings-view-checkbox`);o.type=`checkbox`,o.value=r.id,o.checked=e.projects.includes(r.id),o.addEventListener(`change`,()=>{e.projects=a.filter(e=>e.checked).map(e=>e.value),i.checked=e.projects.length===0}),a.push(o),t.append(o,u(`span`,null,r.name)),r.agent!==`claude-code`&&(t.append(u(`span`,`hooks-choice-note`,r.agent)),t.title=`Not a Claude Code project: this hook will not reach its sessions.`),n.append(t)}return i.addEventListener(`change`,()=>{if(!i.checked)i.checked=e.projects.length===0;else{for(let e of a)e.checked=!1;e.projects=[]}}),n}function et(e){let t=u(`div`,`hooks-templates`);t.append(u(`span`,`hooks-templates-label`,ae));for(let n of Te){let r=q(`hooks-chip`,n.label,()=>Z(null,We(n,e)));r.title=n.summary,t.append(r)}return t}function X(e){L&&(e?L.show(`error`,e):L.clear())}function tt(e){let t=T(M.report),n=ee(M.report),r=G(e.id?be:ye,xe);r.classList.add(`hooks-editor`);let i=u(`form`,`hooks-form`);i.addEventListener(`submit`,e=>{e.preventDefault(),rt()}),i.addEventListener(`keydown`,e=>{e.key===`Escape`?(e.preventDefault(),nt()):e.key===`Enter`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),rt())}),e.id||i.append(et(t));let a=u(`span`,`hooks-field-hint`,O(t,e.event)),o=Y(e.matcher,``,t=>{e.matcher=t}),s=J(`Command`,Xe(e.command,t=>{e.command=t}),`Runs through the shell with the event JSON on stdin. Exit 2 blocks the action where the event allows it.`),c=J(`URL`,Y(e.url,`http://127.0.0.1:8080/hook`,t=>{e.url=t}),`Claude Code POSTs the event JSON to it.`),l=()=>{s.hidden=e.type!==`command`,c.hidden=e.type!==`http`};l();let d=J(`Matcher`,o,null);d.append(a);let f=()=>{let n=t.find(t=>t.name===e.event);a.textContent=O(t,e.event),o.disabled=!!n&&!n.matcher,o.disabled&&(o.value=``,e.matcher=``)};f();let p=u(`input`,`settings-view-input hooks-timeout`);p.type=`number`,p.inputMode=`numeric`,p.min=`1`,p.max=String(E(M.report)),p.value=e.timeout,p.addEventListener(`input`,()=>{e.timeout=p.value});let h=u(`label`,`settings-view-toggle hooks-choice`),g=u(`input`,`settings-view-checkbox`);g.type=`checkbox`,g.checked=e.enabled,g.addEventListener(`change`,()=>{e.enabled=g.checked}),h.append(g,u(`span`,null,`Enabled`)),i.append(J(`Name`,Y(e.name,`Lint after edits`,t=>{e.name=t}),null),J(`Event`,Ze(e,t,t=>{e.event=t,f()}),null),d,J(`Type`,Qe(e,t=>{e.type=t,l()}),null),s,c,J(`Timeout (seconds)`,p,Ce),J(`Projects`,$e(e,n),null),J(``,h,null)),L=m(`hooks-editor-status`);let _=u(`div`,`hooks-editor-footer`),v=u(`span`,`hooks-editor-shortcut`,pe),y=q(`btn-dialog btn-dialog-cancel`,`Cancel`,nt),b=u(`button`,`btn-dialog btn-dialog-confirm`,e.id?`Save changes`:`Add hook`);return b.type=`submit`,R=b,_.append(L.element,v,y,b),i.append(_),r.append(i),r}function Z(e,t=null){P=t||(e?A(e):k(T(M.report))),F=j(e?A(e):k(T(M.report))),I=tt(P),$({force:!0}),I.scrollIntoView({block:`nearest`});let n=I.querySelector(`input[type=text]`);n instanceof HTMLInputElement&&n.focus()}function Q(){P=null,F=null,I=null,L=null,R=null,z=!1,W=!0,$({force:!0})}function nt(){!P||!F||!Ge(P,F)?Q():_({title:de,message:fe,confirmLabel:`Discard`,danger:!0,onConfirm:Q})}async function rt(){if(!P||z)return;let e=Ue(P,T(M.report),E(M.report));if(e){X(e);return}let t=L,n=R;z=!0,t?.show(`busy`,`Saving the hook.`),n&&(n.disabled=!0);let r=await Je(`save-hook`,{hook:j(P)});z=!1,n&&(n.disabled=!1),t===L&&(r?X(r):(Q(),y()))}function it(e){let t=u(`details`,`hooks-preview`);t.open=V.has(e.id),t.addEventListener(`toggle`,()=>{t.open?V.add(e.id):V.delete(e.id)});let n=u(`summary`,`hooks-preview-summary`,ce);n.title=le;let r=u(`pre`,`hooks-preview-code`,Pe(e));return t.append(n,r),t}function at(e,{grouped:t=!1}={}){let n=ee(M.report),r=u(`article`,`hooks-row`);r.setAttribute(`aria-label`,e.name),e.enabled===!1&&(r.dataset.state=`off`);let i=u(`div`,`hooks-row-main`),a=u(`div`,`hooks-row-head`);a.append(u(`span`,`hooks-row-name`,e.name));let o=t?e.matcher||``:Be(e);o&&a.append(u(`span`,`hooks-row-event`,o));let s=u(`code`,`hooks-row-target`,Ie(e));s.title=Ie(e);let c=u(`p`,`hooks-row-meta`,[Le(e.type),Re(e),ze(e,n)].filter(Boolean).join(` / `));i.append(a,s,c);let l=He(e,n);l.length>0&&i.append(K(`hooks-row-meta`,`Scoped to a project no longer in config: ${l.join(`, `)}`,`warn`)),i.append(it(e));let d=U.get(e.id);if(d){let e=m(`hooks-row-status`);e.show(d.tone,d.text),i.append(e.element)}let f=u(`div`,`hooks-row-actions`),p=u(`label`,`settings-view-toggle hooks-choice`),h=u(`input`,`settings-view-checkbox`);h.type=`checkbox`,h.checked=e.enabled!==!1,h.disabled=H.has(e.id),h.setAttribute(`aria-label`,`${e.name} enabled`),h.addEventListener(`change`,()=>{Ye(e.id,`save-hook`,{hook:Ke(e)},h.checked?`Turning the hook on.`:`Turning the hook off.`)}),p.append(h,u(`span`,null,`On`));let g=q(`hooks-btn`,`Edit`,()=>Z(e),`Edit ${e.name}`),v=q(`hooks-btn`,ue,()=>{let t=A({...e,name:Fe(e.name)});t.id=null,Z(null,t)},`Duplicate ${e.name}`),y=q(`hooks-btn hooks-btn-danger`,`Delete`,()=>{_({title:`Delete hook`,message:qe(e),confirmLabel:`Delete`,danger:!0,onConfirm:()=>{Ye(e.id,`delete-hook`,{id:e.id},`Deleting the hook.`)}})},`Delete ${e.name}`);return y.disabled=H.has(e.id),f.append(p,g,v,y),r.append(i,f),r}function ot(e){let t=u(`article`,`hooks-row hooks-row-builtin`),n=u(`div`,`hooks-row-main`);return n.append(u(`span`,`hooks-row-event`,Ve(e)),u(`p`,`hooks-row-meta`,e.purpose)),t.append(n),t}function st(){let e=G(`Hooks`,ne),t=u(`div`,`hooks-stats`);for(let e of ke(M.report))t.append(d(`hooks`,e.label,e.value,e.tone));return e.append(t,K(`hooks-meta`,he)),e}function ct(){let e=u(`input`,`settings-view-input hooks-filter`);return e.type=`search`,e.value=B,e.placeholder=oe,e.setAttribute(`aria-label`,oe),e.addEventListener(`input`,()=>{B=e.value;let t=N?.querySelector(`.hooks-list-yours`);t&&t.replaceWith(ut())}),e}function lt(){let e=u(`div`,`hooks-empty-state`);return e.append(K(`hooks-empty`,ie),et(T(M.report))),e}function ut(){let e=u(`div`,`hooks-list-yours`),t=C(M.report);if(t.length===0)return e.append(lt()),e;let n=je(Ae(t,T(M.report)),B);if(n.length===0)return e.append(K(`hooks-empty`,se)),e;for(let t of Ne(n)){let n=u(`div`,`hooks-group`);n.append(u(`h3`,`hooks-group-title`,t.event));let r=u(`div`,`hooks-list`);for(let e of t.hooks)r.append(at(e,{grouped:!0}));n.append(r),e.append(n)}return e}function dt(){let e=G(ve,null),t=q(`hooks-btn hooks-btn-add`,`+ New hook`,()=>Z(null));t.disabled=!!P;let n=e.querySelector(`.hooks-section-head`);return n&&n.append(t),Me(C(M.report))&&e.append(ct()),e.append(ut()),e}function ft(){let e=u(`details`,`hooks-builtin`),t=u(`summary`,`hooks-builtin-summary`);t.append(u(`span`,`hooks-section-title`,`${ge} (${w(M.report).length})`),u(`span`,`hooks-section-hint`,_e));let n=u(`div`,`hooks-list`);for(let e of w(M.report))n.append(ot(e));return e.append(t,n),e}function pt(){let e=u(`div`,`hooks-content`);return M.report?De(M.report)?(e.append(K(`hooks-warning`,Oe(M.report))),e):(e.append(st()),I&&e.append(I),e.append(dt(),ft()),e):(e.append(M.hasReportSendFailed?K(`hooks-warning`,c):K(`hooks-empty`,re)),e)}function $({force:e=!1}={}){if(!N||!e&&f(N)||(M=v(),N.replaceChildren(pt()),!W))return;W=!1;let t=N.querySelector(`.hooks-btn-add`);t instanceof HTMLButtonElement&&t.focus()}function mt(e){N||(N=u(`div`,`hooks-panel`),e.append(N),b(()=>$()),$({force:!0}))}function ht(e){e===`shown`&&$({force:!0}),y()}var gt={mount:mt,refresh:ht};export{gt as view};