mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-05-27 18:25:27 +08:00
Update agent
This commit is contained in:
@@ -138,18 +138,53 @@ async function renderFlowChartMermaid(chart, container, onInspect) {
|
|||||||
const zoomMin = 0.2;
|
const zoomMin = 0.2;
|
||||||
const zoomMax = 3;
|
const zoomMax = 3;
|
||||||
const zoomStep = 0.1;
|
const zoomStep = 0.1;
|
||||||
container.addEventListener("wheel", (e) => {
|
|
||||||
if (!e.ctrlKey) return;
|
function applyZoom() {
|
||||||
e.preventDefault();
|
|
||||||
const delta = e.deltaY > 0 ? -zoomStep : zoomStep;
|
|
||||||
zoomLevel = Math.min(zoomMax, Math.max(zoomMin, zoomLevel + delta));
|
|
||||||
const svgInner = container.querySelector("svg");
|
const svgInner = container.querySelector("svg");
|
||||||
if (svgInner) {
|
if (svgInner) {
|
||||||
svgInner.style.transformOrigin = "top left";
|
svgInner.style.transformOrigin = "top left";
|
||||||
svgInner.style.transform = `scale(${zoomLevel})`;
|
svgInner.style.transform = `scale(${zoomLevel})`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container.addEventListener("wheel", (e) => {
|
||||||
|
if (!e.ctrlKey) return;
|
||||||
|
e.preventDefault();
|
||||||
|
const delta = e.deltaY > 0 ? -zoomStep : zoomStep;
|
||||||
|
zoomLevel = Math.min(zoomMax, Math.max(zoomMin, zoomLevel + delta));
|
||||||
|
applyZoom();
|
||||||
}, { passive: false });
|
}, { passive: false });
|
||||||
|
|
||||||
|
// Touch pinch-to-zoom (two fingers)
|
||||||
|
let lastTouchDist = null;
|
||||||
|
container.addEventListener("touchstart", (e) => {
|
||||||
|
if (e.touches.length === 2) {
|
||||||
|
e.preventDefault();
|
||||||
|
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
||||||
|
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
||||||
|
lastTouchDist = Math.hypot(dx, dy);
|
||||||
|
}
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
container.addEventListener("touchmove", (e) => {
|
||||||
|
if (e.touches.length === 2 && lastTouchDist !== null) {
|
||||||
|
e.preventDefault();
|
||||||
|
const dx = e.touches[0].clientX - e.touches[1].clientX;
|
||||||
|
const dy = e.touches[0].clientY - e.touches[1].clientY;
|
||||||
|
const newDist = Math.hypot(dx, dy);
|
||||||
|
const scale = newDist / lastTouchDist;
|
||||||
|
zoomLevel = Math.min(zoomMax, Math.max(zoomMin, zoomLevel * scale));
|
||||||
|
lastTouchDist = newDist;
|
||||||
|
applyZoom();
|
||||||
|
}
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
container.addEventListener("touchend", (e) => {
|
||||||
|
if (e.touches.length < 2) {
|
||||||
|
lastTouchDist = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Track currently selected TaskNode/CondNode
|
// Track currently selected TaskNode/CondNode
|
||||||
let currentSelectedGroup = null;
|
let currentSelectedGroup = null;
|
||||||
let currentSelectedOriginalStrokeWidth = null;
|
let currentSelectedOriginalStrokeWidth = null;
|
||||||
|
|||||||
@@ -172,3 +172,54 @@ html, body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Phone-specific layout ---- */
|
||||||
|
|
||||||
|
/* Back button: hidden on desktop, visible only in phone mode */
|
||||||
|
.phone-back-btn {
|
||||||
|
display: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-bottom: none;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
background: #dc2626;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: auto;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-back-btn:hover {
|
||||||
|
background: #b91c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.phone-back-btn {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resize-bar {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-part {
|
||||||
|
display: none !important;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1000;
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-part.phone-visible {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-part {
|
||||||
|
width: 100% !important;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Copilot Portal - Job Tracking</title>
|
<title>Copilot Portal - Job Tracking</title>
|
||||||
<link rel="stylesheet" href="jobTracking.css">
|
<link rel="stylesheet" href="jobTracking.css">
|
||||||
<link rel="stylesheet" href="messageBlock.css">
|
<link rel="stylesheet" href="messageBlock.css">
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ let chartController = null; // returned from renderFlowChartMermaid
|
|||||||
let jobStatus = isPreviewMode ? "PREVIEW" : "RUNNING"; // PREVIEW | RUNNING | SUCCEEDED | FAILED | CANCELED
|
let jobStatus = isPreviewMode ? "PREVIEW" : "RUNNING"; // PREVIEW | RUNNING | SUCCEEDED | FAILED | CANCELED
|
||||||
let jobStopped = false;
|
let jobStopped = false;
|
||||||
|
|
||||||
|
|
||||||
// Map: workId -> { taskId, sessions: Map<sessionId, { name, renderer, div, active }>, attemptCount }
|
// Map: workId -> { taskId, sessions: Map<sessionId, { name, renderer, div, active }>, attemptCount }
|
||||||
const workIdData = {};
|
const workIdData = {};
|
||||||
|
|
||||||
@@ -116,13 +117,6 @@ function showJsonView() {
|
|||||||
function showTaskSessionTabs(workId) {
|
function showTaskSessionTabs(workId) {
|
||||||
sessionResponsePart.innerHTML = "";
|
sessionResponsePart.innerHTML = "";
|
||||||
const data = workIdData[workId];
|
const data = workIdData[workId];
|
||||||
if (!data) {
|
|
||||||
sessionResponsePart.textContent = "No session data for this task.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset active tab tracking so the first switchTabForWork always applies
|
|
||||||
data.activeTabSessionId = null;
|
|
||||||
|
|
||||||
tabContainer = document.createElement("div");
|
tabContainer = document.createElement("div");
|
||||||
tabContainer.className = "tab-container";
|
tabContainer.className = "tab-container";
|
||||||
@@ -137,33 +131,56 @@ function showTaskSessionTabs(workId) {
|
|||||||
|
|
||||||
sessionResponsePart.appendChild(tabContainer);
|
sessionResponsePart.appendChild(tabContainer);
|
||||||
|
|
||||||
// Ensure "Driving" tab always appears first
|
if (!data || data.sessions.size === 0) {
|
||||||
const sortedEntries = [...data.sessions.entries()].sort((a, b) => {
|
// No session data yet — show placeholder in tab content
|
||||||
if (a[1].name === "Driving") return -1;
|
const placeholder = document.createElement("div");
|
||||||
if (b[1].name === "Driving") return 1;
|
placeholder.style.padding = "16px";
|
||||||
return 0;
|
placeholder.textContent = "No session data for this task.";
|
||||||
});
|
tabContent.appendChild(placeholder);
|
||||||
|
} else {
|
||||||
|
// Reset active tab tracking so the first switchTabForWork always applies
|
||||||
|
data.activeTabSessionId = null;
|
||||||
|
|
||||||
for (const [sessionId, sessionInfo] of sortedEntries) {
|
// Ensure "Driving" tab always appears first
|
||||||
const tabBtn = document.createElement("button");
|
const sortedEntries = [...data.sessions.entries()].sort((a, b) => {
|
||||||
tabBtn.className = "tab-header-btn";
|
if (a[1].name === "Driving") return -1;
|
||||||
tabBtn.textContent = sessionInfo.name;
|
if (b[1].name === "Driving") return 1;
|
||||||
tabBtn.dataset.sessionId = sessionId;
|
return 0;
|
||||||
tabBtn.addEventListener("click", () => {
|
|
||||||
switchTabForWork(workId, tabBtn.dataset.sessionId);
|
|
||||||
});
|
});
|
||||||
tabHeaders.appendChild(tabBtn);
|
|
||||||
|
|
||||||
// Append the session's div to tab content (hidden by default)
|
for (const [sessionId, sessionInfo] of sortedEntries) {
|
||||||
sessionInfo.div.style.display = "none";
|
const tabBtn = document.createElement("button");
|
||||||
tabContent.appendChild(sessionInfo.div);
|
tabBtn.className = "tab-header-btn";
|
||||||
|
tabBtn.textContent = sessionInfo.name;
|
||||||
|
tabBtn.dataset.sessionId = sessionId;
|
||||||
|
tabBtn.addEventListener("click", () => {
|
||||||
|
switchTabForWork(workId, tabBtn.dataset.sessionId);
|
||||||
|
});
|
||||||
|
tabHeaders.appendChild(tabBtn);
|
||||||
|
|
||||||
|
// Append the session's div to tab content (hidden by default)
|
||||||
|
sessionInfo.div.style.display = "none";
|
||||||
|
tabContent.appendChild(sessionInfo.div);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate the first tab
|
||||||
|
const firstEntry = sortedEntries[0];
|
||||||
|
if (firstEntry) {
|
||||||
|
switchTabForWork(workId, firstEntry[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate the first tab
|
// Add "Back" button (visible only in phone mode via CSS)
|
||||||
const firstEntry = sortedEntries[0];
|
const backBtn = document.createElement("button");
|
||||||
if (firstEntry) {
|
backBtn.className = "phone-back-btn";
|
||||||
switchTabForWork(workId, firstEntry[0]);
|
backBtn.textContent = "Back";
|
||||||
}
|
backBtn.addEventListener("click", () => {
|
||||||
|
// Unselect the inspected node
|
||||||
|
inspectedWorkId = null;
|
||||||
|
rightPart.classList.remove("phone-visible");
|
||||||
|
showJsonView();
|
||||||
|
});
|
||||||
|
tabHeaders.appendChild(backBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshSessionResponsePart() {
|
function refreshSessionResponsePart() {
|
||||||
@@ -177,6 +194,12 @@ function refreshSessionResponsePart() {
|
|||||||
function onInspect(workId) {
|
function onInspect(workId) {
|
||||||
inspectedWorkId = workId;
|
inspectedWorkId = workId;
|
||||||
refreshSessionResponsePart();
|
refreshSessionResponsePart();
|
||||||
|
if (workId !== null) {
|
||||||
|
// In phone mode CSS makes this a full-screen overlay; on desktop it has no effect
|
||||||
|
rightPart.classList.add("phone-visible");
|
||||||
|
} else {
|
||||||
|
rightPart.classList.remove("phone-visible");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Live Polling Helpers ----
|
// ---- Live Polling Helpers ----
|
||||||
@@ -317,6 +340,9 @@ function startTaskPolling(taskId, workId) {
|
|||||||
div.style.display = "none";
|
div.style.display = "none";
|
||||||
tabContent.insertBefore(div, tabContent.firstChild);
|
tabContent.insertBefore(div, tabContent.firstChild);
|
||||||
}
|
}
|
||||||
|
// Ensure Back button stays at the end
|
||||||
|
const existingBackBtn = tabHeaders.querySelector(".phone-back-btn");
|
||||||
|
if (existingBackBtn) tabHeaders.appendChild(existingBackBtn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,7 +375,13 @@ function startTaskPolling(taskId, workId) {
|
|||||||
tabBtn.addEventListener("click", () => {
|
tabBtn.addEventListener("click", () => {
|
||||||
switchTabForWork(workId, sessionId);
|
switchTabForWork(workId, sessionId);
|
||||||
});
|
});
|
||||||
tabHeaders.appendChild(tabBtn);
|
// Insert before phone Back button if present
|
||||||
|
const phoneBackBtn = tabHeaders.querySelector(".phone-back-btn");
|
||||||
|
if (phoneBackBtn) {
|
||||||
|
tabHeaders.insertBefore(tabBtn, phoneBackBtn);
|
||||||
|
} else {
|
||||||
|
tabHeaders.appendChild(tabBtn);
|
||||||
|
}
|
||||||
|
|
||||||
div.style.display = "none";
|
div.style.display = "none";
|
||||||
tabContent.appendChild(div);
|
tabContent.appendChild(div);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"testExecute": "node test/runTests.mjs"
|
"testExecute": "node test/runTests.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@github/copilot-sdk": "^0.1.4"
|
"@github/copilot-sdk": "^0.1.29"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.49.0",
|
"@playwright/test": "^1.49.0",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CopilotClient, defineTool, type CopilotSession } from "@github/copilot-sdk";
|
import { CopilotClient, defineTool, approveAll, type CopilotSession } from "@github/copilot-sdk";
|
||||||
|
|
||||||
export interface ICopilotSession {
|
export interface ICopilotSession {
|
||||||
get rawSection(): CopilotSession;
|
get rawSection(): CopilotSession;
|
||||||
@@ -82,6 +82,7 @@ export async function startSession(
|
|||||||
streaming: true,
|
streaming: true,
|
||||||
workingDirectory,
|
workingDirectory,
|
||||||
tools: jobTools,
|
tools: jobTools,
|
||||||
|
onPermissionRequest: approveAll,
|
||||||
hooks: {
|
hooks: {
|
||||||
onPreToolUse: async (input) => {
|
onPreToolUse: async (input) => {
|
||||||
if (input.toolName === "glob") {
|
if (input.toolName === "glob") {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
apiCopilotSessionQuery,
|
apiCopilotSessionQuery,
|
||||||
apiCopilotSessionLive,
|
apiCopilotSessionLive,
|
||||||
hasRunningSessions,
|
hasRunningSessions,
|
||||||
|
helperGetModels,
|
||||||
} from "./copilotApi.js";
|
} from "./copilotApi.js";
|
||||||
import {
|
import {
|
||||||
apiTaskList,
|
apiTaskList,
|
||||||
@@ -96,6 +97,19 @@ async function installJobsEntry(entryValue: Entry): Promise<void> {
|
|||||||
if (hasRunningSessions()) {
|
if (hasRunningSessions()) {
|
||||||
throw new Error("Cannot call installJobsEntry while sessions are running.");
|
throw new Error("Cannot call installJobsEntry while sessions are running.");
|
||||||
}
|
}
|
||||||
|
const models = await helperGetModels();
|
||||||
|
const validModelIds = new Set(models.map(m => m.id));
|
||||||
|
for (const [category, modelId] of Object.entries(entryValue.models)) {
|
||||||
|
if (!validModelIds.has(modelId)) {
|
||||||
|
throw new Error(`entry.models["${category}"] refers to model "${modelId}" which is not a valid model.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < entryValue.drivingSessionRetries.length; i++) {
|
||||||
|
const modelId = entryValue.drivingSessionRetries[i].modelId;
|
||||||
|
if (!validModelIds.has(modelId)) {
|
||||||
|
throw new Error(`entry.drivingSessionRetries[${i}].modelId refers to model "${modelId}" which is not a valid model.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
installedEntry = entryValue;
|
installedEntry = entryValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,12 +322,15 @@ const server = http.createServer((req, res) => {
|
|||||||
serveStaticFile(res, filePath);
|
serveStaticFile(res, filePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Install the jobs entry (only if not in test mode)
|
// Install the jobs entry (only if not in test mode), then start server
|
||||||
if (!testMode) {
|
async function startServer(): Promise<void> {
|
||||||
installJobsEntry(entry);
|
if (!testMode) {
|
||||||
|
await installJobsEntry(entry);
|
||||||
|
}
|
||||||
|
server.listen(port, () => {
|
||||||
|
console.log(`http://localhost:${port}`);
|
||||||
|
console.log(`http://localhost:${port}/api/stop`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
server.listen(port, () => {
|
startServer();
|
||||||
console.log(`http://localhost:${port}`);
|
|
||||||
console.log(`http://localhost:${port}/api/stop`);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ const entryInput: Entry = {
|
|||||||
planning: "gpt-5.2",
|
planning: "gpt-5.2",
|
||||||
coding: "gpt-5.2-codex",
|
coding: "gpt-5.2-codex",
|
||||||
reviewers1: "gpt-5.3-codex",
|
reviewers1: "gpt-5.3-codex",
|
||||||
reviewers2: "claude-opus-4.5",
|
reviewers2: "claude-opus-4.6",
|
||||||
reviewers3: "gemini-3-pro-preview"
|
reviewers3: "claude-sonnet-4.6"
|
||||||
},
|
},
|
||||||
drivingSessionRetries: [
|
drivingSessionRetries: [
|
||||||
{ modelId: "gpt-5-mini", retries: 5 },
|
{ modelId: "gpt-5-mini", retries: 5 },
|
||||||
@@ -64,121 +64,123 @@ const entryInput: Entry = {
|
|||||||
promptVariables: {
|
promptVariables: {
|
||||||
reviewerBoardFiles: [
|
reviewerBoardFiles: [
|
||||||
"## Your Identity",
|
"## Your Identity",
|
||||||
"You are $task-model, one of the reviewers in the review board.",
|
"- You are $task-model, one of the reviewers in the review board.",
|
||||||
|
"- The review document you are going to create is Copilot_Review_Writing_{YOUR-MODEL}.md",
|
||||||
|
"- You are going to review a target document, as well as any existing Copilot_Review_Finished_{OTHER-MODEL}.md.",
|
||||||
"## Reviewer Board Files",
|
"## Reviewer Board Files",
|
||||||
"- gpt -> Copilot_Review_*_GPT.md",
|
"- gpt -> Copilot_Review_*_GPT.md",
|
||||||
"- claude opus -> Copilot_Review_*_OPUS.md",
|
"- claude opus -> Copilot_Review_*_OPUS.md",
|
||||||
"- gemini -> Copilot_Review_*_GEMINI.md",
|
"- claude sonnet -> Copilot_Review_*_SONNET.md",
|
||||||
],
|
],
|
||||||
copilotSdkTips: [
|
copilotSdkTips: [
|
||||||
"NOTE: If you can't find the file, try different ways to make sure, including absolute path, relative path, powershell tool, view tool, slash and backslash, etc.",
|
"- NOTE: If you can't find the file, try different ways to make sure, including absolute path, relative path, powershell tool, view tool, slash and backslash, etc.",
|
||||||
"AVOID the glob tool to find any files, it does not work on Windows."
|
"- AVOID the glob tool to find any files, it does not work on Windows."
|
||||||
],
|
],
|
||||||
defineRepoRoot: [
|
defineRepoRoot: [
|
||||||
"REPO-ROOT is the root directory of the repo (aka the working directory you are currently in)"
|
"- REPO-ROOT is the root directory of the repo (aka the working directory you are currently in)"
|
||||||
],
|
],
|
||||||
noQuestion: [
|
noQuestion: [
|
||||||
"DO NOT ask user if you can start doing something, especially after you made a plan, always perform your job automatically and proactively til the end."
|
"- DO NOT ask user if you can start doing something, especially after you made a plan, always perform your job automatically and proactively til the end."
|
||||||
],
|
],
|
||||||
cppjob: [
|
cppjob: [
|
||||||
"$defineRepoRoot",
|
"$defineRepoRoot",
|
||||||
"$copilotSdkTips",
|
"$copilotSdkTips",
|
||||||
"YOU MUST FOLLOW REPO-ROOT/.github/copilot-instructions.md as a general guideline for all your tasks."
|
"- YOU MUST FOLLOW REPO-ROOT/.github/copilot-instructions.md as a general guideline for all your tasks."
|
||||||
],
|
],
|
||||||
scrum: [
|
scrum: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/0-scrum.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/0-scrum.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
design: [
|
design: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/1-design.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/1-design.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
plan: [
|
plan: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/2-planning.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/2-planning.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
summary: [
|
summary: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/3-summarizing.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/3-summarizing.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
codingPrefix: [
|
codingPrefix: [
|
||||||
"**IMPORT**: It is FORBIDDEN to modify any script files in `REPO-ROOT/.github/Scripts`. If you are getting trouble, the only reason is your code has problem. Fix the code instead of any other kind of working around.",
|
"- **IMPORT**: It is FORBIDDEN to modify any script files in `REPO-ROOT/.github/Scripts`. If you are getting trouble, the only reason is your code has problem. Fix the code instead of any other kind of working around.",
|
||||||
],
|
],
|
||||||
execute: [
|
execute: [
|
||||||
"$codingPrefix",
|
"$codingPrefix",
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/4-execution.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/4-execution.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
verify: [
|
verify: [
|
||||||
"$codingPrefix",
|
"$codingPrefix",
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/5-verifying.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/5-verifying.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
refine: [
|
refine: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/refine.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/refine.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
review: [
|
review: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/review.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/review.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
ask: [
|
ask: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/ask.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/ask.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
code: [
|
code: [
|
||||||
"Execute the instruction in REPO-ROOT/.github/prompts/code.prompt.md immediately.",
|
"- Execute the instruction in REPO-ROOT/.github/prompts/code.prompt.md immediately.",
|
||||||
"$noQuestion"
|
"$noQuestion"
|
||||||
],
|
],
|
||||||
reportDocument: [
|
reportDocument: [
|
||||||
"YOU MUST use the job_prepare_document tool with an argument: an absolute path of the document you are about to create or update.",
|
"- YOU MUST use the job_prepare_document tool with an argument: an absolute path of the document you are about to create or update.",
|
||||||
"YOU MUST use the job_prepare_document tool even when you think nothing needs to be updated, it is to make sure you are clear about which document to work on."
|
"- YOU MUST use the job_prepare_document tool even when you think nothing needs to be updated, it is to make sure you are clear about which document to work on."
|
||||||
],
|
],
|
||||||
reportBoolean: [
|
reportBoolean: [
|
||||||
"YOU MUST use either job_boolean_true tool or job_boolean_false tool to answer an yes/no question, with the reason in the argument."
|
"- YOU MUST use either job_boolean_true tool or job_boolean_false tool to answer an yes/no question, with the reason in the argument."
|
||||||
],
|
],
|
||||||
simpleCondition: [
|
simpleCondition: [
|
||||||
"$defineRepoRoot",
|
"$defineRepoRoot",
|
||||||
"$copilotSdkTips",
|
"$copilotSdkTips",
|
||||||
"$reportBoolean",
|
"$reportBoolean",
|
||||||
"Use job_boolean_true tool if the below condition satisfies, or use job_boolean_false tool if it does not satisfy."
|
"- Use job_boolean_true tool if the below condition satisfies, or use job_boolean_false tool if it does not satisfy."
|
||||||
],
|
],
|
||||||
scrumDocReady: [
|
scrumDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Scrum.md should exist and its content should not be just a title."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Scrum.md should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
designDocReady: [
|
designDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Task.md should exist and its content should not be just a title."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Task.md should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
planDocReady: [
|
planDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Planning.md should exist and its content should not be just a title."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Planning.md should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
execDocReady: [
|
execDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Execution.md should exist and its content should not be just a title."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Execution.md should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
execDocVerified: [
|
execDocVerified: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Execution.md should exist and it has a `# !!!VERIFIED!!!`."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Execution.md should exist and it has a `# !!!VERIFIED!!!`."
|
||||||
],
|
],
|
||||||
reviewDocReady: [
|
reviewDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"REPO-ROOT/.github/TaskLogs/Copilot_Review.md should exist and its content should not be just a title."
|
"- REPO-ROOT/.github/TaskLogs/Copilot_Review.md should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
reportedDocReady: [
|
reportedDocReady: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"$reported-document should exist and its content should not be just a title."
|
"- $reported-document should exist and its content should not be just a title."
|
||||||
],
|
],
|
||||||
clearBuildTestLog: [
|
clearBuildTestLog: [
|
||||||
"In REPO-ROOT/.github/Scripts, delete both Build.log and Execute.log."
|
"- In REPO-ROOT/.github/Scripts, delete both Build.log and Execute.log."
|
||||||
],
|
],
|
||||||
buildSucceededFragment: [
|
buildSucceededFragment: [
|
||||||
"REPO-ROOT/.github/Scripts/Build.log must exist and the last several lines shows there is no error"
|
"- REPO-ROOT/.github/Scripts/Build.log must exist and the last several lines shows there is no error"
|
||||||
],
|
],
|
||||||
testPassedFragment: [
|
testPassedFragment: [
|
||||||
"REPO-ROOT/.github/Scripts/Execute.log must exist and the last several lines shows how many test files and test cases passed"
|
"- REPO-ROOT/.github/Scripts/Execute.log must exist and the last several lines shows how many test files and test cases passed"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
tasks: {
|
tasks: {
|
||||||
@@ -334,7 +336,7 @@ const entryInput: Entry = {
|
|||||||
},
|
},
|
||||||
criteria: {
|
criteria: {
|
||||||
runConditionInSameSession: false,
|
runConditionInSameSession: false,
|
||||||
condition: ["$simpleCondition", "All REPO-ROOT/.github/TaskLogs/Copilot_(Task|Planning|Execution).md must have been deleted."],
|
condition: ["$simpleCondition", "- All REPO-ROOT/.github/TaskLogs/Copilot_(Task|Planning|Execution).md must have been deleted."],
|
||||||
failureAction: retryFailedCondition()
|
failureAction: retryFailedCondition()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -404,7 +406,7 @@ const entryInput: Entry = {
|
|||||||
prompt: ["$cppjob", "$review", "# Apply", "$reviewerBoardFiles"],
|
prompt: ["$cppjob", "$review", "# Apply", "$reviewerBoardFiles"],
|
||||||
criteria: {
|
criteria: {
|
||||||
runConditionInSameSession: false,
|
runConditionInSameSession: false,
|
||||||
condition: ["$simpleCondition", "Every REPO-ROOT/.github/TaskLogs/Copilot_Review*.md must have been deleted."],
|
condition: ["$simpleCondition", "- Every REPO-ROOT/.github/TaskLogs/Copilot_Review*.md must have been deleted."],
|
||||||
failureAction: retryFailedCondition()
|
failureAction: retryFailedCondition()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -419,7 +421,7 @@ const entryInput: Entry = {
|
|||||||
prompt: ["$cppjob", "$code", "$user-input"],
|
prompt: ["$cppjob", "$code", "$user-input"],
|
||||||
criteria: {
|
criteria: {
|
||||||
runConditionInSameSession: true,
|
runConditionInSameSession: true,
|
||||||
condition: ["$simpleCondition", "Both conditions satisfy: 1) $buildSucceededFragment; 2) $testPassedFragment."],
|
condition: ["$simpleCondition", "- Both conditions satisfy: 1) $buildSucceededFragment; 2) $testPassedFragment."],
|
||||||
failureAction: retryFailedCondition()
|
failureAction: retryFailedCondition()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -428,27 +430,27 @@ const entryInput: Entry = {
|
|||||||
requireUserInput: false,
|
requireUserInput: false,
|
||||||
prompt: [
|
prompt: [
|
||||||
"$defineRepoRoot",
|
"$defineRepoRoot",
|
||||||
"Call REPO-ROOT/.github/Scripts/copilotGitCommit.ps1",
|
"- Call REPO-ROOT/.github/Scripts/copilotGitCommit.ps1",
|
||||||
"DO NOT git push."
|
"- DO NOT git push."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"git-push": {
|
"git-push": {
|
||||||
model: { category: "driving" },
|
model: { category: "driving" },
|
||||||
requireUserInput: false,
|
requireUserInput: false,
|
||||||
prompt: [
|
prompt: [
|
||||||
"`git add` to add all files.",
|
"- `git add` to add all files.",
|
||||||
"`git status` to list affected files.",
|
"- `git status` to list affected files.",
|
||||||
"`git commit -am` everything with this message: [BOT] Backup.",
|
"- `git commit -am` everything with this message: [BOT] Backup.",
|
||||||
"`git branch` to see the current branch.",
|
"- `git branch` to see the current branch.",
|
||||||
"`git push` to the current branch.",
|
"- `git push` to the current branch.",
|
||||||
"DO NOT run multiple commands at once."
|
"- DO NOT run multiple commands at once."
|
||||||
],
|
],
|
||||||
criteria: {
|
criteria: {
|
||||||
runConditionInSameSession: true,
|
runConditionInSameSession: true,
|
||||||
condition: [
|
condition: [
|
||||||
"$simpleCondition",
|
"$simpleCondition",
|
||||||
"`git status` to list file affected, make sure there is nothing uncommited.",
|
"- `git status` to list file affected, make sure there is nothing uncommited.",
|
||||||
"But it is fine if all uncommited changes are only whitespace related."
|
"- But it is fine if all uncommited changes are only whitespace related."
|
||||||
],
|
],
|
||||||
failureAction: retryFailedCondition()
|
failureAction: retryFailedCondition()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,6 +306,66 @@ describe("API: copilot/test/installJobsEntry", () => {
|
|||||||
assert.strictEqual(data.result, "OK", `installJobsEntry should succeed: ${JSON.stringify(data)}`);
|
assert.strictEqual(data.result, "OK", `installJobsEntry should succeed: ${JSON.stringify(data)}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("rejects entry with invalid model IDs", async () => {
|
||||||
|
const invalidModelEntryPath = path.join(__dirname, "invalidModelEntry.json");
|
||||||
|
const fs = await import("node:fs");
|
||||||
|
// A structurally valid entry but with a model ID that doesn't exist
|
||||||
|
fs.writeFileSync(invalidModelEntryPath, JSON.stringify({
|
||||||
|
models: { driving: "nonexistent-model-xyz" },
|
||||||
|
drivingSessionRetries: [{ modelId: "nonexistent-model-xyz", retries: 1 }],
|
||||||
|
promptVariables: {},
|
||||||
|
grid: [],
|
||||||
|
tasks: {
|
||||||
|
"dummy-task": { model: { category: "driving" }, prompt: ["hello"], requireUserInput: false }
|
||||||
|
},
|
||||||
|
jobs: {}
|
||||||
|
}));
|
||||||
|
try {
|
||||||
|
const data = await fetchJson("/api/copilot/test/installJobsEntry", {
|
||||||
|
method: "POST",
|
||||||
|
body: invalidModelEntryPath,
|
||||||
|
});
|
||||||
|
assert.strictEqual(data.result, "Rejected", `should reject invalid model: ${JSON.stringify(data)}`);
|
||||||
|
assert.ok(data.error, "should have error message about invalid model");
|
||||||
|
assert.ok(data.error.includes("nonexistent-model-xyz"), "error should mention the invalid model name");
|
||||||
|
} finally {
|
||||||
|
fs.unlinkSync(invalidModelEntryPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects entry with invalid drivingSessionRetries model IDs", async () => {
|
||||||
|
const invalidRetryEntryPath = path.join(__dirname, "invalidRetryEntry.json");
|
||||||
|
const fs = await import("node:fs");
|
||||||
|
const modelsData = await fetchJson("/api/copilot/models");
|
||||||
|
const freeModel = modelsData.models.find((m) => m.multiplier === 0);
|
||||||
|
// Use a valid model for entry.models but an invalid model in drivingSessionRetries
|
||||||
|
fs.writeFileSync(invalidRetryEntryPath, JSON.stringify({
|
||||||
|
models: { driving: freeModel.id },
|
||||||
|
drivingSessionRetries: [
|
||||||
|
{ modelId: freeModel.id, retries: 1 },
|
||||||
|
{ modelId: "nonexistent-retry-model-xyz", retries: 2 }
|
||||||
|
],
|
||||||
|
promptVariables: {},
|
||||||
|
grid: [],
|
||||||
|
tasks: {
|
||||||
|
"dummy-task": { model: { category: "driving" }, prompt: ["hello"], requireUserInput: false }
|
||||||
|
},
|
||||||
|
jobs: {}
|
||||||
|
}));
|
||||||
|
try {
|
||||||
|
const data = await fetchJson("/api/copilot/test/installJobsEntry", {
|
||||||
|
method: "POST",
|
||||||
|
body: invalidRetryEntryPath,
|
||||||
|
});
|
||||||
|
assert.strictEqual(data.result, "Rejected", `should reject invalid drivingSessionRetries model: ${JSON.stringify(data)}`);
|
||||||
|
assert.ok(data.error, "should have error message about invalid model");
|
||||||
|
assert.ok(data.error.includes("nonexistent-retry-model-xyz"), "error should mention the invalid model name");
|
||||||
|
assert.ok(data.error.includes("drivingSessionRetries"), "error should mention drivingSessionRetries");
|
||||||
|
} finally {
|
||||||
|
fs.unlinkSync(invalidRetryEntryPath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("rejects when session is running", async () => {
|
it("rejects when session is running", async () => {
|
||||||
const modelsData = await fetchJson("/api/copilot/models");
|
const modelsData = await fetchJson("/api/copilot/models");
|
||||||
const freeModel = modelsData.models.find((m) => m.multiplier === 0);
|
const freeModel = modelsData.models.find((m) => m.multiplier === 0);
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ Prints the following URL for shortcut:
|
|||||||
### installJobsEntry
|
### installJobsEntry
|
||||||
|
|
||||||
`async installJobsEntry(entry: Entry): Promise<void>;`
|
`async installJobsEntry(entry: Entry): Promise<void>;`
|
||||||
|
- Verify if all `entry.model[name]` is a valid model with `helperGetModels`.
|
||||||
|
- Verify if all `entry.drivingSessionRetries[index].modelId` is a valid model with `helperGetModels`.
|
||||||
- Use the entry. It could be `entry` from `jobsData.ts` or whatever.
|
- Use the entry. It could be `entry` from `jobsData.ts` or whatever.
|
||||||
- This function can only be called when no session is running, otherwise throws.
|
- This function can only be called when no session is running, otherwise throws.
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,8 @@ When the user holds **Ctrl** and scrolls the mouse wheel over the `#chart-contai
|
|||||||
- CSS `transform: scale(...)` with `transform-origin: top left` is applied to the SVG element.
|
- CSS `transform: scale(...)` with `transform-origin: top left` is applied to the SVG element.
|
||||||
- The default browser scroll/zoom behavior is suppressed (`preventDefault`).
|
- The default browser scroll/zoom behavior is suppressed (`preventDefault`).
|
||||||
|
|
||||||
|
User should be able to zoom in and zoom out also using two touch points (two fingers).
|
||||||
|
|
||||||
#### Interaction with `ChartNode` which has a `TaskNode` or `CondNode` hint
|
#### Interaction with `ChartNode` which has a `TaskNode` or `CondNode` hint
|
||||||
|
|
||||||
Clicking it select (exclusive) or unselect the text:
|
Clicking it select (exclusive) or unselect the text:
|
||||||
@@ -252,3 +254,16 @@ When a task is being inspected:
|
|||||||
- Each task session has its own tab.
|
- Each task session has its own tab.
|
||||||
- Clicking a tab shows responses from a session using `Session Response Rendering` from `Shared.md`.
|
- Clicking a tab shows responses from a session using `Session Response Rendering` from `Shared.md`.
|
||||||
- When the selected `ChartNode` is restarted, tabs should be cleared before adding new sessions.
|
- When the selected `ChartNode` is restarted, tabs should be cleared before adding new sessions.
|
||||||
|
|
||||||
|
### Phone Specific Layout/Behavior
|
||||||
|
|
||||||
|
**IMPORTANT**:
|
||||||
|
- Phone mode is defined by `max=width: 768px`. The session only applies when the webpage is in phone mode.
|
||||||
|
- On a PC browser while resizing, it should be able to switch between phone mode and PC mode in any status.
|
||||||
|
- Build the webpage fully reactive, which means it is not allowed to save the "mode" in anyway even temporarily.
|
||||||
|
|
||||||
|
- The `Session Response Part` is not visible at the beginning.
|
||||||
|
- There is also no draggable bar between it and the `Job Part`.
|
||||||
|
- When a `ChartNode` is clicked, the `Session Response Part` becomes visible and occupy the whole window.
|
||||||
|
- At the very right of the tab header of the `Session Response Part`, there should be a "Back" button.
|
||||||
|
- Clicking the button hide the `Session Response Part` and the `Job Part` becomes available again.
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ Prints the following URL for shortcut:
|
|||||||
### installJobsEntry
|
### installJobsEntry
|
||||||
|
|
||||||
`async installJobsEntry(entry: Entry): Promise<void>;`
|
`async installJobsEntry(entry: Entry): Promise<void>;`
|
||||||
|
- Verify if all `entry.model[name]` is a valid model with `helperGetModels`.
|
||||||
|
- Verify if all `entry.drivingSessionRetries[index].modelId` is a valid model with `helperGetModels`.
|
||||||
- Use the entry. It could be `entry` from `jobsData.ts` or whatever.
|
- Use the entry. It could be `entry` from `jobsData.ts` or whatever.
|
||||||
- This function can only be called when no session is running, otherwise throws.
|
- This function can only be called when no session is running, otherwise throws.
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,8 @@ When the user holds **Ctrl** and scrolls the mouse wheel over the `#chart-contai
|
|||||||
- CSS `transform: scale(...)` with `transform-origin: top left` is applied to the SVG element.
|
- CSS `transform: scale(...)` with `transform-origin: top left` is applied to the SVG element.
|
||||||
- The default browser scroll/zoom behavior is suppressed (`preventDefault`).
|
- The default browser scroll/zoom behavior is suppressed (`preventDefault`).
|
||||||
|
|
||||||
|
User should be able to zoom in and zoom out also using two touch points (two fingers).
|
||||||
|
|
||||||
#### Interaction with `ChartNode` which has a `TaskNode` or `CondNode` hint
|
#### Interaction with `ChartNode` which has a `TaskNode` or `CondNode` hint
|
||||||
|
|
||||||
Clicking it select (exclusive) or unselect the text:
|
Clicking it select (exclusive) or unselect the text:
|
||||||
@@ -252,3 +254,16 @@ When a task is being inspected:
|
|||||||
- Each task session has its own tab.
|
- Each task session has its own tab.
|
||||||
- Clicking a tab shows responses from a session using `Session Response Rendering` from `Shared.md`.
|
- Clicking a tab shows responses from a session using `Session Response Rendering` from `Shared.md`.
|
||||||
- When the selected `ChartNode` is restarted, tabs should be cleared before adding new sessions.
|
- When the selected `ChartNode` is restarted, tabs should be cleared before adding new sessions.
|
||||||
|
|
||||||
|
### Phone Specific Layout/Behavior
|
||||||
|
|
||||||
|
**IMPORTANT**:
|
||||||
|
- Phone mode is defined by `max=width: 768px`. The session only applies when the webpage is in phone mode.
|
||||||
|
- On a PC browser while resizing, it should be able to switch between phone mode and PC mode in any status.
|
||||||
|
- Build the webpage fully reactive, which means it is not allowed to save the "mode" in anyway even temporarily.
|
||||||
|
|
||||||
|
- The `Session Response Part` is not visible at the beginning.
|
||||||
|
- There is also no draggable bar between it and the `Job Part`.
|
||||||
|
- When a `ChartNode` is clicked, the `Session Response Part` becomes visible and occupy the whole window.
|
||||||
|
- At the very right of the tab header of the `Session Response Part`, there should be a "Back" button.
|
||||||
|
- Clicking the button hide the `Session Response Part` and the `Job Part` becomes available again.
|
||||||
|
|||||||
+39
-39
@@ -2,56 +2,56 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@github/copilot-darwin-arm64@0.0.403":
|
"@github/copilot-darwin-arm64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.403.tgz#e1cbc91f73639c8217fd2cc61498bc311e2af45c"
|
resolved "https://registry.yarnpkg.com/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.420.tgz#560ca002fa491c04fdb6f74f84fee87e52575c53"
|
||||||
integrity sha512-dOw8IleA0d1soHnbr/6wc6vZiYWNTKMgfTe/NET1nCfMzyKDt/0F0I7PT5y+DLujJknTla/ZeEmmBUmliTW4Cg==
|
integrity sha512-sj8Oxcf3oKDbeUotm2gtq5YU1lwCt3QIzbMZioFD/PMLOeqSX/wrecI+c0DDYXKofFhALb0+DxxnWgbEs0mnkQ==
|
||||||
|
|
||||||
"@github/copilot-darwin-x64@0.0.403":
|
"@github/copilot-darwin-x64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.403.tgz#b246b0b91f31e13650d99c59716fd74ab87465f5"
|
resolved "https://registry.yarnpkg.com/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.420.tgz#1d5cf40ac4e04bbd69fb0a79abf3743897c5f795"
|
||||||
integrity sha512-aK2jSNWgY8eiZ+TmrvGhssMCPDTKArc0ip6Ul5OaslpytKks8hyXoRbxGD0N9sKioSUSbvKUf+1AqavbDpJO+w==
|
integrity sha512-2acA93IqXz1uuz3TVUm0Y7BVrBr0MySh1kQa8LqMILhTsG0YHRMm8ybzTp2HA7Mi1tl5CjqMSk163kkS7OzfUA==
|
||||||
|
|
||||||
"@github/copilot-linux-arm64@0.0.403":
|
"@github/copilot-linux-arm64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.403.tgz#5453ec3bd565cc92676b450b2edb66e49f60909d"
|
resolved "https://registry.yarnpkg.com/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.420.tgz#e247517854927a14f5c076bfa99309160afec2d7"
|
||||||
integrity sha512-KhoR2iR70O6vCkzf0h8/K+p82qAgOvMTgAPm9bVEHvbdGFR7Py9qL5v03bMbPxsA45oNaZAkzDhfTAqWhIAZsQ==
|
integrity sha512-h/IvEryTOYm1HzR2GNq8s2aDtN4lvT4MxldfZuS42CtWJDOfVG2jLLsoHWU1T3QV8j1++PmDgE//HX0JLpLMww==
|
||||||
|
|
||||||
"@github/copilot-linux-x64@0.0.403":
|
"@github/copilot-linux-x64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.403.tgz#17a7eba380be8553610ee6632d6a81ba229722eb"
|
resolved "https://registry.yarnpkg.com/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.420.tgz#00d22974499f0fab6354fe4e22f6be59b800ab98"
|
||||||
integrity sha512-eoswUc9vo4TB+/9PgFJLVtzI4dPjkpJXdCsAioVuoqPdNxHxlIHFe9HaVcqMRZxUNY1YHEBZozy+IpUEGjgdfQ==
|
integrity sha512-iL2NpZvXIDZ+3lw7sO2fo5T0nKmP5dZbU2gdYcv+SFBm/ONhCxIY5VRX4yN/9VkFaa9ePv5JzCnsl3vZINiDxg==
|
||||||
|
|
||||||
"@github/copilot-sdk@^0.1.4":
|
"@github/copilot-sdk@^0.1.29":
|
||||||
version "0.1.23"
|
version "0.1.29"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-sdk/-/copilot-sdk-0.1.23.tgz#120986bf5719880dedf076c0f2a55f855566ff40"
|
resolved "https://registry.yarnpkg.com/@github/copilot-sdk/-/copilot-sdk-0.1.29.tgz#8809df61ab53f100f8390234d9946cdc2acae24b"
|
||||||
integrity sha512-0by81bsBQlDKE5VbcegZfUMvPyPm1aXwSGS2rGaMAFxv3ps+dACf1Voruxik7hQTae0ziVFJjuVrlxZoRaXBLw==
|
integrity sha512-GdcN6bJTeesr1HP6IrhN2MznIf1B3ufqd3PX+uKbDLXNriOmP65Ai29/hxzTidNLHyOf6rW4NwmFfkMXiKfCBw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@github/copilot" "^0.0.403"
|
"@github/copilot" "^0.0.420"
|
||||||
vscode-jsonrpc "^8.2.1"
|
vscode-jsonrpc "^8.2.1"
|
||||||
zod "^4.3.6"
|
zod "^4.3.6"
|
||||||
|
|
||||||
"@github/copilot-win32-arm64@0.0.403":
|
"@github/copilot-win32-arm64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.403.tgz#3cdaee25b2454ceb6d8293f06b258c95307b94ae"
|
resolved "https://registry.yarnpkg.com/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.420.tgz#733c45aced1e42c2877ae44012074abbcce3d55d"
|
||||||
integrity sha512-djWjzCsp2xPNafMyOZ/ivU328/WvWhdroGie/DugiJBTgQL2SP0quWW1fhTlDwE81a3g9CxfJonaRgOpFTJTcg==
|
integrity sha512-Njlc2j9vYSBAL+lC6FIEhQ3C+VxO3xavwKnw0ecVRiNLcGLyPrTdzPfPQOmEjC63gpVCqLabikoDGv8fuLPA2w==
|
||||||
|
|
||||||
"@github/copilot-win32-x64@0.0.403":
|
"@github/copilot-win32-x64@0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.403.tgz#d22bdd50d9b0674d73981a413df881fd8229f5ce"
|
resolved "https://registry.yarnpkg.com/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.420.tgz#d45f47f2f08d4bba87760b8afb21af19d1988780"
|
||||||
integrity sha512-lju8cHy2E6Ux7R7tWyLZeksYC2MVZu9i9ocjiBX/qfG2/pNJs7S5OlkwKJ0BSXSbZEHQYq7iHfEWp201bVfk9A==
|
integrity sha512-rZlH35oNehAP2DvQbu4vQFVNeCh/1p3rUjafBYaEY0Nkhx7RmdrYBileL5U3PtRPPRsBPaq3Qp+pVIrGoCDLzQ==
|
||||||
|
|
||||||
"@github/copilot@^0.0.403":
|
"@github/copilot@^0.0.420":
|
||||||
version "0.0.403"
|
version "0.0.420"
|
||||||
resolved "https://registry.yarnpkg.com/@github/copilot/-/copilot-0.0.403.tgz#56e44b5a0640685f0b34507bbb12f47229798940"
|
resolved "https://registry.yarnpkg.com/@github/copilot/-/copilot-0.0.420.tgz#596349de076566a310836a7e06e6807b87ea6bfe"
|
||||||
integrity sha512-v5jUdtGJReLmE1rmff/LZf+50nzmYQYAaSRNtVNr9g0j0GkCd/noQExe31i1+PudvWU0ZJjltR0B8pUfDRdA9Q==
|
integrity sha512-UpPuSjxUxQ+j02WjZEFffWf0scLb23LvuGHzMFtaSsweR+P/BdbtDUI5ZDIA6T0tVyyt6+X1/vgfsJiRqd6jig==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@github/copilot-darwin-arm64" "0.0.403"
|
"@github/copilot-darwin-arm64" "0.0.420"
|
||||||
"@github/copilot-darwin-x64" "0.0.403"
|
"@github/copilot-darwin-x64" "0.0.420"
|
||||||
"@github/copilot-linux-arm64" "0.0.403"
|
"@github/copilot-linux-arm64" "0.0.420"
|
||||||
"@github/copilot-linux-x64" "0.0.403"
|
"@github/copilot-linux-x64" "0.0.420"
|
||||||
"@github/copilot-win32-arm64" "0.0.403"
|
"@github/copilot-win32-arm64" "0.0.420"
|
||||||
"@github/copilot-win32-x64" "0.0.403"
|
"@github/copilot-win32-x64" "0.0.420"
|
||||||
|
|
||||||
"@playwright/test@^1.49.0":
|
"@playwright/test@^1.49.0":
|
||||||
version "1.58.2"
|
version "1.58.2"
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
## Goal and Constraints
|
## Goal and Constraints
|
||||||
|
|
||||||
- Your goal is to finish a design document in `Copilot_Task.md` to address a problem.
|
- Your goal is to finish a design document in `Copilot_Task.md` to address a problem.
|
||||||
- You are only allowed to update `Copilot_Task.md` and mark a task being taken in `Copilot_Scrum.md`.
|
- You are only allowed to update `Copilot_Task.md`
|
||||||
|
- When the task comes from `Copilot_Scrum.md`, you should mark a task being taken in `Copilot_Scrum.md`.
|
||||||
- You are not allowed to modify any other files.
|
- You are not allowed to modify any other files.
|
||||||
- The phrasing of the request may look like asking for code change, but your actual work is to write the design document.
|
- The phrasing of the request may look like asking for code change, but your actual work is to write the design document.
|
||||||
|
|
||||||
@@ -37,12 +38,14 @@ Ignore this section if there is no "# Problem" in the LATEST chat message
|
|||||||
I am starting a fresh new request.
|
I am starting a fresh new request.
|
||||||
|
|
||||||
- Find and execute `copilotPrepare.ps1` to clean up everything from the last run.
|
- Find and execute `copilotPrepare.ps1` to clean up everything from the last run.
|
||||||
|
- This script will clean up everything in `Copilot_Task.md`, `Copilot_Planning.md` and `Copilot_Execution.md`.
|
||||||
|
- It is normal to find large amount of changes in these 3 files, DO NOT panic.
|
||||||
- After `copilotPrepare.ps1` finishes, copy precisely my problem description in `# Problem` from the LATEST chat message under a `# PROBLEM DESCRIPTION`.
|
- After `copilotPrepare.ps1` finishes, copy precisely my problem description in `# Problem` from the LATEST chat message under a `# PROBLEM DESCRIPTION`.
|
||||||
- If the problem description is `Next`:
|
- Find task from `Copilot_Scrum.md` if the problem description is in the following format:
|
||||||
- Find the first incomplete task in `Copilot_Scrum.md`.
|
- `Next`: Find the first incomplete task in `Copilot_Scrum.md`.
|
||||||
- If the problem description is like `Complete task No.X`:
|
- `Complete task No.X`: Locate the specific task in `Copilot_Scrum.md`.
|
||||||
- Locate the specific task in `Copilot_Scrum.md`.
|
- There is a bullet list of all tasks at the beginning of `# TASKS`. Mark the specific task as being taken by changing `[ ]` to `[x]`.
|
||||||
- There is a bullet list of all tasks at the beginning of `# TASKS`. Mark the specific task as being taken by changing `[ ]` to `[x]`.
|
- Otherwise, the task is the problem description itself.
|
||||||
- Find the details of the specific task, copy everything in this task to `# PROBLEM DESCRIPTION`.
|
- Find the details of the specific task, copy everything in this task to `# PROBLEM DESCRIPTION`.
|
||||||
- Add an empty `# UPDATES` section after `# PROBLEM DESCRIPTION`.
|
- Add an empty `# UPDATES` section after `# PROBLEM DESCRIPTION`.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user