mirror of
https://github.com/samsonjs/Peekaboo.git
synced 2026-04-27 15:07:41 +00:00
rename swift-cli to peekaboo-cli
This commit is contained in:
parent
99acdff66f
commit
857ce73b94
11 changed files with 36 additions and 34 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build:swift": "./scripts/build-swift-cli.sh",
|
"build:swift": "./scripts/build-peekaboo-cli.sh",
|
||||||
"build:all": "npm run build:swift && npm run build",
|
"build:all": "npm run build:swift && npm run build",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"prepublishOnly": "npm run build:all",
|
"prepublishOnly": "npm run build:all",
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test:coverage": "jest --coverage",
|
"test:coverage": "jest --coverage",
|
||||||
"test:swift": "cd swift-cli && swift test",
|
"test:swift": "cd peekaboo-cli && swift test",
|
||||||
"test:integration": "npm run build && npm run test:swift && npm test",
|
"test:integration": "npm run build && npm run test:swift && npm test",
|
||||||
"test:all": "npm run test:integration",
|
"test:all": "npm run test:integration",
|
||||||
"postinstall": "chmod +x dist/index.js 2>/dev/null || true"
|
"postinstall": "chmod +x dist/index.js 2>/dev/null || true"
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ set -e
|
||||||
|
|
||||||
echo "Building Swift CLI..."
|
echo "Building Swift CLI..."
|
||||||
|
|
||||||
# Change to swift-cli directory
|
# Change to peekaboo-cli directory
|
||||||
cd "$(dirname "$0")/../swift-cli"
|
cd "$(dirname "$0")/../peekaboo-cli"
|
||||||
|
|
||||||
# Build the Swift CLI in release mode
|
# Build the Swift CLI in release mode
|
||||||
swift build --configuration release
|
swift build --configuration release
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e # Exit immediately if a command exits with a non-zero status.
|
set -e # Exit immediately if a command exits with a non-zero status.
|
||||||
|
|
||||||
PROJECT_ROOT_REL=".." # Relative path to project root from swift-cli
|
PROJECT_ROOT_REL=".." # Relative path to project root from peekaboo-cli
|
||||||
PROJECT_ROOT=$(cd "$(dirname "$0")/$PROJECT_ROOT_REL" && pwd)
|
PROJECT_ROOT=$(cd "$(dirname "$0")/$PROJECT_ROOT_REL" && pwd)
|
||||||
SWIFT_PROJECT_PATH="$PROJECT_ROOT/swift-cli"
|
SWIFT_PROJECT_PATH="$PROJECT_ROOT/peekaboo-cli"
|
||||||
FINAL_BINARY_NAME="peekaboo"
|
FINAL_BINARY_NAME="peekaboo"
|
||||||
FINAL_BINARY_PATH="$PROJECT_ROOT/$FINAL_BINARY_NAME"
|
FINAL_BINARY_PATH="$PROJECT_ROOT/$FINAL_BINARY_NAME"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { ToolContext, AIProvider } from '../types/index.js';
|
import { ToolContext, AIProvider } from '../types/index.js';
|
||||||
import { readImageAsBase64 } from '../utils/swift-cli.js';
|
import { readImageAsBase64 } from '../utils/peekaboo-cli.js';
|
||||||
import {
|
import {
|
||||||
parseAIProviders,
|
parseAIProviders,
|
||||||
isProviderAvailable,
|
isProviderAvailable,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { ToolContext, ImageCaptureData, SavedFile } from '../types/index.js';
|
import { ToolContext, ImageCaptureData, SavedFile } from '../types/index.js';
|
||||||
import { executeSwiftCli, readImageAsBase64 } from '../utils/swift-cli.js';
|
import { executeSwiftCli, readImageAsBase64 } from '../utils/peekaboo-cli.js';
|
||||||
|
|
||||||
export const imageToolSchema = z.object({
|
export const imageToolSchema = z.object({
|
||||||
app: z.string().optional().describe("Optional. Target application: name, bundle ID, or partial name. If omitted, captures screen(s). Uses fuzzy matching."),
|
app: z.string().optional().describe("Optional. Target application: name, bundle ID, or partial name. If omitted, captures screen(s). Uses fuzzy matching."),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { ToolContext, ApplicationListData, WindowListData } from '../types/index.js';
|
import { ToolContext, ApplicationListData, WindowListData } from '../types/index.js';
|
||||||
import { executeSwiftCli } from '../utils/swift-cli.js';
|
import { executeSwiftCli } from '../utils/peekaboo-cli.js';
|
||||||
import { generateServerStatusString } from '../utils/server-status.js';
|
import { generateServerStatusString } from '../utils/server-status.js';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { imageToolHandler, buildSwiftCliArgs, ImageToolInput } from '../../../src/tools/image';
|
import { imageToolHandler, buildSwiftCliArgs, ImageToolInput } from '../../../src/tools/image';
|
||||||
import { executeSwiftCli, readImageAsBase64 } from '../../../src/utils/swift-cli';
|
import { executeSwiftCli, readImageAsBase64 } from '../../../src/utils/peekaboo-cli';
|
||||||
import { mockSwiftCli } from '../../mocks/swift-cli.mock';
|
import { mockSwiftCli } from '../../mocks/peekaboo-cli.mock';
|
||||||
import { pino } from 'pino';
|
import { pino } from 'pino';
|
||||||
import { SavedFile, ImageCaptureData } from '../../../src/types';
|
import { SavedFile, ImageCaptureData } from '../../../src/types';
|
||||||
|
|
||||||
// Mock the Swift CLI utility
|
// Mock the Swift CLI utility
|
||||||
jest.mock('../../../src/utils/swift-cli', () => ({
|
jest.mock('../../../src/utils/peekaboo-cli', () => ({
|
||||||
executeSwiftCli: jest.fn(),
|
executeSwiftCli: jest.fn(),
|
||||||
readImageAsBase64: jest.fn()
|
readImageAsBase64: jest.fn()
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { pino } from 'pino';
|
import { pino } from 'pino';
|
||||||
import { listToolHandler, buildSwiftCliArgs, ListToolInput } from '../../../src/tools/list';
|
import { listToolHandler, buildSwiftCliArgs, ListToolInput, listToolSchema } from '../../../src/tools/list';
|
||||||
import { executeSwiftCli } from '../../../src/utils/swift-cli';
|
import { executeSwiftCli } from '../../../src/utils/peekaboo-cli';
|
||||||
import { generateServerStatusString } from '../../../src/utils/server-status';
|
import { generateServerStatusString } from '../../../src/utils/server-status';
|
||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
// import path from 'path'; // path is still used by the test itself for expect.stringContaining if needed, but not for mocking resolve/dirname
|
// import path from 'path'; // path is still used by the test itself for expect.stringContaining if needed, but not for mocking resolve/dirname
|
||||||
|
|
@ -8,7 +8,7 @@ import fs from 'fs/promises';
|
||||||
import { ToolContext, ApplicationListData, WindowListData } from '../../../src/types/index.js';
|
import { ToolContext, ApplicationListData, WindowListData } from '../../../src/types/index.js';
|
||||||
|
|
||||||
// Mocks
|
// Mocks
|
||||||
jest.mock('../../../src/utils/swift-cli');
|
jest.mock('../../../src/utils/peekaboo-cli');
|
||||||
jest.mock('../../../src/utils/server-status');
|
jest.mock('../../../src/utils/server-status');
|
||||||
jest.mock('fs/promises');
|
jest.mock('fs/promises');
|
||||||
|
|
||||||
|
|
@ -230,13 +230,15 @@ describe('List Tool', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle missing app parameter for application_windows', async () => {
|
it('should handle missing app parameter for application_windows', async () => {
|
||||||
const result = await listToolHandler({
|
// The Zod schema validation should catch this before the handler is called
|
||||||
item_type: 'application_windows'
|
// In real usage, this would throw a validation error
|
||||||
}, mockContext);
|
// For testing, we can simulate what would happen if validation was bypassed
|
||||||
|
expect(() => {
|
||||||
expect(result.isError).toBe(true);
|
listToolSchema.parse({
|
||||||
expect(result.content[0].text).toBe("For 'application_windows', 'app' identifier is required.");
|
item_type: 'application_windows'
|
||||||
expect(mockExecuteSwiftCli).not.toHaveBeenCalled();
|
// missing app parameter
|
||||||
|
});
|
||||||
|
}).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle empty applications list', async () => {
|
it('should handle empty applications list', async () => {
|
||||||
|
|
@ -364,7 +366,7 @@ describe('List Tool', () => {
|
||||||
|
|
||||||
const result = await listToolHandler({
|
const result = await listToolHandler({
|
||||||
item_type: 'running_applications'
|
item_type: 'running_applications'
|
||||||
}, mockContext);
|
}, mockContext) as any;
|
||||||
|
|
||||||
expect(result.isError).toBe(true);
|
expect(result.isError).toBe(true);
|
||||||
expect(result.content[0].text).toContain('Invalid response');
|
expect(result.content[0].text).toContain('Invalid response');
|
||||||
|
|
@ -379,7 +381,7 @@ describe('List Tool', () => {
|
||||||
const result = await listToolHandler({
|
const result = await listToolHandler({
|
||||||
item_type: 'application_windows',
|
item_type: 'application_windows',
|
||||||
app: 'Safari'
|
app: 'Safari'
|
||||||
}, mockContext);
|
}, mockContext) as any;
|
||||||
|
|
||||||
expect(result.isError).toBe(true);
|
expect(result.isError).toBe(true);
|
||||||
expect(result.content[0].text).toContain('Invalid response');
|
expect(result.content[0].text).toContain('Invalid response');
|
||||||
|
|
@ -459,7 +461,7 @@ describe('List Tool', () => {
|
||||||
|
|
||||||
const result = await listToolHandler({
|
const result = await listToolHandler({
|
||||||
item_type: 'server_status'
|
item_type: 'server_status'
|
||||||
}, mockContext);
|
}, mockContext) as any;
|
||||||
|
|
||||||
expect(result.isError).toBe(true);
|
expect(result.isError).toBe(true);
|
||||||
expect(result.content[0].text).toContain('Unexpected error');
|
expect(result.content[0].text).toContain('Unexpected error');
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { executeSwiftCli, initializeSwiftCliPath } from '../../../src/utils/swift-cli';
|
import { executeSwiftCli, initializeSwiftCliPath } from '../../../src/utils/peekaboo-cli';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import path from 'path'; // Import path for joining
|
import path from 'path'; // Import path for joining
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ describe('Swift CLI Utility', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
process.env.CLI_PATH = '';
|
process.env.PEEKABOO_CLI_PATH = '';
|
||||||
// Reset the internal resolvedCliPath by re-importing or having a reset function (not available here)
|
// Reset the internal resolvedCliPath by re-importing or having a reset function (not available here)
|
||||||
// For now, we will rely on initializeSwiftCliPath overwriting it or testing its logic flow.
|
// For now, we will rely on initializeSwiftCliPath overwriting it or testing its logic flow.
|
||||||
// This is a limitation of testing module-scoped variables without a reset mechanism.
|
// This is a limitation of testing module-scoped variables without a reset mechanism.
|
||||||
|
|
@ -36,18 +36,18 @@ describe('Swift CLI Utility', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('executeSwiftCli with path resolution', () => {
|
describe('executeSwiftCli with path resolution', () => {
|
||||||
it('should use CLI path from CLI_PATH if set and valid', async () => {
|
it('should use CLI path from PEEKABOO_CLI_PATH if set and valid', async () => {
|
||||||
process.env.CLI_PATH = CUSTOM_CLI_PATH;
|
process.env.PEEKABOO_CLI_PATH = CUSTOM_CLI_PATH;
|
||||||
mockExistsSync.mockReturnValue(true); // Simulate path exists
|
mockExistsSync.mockReturnValue(true); // Simulate path exists
|
||||||
initializeSwiftCliPath(MOCK_PACKAGE_ROOT); // Root dir is secondary if CLI_PATH is valid
|
initializeSwiftCliPath(MOCK_PACKAGE_ROOT); // Root dir is secondary if PEEKABOO_CLI_PATH is valid
|
||||||
|
|
||||||
mockSpawn.mockReturnValue({ stdout: { on: jest.fn() }, stderr: { on: jest.fn() }, on: jest.fn((e,c) => {if(e==='close')c(0)}) });
|
mockSpawn.mockReturnValue({ stdout: { on: jest.fn() }, stderr: { on: jest.fn() }, on: jest.fn((e,c) => {if(e==='close')c(0)}) });
|
||||||
await executeSwiftCli(['test'], mockLogger);
|
await executeSwiftCli(['test'], mockLogger);
|
||||||
expect(mockSpawn).toHaveBeenCalledWith(CUSTOM_CLI_PATH, ['test', '--json-output']);
|
expect(mockSpawn).toHaveBeenCalledWith(CUSTOM_CLI_PATH, ['test', '--json-output']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use bundled path if CLI_PATH is set but invalid', async () => {
|
it('should use bundled path if PEEKABOO_CLI_PATH is set but invalid', async () => {
|
||||||
process.env.CLI_PATH = '/invalid/path/peekaboo';
|
process.env.PEEKABOO_CLI_PATH = '/invalid/path/peekaboo';
|
||||||
mockExistsSync.mockReturnValue(false); // Simulate path does NOT exist
|
mockExistsSync.mockReturnValue(false); // Simulate path does NOT exist
|
||||||
initializeSwiftCliPath(MOCK_PACKAGE_ROOT);
|
initializeSwiftCliPath(MOCK_PACKAGE_ROOT);
|
||||||
|
|
||||||
|
|
@ -59,8 +59,8 @@ describe('Swift CLI Utility', () => {
|
||||||
// expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('PEEKABOO_CLI_PATH is set to '/invalid/custom/path', but this path does not exist'));
|
// expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('PEEKABOO_CLI_PATH is set to '/invalid/custom/path', but this path does not exist'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should use bundled path derived from packageRootDir if CLI_PATH is not set', async () => {
|
it('should use bundled path derived from packageRootDir if PEEKABOO_CLI_PATH is not set', async () => {
|
||||||
// CLI_PATH is empty by default from beforeEach
|
// PEEKABOO_CLI_PATH is empty by default from beforeEach
|
||||||
initializeSwiftCliPath(MOCK_PACKAGE_ROOT);
|
initializeSwiftCliPath(MOCK_PACKAGE_ROOT);
|
||||||
|
|
||||||
mockSpawn.mockReturnValue({ stdout: { on: jest.fn() }, stderr: { on: jest.fn() }, on: jest.fn((e,c) => {if(e==='close')c(0)}) });
|
mockSpawn.mockReturnValue({ stdout: { on: jest.fn() }, stderr: { on: jest.fn() }, on: jest.fn((e,c) => {if(e==='close')c(0)}) });
|
||||||
Loading…
Reference in a new issue