mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 00:19:42 +02:00
chore: version packages
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
# aicodeman
|
# aicodeman
|
||||||
|
|
||||||
|
## 0.5.9
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Mobile keyboard accessory bar: add configurable "Extended Keyboard Bar" setting (Settings > Display > Input) that toggles between simple mode (up/down arrows, /init, /clear, /compact, paste, dismiss) and extended mode (adds left/right arrows, Tab, Shift+Tab, Ctrl+O, Alt+Enter, Esc). Default is simple mode. Setting is device-specific (not synced to server).
|
||||||
|
|
||||||
|
Restyle dismiss button: muted steel-blue tone, fills remaining bar space via flex, larger tap target. Arrow buttons now blue.
|
||||||
|
|
||||||
|
Fix paste overlay visibility on mobile: dialog repositioned to top of screen (15vh from top) so the virtual keyboard doesn't cover it. Textarea enlarged for better usability.
|
||||||
|
|
||||||
|
(Also includes all v0.5.8 changes: case reorder/delete, XSS sanitization, auto-attach PTY on restart, mobile keyboard buttons, macOS installer fixes, terminal flicker fix, state store collision fix.)
|
||||||
|
|
||||||
## 0.5.8
|
## 0.5.8
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ When user says "COM":
|
|||||||
4. **Sync CLAUDE.md version**: Update the `**Version**` line below to match the new version from `package.json`
|
4. **Sync CLAUDE.md version**: Update the `**Version**` line below to match the new version from `package.json`
|
||||||
5. **Commit and deploy**: `git add -A && git commit -m "chore: version packages" && git push && npm run build && systemctl --user restart codeman-web`
|
5. **Commit and deploy**: `git add -A && git commit -m "chore: version packages" && git push && npm run build && systemctl --user restart codeman-web`
|
||||||
|
|
||||||
**Version**: 0.5.8 (must match `package.json`)
|
**Version**: 0.5.9 (must match `package.json`)
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "aicodeman",
|
"name": "aicodeman",
|
||||||
"version": "0.5.8",
|
"version": "0.5.9",
|
||||||
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
"description": "The missing control plane for AI coding agents - run 20 autonomous agents with real-time monitoring and session persistence",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
|||||||
@@ -523,6 +523,9 @@ class CodemanApp {
|
|||||||
SwipeHandler.init();
|
SwipeHandler.init();
|
||||||
VoiceInput.init();
|
VoiceInput.init();
|
||||||
KeyboardAccessoryBar.init();
|
KeyboardAccessoryBar.init();
|
||||||
|
// Apply keyboard bar mode from settings
|
||||||
|
const _kbSettings = this.loadAppSettingsFromStorage();
|
||||||
|
if (_kbSettings.extendedKeyboardBar) KeyboardAccessoryBar.setMode('extended');
|
||||||
this.applyHeaderVisibilitySettings();
|
this.applyHeaderVisibilitySettings();
|
||||||
this.applyTabWrapSettings();
|
this.applyTabWrapSettings();
|
||||||
this.applyMonitorVisibility();
|
this.applyMonitorVisibility();
|
||||||
|
|||||||
@@ -892,6 +892,17 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-item settings-item-multiline" title="Show additional buttons (Tab, Shift+Tab, Ctrl+O, Esc, Alt+Enter, left/right arrows) in the mobile keyboard accessory bar.">
|
||||||
|
<div class="settings-item-text">
|
||||||
|
<span class="settings-item-label">Extended Keyboard Bar</span>
|
||||||
|
<span class="settings-item-desc">Extra keys: Tab, Esc, arrows, Ctrl+O</span>
|
||||||
|
</div>
|
||||||
|
<label class="switch switch-sm">
|
||||||
|
<input type="checkbox" id="appSettingsExtendedKeyboardBar">
|
||||||
|
<span class="slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Header Displays Section -->
|
<!-- Header Displays Section -->
|
||||||
<div class="settings-section-header">Header Displays</div>
|
<div class="settings-section-header">Header Displays</div>
|
||||||
<div class="settings-item" title="Show A-/A+ font size buttons in header">
|
<div class="settings-item" title="Show A-/A+ font size buttons in header">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Defines two exports:
|
* Defines two exports:
|
||||||
*
|
*
|
||||||
* - KeyboardAccessoryBar (singleton object) — Quick action buttons shown above the virtual
|
* - KeyboardAccessoryBar (singleton object) — Quick action buttons shown above the virtual
|
||||||
* keyboard on mobile: Esc, arrow up/down, Tab, Shift+Tab, Ctrl+O, /init, /clear, /compact, paste, and dismiss.
|
* keyboard on mobile: arrow up/down, /init, /clear, /compact, paste, and dismiss.
|
||||||
* Destructive actions (/clear, /compact) require double-tap confirmation (2s amber state).
|
* Destructive actions (/clear, /compact) require double-tap confirmation (2s amber state).
|
||||||
* Commands are sent as text + Enter separately for Ink compatibility.
|
* Commands are sent as text + Enter separately for Ink compatibility.
|
||||||
* Only initializes on touch devices (MobileDetection.isTouchDevice guard).
|
* Only initializes on touch devices (MobileDetection.isTouchDevice guard).
|
||||||
@@ -33,16 +33,37 @@
|
|||||||
*/
|
*/
|
||||||
const KeyboardAccessoryBar = {
|
const KeyboardAccessoryBar = {
|
||||||
element: null,
|
element: null,
|
||||||
|
_mode: 'simple', // 'simple' or 'extended'
|
||||||
|
|
||||||
/** Create and inject the accessory bar */
|
/** HTML for simple mode: arrows, commands, paste, dismiss */
|
||||||
init() {
|
_simpleButtons: `
|
||||||
// Only on mobile
|
<button class="accessory-btn accessory-btn-arrow" data-action="scroll-up" title="Arrow up">
|
||||||
if (!MobileDetection.isTouchDevice()) return;
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<path d="M5 15l7-7 7 7"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="accessory-btn accessory-btn-arrow" data-action="scroll-down" title="Arrow down">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||||
|
<path d="M19 9l-7 7-7-7"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="accessory-btn" data-action="init" title="/init">/init</button>
|
||||||
|
<button class="accessory-btn" data-action="clear" title="/clear">/clear</button>
|
||||||
|
<button class="accessory-btn" data-action="compact" title="/compact">/compact</button>
|
||||||
|
<button class="accessory-btn" data-action="paste" title="Paste from clipboard">
|
||||||
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/>
|
||||||
|
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="accessory-btn accessory-btn-dismiss" data-action="dismiss" title="Dismiss keyboard">
|
||||||
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
||||||
|
<path d="M19 9l-7 7-7-7"/>
|
||||||
|
</svg>
|
||||||
|
</button>`,
|
||||||
|
|
||||||
// Create accessory bar element
|
/** HTML for extended mode: all keys including arrows, Tab, Esc, etc. */
|
||||||
this.element = document.createElement('div');
|
_extendedButtons: `
|
||||||
this.element.className = 'keyboard-accessory-bar';
|
|
||||||
this.element.innerHTML = `
|
|
||||||
<button class="accessory-btn accessory-btn-arrow" data-action="scroll-up" title="Arrow up">
|
<button class="accessory-btn accessory-btn-arrow" data-action="scroll-up" title="Arrow up">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||||
<path d="M5 15l7-7 7 7"/>
|
<path d="M5 15l7-7 7 7"/>
|
||||||
@@ -77,12 +98,21 @@ const KeyboardAccessoryBar = {
|
|||||||
<button class="accessory-btn" data-action="init" title="/init">/init</button>
|
<button class="accessory-btn" data-action="init" title="/init">/init</button>
|
||||||
<button class="accessory-btn" data-action="clear" title="/clear">/clear</button>
|
<button class="accessory-btn" data-action="clear" title="/clear">/clear</button>
|
||||||
<button class="accessory-btn" data-action="compact" title="/compact">/compact</button>
|
<button class="accessory-btn" data-action="compact" title="/compact">/compact</button>
|
||||||
<button class="accessory-btn accessory-btn-arrow" data-action="dismiss" title="Dismiss keyboard">
|
<button class="accessory-btn accessory-btn-dismiss" data-action="dismiss" title="Dismiss keyboard">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
|
||||||
<path d="M19 9l-7 7-7-7"/>
|
<path d="M19 9l-7 7-7-7"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>`,
|
||||||
`;
|
|
||||||
|
/** Create and inject the accessory bar */
|
||||||
|
init() {
|
||||||
|
// Only on mobile
|
||||||
|
if (!MobileDetection.isTouchDevice()) return;
|
||||||
|
|
||||||
|
// Create accessory bar element
|
||||||
|
this.element = document.createElement('div');
|
||||||
|
this.element.className = 'keyboard-accessory-bar';
|
||||||
|
this.element.innerHTML = this._simpleButtons;
|
||||||
|
|
||||||
// Add click handlers — preventDefault stops event from reaching terminal
|
// Add click handlers — preventDefault stops event from reaching terminal
|
||||||
this.element.addEventListener('click', (e) => {
|
this.element.addEventListener('click', (e) => {
|
||||||
@@ -95,7 +125,8 @@ const KeyboardAccessoryBar = {
|
|||||||
this.handleAction(action, btn);
|
this.handleAction(action, btn);
|
||||||
|
|
||||||
// Refocus terminal so keyboard stays open (tap blurs terminal → keyboard dismisses → toolbar shifts)
|
// Refocus terminal so keyboard stays open (tap blurs terminal → keyboard dismisses → toolbar shifts)
|
||||||
if ((action === 'scroll-up' || action === 'scroll-down' || action === 'arrow-left' || action === 'arrow-right' || action === 'tab' || action === 'shift-tab' || action === 'ctrl-o' || action === 'opt-enter' || action === 'esc') ||
|
const refocusActions = new Set(['scroll-up', 'scroll-down', 'arrow-left', 'arrow-right', 'tab', 'shift-tab', 'ctrl-o', 'opt-enter', 'esc']);
|
||||||
|
if (refocusActions.has(action) ||
|
||||||
((action === 'clear' || action === 'compact') && this._confirmAction)) {
|
((action === 'clear' || action === 'compact') && this._confirmAction)) {
|
||||||
if (typeof app !== 'undefined' && app.terminal) {
|
if (typeof app !== 'undefined' && app.terminal) {
|
||||||
app.terminal.focus();
|
app.terminal.focus();
|
||||||
@@ -110,6 +141,14 @@ const KeyboardAccessoryBar = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** Switch between 'simple' and 'extended' button layouts */
|
||||||
|
setMode(mode) {
|
||||||
|
if (mode === this._mode || !this.element) return;
|
||||||
|
this._mode = mode;
|
||||||
|
this.clearConfirm();
|
||||||
|
this.element.innerHTML = mode === 'extended' ? this._extendedButtons : this._simpleButtons;
|
||||||
|
},
|
||||||
|
|
||||||
_confirmTimer: null,
|
_confirmTimer: null,
|
||||||
_confirmAction: null,
|
_confirmAction: null,
|
||||||
|
|
||||||
|
|||||||
+51
-12
@@ -937,13 +937,33 @@ html.mobile-init .file-browser-panel {
|
|||||||
|
|
||||||
.accessory-btn-arrow {
|
.accessory-btn-arrow {
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
background: #1e3a5f;
|
background: #2563eb;
|
||||||
border-color: rgba(59, 130, 246, 0.3);
|
border-color: rgba(59, 130, 246, 0.5);
|
||||||
color: #93c5fd;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accessory-btn-arrow:active {
|
.accessory-btn-arrow:active {
|
||||||
|
background: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss {
|
||||||
|
margin-left: auto;
|
||||||
|
flex: 1 1 0;
|
||||||
|
max-width: 100px;
|
||||||
|
padding: 10px 8px;
|
||||||
background: #2563eb;
|
background: #2563eb;
|
||||||
|
border-color: rgba(59, 130, 246, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss svg {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss:active {
|
||||||
|
background: #1d4ed8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Voice preview — positioned above accessory bar on mobile */
|
/* Voice preview — positioned above accessory bar on mobile */
|
||||||
@@ -975,9 +995,9 @@ html.mobile-init .file-browser-panel {
|
|||||||
background: rgba(0, 0, 0, 0.6);
|
background: rgba(0, 0, 0, 0.6);
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-bottom: env(safe-area-inset-bottom, 12px);
|
padding-top: 15vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.paste-dialog {
|
.paste-dialog {
|
||||||
@@ -987,13 +1007,12 @@ html.mobile-init .file-browser-panel {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
width: calc(100% - 24px);
|
width: calc(100% - 24px);
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.paste-textarea {
|
.paste-textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 60px;
|
min-height: 80px;
|
||||||
max-height: 120px;
|
max-height: 200px;
|
||||||
background: var(--bg-primary, #0d0d14);
|
background: var(--bg-primary, #0d0d14);
|
||||||
color: var(--text-primary, #e0e0e0);
|
color: var(--text-primary, #e0e0e0);
|
||||||
border: 1px solid var(--border-color, #444);
|
border: 1px solid var(--border-color, #444);
|
||||||
@@ -2104,13 +2123,33 @@ html.mobile-init .file-browser-panel {
|
|||||||
|
|
||||||
.accessory-btn-arrow {
|
.accessory-btn-arrow {
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
background: #1e3a5f;
|
background: #2563eb;
|
||||||
border-color: rgba(59, 130, 246, 0.3);
|
border-color: rgba(59, 130, 246, 0.5);
|
||||||
color: #93c5fd;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accessory-btn-arrow:active {
|
.accessory-btn-arrow:active {
|
||||||
background: #2563eb;
|
background: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss {
|
||||||
|
margin-left: auto;
|
||||||
|
flex: 1 1 0;
|
||||||
|
max-width: 80px;
|
||||||
|
padding: 10px 8px;
|
||||||
|
background: #334d6e;
|
||||||
|
border-color: rgba(100, 150, 200, 0.4);
|
||||||
|
color: #c0d4e8;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accessory-btn-dismiss:active {
|
||||||
|
background: #3d5f85;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
|
|||||||
@@ -319,6 +319,7 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
this.loadTunnelStatus();
|
this.loadTunnelStatus();
|
||||||
document.getElementById('appSettingsLocalEcho').checked = settings.localEchoEnabled ?? MobileDetection.isTouchDevice();
|
document.getElementById('appSettingsLocalEcho').checked = settings.localEchoEnabled ?? MobileDetection.isTouchDevice();
|
||||||
document.getElementById('appSettingsCjkInput').checked = settings.cjkInputEnabled ?? false;
|
document.getElementById('appSettingsCjkInput').checked = settings.cjkInputEnabled ?? false;
|
||||||
|
document.getElementById('appSettingsExtendedKeyboardBar').checked = settings.extendedKeyboardBar ?? false;
|
||||||
document.getElementById('appSettingsTabTwoRows').checked = settings.tabTwoRows ?? defaults.tabTwoRows ?? false;
|
document.getElementById('appSettingsTabTwoRows').checked = settings.tabTwoRows ?? defaults.tabTwoRows ?? false;
|
||||||
// Claude CLI settings
|
// Claude CLI settings
|
||||||
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
const claudeModeSelect = document.getElementById('appSettingsClaudeMode');
|
||||||
@@ -1125,6 +1126,7 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
tunnelEnabled: document.getElementById('appSettingsTunnelEnabled').checked,
|
tunnelEnabled: document.getElementById('appSettingsTunnelEnabled').checked,
|
||||||
localEchoEnabled: document.getElementById('appSettingsLocalEcho').checked,
|
localEchoEnabled: document.getElementById('appSettingsLocalEcho').checked,
|
||||||
cjkInputEnabled: document.getElementById('appSettingsCjkInput').checked,
|
cjkInputEnabled: document.getElementById('appSettingsCjkInput').checked,
|
||||||
|
extendedKeyboardBar: document.getElementById('appSettingsExtendedKeyboardBar').checked,
|
||||||
tabTwoRows: document.getElementById('appSettingsTabTwoRows').checked,
|
tabTwoRows: document.getElementById('appSettingsTabTwoRows').checked,
|
||||||
// Claude CLI settings
|
// Claude CLI settings
|
||||||
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
claudeMode: document.getElementById('appSettingsClaudeMode').value,
|
||||||
@@ -1245,9 +1247,12 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
// Apply CJK input visibility immediately
|
// Apply CJK input visibility immediately
|
||||||
this._updateCjkInputState();
|
this._updateCjkInputState();
|
||||||
|
|
||||||
|
// Apply keyboard bar mode
|
||||||
|
KeyboardAccessoryBar.setMode(settings.extendedKeyboardBar ? 'extended' : 'simple');
|
||||||
|
|
||||||
// Save to server (includes notification prefs for cross-browser persistence)
|
// Save to server (includes notification prefs for cross-browser persistence)
|
||||||
// Strip device-specific keys — localEchoEnabled/cjkInputEnabled are per-platform
|
// Strip device-specific keys — localEchoEnabled/cjkInputEnabled are per-platform
|
||||||
const { localEchoEnabled: _leo, cjkInputEnabled: _cjk, ...serverSettings } = settings;
|
const { localEchoEnabled: _leo, cjkInputEnabled: _cjk, extendedKeyboardBar: _ekb, ...serverSettings } = settings;
|
||||||
try {
|
try {
|
||||||
await this._apiPut('/api/settings', { ...serverSettings, notificationPreferences: notifPrefsToSave, voiceSettings });
|
await this._apiPut('/api/settings', { ...serverSettings, notificationPreferences: notifPrefsToSave, voiceSettings });
|
||||||
|
|
||||||
@@ -1631,7 +1636,7 @@ Object.assign(CodemanApp.prototype, {
|
|||||||
const displayKeys = new Set([
|
const displayKeys = new Set([
|
||||||
'showFontControls', 'showSystemStats', 'showTokenCount', 'showCost',
|
'showFontControls', 'showSystemStats', 'showTokenCount', 'showCost',
|
||||||
'showMonitor', 'showProjectInsights', 'showFileBrowser', 'showSubagents',
|
'showMonitor', 'showProjectInsights', 'showFileBrowser', 'showSubagents',
|
||||||
'subagentActiveTabOnly', 'tabTwoRows', 'localEchoEnabled', 'cjkInputEnabled',
|
'subagentActiveTabOnly', 'tabTwoRows', 'localEchoEnabled', 'cjkInputEnabled', 'extendedKeyboardBar',
|
||||||
]);
|
]);
|
||||||
// Merge settings: non-display keys always sync from server,
|
// Merge settings: non-display keys always sync from server,
|
||||||
// display keys only seed from server when localStorage has no value
|
// display keys only seed from server when localStorage has no value
|
||||||
|
|||||||
Reference in New Issue
Block a user