Initialize smartkvm package

This commit is contained in:
2026-05-16 13:41:55 +00:00
commit 8588c6c70d
18 changed files with 8751 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { SmartBrowserKvm } from '../ts/smartkvm.classes.browserkvm.js';
tap.test('SmartBrowserKvm manual smoke test', async () => {
if (!process.env.SMARTKVM_TEST_URL) {
expect(true).toBeTrue();
return;
}
const kvm = new SmartBrowserKvm({
url: process.env.SMARTKVM_TEST_URL,
username: process.env.SMARTKVM_TEST_USERNAME,
password: process.env.SMARTKVM_TEST_PASSWORD,
headless: process.env.SMARTKVM_TEST_HEADLESS !== 'false',
ignoreHttpsErrors: true,
timeoutMs: 30000,
});
try {
await kvm.connect();
const frame = await kvm.captureFrame();
expect(frame.mimeType).toEqual('image/png');
expect(frame.dataBase64).toBeTypeofString();
} finally {
await kvm.disconnect();
}
});
export default tap.start();
+59
View File
@@ -0,0 +1,59 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import {
createWrappedKvmCommand,
parseWrappedKvmCommandOutput,
} from '../ts/smartkvm.commandwrappers.js';
tap.test('bash wrapper should contain OCR-friendly markers', async () => {
const wrappedCommand = createWrappedKvmCommand('echo hello', 'bash');
expect(wrappedCommand.commandId).toMatch(/^[a-f0-9]{32}$/);
expect(wrappedCommand.startMarker).toEqual(`SMARTKVM_START_${wrappedCommand.commandId}`);
expect(wrappedCommand.endMarkerPrefix).toEqual(`SMARTKVM_END_${wrappedCommand.commandId}_`);
expect(wrappedCommand.textToType).toInclude(wrappedCommand.startMarker);
expect(wrappedCommand.textToType).toInclude(wrappedCommand.endMarkerPrefix);
expect(wrappedCommand.textToType).toInclude('echo hello');
});
tap.test('powershell wrapper should contain valid markers', async () => {
const wrappedCommand = createWrappedKvmCommand('Get-Location', 'powershell');
expect(wrappedCommand.textToType).toInclude(wrappedCommand.startMarker);
expect(wrappedCommand.textToType).toInclude(wrappedCommand.endMarkerPrefix);
expect(wrappedCommand.textToType).toInclude('try { Get-Location;');
});
tap.test('cmd wrapper should contain valid markers', async () => {
const wrappedCommand = createWrappedKvmCommand('dir', 'cmd');
expect(wrappedCommand.textToType).toInclude(`echo ${wrappedCommand.startMarker}`);
expect(wrappedCommand.textToType).toInclude(`echo ${wrappedCommand.endMarkerPrefix}%ERRORLEVEL%`);
});
tap.test('parser should extract command output and exit code', async () => {
const parsedResult = parseWrappedKvmCommandOutput({
commandId: 'abc123',
startMarker: 'SMARTKVM_START_abc123',
endMarkerPrefix: 'SMARTKVM_END_abc123_',
rawText: `something before
SMARTKVM_START_abc123
hello world
SMARTKVM_END_abc123_0
prompt after`,
});
expect(parsedResult.completed).toBeTrue();
expect(parsedResult.exitCode).toEqual(0);
expect(parsedResult.combinedText).toEqual('hello world');
});
tap.test('parser should return incomplete result if markers are missing', async () => {
const parsedResult = parseWrappedKvmCommandOutput({
commandId: 'abc123',
startMarker: 'SMARTKVM_START_abc123',
endMarkerPrefix: 'SMARTKVM_END_abc123_',
rawText: 'hello world',
});
expect(parsedResult.completed).toBeFalse();
expect(parsedResult.combinedText).toEqual('hello world');
});
export default tap.start();
+109
View File
@@ -0,0 +1,109 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import { SmartKvmTerminal } from '../ts/smartkvm.classes.kvmterminal.js';
import type {
IKvmDriver,
IKvmFrame,
IOcrEngine,
IOcrRecognizeOptions,
TKvmKey,
TKvmKind,
} from '../ts/smartkvm.interfaces.js';
class MockKvmDriver implements IKvmDriver {
public readonly kind: TKvmKind = 'generic';
public typedTexts: string[] = [];
public pressedKeys: TKvmKey[] = [];
public pressedShortcuts: TKvmKey[][] = [];
public focusViewerCalls = 0;
public async connect(): Promise<void> {}
public async disconnect(): Promise<void> {}
public async focusViewer(): Promise<void> {
this.focusViewerCalls++;
}
public async captureFrame(): Promise<IKvmFrame> {
return {
timestamp: Date.now(),
width: 1,
height: 1,
mimeType: 'image/png',
dataBase64: 'iVBORw0KGgo=',
};
}
public async typeText(text: string): Promise<void> {
this.typedTexts.push(text);
}
public async pressKey(key: TKvmKey): Promise<void> {
this.pressedKeys.push(key);
}
public async pressShortcut(keys: TKvmKey[]): Promise<void> {
this.pressedShortcuts.push(keys);
}
public async wait(): Promise<void> {}
}
tap.test('SmartKvmTerminal should run wrapped commands through mock KVM and OCR', async () => {
const mockKvm = new MockKvmDriver();
let recognizeCalls = 0;
const mockOcrEngine: IOcrEngine = {
recognize: async (_frame: IKvmFrame, options?: IOcrRecognizeOptions) => {
recognizeCalls++;
expect(options?.language).toEqual('eng');
const typedText = mockKvm.typedTexts.join('\n');
const commandId = typedText.match(/SMARTKVM_START_([a-f0-9]+)/)?.[1] ?? 'missing';
if (recognizeCalls === 1) {
return {
text: `SMARTKVM_START_${commandId}\npartial output`,
};
}
return {
text: `prompt\nSMARTKVM_START_${commandId}\nhello terminal\nSMARTKVM_END_${commandId}_0\nprompt`,
};
},
};
const terminal = new SmartKvmTerminal({
kvm: mockKvm,
ocrEngine: mockOcrEngine,
shellHint: 'bash',
commandTimeoutMs: 2000,
ocrPollIntervalMs: 1,
});
const result = await terminal.runCommand('echo hello');
expect(mockKvm.focusViewerCalls).toBeGreaterThan(0);
expect(mockKvm.typedTexts[0]).toInclude('echo hello');
expect(mockKvm.typedTexts[0]).toInclude('SMARTKVM_START_');
expect(mockKvm.pressedKeys).toContain('Enter');
expect(recognizeCalls).toEqual(2);
expect(result.completed).toBeTrue();
expect(result.timedOut).toBeFalse();
expect(result.exitCode).toEqual(0);
expect(result.combinedText).toEqual('hello terminal');
});
tap.test('SmartKvmTerminal bootstrap should use generic Linux shortcut', async () => {
const mockKvm = new MockKvmDriver();
const terminal = new SmartKvmTerminal({
kvm: mockKvm,
ocrEngine: {
recognize: async () => ({ text: '' }),
},
osHint: 'linux',
});
await terminal.bootstrap();
expect(mockKvm.pressedShortcuts).toEqual([['Control', 'Alt', 'T']]);
});
export default tap.start();