Fix Antigravity model list and enhance clipboard-guided handoff UX
This commit is contained in:
1 parent
0467eebf0e
commit
29ef28b7cf
4 files changed
+124
-23
No files matched your search
+92
-16
@@ -1851,14 +1851,13 @@ const DEV_TARGETS = {
|
||||
antigravity: {
|
||||
id: "antigravity",
|
||||
label: "🛸 Google Antigravity",
|
||||
defaultModel: "gemini-3.1-pro",
|
||||
defaultModel: "gemini-3.8-flash",
|
||||
models: [
|
||||
{ id: "gemini-3.1-pro", label: "Gemini 3.1 Pro (Recommended — Full-Stack & Architecture)" },
|
||||
{ id: "gemini-3.0-pro", label: "Gemini 3.0 Pro (Deep Reasoning & Complex Refactors)" },
|
||||
{ id: "gemini-3.1-flash", label: "Gemini 3.1 Flash (Fast Iteration & UI Prototyping)" },
|
||||
{ id: "gemini-3.1-flash-lite", label: "Gemini 3.1 Flash-Lite (Lightweight & Rapid Tasks)" },
|
||||
{ id: "claude-sonnet-4.5", label: "Claude 4.5 Sonnet (via Antigravity Model Selector)" },
|
||||
{ id: "claude-opus-4.5", label: "Claude 4.5 Opus (via Antigravity Model Selector)" }
|
||||
{ id: "gemini-4-argon", label: "Gemini 4 Argon (Medium)" },
|
||||
{ id: "gemini-3.8-flash", label: "Gemini 3.8 Flash (Medium)" },
|
||||
{ id: "claude-opus-5.5", label: "Claude Opus 5.5 (Medium)" },
|
||||
{ id: "claude-sonnet-5.5", label: "Claude Sonnet 5.5 (Medium)" },
|
||||
{ id: "gpt-oss-120b", label: "GPT-OSS 120B (Medium)" }
|
||||
]
|
||||
},
|
||||
codex: {
|
||||
@@ -1875,6 +1874,33 @@ const DEV_TARGETS = {
|
||||
}
|
||||
};
|
||||
|
||||
async function copyTextToClipboard(text) {
|
||||
if (!text) return false;
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return true;
|
||||
} catch {
|
||||
// Fall through to fallback
|
||||
}
|
||||
}
|
||||
try {
|
||||
const textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
textArea.style.position = "fixed";
|
||||
textArea.style.left = "-999999px";
|
||||
textArea.style.top = "-999999px";
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
const successful = document.execCommand("copy");
|
||||
textArea.remove();
|
||||
return successful;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let activeDevTarget = "antigravity";
|
||||
|
||||
function populateDevModelOptions(targetApp) {
|
||||
@@ -1940,6 +1966,14 @@ async function openDevHandoffModal(defaultTarget = "antigravity") {
|
||||
homelabCb.checked = state.activeIdea.category === "project" || !isCurrentProductTShirt();
|
||||
}
|
||||
|
||||
const instructionNote = document.getElementById("dev-handoff-instruction-note");
|
||||
if (instructionNote) {
|
||||
instructionNote.innerHTML =
|
||||
activeDevTarget === "codex"
|
||||
? "🤖 Submitting opens OpenAI Codex with the prompt preloaded and saves the full spec to your workspace."
|
||||
: "🛸 Submitting switches focus to Antigravity and copies the complete project specification to your clipboard. Simply press <kbd>Ctrl+V</kbd> in Antigravity's chat to start coding.";
|
||||
}
|
||||
|
||||
document.getElementById("dev-handoff-result-box")?.classList.add("hidden");
|
||||
modal.classList.remove("hidden");
|
||||
await refreshDevSpecPreview();
|
||||
@@ -2806,6 +2840,13 @@ function bindGlobalEvents() {
|
||||
? "🚀 Submit & Open in OpenAI Codex"
|
||||
: "🚀 Submit & Launch in Antigravity";
|
||||
}
|
||||
const instructionNote = document.getElementById("dev-handoff-instruction-note");
|
||||
if (instructionNote) {
|
||||
instructionNote.innerHTML =
|
||||
activeDevTarget === "codex"
|
||||
? "🤖 Submitting opens OpenAI Codex with the prompt preloaded and saves the full spec to your workspace."
|
||||
: "🛸 Submitting switches focus to Antigravity and copies the complete project specification to your clipboard. Simply press <kbd>Ctrl+V</kbd> in Antigravity's chat to start coding.";
|
||||
}
|
||||
await refreshDevSpecPreview();
|
||||
});
|
||||
});
|
||||
@@ -2816,8 +2857,8 @@ function bindGlobalEvents() {
|
||||
document.getElementById("btn-copy-dev-spec")?.addEventListener("click", async () => {
|
||||
const text = document.getElementById("dev-spec-preview-textarea")?.value || "";
|
||||
if (!text) return;
|
||||
await navigator.clipboard.writeText(text);
|
||||
showToast("📋 Copied full development specification to clipboard!");
|
||||
const ok = await copyTextToClipboard(text);
|
||||
showToast(ok ? "📋 Copied full development specification to clipboard!" : "⚠️ Unable to auto-copy; please copy text manually.");
|
||||
});
|
||||
|
||||
document.getElementById("btn-download-dev-spec")?.addEventListener("click", () => {
|
||||
@@ -2852,11 +2893,7 @@ function bindGlobalEvents() {
|
||||
|
||||
try {
|
||||
// 1. Copy full specification to clipboard so it's immediately ready to paste (Ctrl+V) in Antigravity or Codex
|
||||
try {
|
||||
await navigator.clipboard.writeText(customPrompt);
|
||||
} catch {
|
||||
// Ignore clipboard permission errors if non-HTTPS context
|
||||
}
|
||||
await copyTextToClipboard(customPrompt);
|
||||
|
||||
// 2. Persist handoff package & workspace on server
|
||||
const res = await apiFetch(`/api/ideas/${state.activeIdeaId}/dev-handoff`, {
|
||||
@@ -2876,12 +2913,50 @@ function bindGlobalEvents() {
|
||||
|
||||
if (resultBox) {
|
||||
resultBox.classList.remove("hidden");
|
||||
const modelName = handoff.modelLabel || handoff.model;
|
||||
|
||||
if (activeDevTarget === "antigravity") {
|
||||
resultBox.innerHTML = `
|
||||
<div style="background:linear-gradient(135deg, rgba(76,140,245,0.12), rgba(52,199,89,0.12)); border:1px solid rgba(76,140,245,0.35); border-radius:8px; padding:0.85rem; margin-top:0.4rem;">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:0.5rem;">
|
||||
<div style="font-weight:700;font-size:0.95rem;display:flex;align-items:center;gap:0.4rem;">
|
||||
<span>🛸</span> Switched to Google Antigravity!
|
||||
</div>
|
||||
<div style="display:flex;gap:0.4rem;flex-wrap:wrap;">
|
||||
<button type="button" id="btn-copy-dev-spec-again" class="btn btn-secondary btn-xs">
|
||||
📋 Copy Spec Again
|
||||
</button>
|
||||
<a href="${escapeHtml(handoff.deepLinkUrl)}" class="btn btn-primary btn-xs">
|
||||
🛸 Re-Focus Antigravity
|
||||
</a>
|
||||
<a href="${escapeHtml(handoff.specUrl)}" target="_blank" rel="noopener noreferrer" class="btn btn-ghost btn-xs">
|
||||
📄 View SPEC.md
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:0.6rem;padding:0.65rem 0.8rem;background:var(--bg-card);border-radius:6px;border:1px dashed var(--border-color);font-size:0.85rem;line-height:1.5;">
|
||||
<div style="color:var(--text-main);font-weight:600;">
|
||||
👉 Ready to develop with <strong>${escapeHtml(modelName)}</strong>!
|
||||
</div>
|
||||
<div style="margin-top:0.25rem;color:var(--text-secondary);">
|
||||
The full specification for <strong>${escapeHtml(state.activeIdea.title)}</strong> has been loaded onto your clipboard! Since Antigravity requires starting or selecting your conversation, simply click into Antigravity's chat bar and press <kbd style="background:var(--bg-base);padding:2px 6px;border-radius:4px;border:1px solid var(--border-color);font-weight:700;">Ctrl+V</kbd> (or <kbd style="background:var(--bg-base);padding:2px 6px;border-radius:4px;border:1px solid var(--border-color);font-weight:700;">Cmd+V</kbd>) to paste the prompt and begin.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.getElementById("btn-copy-dev-spec-again")?.addEventListener("click", async () => {
|
||||
const reCopied = await copyTextToClipboard(customPrompt);
|
||||
showToast(reCopied ? "📋 Specification copied to clipboard! Press Ctrl+V in Antigravity." : "⚠️ Please copy manually from the preview below.");
|
||||
});
|
||||
} else {
|
||||
resultBox.innerHTML = `
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:0.5rem;">
|
||||
<strong>✅ Ready in ${escapeHtml(handoff.targetLabel)} (${escapeHtml(handoff.model)})</strong>
|
||||
<div style="display:flex;gap:0.4rem;">
|
||||
<a href="${escapeHtml(handoff.deepLinkUrl)}" class="btn btn-primary btn-xs">
|
||||
🚀 Open ${activeDevTarget === "codex" ? "Codex App" : "Antigravity App"}
|
||||
🚀 Open Codex App
|
||||
</a>
|
||||
<a href="${escapeHtml(handoff.specUrl)}" target="_blank" rel="noopener noreferrer" class="btn btn-ghost btn-xs">
|
||||
📄 View SPEC.md
|
||||
@@ -2898,8 +2973,9 @@ function bindGlobalEvents() {
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
showToast(`🚀 Copied full spec & launching ${handoff.targetLabel} (${handoff.model})!`);
|
||||
showToast(`🛸 Copied spec & launching Antigravity! Paste with Ctrl+V.`);
|
||||
await loadIdeas();
|
||||
renderDrawerContent();
|
||||
|
||||
|
||||
@@ -936,6 +936,10 @@
|
||||
|
||||
<div id="dev-handoff-result-box" class="nb-edit-box hidden"></div>
|
||||
|
||||
<div id="dev-handoff-instruction-note" class="muted-label" style="font-size:0.8rem; padding:0.4rem 0.6rem; background:rgba(76,140,245,0.08); border-radius:6px; border-left:3px solid var(--accent-primary); margin-top:0.4rem;">
|
||||
🛸 Submitting switches focus to Antigravity and copies the complete project specification to your clipboard. Simply press <kbd>Ctrl+V</kbd> in Antigravity's chat to start coding.
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" id="btn-cancel-dev-modal" class="btn btn-ghost">Cancel</button>
|
||||
<button type="submit" id="btn-submit-dev-handoff" class="btn btn-primary">
|
||||
|
||||
@@ -424,14 +424,13 @@ export const DEV_HANDOFF_TARGETS = {
|
||||
id: "antigravity",
|
||||
label: "🛸 Google Antigravity",
|
||||
protocol: "antigravity://",
|
||||
defaultModel: "gemini-3.1-pro",
|
||||
defaultModel: "gemini-3.8-flash",
|
||||
models: [
|
||||
{ id: "gemini-3.1-pro", label: "Gemini 3.1 Pro (Recommended — Full-Stack & Architecture)" },
|
||||
{ id: "gemini-3.0-pro", label: "Gemini 3.0 Pro (Deep Reasoning & Complex Refactors)" },
|
||||
{ id: "gemini-3.1-flash", label: "Gemini 3.1 Flash (Fast Iteration & UI Prototyping)" },
|
||||
{ id: "gemini-3.1-flash-lite", label: "Gemini 3.1 Flash-Lite (Lightweight & Rapid Tasks)" },
|
||||
{ id: "claude-sonnet-4.5", label: "Claude 4.5 Sonnet (via Antigravity Model Selector)" },
|
||||
{ id: "claude-opus-4.5", label: "Claude 4.5 Opus (via Antigravity Model Selector)" }
|
||||
{ id: "gemini-4-argon", label: "Gemini 4 Argon (Medium)" },
|
||||
{ id: "gemini-3.8-flash", label: "Gemini 3.8 Flash (Medium)" },
|
||||
{ id: "claude-opus-5.5", label: "Claude Opus 5.5 (Medium)" },
|
||||
{ id: "claude-sonnet-5.5", label: "Claude Sonnet 5.5 (Medium)" },
|
||||
{ id: "gpt-oss-120b", label: "GPT-OSS 120B (Medium)" }
|
||||
]
|
||||
},
|
||||
codex: {
|
||||
@@ -688,10 +687,14 @@ export async function executeDevelopmentHandoff({
|
||||
}
|
||||
}
|
||||
|
||||
const modelObj = targetMeta.models.find((m) => m.id === chosenModel);
|
||||
const modelLabel = modelObj ? modelObj.label : chosenModel;
|
||||
|
||||
return {
|
||||
targetApp,
|
||||
targetLabel: targetMeta.label,
|
||||
model: chosenModel,
|
||||
modelLabel,
|
||||
slug,
|
||||
specMarkdown: compiledSpec,
|
||||
specUrl,
|
||||
|
||||
@@ -269,6 +269,24 @@ test("Development Handoff endpoint compiles full Spark spec and submits to Antig
|
||||
assert.equal(handoffData.handoff.model, "gpt-5.6-sol");
|
||||
assert.match(handoffData.handoff.deepLinkUrl, /^codex:\/\/threads\/new/);
|
||||
assert.equal(handoffData.idea.status, "building");
|
||||
|
||||
// Verify Antigravity handoff with updated models (Gemini 3.8 Flash default)
|
||||
const agyRes = await fetch(`${baseUrl}/api/ideas/1/dev-handoff`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
targetApp: "antigravity",
|
||||
model: "gemini-3.8-flash",
|
||||
includeHomelab: true,
|
||||
moveStatusToBuilding: true
|
||||
})
|
||||
});
|
||||
assert.equal(agyRes.status, 200);
|
||||
const agyData = await agyRes.json();
|
||||
assert.equal(agyData.handoff.targetApp, "antigravity");
|
||||
assert.equal(agyData.handoff.model, "gemini-3.8-flash");
|
||||
assert.equal(agyData.handoff.modelLabel, "Gemini 3.8 Flash (Medium)");
|
||||
assert.match(agyData.handoff.deepLinkUrl, /^antigravity:\/\/new\?model=gemini-3\.8-flash/);
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user