Compare commits

...

2 Commits

Author SHA1 Message Date
MHSanaei 49773c18de fix(xray): force full restart for inbounds with a VLESS reverse client
Hot-applying an inbound change swaps it via DelInbound+AddInbound on
the running core. That unregisters any client's reverse.tag handler
on the xray-core side without closing the bridge's already-established
connection, so the reverse tunnel is silently orphaned until someone
manually restarts xray. diffInbounds now bails out of the hot-apply
path whenever the old or new inbound carries a reverse-tagged client,
falling back to a full restart, which actually drops the socket and
lets the bridge redial on its own.

Also scope the .claude ignore rule to its contents (.claude/*) instead
of the whole directory, so individual files under .claude/ can be
tracked selectively.
2026-07-01 14:02:13 +02:00
MHSanaei 427613b308 chore(ci): upgrade claude-bot to Sonnet 5 and set explicit effort levels
Sonnet 5 reaches near-Opus quality on coding/agentic work at lower cost;
pin effort explicitly (xhigh/max) instead of relying on model defaults.
2026-07-01 00:43:27 +02:00
3 changed files with 36 additions and 4 deletions
+6 -3
View File
@@ -30,7 +30,8 @@ jobs:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
allowed_non_write_users: "*"
claude_args: |
--model claude-sonnet-4-6
--model claude-sonnet-5
--effort xhigh
--max-turns 300
--allowedTools "Bash(gh:*),Read,Glob,Grep"
prompt: |
@@ -282,7 +283,8 @@ jobs:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
allowed_non_write_users: "*"
claude_args: |
--model claude-opus-4-8
--model claude-sonnet-5
--effort max
--max-turns 250
--allowedTools "Bash(gh:*),Bash(git:*),Read,Glob,Grep"
prompt: |
@@ -500,7 +502,8 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
claude_args: |
--model claude-opus-4-8
--model claude-sonnet-5
--effort max
--max-turns 250
--allowedTools "Bash(gh:*),Bash(git:*),Read,Glob,Grep,Edit,Write"
--append-system-prompt "You are replying to an @claude mention in the MHSanaei/3x-ui repository, an open-source web panel for managing Xray-core servers. The full repo source is checked out in the working directory; use Read, Glob and Grep to open and verify the relevant files before stating any default, path, flag, option name, or behavior.
+1 -1
View File
@@ -2,7 +2,7 @@
.idea/
.vscode/
.cursor/
.claude/
.claude/*
.cache/
.sync*
+29
View File
@@ -108,6 +108,10 @@ func diffInbounds(oldCfg, newCfg *Config, diff *HotDiff) bool {
if oldIb.Tag == apiTag || oldIb.Tag == "api" {
return false
}
if exists && (inboundHasReverseClient(oldIb) || inboundHasReverseClient(newIb)) {
logger.Debug("hot diff: inbound [", oldIb.Tag, "] carries a reverse-tagged client, forcing a full restart instead of a hot swap")
return false
}
diff.RemovedInboundTags = append(diff.RemovedInboundTags, oldIb.Tag)
if exists {
raw, err := json.Marshal(newIb)
@@ -134,6 +138,31 @@ func diffInbounds(oldCfg, newCfg *Config, diff *HotDiff) bool {
return true
}
func inboundHasReverseClient(ib *InboundConfig) bool {
if ib == nil {
return false
}
var settings struct {
Clients []struct {
Reverse json.RawMessage `json:"reverse"`
} `json:"clients"`
}
if err := json.Unmarshal(ib.Settings, &settings); err != nil {
return false
}
for _, c := range settings.Clients {
if len(c.Reverse) == 0 {
continue
}
var tag any
if err := json.Unmarshal(c.Reverse, &tag); err != nil || tag == nil {
continue
}
return true
}
return false
}
// diffOutbounds fills diff with outbound removals/additions keyed by tag.
// The first outbound is xray's default handler and the API can only append,
// so any change to its identity or content forces a restart. Reordering of