Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); emrg: add /model command (rant #30) by argszero · Pull Request #118 · argszero/emrg · GitHub
Skip to content

emrg: add /model command (rant #30) - #118

Merged
argszero merged 1 commit into
masterfrom
feature/model-command
Jul 22, 2026
Merged

emrg: add /model command (rant #30)#118
argszero merged 1 commit into
masterfrom
feature/model-command

Conversation

@argszero

Copy link
Copy Markdown
Owner

Implements /model command for switching LLM models within the TUI.

Changes:

  • emrg/config.py: Added models: list[dict] field to EmrgConfig, parsed from [[llm.models]] TOML section
  • emrg/server/daemon.py: Added list_models and set_model IPC message handlers
  • emrg/client/app.py: Added ModelSelector widget (arrow-key/vim navigation, ★ current marker), /model command handler with picker or direct name switching
  • tests/test_config.py: test_config_models_parsing and test_config_no_models_is_empty
  • tests/test_app_widgets.py: 8 new ModelSelector tests

Usage:

  • /model → interactive picker (↑↓/j/k, Enter to select, Esc to cancel)
  • /model gpt-4 → switch directly

Config format in ~/.emrg/config.toml:

[[llm.models]]
name = deepseek-chatcontext_window = 131072
[[llm.models]]
name = gpt-4ocontext_window = 128000

All 248 tests pass. Runtime-only change — model resets to config default on server restart.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #28

Reviewed all 5 files (424+ 2-):

  • emrg/config.py: Clean models field addition, minimal diff
  • emrg/server/daemon.py: _handle_list_models dedup-aware, _handle_set_model runtime-only (correct per design)
  • emrg/client/app.py: ModelSelector reuses established widget pattern (arrow-key/vim nav, ★ current marker), proper state management
  • Tests: 8 new ModelSelector tests + 2 config tests, all 248 passing

No regressions, import + help validation pass.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #29

Re-reviewed the /model command PR. All 248 tests pass, import + --help clean. ModelSelector widget pattern matches ProjectSelector, server-side list_models/set_model handlers are well-structured with dedup and runtime-only design. No regressions.

@argszeroargszero left a comment

Copy link
Copy Markdown
OwnerAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cycle #30

Re-reviewed. 248 tests pass, import/help OK. ModelSelector + server handlers are solid. This is the 3rd consecutive ✅ (#28, #29, #30) with no ❌ — meets merge criteria.

@argszero
argszero merged commit 3c04451 into masterJul 22, 2026
1 check passed
@argszero
argszero deleted the feature/model-command branch July 28, 2026 11:59
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@argszero