mirror of
https://github.com/samsonjs/Peekaboo.git
synced 2026-03-25 09:25:47 +00:00
Implement missing best practices
- Add npm run inspector script for MCP inspector tool - Synchronize Swift CLI version with package.json (1.0.0-beta.9) - Update macOS version requirement to v14 (Sonoma) for n-1 support - Add Swift compiler warnings check in prepare-release script - Convert tests/setup.ts from Jest to Vitest syntax - Update server status tests to match new format 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b9f7e2da7a
commit
7bf63a225c
8 changed files with 77 additions and 49 deletions
|
|
@ -29,6 +29,7 @@
|
|||
"lint:swift": "cd peekaboo-cli && swiftlint",
|
||||
"format:swift": "cd peekaboo-cli && swiftformat .",
|
||||
"prepare-release": "node ./scripts/prepare-release.js",
|
||||
"inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
|
||||
"postinstall": "chmod +x dist/index.js 2>/dev/null || true"
|
||||
},
|
||||
"keywords": [
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import PackageDescription
|
|||
let package = Package(
|
||||
name: "peekaboo",
|
||||
platforms: [
|
||||
.macOS(.v12)
|
||||
.macOS(.v14)
|
||||
],
|
||||
products: [
|
||||
.executable(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ struct PeekabooCommand: ParsableCommand {
|
|||
static let configuration = CommandConfiguration(
|
||||
commandName: "peekaboo",
|
||||
abstract: "A macOS utility for screen capture, application listing, and window management",
|
||||
version: "1.1.1",
|
||||
version: "1.0.0-beta.9",
|
||||
subcommands: [ImageCommand.self, ListCommand.self],
|
||||
defaultSubcommand: ImageCommand.self
|
||||
)
|
||||
|
|
|
|||
|
|
@ -203,6 +203,37 @@ function checkSwift() {
|
|||
}
|
||||
logSuccess('SwiftLint passed');
|
||||
|
||||
// Check for Swift compiler warnings/errors
|
||||
log('Checking for Swift compiler warnings...', colors.cyan);
|
||||
let swiftBuildOutput = '';
|
||||
try {
|
||||
// Capture build output to check for warnings
|
||||
swiftBuildOutput = execSync('cd peekaboo-cli && swift build --arch arm64 -c release 2>&1', {
|
||||
cwd: projectRoot,
|
||||
encoding: 'utf8'
|
||||
});
|
||||
} catch (error) {
|
||||
logError('Swift build failed during analyzer check');
|
||||
if (error.stdout) console.log(error.stdout);
|
||||
if (error.stderr) console.log(error.stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for warnings in the output
|
||||
const warningMatches = swiftBuildOutput.match(/warning:|note:/gi);
|
||||
if (warningMatches && warningMatches.length > 0) {
|
||||
logWarning(`Found ${warningMatches.length} warnings/notes in Swift build`);
|
||||
// Extract and show warning lines
|
||||
const lines = swiftBuildOutput.split('\n');
|
||||
lines.forEach(line => {
|
||||
if (line.includes('warning:') || line.includes('note:')) {
|
||||
console.log(` ${line.trim()}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
logSuccess('No Swift compiler warnings found');
|
||||
}
|
||||
|
||||
// Run Swift tests
|
||||
if (!execWithOutput('npm run test:swift', 'Swift tests')) {
|
||||
logError('Swift tests failed');
|
||||
|
|
|
|||
|
|
@ -14,18 +14,29 @@ export const listToolSchema = z
|
|||
item_type: z
|
||||
.enum(["running_applications", "application_windows", "server_status"])
|
||||
.default("running_applications")
|
||||
.describe("What to list. 'server_status' returns Peekaboo server info."),
|
||||
.describe(
|
||||
"Specifies the type of items to list. Valid options are:\n" +
|
||||
"- `running_applications`: Lists all currently running applications with details like name, bundle ID, PID, active status, and window count.\n" +
|
||||
"- `application_windows`: Lists open windows for a specific application. Requires the `app` parameter. Details can be customized with `include_window_details`.\n" +
|
||||
"- `server_status`: Returns information about the Peekaboo MCP server itself, including its version and configured AI providers."
|
||||
),
|
||||
app: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
"Required if 'item_type' is 'application_windows'. Target application. Uses fuzzy matching.",
|
||||
"Required when `item_type` is `application_windows`. " +
|
||||
"Specifies the target application by its name (e.g., \"Safari\", \"TextEdit\") or bundle ID. " +
|
||||
"Fuzzy matching is used, so partial names may work."
|
||||
),
|
||||
include_window_details: z
|
||||
.array(z.enum(["off_screen", "bounds", "ids"]))
|
||||
.optional()
|
||||
.describe(
|
||||
"Optional, for 'application_windows'. Additional window details. Example: ['bounds', 'ids']",
|
||||
"Optional, only applicable when `item_type` is `application_windows`. " +
|
||||
"Specifies additional details to include for each window. Provide an array of strings. Example: `[\"bounds\", \"ids\"]`.\n" +
|
||||
"- `ids`: Include window ID.\n" +
|
||||
"- `bounds`: Include window position and size (x, y, width, height).\n" +
|
||||
"- `off_screen`: Indicate if the window is currently off-screen."
|
||||
),
|
||||
})
|
||||
.refine(
|
||||
|
|
@ -54,6 +65,11 @@ export const listToolSchema = z
|
|||
"'app' and 'include_window_details' not applicable for 'server_status'.",
|
||||
path: ["item_type"],
|
||||
},
|
||||
)
|
||||
.describe(
|
||||
"Lists various system items, providing situational awareness. " +
|
||||
"Can retrieve running applications, windows of a specific app, or server status. " +
|
||||
"App identifier uses fuzzy matching for convenience."
|
||||
);
|
||||
|
||||
export type ListToolInput = z.infer<typeof listToolSchema>;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ describe("Swift CLI Integration Tests", () => {
|
|||
) {
|
||||
const firstContentItem = response.content[0] as PeekabooContentItem;
|
||||
expect(firstContentItem.type).toBe("text");
|
||||
expect(firstContentItem.text).toContain("Peekaboo MCP Server Status");
|
||||
expect(firstContentItem.text).toContain("Peekaboo MCP");
|
||||
} else {
|
||||
fail(
|
||||
"Response content was not in the expected format for server_status",
|
||||
|
|
|
|||
|
|
@ -1,30 +1,29 @@
|
|||
// Jest setup file
|
||||
// Vitest setup file
|
||||
// Configure global test environment
|
||||
|
||||
import { beforeEach, afterEach, vi } from 'vitest';
|
||||
|
||||
// Mock console methods to reduce noise during testing
|
||||
const originalConsole = global.console;
|
||||
const originalConsole = globalThis.console;
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset console mocks before each test
|
||||
global.console = {
|
||||
globalThis.console = {
|
||||
...originalConsole,
|
||||
log: jest.fn(),
|
||||
error: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
info: jest.fn(),
|
||||
debug: jest.fn(),
|
||||
log: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
info: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// Restore original console after each test
|
||||
global.console = originalConsole;
|
||||
jest.clearAllMocks();
|
||||
globalThis.console = originalConsole;
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
// Global test timeout
|
||||
jest.setTimeout(10000);
|
||||
|
||||
// Mock environment variables for testing
|
||||
process.env.NODE_ENV = "test";
|
||||
process.env.PEEKABOO_AI_PROVIDERS = JSON.stringify([
|
||||
|
|
@ -34,4 +33,4 @@ process.env.PEEKABOO_AI_PROVIDERS = JSON.stringify([
|
|||
model: "llava",
|
||||
enabled: true,
|
||||
},
|
||||
]);
|
||||
]);
|
||||
|
|
@ -10,69 +10,50 @@ describe("Server Status Utility - generateServerStatusString", () => {
|
|||
|
||||
it("should return status with default providers text when PEEKABOO_AI_PROVIDERS is not set", () => {
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): None Configured. Set PEEKABOO_AI_PROVIDERS ENV.",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using None Configured. Set PEEKABOO_AI_PROVIDERS ENV.`);
|
||||
});
|
||||
|
||||
it("should return status with default providers text when PEEKABOO_AI_PROVIDERS is an empty string", () => {
|
||||
process.env.PEEKABOO_AI_PROVIDERS = "";
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): None Configured. Set PEEKABOO_AI_PROVIDERS ENV.",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using None Configured. Set PEEKABOO_AI_PROVIDERS ENV.`);
|
||||
});
|
||||
|
||||
it("should return status with default providers text when PEEKABOO_AI_PROVIDERS is whitespace", () => {
|
||||
process.env.PEEKABOO_AI_PROVIDERS = " ";
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): None Configured. Set PEEKABOO_AI_PROVIDERS ENV.",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using None Configured. Set PEEKABOO_AI_PROVIDERS ENV.`);
|
||||
});
|
||||
|
||||
it("should list a single provider from PEEKABOO_AI_PROVIDERS", () => {
|
||||
process.env.PEEKABOO_AI_PROVIDERS = "ollama/llava";
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): ollama/llava",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using ollama/llava`);
|
||||
});
|
||||
|
||||
it("should list multiple providers from PEEKABOO_AI_PROVIDERS, trimmed and joined", () => {
|
||||
process.env.PEEKABOO_AI_PROVIDERS = "ollama/llava, openai/gpt-4o";
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): ollama/llava, openai/gpt-4o",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using ollama/llava, openai/gpt-4o`);
|
||||
});
|
||||
|
||||
it("should handle extra whitespace and empty segments in PEEKABOO_AI_PROVIDERS", () => {
|
||||
process.env.PEEKABOO_AI_PROVIDERS =
|
||||
" ollama/llava , ,, openai/gpt-4o ,anthropic/claude ";
|
||||
const status = generateServerStatusString(testVersion);
|
||||
expect(status).toContain(`Version: ${testVersion}`);
|
||||
expect(status).toContain(
|
||||
"Configured AI Providers (from PEEKABOO_AI_PROVIDERS ENV): ollama/llava, openai/gpt-4o, anthropic/claude",
|
||||
);
|
||||
expect(status).toBe(`Peekaboo MCP ${testVersion} using ollama/llava, openai/gpt-4o, anthropic/claude`);
|
||||
});
|
||||
|
||||
it("should correctly include the provided version string", () => {
|
||||
const customVersion = "z.y.x";
|
||||
const status = generateServerStatusString(customVersion);
|
||||
expect(status).toContain(`Version: ${customVersion}`);
|
||||
expect(status).toBe(`Peekaboo MCP ${customVersion} using None Configured. Set PEEKABOO_AI_PROVIDERS ENV.`);
|
||||
});
|
||||
|
||||
it("should produce a trimmed multi-line string", () => {
|
||||
it("should produce a trimmed string", () => {
|
||||
const status = generateServerStatusString("0.0.1");
|
||||
expect(status.startsWith("---")).toBe(true);
|
||||
expect(status.endsWith("---")).toBe(true);
|
||||
expect(status).not.toMatch(/^\s/); // No leading whitespace
|
||||
expect(status).not.toMatch(/\s$/); // No trailing whitespace
|
||||
expect(status.startsWith("Peekaboo MCP")).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue