feat: implement robust multi-tier text input architecture and ADB diagnostics

- Android Text Input & IME Normalization:
  - Implement progressive 3-tier input architecture in AndroidAdbDriver and AndroidDeviceController:
    - Tier 1 (Primary): Zero-dependency clipboard injection + KEYCODE_PASTE (immune to IME Pinyin interception, full Unicode/Emoji support, preserves multiline formatting).
    - Tier 2 (Broadcast): Base64 broadcast injection when ADBKeyboard is active.
    - Tier 3 (Fallback): Native ADB physical keyevent fallback.
  - Add literal newline normalization (\r\n, \n, \r) to prevent JSON escape string corruption (e.g. '10086\n' -> '10086、n').
  - Add set_clipboard method to UIAutomatorClient without auxiliary APK requirements.

- Diagnostics & System Probes:
  - Add adb_keys diagnostics probe for ADB key auth checks.
  - Integrate diagnostics into CLI doctor command.

- Admin Console & Showcase UI:
  - Improve model service and system router in admin console.
  - Enhance workspace stream view and session state in showcase UI.
This commit is contained in:
somew1nd committed 2026-08-24 16:48:45 -07:00
1 parent 42b8988661
commit ea3708a98f
19 files changed
+785 -89

No files matched your search

@@ -244,15 +244,15 @@
<!-- Floating Top-Right Badges & Toolbar (Pinned overlay, hidden in empty/initial state) -->
<div class="stream-floating-toolbar" *ngIf="consolidatedBlocks().length > 0 || showPlanningLoader()">
<!-- Active Model Info Chip (Informational Metadata, Not a Button) -->
<!-- Active Architecture Info Chip (Informational Metadata, Not a Button) -->
<div
class="model-info-chip"
[ngClass]="getModelClass(model.name)"
*ngIf="agentService.activeModel() as model"
[title]="'Active Model: ' + model.id + ' (' + model.provider + ')'"
[title]="getArchitectureTooltip(model)"
>
<span class="material-symbols-outlined model-icon">{{ getModelIcon(model.name) }}</span>
<span class="model-label">Model:</span>
<span class="model-label">Architecture:</span>
<span class="model-name">{{ getModelDisplayName(model.name) }}</span>
</div>
@@ -20,7 +20,7 @@ import { FormsModule } from '@angular/forms';
import { RouterLink } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { AgentService, StartupProgressEvent } from '../../services/agent.service';
import { Session } from '../../core/models/session.model';
import { Session, ModelInfo } from '../../core/models/session.model';
import { MarkdownSegment, MarkdownLine, NoteMilestone, ParsedNote } from '../../core/models/markdown.model';
import { StepBlock, PhaseBlock, StepEvent, ActionParam, CheckerResult } from '../../core/models/stream.model';
@@ -1262,6 +1262,19 @@ export class AgentStreamComponent implements AfterViewInit {
return '';
}
public getArchitectureTooltip(model?: ModelInfo | null): string {
if (!model) return 'Agent Architecture: ARTEMIS Flash (Reactive Fast Loop)';
const name = this.getModelDisplayName(model.name);
const isPro = name.toLowerCase().includes('pro');
const archDesc = isPro
? 'ARTEMIS Pro (Multi-Agent Cognitive State Graph)'
: 'ARTEMIS Flash (Reactive Fast Loop)';
if (model.id) {
return `Agent Architecture: ${archDesc} · LLM: ${model.id} (${model.provider || 'google'})`;
}
return `Agent Architecture: ${archDesc}`;
}
public formatTokenCount(tokens?: number): string {
return formatTokenCount(tokens);
}
@@ -18,6 +18,7 @@ export interface ModelInfo {
name: string;
id: string;
provider: string;
architecture?: string;
}
export interface TaskQueueItem {
@@ -1576,13 +1576,14 @@
<!-- Composer Bottom Action Bar -->
<div class="composer-action-bar">
<div class="bar-left">
<!-- Frosted Glass Model Toggle Capsule -->
<!-- Frosted Glass Architecture Toggle Capsule -->
<div class="model-toggle-capsule">
<button
type="button"
class="model-toggle-btn btn-flash"
[class.active]="selectedProfile() === 'flash'"
(click)="setProfile('flash')"
title="Flash: Reactive fast-loop architecture for standard app workflows (3–5s/step)"
>
<span class="material-symbols-outlined btn-icon">bolt</span>
<span class="btn-text">Flash</span>
@@ -1592,6 +1593,7 @@
class="model-toggle-btn btn-pro"
[class.active]="selectedProfile() === 'pro'"
(click)="setProfile('pro')"
title="Pro: Multi-agent graph architecture with planner & closed-loop verification for complex tasks"
>
<span class="material-symbols-outlined btn-icon">psychology</span>
<span class="btn-text">Pro</span>
@@ -1745,7 +1747,8 @@
<span class="app-names-label">{{ getAppNamesDisplay(item.apps) }}</span>
</div>
<span class="mode-badge" [class.mode-pro]="item.profile === 'pro'" [class.mode-flash]="item.profile === 'flash'">
<span class="mode-badge" [class.mode-pro]="item.profile === 'pro'" [class.mode-flash]="item.profile === 'flash'"
[title]="item.profile === 'pro' ? 'Uses ARTEMIS Pro (Multi-Agent Cognitive State Graph)' : 'Uses ARTEMIS Flash (Reactive Fast Loop)'">
{{ item.profile === 'pro' ? 'Pro' : 'Flash' }}
</span>
</div>
@@ -103,8 +103,8 @@
rows="1"
[disabled]="isSubmitting"
[placeholder]="selectedProfile() === 'pro'
? 'Pro: Best for complex long-running tasks, deep reasoning & video analysis'
: 'Flash: Fast execution for direct actions and tasks within 25 steps'"
? 'Pro: Multi-agent cognitive graph architecture for complex multi-step tasks'
: 'Flash: Reactive fast loop for standard app workflows within 25 steps'"
class="dock-textarea"
spellcheck="false"
></textarea>
@@ -141,17 +141,17 @@
<!-- Bottom Segmented Controls Row -->
<div class="card-footer-row">
<div class="footer-left-group">
<!-- Segmented Model Toggle (Flash / Pro) -->
<div class="model-profile-toggle" role="group" aria-label="Select AI Model">
<!-- Segmented Architecture Toggle (Flash / Pro) -->
<div class="model-profile-toggle" role="group" aria-label="Select Agent Architecture">
<button type="button" class="profile-toggle-pill" [class.active]="selectedProfile() === 'flash'"
(mousedown)="$event.preventDefault()" (click)="setProfile('flash', $event)"
title="Flash: Fast execution for standard app workflows">
title="Flash: Reactive fast-loop architecture for standard app workflows (3–5s/step)">
<span class="material-symbols-outlined pill-icon icon-flash">bolt</span>
<span class="pill-label">Flash</span>
</button>
<button type="button" class="profile-toggle-pill" [class.active]="selectedProfile() === 'pro'"
(mousedown)="$event.preventDefault()" (click)="setProfile('pro', $event)"
title="Pro: Deep multimodal reasoning for complex multi-step tasks">
title="Pro: Multi-agent cognitive graph architecture with planner & closed-loop verification for complex tasks">
<span class="material-symbols-outlined pill-icon icon-pro">psychology</span>
<span class="pill-label">Pro</span>
</button>
@@ -64,7 +64,7 @@ export class WorkspaceComponent implements OnInit {
}
/**
* Set model profile ('flash' vs 'pro')
* Set agent architecture profile ('flash' vs 'pro')
*/
public setProfile(profile: 'flash' | 'pro', event?: MouseEvent): void {
if (event) {