Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
518 changes: 370 additions & 148 deletions chat-sample/package-lock.json

Large diffs are not rendered by default.

35 changes: 30 additions & 5 deletions chat-sample/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "chat-sample",
"publisher": "vscode-samples",
"publisher": "vscode-samples-justin",
"displayName": "Copilot Chat Sample",
"description": "Sample chat extension, a trusty cat tutor that will can teach you computer science topics.",
"repository": {
Expand All @@ -15,6 +15,9 @@
"AI",
"Chat"
],
"enabledApiProposals": [
"languageModelDataPart"
],
"activationEvents": [],
"contributes": {
"chatParticipants": [
Expand All @@ -26,8 +29,8 @@
"isSticky": true,
"commands": [
{
"name": "randomTeach",
"description": "Pick at random a computer science concept then explain it in purfect way of a cat"
"name": "catTakePhoto",
"description": "The cat is trying to take a photo."
},
{
"name": "play",
Expand Down Expand Up @@ -155,6 +158,26 @@
"command"
]
}
},
{
"name": "chat-tools-sample_capture",
"tags": [
"terminal",
"chat-tools-sample",
"screenshot",
"capture"
],
"displayName": "Capture Screenshot",
"modelDescription": "Capture a screenshot and return the image",
"inputSchema": {
"type": "object",
"properties": {
"screenshot": {
"type": "string",
"description": "Take a screenshot of the current window or screen or whatever is available."
}
}
}
}
],
"commands": [
Expand All @@ -173,15 +196,17 @@
},
"dependencies": {
"@vscode/chat-extension-utils": "^0.0.0-alpha.1",
"@vscode/prompt-tsx": "^0.3.0-alpha.12"
"@vscode/prompt-tsx": "^0.3.0-alpha.12",
"screenshot-desktop": "^1.15.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
"@stylistic/eslint-plugin": "^2.9.0",
"@types/screenshot-desktop": "^1.12.3",
"@types/node": "^22",
"@types/vscode": "^1.100.0",
"eslint": "^9.13.0",
"typescript": "^5.9.2",
"typescript-eslint": "^8.39.0"
}
}
}
77 changes: 77 additions & 0 deletions chat-sample/src/listSimulators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as util from 'util';
import { exec as execCallback } from 'child_process';
import * as vscode from 'vscode';

const exec = util.promisify(execCallback);

interface SimulatorDevice {
name: string;
udid: string;
state: string;
}

export async function listSimulators(): Promise<SimulatorDevice[]> {
try {
const { stdout } = await exec('xcrun simctl list devices available --json');
const result = JSON.parse(stdout);
const devices: SimulatorDevice[] = [];

// Parse the devices from all runtimes
Object.values(result.devices).forEach((runtime: any) => {
(runtime as any[]).forEach(device => {
if (device.state === 'Booted' || device.state === 'Shutdown') {
devices.push({
name: device.name,
udid: device.udid,
state: device.state
});
}
});
});

return devices;
} catch (error) {
console.error('Failed to list simulators:', error);
return [];
}
}

export async function captureScreenshot(udid: string): Promise<Uint8Array | undefined> {
try {
// Ensure the simulator is booted
const devices = await listSimulators();
const device = devices.find(d => d.udid === udid);

if (!device) {
throw new Error(`No simulator found with UDID ${udid}`);
}

if (device.state !== 'Booted') {
await exec(`xcrun simctl boot ${udid}`);
// Wait a moment for the simulator to fully boot
await new Promise(resolve => setTimeout(resolve, 5000));
}

// Create a temporary file for the screenshot
const tempDir = vscode.Uri.joinPath(vscode.Uri.file(process.env.TMPDIR || '/tmp'), 'vscode-simulator-capture');
const tempFile = vscode.Uri.joinPath(tempDir, `${udid}.png`);

// Ensure temp directory exists
await vscode.workspace.fs.createDirectory(tempDir);

// Capture the screenshot
await exec(`xcrun simctl io ${udid} screenshot ${tempFile.fsPath}`);

// Read the file
const imageData = await vscode.workspace.fs.readFile(tempFile);

// Clean up
await vscode.workspace.fs.delete(tempFile);

return imageData;
} catch (error) {
console.error('Failed to capture screenshot:', error);
return undefined;
}
}
Loading