@solongate/proxy 0.82.52 → 0.82.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9224,6 +9224,7 @@ function PoliciesPanel({ focused }) {
9224
9224
  const [status, setStatus] = useState4(null);
9225
9225
  const [pendingDel, setPendingDel] = useState4(null);
9226
9226
  const [permCursor, setPermCursor] = useState4(0);
9227
+ const [matchSel, setMatchSel] = useState4(0);
9227
9228
  const [busyCreate, setBusyCreate] = useState4(false);
9228
9229
  const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
9229
9230
  const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
@@ -9388,6 +9389,43 @@ function PoliciesPanel({ focused }) {
9388
9389
  else if (input === "x") discard();
9389
9390
  return;
9390
9391
  }
9392
+ if (view === "match") {
9393
+ const r = rules[ri];
9394
+ if (!r) return setView("rules");
9395
+ const items = matchItems(r);
9396
+ if (key.leftArrow || key.escape) return setView("rule");
9397
+ if (key.upArrow) setMatchSel((n) => Math.max(0, n - 1));
9398
+ else if (key.downArrow) setMatchSel((n) => Math.min(Math.max(0, items.length - 1), n + 1));
9399
+ else if (input === "a") {
9400
+ const next = [...items, ""];
9401
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
9402
+ setMatchSel(next.length - 1);
9403
+ setEditVal("");
9404
+ setEditing(true);
9405
+ } else if (key.return || input === "e") {
9406
+ if (items.length === 0) {
9407
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, [""]) : x));
9408
+ setMatchSel(0);
9409
+ setEditVal("");
9410
+ } else {
9411
+ setEditVal(items[matchSel] ?? "");
9412
+ }
9413
+ setEditing(true);
9414
+ } else if (input === "[" || input === "]") {
9415
+ const side = input === "[" ? "left" : "right";
9416
+ if (items[matchSel] != null) {
9417
+ const next = items.map((v, i) => i === matchSel ? flipStar(v, side) : v);
9418
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
9419
+ }
9420
+ } else if (input === "d") {
9421
+ if (items.length) {
9422
+ const next = items.filter((_, i) => i !== matchSel);
9423
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
9424
+ setMatchSel((n) => Math.max(0, Math.min(n, next.length - 1)));
9425
+ }
9426
+ } else if (input === "s") void save();
9427
+ return;
9428
+ }
9391
9429
  const rule2 = rules[ri];
9392
9430
  if (!rule2) return setView("rules");
9393
9431
  const field = FIELDS[fi];
@@ -9409,14 +9447,13 @@ function PoliciesPanel({ focused }) {
9409
9447
  } else if (field.kind === "perms" && input === " ") {
9410
9448
  const p = PERMS[permCursor % PERMS.length];
9411
9449
  mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
9412
- } else if (field.kind === "match" && input === "[") {
9413
- mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "left") : rr));
9414
- } else if (field.kind === "match" && input === "]") {
9415
- mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "right") : rr));
9450
+ } else if (field.kind === "match" && (key.return || key.rightArrow)) {
9451
+ setMatchSel(0);
9452
+ setView("match");
9416
9453
  } else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
9417
9454
  const d = key.rightArrow ? 1 : -1;
9418
9455
  mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
9419
- } else if ((field.kind === "text" || field.kind === "match") && key.return) {
9456
+ } else if (field.kind === "text" && key.return) {
9420
9457
  setEditVal(field.get(rule2));
9421
9458
  setEditing(true);
9422
9459
  } else if (input === "s") void save();
@@ -9510,6 +9547,59 @@ function PoliciesPanel({ focused }) {
9510
9547
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
9511
9548
  ] }) });
9512
9549
  }
9550
+ if (view === "match") {
9551
+ const r = rules[ri];
9552
+ const items = r ? matchItems(r) : [];
9553
+ const t = r ? currentCType(r) : "none";
9554
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
9555
+ /* @__PURE__ */ jsxs4(Box4, { children: [
9556
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: theme.accentBright, children: "Match values " }),
9557
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: r ? `${r.effect} \xB7 ${t}` : "" }),
9558
+ dirtyTag
9559
+ ] }),
9560
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 select \xB7 enter/e edit \xB7 a add \xB7 [ / ] wildcard L/R \xB7 d remove \xB7 s save \xB7 \u2190 back" }),
9561
+ /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
9562
+ items.length === 0 ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "(no values \u2014 press a to add one)" }) : null,
9563
+ items.map((it, i) => {
9564
+ const sel = i === matchSel;
9565
+ if (sel && editing) {
9566
+ const lE = editVal.startsWith("*");
9567
+ const rE = editVal.length > 0 && editVal.endsWith("*");
9568
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
9569
+ /* @__PURE__ */ jsx4(Text4, { color: theme.accentBright, children: "\u25B8 " }),
9570
+ /* @__PURE__ */ jsx4(Text4, { color: lE ? theme.ok : theme.dim, children: lE ? "\u2731 " : "\xB7 " }),
9571
+ /* @__PURE__ */ jsx4(
9572
+ TextInput3,
9573
+ {
9574
+ value: editVal,
9575
+ onChange: setEditVal,
9576
+ onSubmit: (v) => {
9577
+ const val = v.trim();
9578
+ let next = items.map((x, idx) => idx === i ? val : x);
9579
+ if (val === "") next = next.filter((_, idx) => idx !== i);
9580
+ mutate(rules.map((x, idx) => idx === ri ? setMatchItems(x, next) : x));
9581
+ setMatchSel((n) => Math.max(0, Math.min(n, next.length - 1)));
9582
+ setEditing(false);
9583
+ }
9584
+ }
9585
+ ),
9586
+ /* @__PURE__ */ jsx4(Text4, { color: rE ? theme.ok : theme.dim, children: rE ? " \u2731" : " \xB7" })
9587
+ ] }, i);
9588
+ }
9589
+ const lOn = it.startsWith("*");
9590
+ const rOn = it.length > 0 && it.endsWith("*");
9591
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
9592
+ /* @__PURE__ */ jsx4(Text4, { color: sel ? theme.accentBright : void 0, children: sel ? "\u25B8 " : " " }),
9593
+ /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
9594
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !it, children: it || "(empty)" }),
9595
+ /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
9596
+ ] }, i);
9597
+ })
9598
+ ] }),
9599
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (any run of chars). Type it directly (rm*) or toggle with [ / ]. Green \u2731 = active \xB7 left & right shown as you type. Multiple values = OR (any one matches)." }),
9600
+ status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
9601
+ ] });
9602
+ }
9513
9603
  const rule = rules[ri];
9514
9604
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
9515
9605
  /* @__PURE__ */ jsxs4(Box4, { children: [
@@ -9517,7 +9607,7 @@ function PoliciesPanel({ focused }) {
9517
9607
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
9518
9608
  dirtyTag
9519
9609
  ] }),
9520
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 [ ] wildcards \xB7 s save \xB7 \u2190 back" }),
9610
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit/open \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 s save \xB7 \u2190 back" }),
9521
9611
  /* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
9522
9612
  const active2 = i === fi;
9523
9613
  const label = /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) });
@@ -9535,30 +9625,12 @@ function PoliciesPanel({ focused }) {
9535
9625
  ] }, f.label);
9536
9626
  }
9537
9627
  if (f.kind === "match" && rule) {
9538
- if (active2 && editing) {
9539
- return /* @__PURE__ */ jsxs4(Box4, { children: [
9540
- label,
9541
- /* @__PURE__ */ jsx4(
9542
- TextInput3,
9543
- {
9544
- value: editVal,
9545
- onChange: setEditVal,
9546
- onSubmit: (v2) => {
9547
- if (f.set) mutate(rules.map((r, idx) => idx === ri ? f.set(r, v2) : r));
9548
- setEditing(false);
9549
- }
9550
- }
9551
- )
9552
- ] }, f.label);
9553
- }
9554
- const v = f.get(rule);
9555
- const lOn = starActive(rule, "left");
9556
- const rOn = starActive(rule, "right");
9628
+ const items = matchItems(rule);
9629
+ const preview = items.join(", ");
9557
9630
  return /* @__PURE__ */ jsxs4(Box4, { children: [
9558
9631
  label,
9559
- /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
9560
- /* @__PURE__ */ jsx4(Text4, { dimColor: !v, children: v || "\u2014" }),
9561
- /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
9632
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !preview, children: preview || "\u2014" }),
9633
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: items.length ? ` (${items.length} value${items.length > 1 ? "s" : ""} \xB7 enter: edit)` : " (enter: add values)" })
9562
9634
  ] }, f.label);
9563
9635
  }
9564
9636
  const val = rule ? f.get(rule) : "";
@@ -9584,11 +9656,10 @@ function PoliciesPanel({ focused }) {
9584
9656
  )
9585
9657
  ] }, f.label);
9586
9658
  }) }),
9587
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (matches any run of chars). On Match: [ toggles a leading *, ] a trailing * \xB7 e.g. *ping* matches any command containing ping" }),
9588
9659
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
9589
9660
  ] });
9590
9661
  }
9591
- var CTYPES, CTYPE_GROUP, currentCType, clearConstraints, setCType, cValue, setCValue, matchItems, starActive, toggleStar, migrateEffect, PERMS, permList, permIsAny, togglePerm, permDisplay, ruleHasValues, isBlanketRule, FIELDS;
9662
+ var CTYPES, CTYPE_GROUP, currentCType, clearConstraints, setCType, cValue, setCValue, matchItems, setMatchItems, flipStar, migrateEffect, PERMS, permList, permIsAny, togglePerm, permDisplay, ruleHasValues, isBlanketRule, FIELDS;
9592
9663
  var init_Policies = __esm({
9593
9664
  "src/tui/panels/Policies.tsx"() {
9594
9665
  "use strict";
@@ -9644,20 +9715,13 @@ var init_Policies = __esm({
9644
9715
  const c2 = r[CTYPE_GROUP[t]];
9645
9716
  return [...c2?.allowed ?? [], ...c2?.denied ?? []];
9646
9717
  };
9647
- starActive = (r, side) => {
9648
- const items = matchItems(r);
9649
- return items.length > 0 && items.every((v) => side === "left" ? v.startsWith("*") : v.endsWith("*"));
9650
- };
9651
- toggleStar = (r, side) => {
9718
+ setMatchItems = (r, items) => {
9652
9719
  const t = currentCType(r);
9653
9720
  if (t === "none") return r;
9654
- const on = starActive(r, side);
9655
9721
  const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
9656
- const items = matchItems(r).map(
9657
- (v) => side === "left" ? on ? v.replace(/^\*+/, "") : "*" + v : on ? v.replace(/\*+$/, "") : v + "*"
9658
- );
9659
9722
  return { ...r, [CTYPE_GROUP[t]]: { [listKey]: items } };
9660
9723
  };
9724
+ flipStar = (v, side) => side === "left" ? v.startsWith("*") ? v.replace(/^\*+/, "") : "*" + v : v.endsWith("*") ? v.replace(/\*+$/, "") : v + "*";
9661
9725
  migrateEffect = (r, nextEffect) => {
9662
9726
  const flipped = { ...r, effect: nextEffect };
9663
9727
  const t = currentCType(r);
package/dist/tui/index.js CHANGED
@@ -2466,20 +2466,13 @@ var matchItems = (r) => {
2466
2466
  const c2 = r[CTYPE_GROUP[t]];
2467
2467
  return [...c2?.allowed ?? [], ...c2?.denied ?? []];
2468
2468
  };
2469
- var starActive = (r, side) => {
2470
- const items = matchItems(r);
2471
- return items.length > 0 && items.every((v) => side === "left" ? v.startsWith("*") : v.endsWith("*"));
2472
- };
2473
- var toggleStar = (r, side) => {
2469
+ var setMatchItems = (r, items) => {
2474
2470
  const t = currentCType(r);
2475
2471
  if (t === "none") return r;
2476
- const on = starActive(r, side);
2477
2472
  const listKey = r.effect === "ALLOW" ? "allowed" : "denied";
2478
- const items = matchItems(r).map(
2479
- (v) => side === "left" ? on ? v.replace(/^\*+/, "") : "*" + v : on ? v.replace(/\*+$/, "") : v + "*"
2480
- );
2481
2473
  return { ...r, [CTYPE_GROUP[t]]: { [listKey]: items } };
2482
2474
  };
2475
+ var flipStar = (v, side) => side === "left" ? v.startsWith("*") ? v.replace(/^\*+/, "") : "*" + v : v.endsWith("*") ? v.replace(/\*+$/, "") : v + "*";
2483
2476
  var migrateEffect = (r, nextEffect) => {
2484
2477
  const flipped = { ...r, effect: nextEffect };
2485
2478
  const t = currentCType(r);
@@ -2542,6 +2535,7 @@ function PoliciesPanel({ focused }) {
2542
2535
  const [status, setStatus] = useState4(null);
2543
2536
  const [pendingDel, setPendingDel] = useState4(null);
2544
2537
  const [permCursor, setPermCursor] = useState4(0);
2538
+ const [matchSel, setMatchSel] = useState4(0);
2545
2539
  const [busyCreate, setBusyCreate] = useState4(false);
2546
2540
  const selected = policies[Math.min(pi, Math.max(0, policies.length - 1))];
2547
2541
  const detail = useLoader(() => selected ? api.policies.get(selected.id) : Promise.resolve(null), [selected?.id]);
@@ -2706,6 +2700,43 @@ function PoliciesPanel({ focused }) {
2706
2700
  else if (input === "x") discard();
2707
2701
  return;
2708
2702
  }
2703
+ if (view === "match") {
2704
+ const r = rules[ri];
2705
+ if (!r) return setView("rules");
2706
+ const items = matchItems(r);
2707
+ if (key.leftArrow || key.escape) return setView("rule");
2708
+ if (key.upArrow) setMatchSel((n) => Math.max(0, n - 1));
2709
+ else if (key.downArrow) setMatchSel((n) => Math.min(Math.max(0, items.length - 1), n + 1));
2710
+ else if (input === "a") {
2711
+ const next = [...items, ""];
2712
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
2713
+ setMatchSel(next.length - 1);
2714
+ setEditVal("");
2715
+ setEditing(true);
2716
+ } else if (key.return || input === "e") {
2717
+ if (items.length === 0) {
2718
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, [""]) : x));
2719
+ setMatchSel(0);
2720
+ setEditVal("");
2721
+ } else {
2722
+ setEditVal(items[matchSel] ?? "");
2723
+ }
2724
+ setEditing(true);
2725
+ } else if (input === "[" || input === "]") {
2726
+ const side = input === "[" ? "left" : "right";
2727
+ if (items[matchSel] != null) {
2728
+ const next = items.map((v, i) => i === matchSel ? flipStar(v, side) : v);
2729
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
2730
+ }
2731
+ } else if (input === "d") {
2732
+ if (items.length) {
2733
+ const next = items.filter((_, i) => i !== matchSel);
2734
+ mutate(rules.map((x, i) => i === ri ? setMatchItems(x, next) : x));
2735
+ setMatchSel((n) => Math.max(0, Math.min(n, next.length - 1)));
2736
+ }
2737
+ } else if (input === "s") void save();
2738
+ return;
2739
+ }
2709
2740
  const rule2 = rules[ri];
2710
2741
  if (!rule2) return setView("rules");
2711
2742
  const field = FIELDS[fi];
@@ -2727,14 +2758,13 @@ function PoliciesPanel({ focused }) {
2727
2758
  } else if (field.kind === "perms" && input === " ") {
2728
2759
  const p = PERMS[permCursor % PERMS.length];
2729
2760
  mutate(rules.map((rr, i) => i === ri ? togglePerm(rr, p) : rr));
2730
- } else if (field.kind === "match" && input === "[") {
2731
- mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "left") : rr));
2732
- } else if (field.kind === "match" && input === "]") {
2733
- mutate(rules.map((rr, i) => i === ri ? toggleStar(rr, "right") : rr));
2761
+ } else if (field.kind === "match" && (key.return || key.rightArrow)) {
2762
+ setMatchSel(0);
2763
+ setView("match");
2734
2764
  } else if (field.kind === "priority" && (key.rightArrow || key.leftArrow)) {
2735
2765
  const d = key.rightArrow ? 1 : -1;
2736
2766
  mutate(rules.map((r, i) => i === ri ? { ...r, priority: Math.max(0, r.priority + d) } : r));
2737
- } else if ((field.kind === "text" || field.kind === "match") && key.return) {
2767
+ } else if (field.kind === "text" && key.return) {
2738
2768
  setEditVal(field.get(rule2));
2739
2769
  setEditing(true);
2740
2770
  } else if (input === "s") void save();
@@ -2828,6 +2858,59 @@ function PoliciesPanel({ focused }) {
2828
2858
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
2829
2859
  ] }) });
2830
2860
  }
2861
+ if (view === "match") {
2862
+ const r = rules[ri];
2863
+ const items = r ? matchItems(r) : [];
2864
+ const t = r ? currentCType(r) : "none";
2865
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
2866
+ /* @__PURE__ */ jsxs4(Box4, { children: [
2867
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: theme.accentBright, children: "Match values " }),
2868
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: r ? `${r.effect} \xB7 ${t}` : "" }),
2869
+ dirtyTag
2870
+ ] }),
2871
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 select \xB7 enter/e edit \xB7 a add \xB7 [ / ] wildcard L/R \xB7 d remove \xB7 s save \xB7 \u2190 back" }),
2872
+ /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
2873
+ items.length === 0 ? /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "(no values \u2014 press a to add one)" }) : null,
2874
+ items.map((it, i) => {
2875
+ const sel = i === matchSel;
2876
+ if (sel && editing) {
2877
+ const lE = editVal.startsWith("*");
2878
+ const rE = editVal.length > 0 && editVal.endsWith("*");
2879
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
2880
+ /* @__PURE__ */ jsx4(Text4, { color: theme.accentBright, children: "\u25B8 " }),
2881
+ /* @__PURE__ */ jsx4(Text4, { color: lE ? theme.ok : theme.dim, children: lE ? "\u2731 " : "\xB7 " }),
2882
+ /* @__PURE__ */ jsx4(
2883
+ TextInput3,
2884
+ {
2885
+ value: editVal,
2886
+ onChange: setEditVal,
2887
+ onSubmit: (v) => {
2888
+ const val = v.trim();
2889
+ let next = items.map((x, idx) => idx === i ? val : x);
2890
+ if (val === "") next = next.filter((_, idx) => idx !== i);
2891
+ mutate(rules.map((x, idx) => idx === ri ? setMatchItems(x, next) : x));
2892
+ setMatchSel((n) => Math.max(0, Math.min(n, next.length - 1)));
2893
+ setEditing(false);
2894
+ }
2895
+ }
2896
+ ),
2897
+ /* @__PURE__ */ jsx4(Text4, { color: rE ? theme.ok : theme.dim, children: rE ? " \u2731" : " \xB7" })
2898
+ ] }, i);
2899
+ }
2900
+ const lOn = it.startsWith("*");
2901
+ const rOn = it.length > 0 && it.endsWith("*");
2902
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
2903
+ /* @__PURE__ */ jsx4(Text4, { color: sel ? theme.accentBright : void 0, children: sel ? "\u25B8 " : " " }),
2904
+ /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
2905
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !it, children: it || "(empty)" }),
2906
+ /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
2907
+ ] }, i);
2908
+ })
2909
+ ] }),
2910
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (any run of chars). Type it directly (rm*) or toggle with [ / ]. Green \u2731 = active \xB7 left & right shown as you type. Multiple values = OR (any one matches)." }),
2911
+ status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
2912
+ ] });
2913
+ }
2831
2914
  const rule = rules[ri];
2832
2915
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
2833
2916
  /* @__PURE__ */ jsxs4(Box4, { children: [
@@ -2835,7 +2918,7 @@ function PoliciesPanel({ focused }) {
2835
2918
  /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: rule?.id ?? "" }),
2836
2919
  dirtyTag
2837
2920
  ] }),
2838
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 [ ] wildcards \xB7 s save \xB7 \u2190 back" }),
2921
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: "\u2191\u2193 field \xB7 enter edit/open \xB7 space toggle \xB7 \u2190\u2192 move/pick \xB7 s save \xB7 \u2190 back" }),
2839
2922
  /* @__PURE__ */ jsx4(Box4, { marginTop: 1, flexDirection: "column", children: FIELDS.map((f, i) => {
2840
2923
  const active2 = i === fi;
2841
2924
  const label = /* @__PURE__ */ jsx4(Text4, { color: active2 ? theme.accentBright : void 0, children: (active2 ? "\u25B8 " : " ") + f.label.padEnd(13) });
@@ -2853,30 +2936,12 @@ function PoliciesPanel({ focused }) {
2853
2936
  ] }, f.label);
2854
2937
  }
2855
2938
  if (f.kind === "match" && rule) {
2856
- if (active2 && editing) {
2857
- return /* @__PURE__ */ jsxs4(Box4, { children: [
2858
- label,
2859
- /* @__PURE__ */ jsx4(
2860
- TextInput3,
2861
- {
2862
- value: editVal,
2863
- onChange: setEditVal,
2864
- onSubmit: (v2) => {
2865
- if (f.set) mutate(rules.map((r, idx) => idx === ri ? f.set(r, v2) : r));
2866
- setEditing(false);
2867
- }
2868
- }
2869
- )
2870
- ] }, f.label);
2871
- }
2872
- const v = f.get(rule);
2873
- const lOn = starActive(rule, "left");
2874
- const rOn = starActive(rule, "right");
2939
+ const items = matchItems(rule);
2940
+ const preview = items.join(", ");
2875
2941
  return /* @__PURE__ */ jsxs4(Box4, { children: [
2876
2942
  label,
2877
- /* @__PURE__ */ jsx4(Text4, { color: lOn ? theme.ok : theme.dim, children: lOn ? "\u2731 " : "\xB7 " }),
2878
- /* @__PURE__ */ jsx4(Text4, { dimColor: !v, children: v || "\u2014" }),
2879
- /* @__PURE__ */ jsx4(Text4, { color: rOn ? theme.ok : theme.dim, children: rOn ? " \u2731" : " \xB7" })
2943
+ /* @__PURE__ */ jsx4(Text4, { dimColor: !preview, children: preview || "\u2014" }),
2944
+ /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: items.length ? ` (${items.length} value${items.length > 1 ? "s" : ""} \xB7 enter: edit)` : " (enter: add values)" })
2880
2945
  ] }, f.label);
2881
2946
  }
2882
2947
  const val = rule ? f.get(rule) : "";
@@ -2902,7 +2967,6 @@ function PoliciesPanel({ focused }) {
2902
2967
  )
2903
2968
  ] }, f.label);
2904
2969
  }) }),
2905
- /* @__PURE__ */ jsx4(Text4, { color: theme.dim, children: " * = wildcard (matches any run of chars). On Match: [ toggles a leading *, ] a trailing * \xB7 e.g. *ping* matches any command containing ping" }),
2906
2970
  status ? /* @__PURE__ */ jsx4(Text4, { color: status.startsWith("\u2717") ? theme.bad : theme.ok, children: status }) : null
2907
2971
  ] });
2908
2972
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.82.52",
3
+ "version": "0.82.54",
4
4
  "description": "AI tool security proxy: protect any AI tool server with customizable policies, path/command constraints, rate limiting, and audit logging. No code changes required.",
5
5
  "type": "module",
6
6
  "bin": {