greptile 2.3.0 → 2.4.0
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/build-app.sh +1 -1
- package/greptile-fix +5 -0
- package/greptile-fix.applescript +17 -2
- package/health-server.js +44 -8
- package/package.json +1 -1
package/build-app.sh
CHANGED
|
@@ -45,7 +45,7 @@ TEMP_SCRIPT="$(mktemp /tmp/greptile-fix-XXXXXX.applescript)"
|
|
|
45
45
|
trap 'rm -f "$TEMP_SCRIPT"' EXIT
|
|
46
46
|
|
|
47
47
|
# Escape sed special characters in the directory path (& \ /)
|
|
48
|
-
ESCAPED_DIR="$(printf '%s' "$GREPTILE_FIX_DIR" | sed 's/[
|
|
48
|
+
ESCAPED_DIR="$(printf '%s' "$GREPTILE_FIX_DIR" | sed 's/[&\\/]/\\&/g')"
|
|
49
49
|
sed "s|PATH=/opt/homebrew/bin:/usr/local/bin:|PATH=$ESCAPED_DIR:/opt/homebrew/bin:/usr/local/bin:|" \
|
|
50
50
|
"$SCRIPT_DIR/greptile-fix.applescript" > "$TEMP_SCRIPT"
|
|
51
51
|
|
package/greptile-fix
CHANGED
|
@@ -187,6 +187,7 @@ esac
|
|
|
187
187
|
# Parse URL parameters
|
|
188
188
|
PROMPT=$(parse_url_param "$URL" "prompt")
|
|
189
189
|
REPO=$(parse_url_param "$URL" "repo")
|
|
190
|
+
ACK_ID=$(parse_url_param "$URL" "ack")
|
|
190
191
|
|
|
191
192
|
if [ -z "$PROMPT" ]; then
|
|
192
193
|
log "ERROR: No prompt parameter in URL"
|
|
@@ -234,5 +235,9 @@ log "Runner script: $RUNNER"
|
|
|
234
235
|
# Print the runner path to stdout — the AppleScript app reads this
|
|
235
236
|
# and uses it to open Terminal (which requires Automation permission
|
|
236
237
|
# that only the .app bundle has).
|
|
238
|
+
# Line 1: runner path, Line 2 (optional): ACK ID for auto-redirect
|
|
237
239
|
echo "$RUNNER"
|
|
240
|
+
if [ -n "$ACK_ID" ]; then
|
|
241
|
+
echo "$ACK_ID"
|
|
242
|
+
fi
|
|
238
243
|
log "Done"
|
package/greptile-fix.applescript
CHANGED
|
@@ -12,8 +12,16 @@ on open location theURL
|
|
|
12
12
|
try
|
|
13
13
|
-- Ensure log directory exists
|
|
14
14
|
do shell script "mkdir -p $HOME/.cache/greptile"
|
|
15
|
-
-- Call greptile-fix to parse URL and create runner script
|
|
16
|
-
|
|
15
|
+
-- Call greptile-fix to parse URL and create runner script
|
|
16
|
+
-- Output: line 1 = runner path, line 2 (optional) = ACK ID for auto-redirect
|
|
17
|
+
set fixOutput to do shell script "PATH=/opt/homebrew/bin:/usr/local/bin:$PATH greptile-fix " & quoted form of theURL & " 2>> $HOME/.cache/greptile/greptile-fix.log"
|
|
18
|
+
|
|
19
|
+
set outputLines to paragraphs of fixOutput
|
|
20
|
+
set runnerPath to item 1 of outputLines
|
|
21
|
+
set ackId to ""
|
|
22
|
+
if (count of outputLines) > 1 then
|
|
23
|
+
set ackId to item 2 of outputLines
|
|
24
|
+
end if
|
|
17
25
|
|
|
18
26
|
if runnerPath is not "" then
|
|
19
27
|
-- Detect terminal by checking running processes via shell (no accessibility permissions needed).
|
|
@@ -56,6 +64,13 @@ on open location theURL
|
|
|
56
64
|
-- Terminal.app, iTerm, and Warp natively execute scripts via "open -a"
|
|
57
65
|
do shell script "open -a " & quoted form of termApp & " " & quoted form of runnerPath
|
|
58
66
|
end if
|
|
67
|
+
|
|
68
|
+
-- Send ACK to health server so the web page can auto-redirect back to the PR
|
|
69
|
+
if ackId is not "" then
|
|
70
|
+
try
|
|
71
|
+
do shell script "curl -s -X POST http://127.0.0.1:4747/ack/" & quoted form of ackId & " --max-time 2 &>/dev/null &"
|
|
72
|
+
end try
|
|
73
|
+
end if
|
|
59
74
|
end if
|
|
60
75
|
on error errMsg
|
|
61
76
|
do shell script "echo '[ERROR] " & quoted form of errMsg & "' >> $HOME/.cache/greptile/greptile-fix.log"
|
package/health-server.js
CHANGED
|
@@ -95,11 +95,13 @@ function checkForUpdate() {
|
|
|
95
95
|
const npmPaths = [
|
|
96
96
|
'/opt/homebrew/bin/npm',
|
|
97
97
|
'/usr/local/bin/npm',
|
|
98
|
-
...(home
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
...(home
|
|
99
|
+
? [
|
|
100
|
+
path.join(home, '.volta/bin/npm'),
|
|
101
|
+
path.join(home, '.asdf/shims/npm'),
|
|
102
|
+
path.join(home, '.local/bin/npm'),
|
|
103
|
+
]
|
|
104
|
+
: []),
|
|
103
105
|
]
|
|
104
106
|
// Also check nvm: find the current default node version's npm
|
|
105
107
|
if (home) {
|
|
@@ -173,12 +175,26 @@ function checkForUpdate() {
|
|
|
173
175
|
})
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
// --- ACK store for "Fix in X" auto-redirect ---
|
|
179
|
+
const ackStore = new Map() // id → timestamp
|
|
180
|
+
const ACK_TTL_MS = 60_000
|
|
181
|
+
|
|
182
|
+
function pruneAcks() {
|
|
183
|
+
const now = Date.now()
|
|
184
|
+
for (const [id, ts] of ackStore) {
|
|
185
|
+
if (now - ts > ACK_TTL_MS) ackStore.delete(id)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
setInterval(pruneAcks, 30_000)
|
|
189
|
+
|
|
190
|
+
const ACK_PATH_RE = /^\/ack\/([a-zA-Z0-9_-]+)$/
|
|
191
|
+
|
|
176
192
|
const ALLOWED_ORIGINS = ['https://app.greptile.com', 'https://app.staging.greptile.com', 'http://localhost:3000']
|
|
177
193
|
|
|
178
194
|
function isAllowedOrigin(origin) {
|
|
179
195
|
if (ALLOWED_ORIGINS.includes(origin)) return true
|
|
180
|
-
// Allow Vercel preview deployments (e.g. https://greptilia-
|
|
181
|
-
if (/^https:\/\/[a-z0-9-]+\.vercel\.app$/.test(origin)) return true
|
|
196
|
+
// Allow Vercel preview deployments (e.g. https://greptilia-abc123.vercel.app)
|
|
197
|
+
if (/^https:\/\/greptilia-[a-z0-9-]+\.vercel\.app$/.test(origin)) return true
|
|
182
198
|
return false
|
|
183
199
|
}
|
|
184
200
|
|
|
@@ -188,7 +204,7 @@ const server = http.createServer((req, res) => {
|
|
|
188
204
|
|
|
189
205
|
if (allowed) {
|
|
190
206
|
res.setHeader('Access-Control-Allow-Origin', origin)
|
|
191
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')
|
|
207
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
|
192
208
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
|
|
193
209
|
res.setHeader('Access-Control-Allow-Private-Network', 'true')
|
|
194
210
|
}
|
|
@@ -205,6 +221,26 @@ const server = http.createServer((req, res) => {
|
|
|
205
221
|
return
|
|
206
222
|
}
|
|
207
223
|
|
|
224
|
+
// ACK endpoints for "Fix in X" auto-redirect
|
|
225
|
+
const urlPath = (req.url || '').split('?')[0]
|
|
226
|
+
const ackMatch = urlPath.match(ACK_PATH_RE)
|
|
227
|
+
if (ackMatch) {
|
|
228
|
+
const id = ackMatch[1]
|
|
229
|
+
if (req.method === 'POST') {
|
|
230
|
+
ackStore.set(id, Date.now())
|
|
231
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
232
|
+
res.end(JSON.stringify({ ok: true }))
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
if (req.method === 'GET') {
|
|
236
|
+
const acked = ackStore.has(id)
|
|
237
|
+
if (acked) ackStore.delete(id)
|
|
238
|
+
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
239
|
+
res.end(JSON.stringify({ acked }))
|
|
240
|
+
return
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
208
244
|
res.writeHead(404)
|
|
209
245
|
res.end()
|
|
210
246
|
})
|