free-coding-models 0.1.75 β 0.1.76
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/README.md +1 -0
- package/bin/free-coding-models.js +245 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
- **π Startup mode menu** β Choose between OpenCode and OpenClaw before the TUI launches
|
|
79
79
|
- **π» OpenCode integration** β Auto-detects NIM setup, sets model as default, launches OpenCode
|
|
80
80
|
- **π¦ OpenClaw integration** β Sets selected model as default provider in `~/.openclaw/openclaw.json`
|
|
81
|
+
- **π Feature Request (J key)** β Send anonymous feedback directly to the project team via a full-screen overlay with multi-line input (includes anonymous OS/terminal metadata in message footer only)
|
|
81
82
|
- **π¨ Clean output** β Zero scrollback pollution, interface stays open until Ctrl+C
|
|
82
83
|
- **πΆ Status indicators** β UP β
Β· No Key π Β· Timeout β³ Β· Overloaded π₯ Β· Not Found π«
|
|
83
84
|
- **π Keyless latency** β Models are pinged even without an API key β a `π NO KEY` status confirms the server is reachable with real latency shown, so you can compare providers before committing to a key
|
|
@@ -123,6 +123,54 @@ const TELEMETRY_CONSENT_ASCII = [
|
|
|
123
123
|
const POSTHOG_PROJECT_KEY_DEFAULT = 'phc_5P1n8HaLof6nHM0tKJYt4bV5pj2XPb272fLVigwf1YQ'
|
|
124
124
|
const POSTHOG_HOST_DEFAULT = 'https://eu.i.posthog.com'
|
|
125
125
|
|
|
126
|
+
// π Discord feature request webhook configuration (anonymous feedback system)
|
|
127
|
+
const DISCORD_WEBHOOK_URL = 'https://discord.com/api/webhooks/1476709155992764427/hmnHNtpducvi5LClhv8DynENjUmmg9q8HI1Bx1lNix56UHqrqZf55rW95LGvNJ2W4j7D'
|
|
128
|
+
const DISCORD_BOT_NAME = 'TUI - Feature Requests'
|
|
129
|
+
const DISCORD_EMBED_COLOR = 0x39FF14 // Vert fluo (RGB: 57, 255, 20)
|
|
130
|
+
|
|
131
|
+
// π sendFeatureRequest: Send anonymous feature request to Discord via webhook
|
|
132
|
+
// π Called when user presses J key, types message, and presses Enter
|
|
133
|
+
// π Returns success/error status for UI feedback
|
|
134
|
+
async function sendFeatureRequest(message) {
|
|
135
|
+
try {
|
|
136
|
+
// π Collect anonymous telemetry for context (no personal data)
|
|
137
|
+
const system = getTelemetrySystem()
|
|
138
|
+
const terminal = getTelemetryTerminal()
|
|
139
|
+
const nodeVersion = process.version
|
|
140
|
+
const arch = process.arch
|
|
141
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown'
|
|
142
|
+
|
|
143
|
+
// π Build Discord embed with rich metadata in footer (compact format)
|
|
144
|
+
const embed = {
|
|
145
|
+
description: message,
|
|
146
|
+
color: DISCORD_EMBED_COLOR,
|
|
147
|
+
timestamp: new Date().toISOString(),
|
|
148
|
+
footer: {
|
|
149
|
+
text: `v${LOCAL_VERSION} β’ ${system} β’ ${terminal} β’ ${nodeVersion} β’ ${arch} β’ ${timezone}`
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const response = await fetch(DISCORD_WEBHOOK_URL, {
|
|
154
|
+
method: 'POST',
|
|
155
|
+
headers: { 'content-type': 'application/json' },
|
|
156
|
+
body: JSON.stringify({
|
|
157
|
+
username: DISCORD_BOT_NAME,
|
|
158
|
+
embeds: [embed]
|
|
159
|
+
}),
|
|
160
|
+
signal: AbortSignal.timeout(10000) // π 10s timeout for webhook
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
if (!response.ok) {
|
|
164
|
+
throw new Error(`HTTP ${response.status}`)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return { success: true, error: null }
|
|
168
|
+
} catch (error) {
|
|
169
|
+
const message = error instanceof Error ? error.message : 'Unknown error'
|
|
170
|
+
return { success: false, error: message }
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
126
174
|
// π parseTelemetryEnv: Convert env var strings into booleans.
|
|
127
175
|
// π Returns true/false when value is recognized, otherwise null.
|
|
128
176
|
function parseTelemetryEnv(value) {
|
|
@@ -1290,8 +1338,8 @@ function renderTable(results, pendingPings, frame, cursor = null, sortColumn = '
|
|
|
1290
1338
|
: chalk.rgb(0, 200, 255)('EnterβOpenCode')
|
|
1291
1339
|
// π Line 1: core navigation + sorting shortcuts
|
|
1292
1340
|
lines.push(chalk.dim(` ββ Navigate β’ `) + actionHint + chalk.dim(` β’ `) + chalk.yellow('F') + chalk.dim(` Favorite β’ R/Y/O/M/L/A/S/C/H/V/B/U Sort β’ `) + chalk.yellow('T') + chalk.dim(` Tier β’ `) + chalk.yellow('N') + chalk.dim(` Origin β’ Wβ/Xβ (${intervalSec}s) β’ `) + chalk.rgb(255, 100, 50).bold('Z') + chalk.dim(` Mode β’ `) + chalk.yellow('P') + chalk.dim(` Settings β’ `) + chalk.rgb(0, 255, 80).bold('K') + chalk.dim(` Help`))
|
|
1293
|
-
// π Line 2: profiles, recommend, and extended hints β gives visibility to less-obvious features
|
|
1294
|
-
lines.push(chalk.dim(` `) + chalk.rgb(200, 150, 255).bold('β§P') + chalk.dim(` Cycle profile β’ `) + chalk.rgb(200, 150, 255).bold('β§S') + chalk.dim(` Save profile β’ `) + chalk.rgb(0, 200, 180).bold('Q') + chalk.dim(` Smart Recommend β’ `) + chalk.yellow('E') + chalk.dim(`/`) + chalk.yellow('D') + chalk.dim(` Tier ββ β’ `) + chalk.yellow('Esc') + chalk.dim(` Close overlay β’ Ctrl+C Exit`))
|
|
1341
|
+
// π Line 2: profiles, recommend, feature request, and extended hints β gives visibility to less-obvious features
|
|
1342
|
+
lines.push(chalk.dim(` `) + chalk.rgb(200, 150, 255).bold('β§P') + chalk.dim(` Cycle profile β’ `) + chalk.rgb(200, 150, 255).bold('β§S') + chalk.dim(` Save profile β’ `) + chalk.rgb(0, 200, 180).bold('Q') + chalk.dim(` Smart Recommend β’ `) + chalk.rgb(57, 255, 20).bold('J') + chalk.dim(` Request feature β’ `) + chalk.yellow('E') + chalk.dim(`/`) + chalk.yellow('D') + chalk.dim(` Tier ββ β’ `) + chalk.yellow('Esc') + chalk.dim(` Close overlay β’ Ctrl+C Exit`))
|
|
1295
1343
|
lines.push('')
|
|
1296
1344
|
lines.push(
|
|
1297
1345
|
chalk.rgb(255, 150, 200)(' Made with π & β by \x1b]8;;https://github.com/vava-nessa\x1b\\vava-nessa\x1b]8;;\x1b\\') +
|
|
@@ -2817,6 +2865,11 @@ async function main() {
|
|
|
2817
2865
|
activeProfile: getActiveProfileName(config), // π Currently loaded profile name (or null)
|
|
2818
2866
|
profileSaveMode: false, // π Whether the inline "Save profile" name input is active
|
|
2819
2867
|
profileSaveBuffer: '', // π Typed characters for the profile name being saved
|
|
2868
|
+
// π Feature Request state (! key opens it)
|
|
2869
|
+
featureRequestOpen: false, // π Whether the feature request overlay is active
|
|
2870
|
+
featureRequestBuffer: '', // π Typed characters for the feature request message
|
|
2871
|
+
featureRequestStatus: 'idle', // π 'idle'|'sending'|'success'|'error' β webhook send status
|
|
2872
|
+
featureRequestError: null, // π Last webhook error message
|
|
2820
2873
|
}
|
|
2821
2874
|
|
|
2822
2875
|
// π Re-clamp viewport on terminal resize
|
|
@@ -3093,6 +3146,7 @@ async function main() {
|
|
|
3093
3146
|
lines.push(` ${chalk.yellow('Z')} Cycle launch mode ${chalk.dim('(OpenCode CLI β OpenCode Desktop β OpenClaw)')}`)
|
|
3094
3147
|
lines.push(` ${chalk.yellow('F')} Toggle favorite on selected row ${chalk.dim('(β pinned at top, persisted)')}`)
|
|
3095
3148
|
lines.push(` ${chalk.yellow('Q')} Smart Recommend ${chalk.dim('(π― find the best model for your task β questionnaire + live analysis)')}`)
|
|
3149
|
+
lines.push(` ${chalk.rgb(57, 255, 20).bold('J')} Request Feature ${chalk.dim('(π send anonymous feedback to the project team)')}`)
|
|
3096
3150
|
lines.push(` ${chalk.yellow('P')} Open settings ${chalk.dim('(manage API keys, provider toggles, analytics, manual update)')}`)
|
|
3097
3151
|
lines.push(` ${chalk.yellow('Shift+P')} Cycle config profile ${chalk.dim('(switch between saved profiles live)')}`)
|
|
3098
3152
|
lines.push(` ${chalk.yellow('Shift+S')} Save current config as a named profile ${chalk.dim('(inline prompt β type name + Enter)')}`)
|
|
@@ -3331,6 +3385,112 @@ async function main() {
|
|
|
3331
3385
|
}, PING_RATE)
|
|
3332
3386
|
}
|
|
3333
3387
|
|
|
3388
|
+
// βββ Feature Request overlay renderer βββββββββββββββββββββββββββββββββββββ
|
|
3389
|
+
// π renderFeatureRequest: Draw the overlay for anonymous Discord feedback.
|
|
3390
|
+
// π Shows an input field where users can type feature requests, then sends to Discord webhook.
|
|
3391
|
+
function renderFeatureRequest() {
|
|
3392
|
+
const EL = '\x1b[K'
|
|
3393
|
+
const lines = []
|
|
3394
|
+
|
|
3395
|
+
// π Calculate available space for multi-line input
|
|
3396
|
+
const maxInputWidth = OVERLAY_PANEL_WIDTH - 8 // 8 = padding (4 spaces each side)
|
|
3397
|
+
const maxInputLines = 10 // Show up to 10 lines of input
|
|
3398
|
+
|
|
3399
|
+
// π Split buffer into lines for display (with wrapping)
|
|
3400
|
+
const wrapText = (text, width) => {
|
|
3401
|
+
const words = text.split(' ')
|
|
3402
|
+
const lines = []
|
|
3403
|
+
let currentLine = ''
|
|
3404
|
+
|
|
3405
|
+
for (const word of words) {
|
|
3406
|
+
const testLine = currentLine ? currentLine + ' ' + word : word
|
|
3407
|
+
if (testLine.length <= width) {
|
|
3408
|
+
currentLine = testLine
|
|
3409
|
+
} else {
|
|
3410
|
+
if (currentLine) lines.push(currentLine)
|
|
3411
|
+
currentLine = word
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
if (currentLine) lines.push(currentLine)
|
|
3415
|
+
return lines
|
|
3416
|
+
}
|
|
3417
|
+
|
|
3418
|
+
const inputLines = wrapText(state.featureRequestBuffer, maxInputWidth)
|
|
3419
|
+
const displayLines = inputLines.slice(0, maxInputLines)
|
|
3420
|
+
|
|
3421
|
+
// π Header
|
|
3422
|
+
lines.push('')
|
|
3423
|
+
lines.push(` ${chalk.bold.rgb(57, 255, 20)('π Feature Request')} ${chalk.dim('β send anonymous feedback to the project team')}`)
|
|
3424
|
+
lines.push('')
|
|
3425
|
+
|
|
3426
|
+
// π Status messages (if any)
|
|
3427
|
+
if (state.featureRequestStatus === 'sending') {
|
|
3428
|
+
lines.push(` ${chalk.yellow('β³ Sending...')}`)
|
|
3429
|
+
lines.push('')
|
|
3430
|
+
} else if (state.featureRequestStatus === 'success') {
|
|
3431
|
+
lines.push(` ${chalk.greenBright.bold('β
Successfully sent!')} ${chalk.dim('Closing overlay in 3 seconds...')}`)
|
|
3432
|
+
lines.push('')
|
|
3433
|
+
lines.push(` ${chalk.dim('Thank you for your feedback! Your feature request has been sent to the project team.')}`)
|
|
3434
|
+
lines.push('')
|
|
3435
|
+
} else if (state.featureRequestStatus === 'error') {
|
|
3436
|
+
lines.push(` ${chalk.red('β Error:')} ${chalk.yellow(state.featureRequestError || 'Failed to send')}`)
|
|
3437
|
+
lines.push(` ${chalk.dim('Press Backspace to edit, or Esc to close')}`)
|
|
3438
|
+
lines.push('')
|
|
3439
|
+
} else {
|
|
3440
|
+
lines.push(` ${chalk.dim('Type your feature request below. Press Enter to send, Esc to cancel.')}`)
|
|
3441
|
+
lines.push(` ${chalk.dim('Your message will be sent anonymously to the project team.')}`)
|
|
3442
|
+
lines.push('')
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
// π Input box with border
|
|
3446
|
+
lines.push(chalk.dim(` ββ ${chalk.cyan('Message')} ${chalk.dim(`(${state.featureRequestBuffer.length}/500 chars)`)} β${'β'.repeat(maxInputWidth - 22)}β`))
|
|
3447
|
+
|
|
3448
|
+
// π Display input lines (or placeholder if empty)
|
|
3449
|
+
if (displayLines.length === 0 && state.featureRequestStatus === 'idle') {
|
|
3450
|
+
lines.push(chalk.dim(` β${' '.repeat(maxInputWidth)}β`))
|
|
3451
|
+
lines.push(chalk.dim(` β ${chalk.white.italic('Type your message here...')}${' '.repeat(Math.max(0, maxInputWidth - 28))}β`))
|
|
3452
|
+
} else {
|
|
3453
|
+
for (const line of displayLines) {
|
|
3454
|
+
const padded = line.padEnd(maxInputWidth)
|
|
3455
|
+
lines.push(` β ${chalk.white(padded)} β`)
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
// π Fill remaining space if needed
|
|
3460
|
+
const linesToFill = Math.max(0, maxInputLines - Math.max(displayLines.length, 1))
|
|
3461
|
+
for (let i = 0; i < linesToFill; i++) {
|
|
3462
|
+
lines.push(chalk.dim(` β${' '.repeat(maxInputWidth)}β`))
|
|
3463
|
+
}
|
|
3464
|
+
|
|
3465
|
+
// π Cursor indicator (only when not sending/success)
|
|
3466
|
+
if (state.featureRequestStatus === 'idle' || state.featureRequestStatus === 'error') {
|
|
3467
|
+
const cursorLine = inputLines.length > 0 ? inputLines.length - 1 : 0
|
|
3468
|
+
const lastDisplayLine = displayLines.length - 1
|
|
3469
|
+
// Add cursor indicator to the last line
|
|
3470
|
+
if (lines.length > 0 && displayLines.length > 0) {
|
|
3471
|
+
const lastLineIdx = lines.findIndex(l => l.includes('β ') && !l.includes('Message'))
|
|
3472
|
+
if (lastLineIdx >= 0 && lastLineIdx < lines.length) {
|
|
3473
|
+
// Add cursor blink
|
|
3474
|
+
const lastLine = lines[lastLineIdx]
|
|
3475
|
+
if (lastLine.includes('β')) {
|
|
3476
|
+
lines[lastLineIdx] = lastLine.replace(/\s+β$/, chalk.rgb(57, 255, 20).bold('β') + ' β')
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
lines.push(chalk.dim(` β${'β'.repeat(maxInputWidth + 2)}β`))
|
|
3483
|
+
|
|
3484
|
+
lines.push('')
|
|
3485
|
+
lines.push(chalk.dim(' Enter Send β’ Esc Cancel β’ Backspace Delete'))
|
|
3486
|
+
|
|
3487
|
+
// π Apply overlay tint and return
|
|
3488
|
+
const FEATURE_REQUEST_OVERLAY_BG = chalk.bgRgb(26, 26, 46) // Dark blue-ish background (RGB: 26, 26, 46)
|
|
3489
|
+
const tintedLines = tintOverlayLines(lines, FEATURE_REQUEST_OVERLAY_BG)
|
|
3490
|
+
const cleared = tintedLines.map(l => l + EL)
|
|
3491
|
+
return cleared.join('\n')
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3334
3494
|
// π stopRecommendAnalysis: cleanup timers if user cancels during analysis
|
|
3335
3495
|
function stopRecommendAnalysis() {
|
|
3336
3496
|
if (state.recommendAnalysisTimer) { clearInterval(state.recommendAnalysisTimer); state.recommendAnalysisTimer = null }
|
|
@@ -3447,6 +3607,73 @@ async function main() {
|
|
|
3447
3607
|
return
|
|
3448
3608
|
}
|
|
3449
3609
|
|
|
3610
|
+
// π Feature Request overlay: intercept ALL keys while overlay is active.
|
|
3611
|
+
// π Enter β send to Discord, Esc β cancel, Backspace β delete char, printable β append to buffer.
|
|
3612
|
+
if (state.featureRequestOpen) {
|
|
3613
|
+
if (key.ctrl && key.name === 'c') { exit(0); return }
|
|
3614
|
+
|
|
3615
|
+
if (key.name === 'escape') {
|
|
3616
|
+
// π Cancel feature request β close overlay
|
|
3617
|
+
state.featureRequestOpen = false
|
|
3618
|
+
state.featureRequestBuffer = ''
|
|
3619
|
+
state.featureRequestStatus = 'idle'
|
|
3620
|
+
state.featureRequestError = null
|
|
3621
|
+
return
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
if (key.name === 'return') {
|
|
3625
|
+
// π Send feature request to Discord webhook
|
|
3626
|
+
const message = state.featureRequestBuffer.trim()
|
|
3627
|
+
if (message.length > 0 && state.featureRequestStatus !== 'sending') {
|
|
3628
|
+
state.featureRequestStatus = 'sending'
|
|
3629
|
+
const result = await sendFeatureRequest(message)
|
|
3630
|
+
if (result.success) {
|
|
3631
|
+
// π Success β show confirmation briefly, then close overlay after 3 seconds
|
|
3632
|
+
state.featureRequestStatus = 'success'
|
|
3633
|
+
setTimeout(() => {
|
|
3634
|
+
state.featureRequestOpen = false
|
|
3635
|
+
state.featureRequestBuffer = ''
|
|
3636
|
+
state.featureRequestStatus = 'idle'
|
|
3637
|
+
state.featureRequestError = null
|
|
3638
|
+
}, 3000)
|
|
3639
|
+
} else {
|
|
3640
|
+
// π Error β show error message, keep overlay open
|
|
3641
|
+
state.featureRequestStatus = 'error'
|
|
3642
|
+
state.featureRequestError = result.error || 'Unknown error'
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
return
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
if (key.name === 'backspace') {
|
|
3649
|
+
// π Don't allow editing while sending or after success
|
|
3650
|
+
if (state.featureRequestStatus === 'sending' || state.featureRequestStatus === 'success') return
|
|
3651
|
+
state.featureRequestBuffer = state.featureRequestBuffer.slice(0, -1)
|
|
3652
|
+
// π Clear error status when user starts editing again
|
|
3653
|
+
if (state.featureRequestStatus === 'error') {
|
|
3654
|
+
state.featureRequestStatus = 'idle'
|
|
3655
|
+
state.featureRequestError = null
|
|
3656
|
+
}
|
|
3657
|
+
return
|
|
3658
|
+
}
|
|
3659
|
+
|
|
3660
|
+
// π Append printable characters (str is the raw character typed)
|
|
3661
|
+
// π Limit to 500 characters (Discord embed description limit)
|
|
3662
|
+
if (str && str.length === 1 && !key.ctrl && !key.meta) {
|
|
3663
|
+
// π Don't allow editing while sending or after success
|
|
3664
|
+
if (state.featureRequestStatus === 'sending' || state.featureRequestStatus === 'success') return
|
|
3665
|
+
if (state.featureRequestBuffer.length < 500) {
|
|
3666
|
+
state.featureRequestBuffer += str
|
|
3667
|
+
// π Clear error status when user starts editing again
|
|
3668
|
+
if (state.featureRequestStatus === 'error') {
|
|
3669
|
+
state.featureRequestStatus = 'idle'
|
|
3670
|
+
state.featureRequestError = null
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
}
|
|
3674
|
+
return
|
|
3675
|
+
}
|
|
3676
|
+
|
|
3450
3677
|
// π Help overlay: full keyboard navigation + key swallowing while overlay is open.
|
|
3451
3678
|
if (state.helpVisible) {
|
|
3452
3679
|
const pageStep = Math.max(1, (state.terminalRows || 1) - 2)
|
|
@@ -3919,6 +4146,15 @@ async function main() {
|
|
|
3919
4146
|
return
|
|
3920
4147
|
}
|
|
3921
4148
|
|
|
4149
|
+
// π J key: open Feature Request overlay (anonymous Discord feedback)
|
|
4150
|
+
if (key.name === 'j') {
|
|
4151
|
+
state.featureRequestOpen = true
|
|
4152
|
+
state.featureRequestBuffer = ''
|
|
4153
|
+
state.featureRequestStatus = 'idle'
|
|
4154
|
+
state.featureRequestError = null
|
|
4155
|
+
return
|
|
4156
|
+
}
|
|
4157
|
+
|
|
3922
4158
|
// π Interval adjustment keys: W=decrease (faster), X=increase (slower)
|
|
3923
4159
|
// π Minimum 1s, maximum 60s
|
|
3924
4160
|
if (key.name === 'w') {
|
|
@@ -4052,11 +4288,11 @@ async function main() {
|
|
|
4052
4288
|
|
|
4053
4289
|
process.stdin.on('keypress', onKeyPress)
|
|
4054
4290
|
|
|
4055
|
-
// π Animation loop: render settings overlay, recommend overlay, help overlay, OR main table
|
|
4291
|
+
// π Animation loop: render settings overlay, recommend overlay, help overlay, feature request overlay, OR main table
|
|
4056
4292
|
const ticker = setInterval(() => {
|
|
4057
4293
|
state.frame++
|
|
4058
4294
|
// π Cache visible+sorted models each frame so Enter handler always matches the display
|
|
4059
|
-
if (!state.settingsOpen && !state.recommendOpen) {
|
|
4295
|
+
if (!state.settingsOpen && !state.recommendOpen && !state.featureRequestOpen) {
|
|
4060
4296
|
const visible = state.results.filter(r => !r.hidden)
|
|
4061
4297
|
state.visibleSorted = sortResultsWithPinnedFavorites(visible, state.sortColumn, state.sortDirection)
|
|
4062
4298
|
}
|
|
@@ -4064,9 +4300,11 @@ async function main() {
|
|
|
4064
4300
|
? renderSettings()
|
|
4065
4301
|
: state.recommendOpen
|
|
4066
4302
|
? renderRecommend()
|
|
4067
|
-
: state.
|
|
4068
|
-
?
|
|
4069
|
-
:
|
|
4303
|
+
: state.featureRequestOpen
|
|
4304
|
+
? renderFeatureRequest()
|
|
4305
|
+
: state.helpVisible
|
|
4306
|
+
? renderHelp()
|
|
4307
|
+
: renderTable(state.results, state.pendingPings, state.frame, state.cursor, state.sortColumn, state.sortDirection, state.pingInterval, state.lastPingTime, state.mode, tierFilterMode, state.scrollOffset, state.terminalRows, originFilterMode, state.activeProfile, state.profileSaveMode, state.profileSaveBuffer)
|
|
4070
4308
|
process.stdout.write(ALT_HOME + content)
|
|
4071
4309
|
}, Math.round(1000 / FPS))
|
|
4072
4310
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "free-coding-models",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.76",
|
|
4
4
|
"description": "Find the fastest coding LLM models in seconds β ping free models from multiple providers, pick the best one for OpenCode, Cursor, or any AI coding assistant.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nvidia",
|