chore: publish from main

This commit is contained in:
github-actions[bot]
2026-07-07 03:45:40 +00:00
parent e051c19731
commit ed1fa3aabc
37 changed files with 70 additions and 37 deletions
@@ -684,7 +684,7 @@ const canvas = createCanvas({
// ─── Join session (tools + canvas) ─── // ─── Join session (tools + canvas) ───
await joinSession({ const session = await joinSession({
canvases: [canvas], canvases: [canvas],
tools: [ tools: [
{ {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 937 KiB

+4 -1
View File
@@ -929,6 +929,9 @@
<div id="game"></div> <div id="game"></div>
<script src="./hud.js"></script> <script src="./hud.js"></script>
<script src="./phaser.min.js"></script> <script src="./phaser.min.js"></script>
<script type="module" src="./game.js"></script> <script type="module">
await window.__agentArcadePhaserReady;
await import("./game.js");
</script>
</body> </body>
</html> </html>
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -266,19 +266,19 @@ export class PlanetGuardianScene extends BaseScene {
this.load.image('def-swarmer', '../assets/defender/swarmer.png'); this.load.image('def-swarmer', '../assets/defender/swarmer.png');
this.load.image('def-baiter', '../assets/defender/baiter.png'); this.load.image('def-baiter', '../assets/defender/baiter.png');
// Sounds from OpenDefender // Sounds from OpenDefender
this.load.audio('snd_laser', '../assets/defender/sounds/sound_laser.wav'); this.load.audio('snd_laser', '../assets/defender/sounds/sound_laser.ogg');
this.load.audio('snd_enemydead', '../assets/defender/sounds/sound_enemydead.wav'); this.load.audio('snd_enemydead', '../assets/defender/sounds/sound_enemydead.ogg');
this.load.audio('snd_explode', '../assets/defender/sounds/sound_explode.wav'); this.load.audio('snd_explode', '../assets/defender/sounds/sound_explode.ogg');
this.load.audio('snd_playerdead', '../assets/defender/sounds/sound_playerdead.wav'); this.load.audio('snd_playerdead', '../assets/defender/sounds/sound_playerdead.ogg');
this.load.audio('snd_bonus', '../assets/defender/sounds/sound_bonus.wav'); this.load.audio('snd_bonus', '../assets/defender/sounds/sound_bonus.ogg');
this.load.audio('snd_humanoiddead', '../assets/defender/sounds/sound_humanoiddead.wav'); this.load.audio('snd_humanoiddead', '../assets/defender/sounds/sound_humanoiddead.ogg');
this.load.audio('snd_start', '../assets/defender/sounds/sound_start.wav'); this.load.audio('snd_start', '../assets/defender/sounds/sound_start.ogg');
this.load.audio('snd_thrust', '../assets/defender/sounds/sound_thurst.wav'); this.load.audio('snd_thrust', '../assets/defender/sounds/sound_thurst.ogg');
this.load.audio('snd_warning', '../assets/defender/sounds/sound_warning.wav'); this.load.audio('snd_warning', '../assets/defender/sounds/sound_warning.ogg');
this.load.audio('snd_baiterwarning', '../assets/defender/sounds/sound_baiterwarning.wav'); this.load.audio('snd_baiterwarning', '../assets/defender/sounds/sound_baiterwarning.ogg');
this.load.audio('snd_player1up', '../assets/defender/sounds/sound_player1up.wav'); this.load.audio('snd_player1up', '../assets/defender/sounds/sound_player1up.ogg');
this.load.audio('snd_enemyshoot', '../assets/defender/sounds/sound_enemyshoot.wav'); this.load.audio('snd_enemyshoot', '../assets/defender/sounds/sound_enemyshoot.ogg');
this.load.audio('snd_enemyshoot2', '../assets/defender/sounds/sound_enemyshoot2.wav'); this.load.audio('snd_enemyshoot2', '../assets/defender/sounds/sound_enemyshoot2.ogg');
} }
create() { create() {
this.initBase(); this.initBase();
+34 -20
View File
@@ -72,6 +72,15 @@ function normalizeText(value, fallback = "") {
return typeof value === "string" ? value.trim() : fallback; return typeof value === "string" ? value.trim() : fallback;
} }
function captureCwd(ctx) {
const dir = ctx?.session?.workingDirectory;
return typeof dir === "string" && dir.trim() ? dir : null;
}
function cwdForContext(ctx) {
return captureCwd(ctx) || servers.get(ctx?.instanceId)?.cwd || null;
}
function escapeHtml(value) { function escapeHtml(value) {
return normalizeText(value).replace(/[&<>"']/g, (char) => { return normalizeText(value).replace(/[&<>"']/g, (char) => {
if (char === "&") return "&amp;"; if (char === "&") return "&amp;";
@@ -385,7 +394,7 @@ async function runGh(args, cwd) {
return result.stdout; return result.stdout;
} }
async function closeGithubIssue(board, item, note) { async function closeGithubIssue(board, item, note, cwd = process.cwd()) {
const issueNumber = normalizeText(item?.number); const issueNumber = normalizeText(item?.number);
const repo = normalizeText(board?.repo || item?.repo); const repo = normalizeText(board?.repo || item?.repo);
if (!issueNumber || !repo) { if (!issueNumber || !repo) {
@@ -397,7 +406,7 @@ async function closeGithubIssue(board, item, note) {
args.push("--comment", comment); args.push("--comment", comment);
} }
try { try {
await runGh(args, activeSession?.workspacePath || process.cwd()); await runGh(args, cwd);
} catch (error) { } catch (error) {
const stderr = normalizeText(error?.stderr || ""); const stderr = normalizeText(error?.stderr || "");
if (stderr.toLowerCase().includes("already closed")) { if (stderr.toLowerCase().includes("already closed")) {
@@ -407,7 +416,7 @@ async function closeGithubIssue(board, item, note) {
} }
} }
async function commentGithubIssue(board, item, note) { async function commentGithubIssue(board, item, note, cwd = process.cwd()) {
const repo = normalizeText(board?.repo || item?.repo); const repo = normalizeText(board?.repo || item?.repo);
const issueNumber = extractIssueNumber(item); const issueNumber = extractIssueNumber(item);
const comment = normalizeText(note); const comment = normalizeText(note);
@@ -418,7 +427,7 @@ async function commentGithubIssue(board, item, note) {
return; return;
} }
try { try {
await runGh(["issue", "comment", issueNumber, "--repo", repo, "--body", comment], activeSession?.workspacePath || process.cwd()); await runGh(["issue", "comment", issueNumber, "--repo", repo, "--body", comment], cwd);
} catch (error) { } catch (error) {
const stderr = normalizeText(error?.stderr || ""); const stderr = normalizeText(error?.stderr || "");
throw new Error(stderr || `Failed to comment on issue #${issueNumber} in ${repo}.`); throw new Error(stderr || `Failed to comment on issue #${issueNumber} in ${repo}.`);
@@ -510,11 +519,11 @@ function pruneDecisionsForCurrentItems(board) {
} }
} }
async function syncBoardFromRepo(board, filtersInput) { async function syncBoardFromRepo(board, filtersInput, cwd = null) {
const workspacePath = activeSession?.workspacePath; const commandCwd = cwd || process.cwd();
let repo = normalizeText(board.repo); let repo = normalizeText(board.repo);
if (!repo && workspacePath) { if (!repo && cwd) {
const repoData = await runGhJson(["repo", "view", "--json", "nameWithOwner"], workspacePath); const repoData = await runGhJson(["repo", "view", "--json", "nameWithOwner"], cwd);
repo = normalizeText(repoData?.nameWithOwner); repo = normalizeText(repoData?.nameWithOwner);
} }
if (!repo) { if (!repo) {
@@ -535,7 +544,7 @@ async function syncBoardFromRepo(board, filtersInput) {
"--json", "--json",
"number,title,url,labels,assignees,createdAt,updatedAt,author,body", "number,title,url,labels,assignees,createdAt,updatedAt,author,body",
], ],
workspacePath || process.cwd(), commandCwd,
); );
const filteredIssues = Array.isArray(issues) ? sortIssues(issues.filter((issue) => issueMatchesFilters(issue, filters)), filters.sortBy) : []; const filteredIssues = Array.isArray(issues) ? sortIssues(issues.filter((issue) => issueMatchesFilters(issue, filters)), filters.sortBy) : [];
@@ -1843,6 +1852,7 @@ async function handleServerRequest(instanceId, req, res) {
await ensureStorageLoaded(); await ensureStorageLoaded();
const board = getOrCreateBoard(entry.boardId); const board = getOrCreateBoard(entry.boardId);
board.title = entry.title; board.title = entry.title;
const cwd = entry.cwd || null;
if (req.method === "GET" && req.url === "/") { if (req.method === "GET" && req.url === "/") {
res.setHeader("Content-Type", "text/html; charset=utf-8"); res.setHeader("Content-Type", "text/html; charset=utf-8");
@@ -1866,7 +1876,7 @@ async function handleServerRequest(instanceId, req, res) {
if (payload?.resetDecisions === true) { if (payload?.resetDecisions === true) {
resetBoardDecisions(board); resetBoardDecisions(board);
} }
await syncBoardFromRepo(board, payload?.filters); await syncBoardFromRepo(board, payload?.filters, cwd);
await persistStorage(); await persistStorage();
res.setHeader("Content-Type", "application/json; charset=utf-8"); res.setHeader("Content-Type", "application/json; charset=utf-8");
res.end(JSON.stringify(buildBoardState(board))); res.end(JSON.stringify(buildBoardState(board)));
@@ -1905,10 +1915,10 @@ async function handleServerRequest(instanceId, req, res) {
return; return;
} }
if (decision === "close") { if (decision === "close") {
await closeGithubIssue(board, item, payload?.note); await closeGithubIssue(board, item, payload?.note, cwd || process.cwd());
} }
if (payload?.quickResponse === true && decision !== "close" && normalizeText(payload?.note)) { if (payload?.quickResponse === true && decision !== "close" && normalizeText(payload?.note)) {
await commentGithubIssue(board, item, payload?.note); await commentGithubIssue(board, item, payload?.note, cwd || process.cwd());
} }
if (decision === "assign_agent") { if (decision === "assign_agent") {
const sessionStatus = await startImplementationSession(board, item, payload?.agent, payload?.note); const sessionStatus = await startImplementationSession(board, item, payload?.agent, payload?.note);
@@ -1932,7 +1942,7 @@ async function handleServerRequest(instanceId, req, res) {
res.end("Not found"); res.end("Not found");
} }
async function startServer(instanceId) { async function startServer(instanceId, cwd) {
const server = createServer((req, res) => { const server = createServer((req, res) => {
handleServerRequest(instanceId, req, res).catch((error) => { handleServerRequest(instanceId, req, res).catch((error) => {
if (res.headersSent) { if (res.headersSent) {
@@ -1946,7 +1956,7 @@ async function startServer(instanceId) {
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
const address = server.address(); const address = server.address();
const port = typeof address === "object" && address ? address.port : 0; const port = typeof address === "object" && address ? address.port : 0;
return { server, url: `http://127.0.0.1:${port}/` }; return { server, url: `http://127.0.0.1:${port}/`, cwd };
} }
const session = await joinSession({ const session = await joinSession({
@@ -1998,6 +2008,7 @@ const session = await joinSession({
additionalProperties: false, additionalProperties: false,
}, },
handler: async (ctx) => { handler: async (ctx) => {
const cwd = cwdForContext(ctx);
await ensureStorageLoaded(); await ensureStorageLoaded();
const board = getOrCreateBoard(normalizeText(ctx.input?.boardId, "default")); const board = getOrCreateBoard(normalizeText(ctx.input?.boardId, "default"));
const title = normalizeText(ctx.input?.title); const title = normalizeText(ctx.input?.title);
@@ -2008,7 +2019,7 @@ const session = await joinSession({
if (repo) { if (repo) {
board.repo = repo; board.repo = repo;
} }
await syncBoardFromRepo(board, ctx.input?.filters); await syncBoardFromRepo(board, ctx.input?.filters, cwd);
await persistStorage(); await persistStorage();
return buildBoardState(board); return buildBoardState(board);
}, },
@@ -2072,6 +2083,7 @@ const session = await joinSession({
additionalProperties: false, additionalProperties: false,
}, },
handler: async (ctx) => { handler: async (ctx) => {
const cwd = cwdForContext(ctx);
await ensureStorageLoaded(); await ensureStorageLoaded();
const board = getOrCreateBoard(normalizeText(ctx.input?.boardId, "default")); const board = getOrCreateBoard(normalizeText(ctx.input?.boardId, "default"));
const itemId = normalizeText(ctx.input?.itemId); const itemId = normalizeText(ctx.input?.itemId);
@@ -2081,10 +2093,10 @@ const session = await joinSession({
throw new Error(`Item "${itemId}" not found`); throw new Error(`Item "${itemId}" not found`);
} }
if (decision === "close") { if (decision === "close") {
await closeGithubIssue(board, item, ctx.input?.note); await closeGithubIssue(board, item, ctx.input?.note, cwd || process.cwd());
} }
if (ctx.input?.commentOnIssue === true && decision !== "close" && normalizeText(ctx.input?.note)) { if (ctx.input?.commentOnIssue === true && decision !== "close" && normalizeText(ctx.input?.note)) {
await commentGithubIssue(board, item, ctx.input?.note); await commentGithubIssue(board, item, ctx.input?.note, cwd || process.cwd());
} }
if (decision === "assign_agent") { if (decision === "assign_agent") {
const sessionStatus = await startImplementationSession(board, item, ctx.input?.agent, ctx.input?.note); const sessionStatus = await startImplementationSession(board, item, ctx.input?.agent, ctx.input?.note);
@@ -2120,6 +2132,8 @@ const session = await joinSession({
}, },
], ],
open: async (ctx) => { open: async (ctx) => {
let entry = servers.get(ctx.instanceId);
const cwd = cwdForContext(ctx);
await ensureStorageLoaded(); await ensureStorageLoaded();
const boardId = normalizeText(ctx.input?.boardId, "default"); const boardId = normalizeText(ctx.input?.boardId, "default");
const board = getOrCreateBoard(boardId); const board = getOrCreateBoard(boardId);
@@ -2139,17 +2153,17 @@ const session = await joinSession({
setBoardItems(board, ctx.input.items, true); setBoardItems(board, ctx.input.items, true);
await persistStorage(); await persistStorage();
} else if (syncFromRepo) { } else if (syncFromRepo) {
await syncBoardFromRepo(board, board.filters); await syncBoardFromRepo(board, board.filters, cwd);
await persistStorage(); await persistStorage();
} }
let entry = servers.get(ctx.instanceId);
if (!entry) { if (!entry) {
entry = await startServer(ctx.instanceId); entry = await startServer(ctx.instanceId, cwd);
servers.set(ctx.instanceId, entry); servers.set(ctx.instanceId, entry);
} }
entry.boardId = boardId; entry.boardId = boardId;
entry.title = title; entry.title = title;
entry.cwd = cwd;
return { return {
title, title,
status: "Swipe to triage backlog", status: "Swipe to triage backlog",
+1 -1
View File
@@ -622,7 +622,7 @@ async function startServer(instanceId, sessionRef, cwd, workspacePath) {
} }
if (url.pathname === "/refresh" && req.method === "POST") { if (url.pathname === "/refresh" && req.method === "POST") {
const data = await gatherContext(repoCwd()); const data = await gatherContext(cwd);
contextCache.set(instanceId, data); contextCache.set(instanceId, data);
await saveContext(workspacePath, data); await saveContext(workspacePath, data);
broadcast(instanceId, data); broadcast(instanceId, data);