@synkro-sh/cli 1.3.28 → 1.3.29
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/bootstrap.js +122 -23
- package/dist/bootstrap.js.map +1 -1
- package/package.json +1 -1
package/dist/bootstrap.js
CHANGED
|
@@ -571,34 +571,49 @@ refresh_jwt() {
|
|
|
571
571
|
return 0
|
|
572
572
|
}
|
|
573
573
|
|
|
574
|
-
# Resolve tier (cached 60 min) \u2014 server is canonical via /cli/me
|
|
574
|
+
# Resolve tier + capture_depth (cached 60 min) \u2014 server is canonical via /cli/me.
|
|
575
575
|
TIER_CACHE_FILE="$HOME/.synkro/.tier-cache-\${SYNKRO_USER_ID:-default}"
|
|
576
|
+
CD_CACHE_FILE="\${TIER_CACHE_FILE}.cd"
|
|
576
577
|
SYNKRO_INFERENCE_TIER=""
|
|
578
|
+
SYNKRO_CAPTURE_DEPTH=""
|
|
577
579
|
if find "$TIER_CACHE_FILE" -mmin -60 2>/dev/null | grep -q .; then
|
|
578
580
|
SYNKRO_INFERENCE_TIER=$(cat "$TIER_CACHE_FILE" 2>/dev/null)
|
|
581
|
+
SYNKRO_CAPTURE_DEPTH=$(cat "$CD_CACHE_FILE" 2>/dev/null)
|
|
579
582
|
fi
|
|
580
583
|
if [ -z "$SYNKRO_INFERENCE_TIER" ]; then
|
|
581
584
|
ME_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 2 2>/dev/null || echo "")
|
|
582
585
|
if [ -n "$ME_RESP" ]; then
|
|
583
586
|
SYNKRO_INFERENCE_TIER=$(echo "$ME_RESP" | jq -r '.tier // empty' 2>/dev/null)
|
|
584
587
|
[ -n "$SYNKRO_INFERENCE_TIER" ] && printf '%s' "$SYNKRO_INFERENCE_TIER" > "$TIER_CACHE_FILE" 2>/dev/null || true
|
|
588
|
+
SYNKRO_CAPTURE_DEPTH=$(echo "$ME_RESP" | jq -r '.capture_depth // empty' 2>/dev/null)
|
|
589
|
+
[ -n "$SYNKRO_CAPTURE_DEPTH" ] && printf '%s' "$SYNKRO_CAPTURE_DEPTH" > "$CD_CACHE_FILE" 2>/dev/null || true
|
|
585
590
|
fi
|
|
586
591
|
fi
|
|
587
592
|
SYNKRO_INFERENCE_TIER="\${SYNKRO_INFERENCE_TIER:-fast}"
|
|
593
|
+
SYNKRO_CAPTURE_DEPTH="\${SYNKRO_CAPTURE_DEPTH:-full}"
|
|
588
594
|
|
|
595
|
+
USE_LOCAL=false
|
|
596
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ] && command -v claude >/dev/null 2>&1; then
|
|
597
|
+
USE_LOCAL=true
|
|
598
|
+
elif [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; then
|
|
599
|
+
USE_LOCAL=true
|
|
600
|
+
fi
|
|
589
601
|
|
|
590
|
-
if [ "$
|
|
602
|
+
if [ "$USE_LOCAL" = "true" ]; then
|
|
591
603
|
# \u2500\u2500\u2500 FREE TIER: grade via the persistent claude daemon (mode=bash). \u2500\u2500\u2500
|
|
592
604
|
|
|
593
|
-
# Fetch org guardrail rules relevant to this command (
|
|
594
|
-
ORG_RULES
|
|
595
|
-
|
|
596
|
-
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
605
|
+
# Fetch org guardrail rules relevant to this command (skip in local_only \u2014 no content leaves device).
|
|
606
|
+
ORG_RULES="[]"
|
|
607
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" != "local_only" ]; then
|
|
608
|
+
ORG_RULES=$(printf '%s' "$COMMAND" | head -c 4000 \\
|
|
609
|
+
| jq -Rs '{content: .}' \\
|
|
610
|
+
| curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules?top_k=15" \\
|
|
611
|
+
-X POST -H "Content-Type: application/json" \\
|
|
612
|
+
-H "Authorization: Bearer $JWT" \\
|
|
613
|
+
-d @- --max-time 2 2>/dev/null \\
|
|
614
|
+
| jq -c '[.rules[]? | {rule_id, text, severity, category}]' 2>/dev/null || echo "[]")
|
|
615
|
+
if [ -z "$ORG_RULES" ] || [ "$ORG_RULES" = "null" ]; then ORG_RULES="[]"; fi
|
|
616
|
+
fi
|
|
602
617
|
|
|
603
618
|
GRADER_PROMPT_FILE=$(mktemp -t synkro-bash-prompt.XXXXXX)
|
|
604
619
|
trap "rm -f \\"$GRADER_PROMPT_FILE\\"" EXIT
|
|
@@ -711,6 +726,36 @@ case "$SEVERITY" in
|
|
|
711
726
|
;;
|
|
712
727
|
esac
|
|
713
728
|
|
|
729
|
+
# Fire-and-forget anonymized telemetry for local_only mode
|
|
730
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ] && [ -n "$VERDICT_KIND" ]; then
|
|
731
|
+
(
|
|
732
|
+
ANON_BODY=$(jq -n \\
|
|
733
|
+
--arg event_id "$(uuidgen 2>/dev/null || echo "evt_$(date +%s)_$$")" \\
|
|
734
|
+
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \\
|
|
735
|
+
--arg hook_type "bash" \\
|
|
736
|
+
--arg verdict "$VERDICT_KIND" \\
|
|
737
|
+
--arg severity "$SEVERITY" \\
|
|
738
|
+
--arg category "$CATEGORY" \\
|
|
739
|
+
--arg model "\${CC_MODEL:-claude-sonnet-4-6}" \\
|
|
740
|
+
--arg tool_name "$TOOL_NAME" \\
|
|
741
|
+
'{
|
|
742
|
+
event_id: $event_id,
|
|
743
|
+
timestamp: $timestamp,
|
|
744
|
+
hook_type: $hook_type,
|
|
745
|
+
verdict: $verdict,
|
|
746
|
+
severity: $severity,
|
|
747
|
+
category: $category,
|
|
748
|
+
model: $model,
|
|
749
|
+
tool_name: $tool_name
|
|
750
|
+
}')
|
|
751
|
+
curl -sS -X POST "\${GATEWAY_URL}/api/v1/events/local-verdict" \\
|
|
752
|
+
-H "Content-Type: application/json" \\
|
|
753
|
+
-H "Authorization: Bearer $JWT" \\
|
|
754
|
+
-d "$ANON_BODY" \\
|
|
755
|
+
--max-time 2 >/dev/null 2>&1
|
|
756
|
+
) &
|
|
757
|
+
fi
|
|
758
|
+
|
|
714
759
|
exit 0
|
|
715
760
|
`;
|
|
716
761
|
CC_EDIT_PRECHECK_SCRIPT = `#!/bin/bash
|
|
@@ -938,31 +983,47 @@ refresh_jwt() {
|
|
|
938
983
|
}
|
|
939
984
|
|
|
940
985
|
|
|
941
|
-
# Resolve tier (cached 60 min) \u2014 server is canonical via /cli/me
|
|
986
|
+
# Resolve tier + capture_depth (cached 60 min) \u2014 server is canonical via /cli/me.
|
|
942
987
|
TIER_CACHE_FILE="$HOME/.synkro/.tier-cache-\${SYNKRO_USER_ID:-default}"
|
|
988
|
+
CD_CACHE_FILE="\${TIER_CACHE_FILE}.cd"
|
|
943
989
|
SYNKRO_INFERENCE_TIER=""
|
|
990
|
+
SYNKRO_CAPTURE_DEPTH=""
|
|
944
991
|
if find "$TIER_CACHE_FILE" -mmin -60 2>/dev/null | grep -q .; then
|
|
945
992
|
SYNKRO_INFERENCE_TIER=$(cat "$TIER_CACHE_FILE" 2>/dev/null)
|
|
993
|
+
SYNKRO_CAPTURE_DEPTH=$(cat "$CD_CACHE_FILE" 2>/dev/null)
|
|
946
994
|
fi
|
|
947
995
|
if [ -z "$SYNKRO_INFERENCE_TIER" ]; then
|
|
948
996
|
ME_RESP=$(curl -sS "\${GATEWAY_URL}/api/v1/cli/me" -H "Authorization: Bearer $JWT" --max-time 2 2>/dev/null || echo "")
|
|
949
997
|
if [ -n "$ME_RESP" ]; then
|
|
950
998
|
SYNKRO_INFERENCE_TIER=$(echo "$ME_RESP" | jq -r '.tier // empty' 2>/dev/null)
|
|
951
999
|
[ -n "$SYNKRO_INFERENCE_TIER" ] && printf '%s' "$SYNKRO_INFERENCE_TIER" > "$TIER_CACHE_FILE" 2>/dev/null || true
|
|
1000
|
+
SYNKRO_CAPTURE_DEPTH=$(echo "$ME_RESP" | jq -r '.capture_depth // empty' 2>/dev/null)
|
|
1001
|
+
[ -n "$SYNKRO_CAPTURE_DEPTH" ] && printf '%s' "$SYNKRO_CAPTURE_DEPTH" > "$CD_CACHE_FILE" 2>/dev/null || true
|
|
952
1002
|
fi
|
|
953
1003
|
fi
|
|
954
1004
|
SYNKRO_INFERENCE_TIER="\${SYNKRO_INFERENCE_TIER:-fast}"
|
|
1005
|
+
SYNKRO_CAPTURE_DEPTH="\${SYNKRO_CAPTURE_DEPTH:-full}"
|
|
955
1006
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1007
|
+
USE_LOCAL=false
|
|
1008
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ] && command -v claude >/dev/null 2>&1; then
|
|
1009
|
+
USE_LOCAL=true
|
|
1010
|
+
elif [ "$SYNKRO_INFERENCE_TIER" = "free" ] && command -v claude >/dev/null 2>&1; then
|
|
1011
|
+
USE_LOCAL=true
|
|
1012
|
+
fi
|
|
1013
|
+
|
|
1014
|
+
if [ "$USE_LOCAL" = "true" ]; then
|
|
1015
|
+
# \u2500\u2500\u2500 LOCAL GRADING: grade via the persistent claude daemon (Python helper).
|
|
1016
|
+
ORG_RULES="[]"
|
|
1017
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" != "local_only" ]; then
|
|
1018
|
+
ORG_RULES=$(printf '%s' "$PROPOSED" | head -c 8000 \\
|
|
1019
|
+
| jq -Rs '{content: .}' \\
|
|
1020
|
+
| curl -sS "\${GATEWAY_URL}/api/v1/cli/pr-rules?top_k=20" \\
|
|
1021
|
+
-X POST -H "Content-Type: application/json" \\
|
|
1022
|
+
-H "Authorization: Bearer $JWT" \\
|
|
1023
|
+
-d @- --max-time 2 2>/dev/null \\
|
|
1024
|
+
| jq -c '[.rules[]? | {rule_id, text, severity, category, mode}]' 2>/dev/null || echo "[]")
|
|
1025
|
+
if [ -z "$ORG_RULES" ] || [ "$ORG_RULES" = "null" ]; then ORG_RULES="[]"; fi
|
|
1026
|
+
fi
|
|
966
1027
|
|
|
967
1028
|
GRADER_PROMPT_FILE=$(mktemp -t synkro-grade.XXXXXX)
|
|
968
1029
|
trap "rm -f \\"$GRADER_PROMPT_FILE\\"" EXIT
|
|
@@ -1088,6 +1149,44 @@ else
|
|
|
1088
1149
|
echo "$RESP_WITH_MSG"
|
|
1089
1150
|
fi
|
|
1090
1151
|
|
|
1152
|
+
# Fire-and-forget anonymized telemetry for local_only mode
|
|
1153
|
+
if [ "$SYNKRO_CAPTURE_DEPTH" = "local_only" ] && [ -n "$DECISION" ]; then
|
|
1154
|
+
LOCAL_VERDICT="allow"
|
|
1155
|
+
LOCAL_SEVERITY="audit"
|
|
1156
|
+
LOCAL_CATEGORY="edit_pass"
|
|
1157
|
+
if [ "$DECISION" = "deny" ]; then
|
|
1158
|
+
LOCAL_VERDICT="warn"
|
|
1159
|
+
LOCAL_SEVERITY="block"
|
|
1160
|
+
LOCAL_CATEGORY="edit_violation"
|
|
1161
|
+
fi
|
|
1162
|
+
(
|
|
1163
|
+
ANON_BODY=$(jq -n \\
|
|
1164
|
+
--arg event_id "$(uuidgen 2>/dev/null || echo "evt_$(date +%s)_$$")" \\
|
|
1165
|
+
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \\
|
|
1166
|
+
--arg hook_type "edit" \\
|
|
1167
|
+
--arg verdict "$LOCAL_VERDICT" \\
|
|
1168
|
+
--arg severity "$LOCAL_SEVERITY" \\
|
|
1169
|
+
--arg category "$LOCAL_CATEGORY" \\
|
|
1170
|
+
--arg model "\${CC_MODEL:-claude-sonnet-4-6}" \\
|
|
1171
|
+
--arg tool_name "$TOOL_NAME" \\
|
|
1172
|
+
'{
|
|
1173
|
+
event_id: $event_id,
|
|
1174
|
+
timestamp: $timestamp,
|
|
1175
|
+
hook_type: $hook_type,
|
|
1176
|
+
verdict: $verdict,
|
|
1177
|
+
severity: $severity,
|
|
1178
|
+
category: $category,
|
|
1179
|
+
model: $model,
|
|
1180
|
+
tool_name: $tool_name
|
|
1181
|
+
}')
|
|
1182
|
+
curl -sS -X POST "\${GATEWAY_URL}/api/v1/events/local-verdict" \\
|
|
1183
|
+
-H "Content-Type: application/json" \\
|
|
1184
|
+
-H "Authorization: Bearer $JWT" \\
|
|
1185
|
+
-d "$ANON_BODY" \\
|
|
1186
|
+
--max-time 2 >/dev/null 2>&1
|
|
1187
|
+
) &
|
|
1188
|
+
fi
|
|
1189
|
+
|
|
1091
1190
|
exit 0
|
|
1092
1191
|
`;
|
|
1093
1192
|
CC_EDIT_CAPTURE_SCRIPT = `#!/bin/bash
|
|
@@ -3371,7 +3470,7 @@ function writeConfigEnv(opts) {
|
|
|
3371
3470
|
`SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
|
|
3372
3471
|
`SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
|
|
3373
3472
|
`SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
|
|
3374
|
-
`SYNKRO_VERSION=${shellQuoteSingle("1.3.
|
|
3473
|
+
`SYNKRO_VERSION=${shellQuoteSingle("1.3.29")}`
|
|
3375
3474
|
];
|
|
3376
3475
|
if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
|
|
3377
3476
|
if (safeOrgId) lines.push(`SYNKRO_ORG_ID=${shellQuoteSingle(safeOrgId)}`);
|