foundry-design-web-adapter 0.2.0-beta.5 → 0.2.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -13
- package/dist/adapter.js +57 -38
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,30 +6,40 @@ Foundry is a local-first precision design workbench for Codex, Cursor, and Claud
|
|
|
6
6
|
|
|
7
7
|
Foundry is distributed through npm, so testers do not need GitHub access.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
> **Current public beta:** `0.2.0-beta.7`. Install Foundry with the `@beta` tag. The unqualified npm `latest` tag still points to an earlier beta and is not the current testing channel.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Full documentation is available at [withfoundry.ai](https://withfoundry.ai).
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
### Recommended: one command
|
|
14
|
+
|
|
15
|
+
Open a terminal in the project, or ask Codex, Cursor, or Claude Code to run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx foundry-design@beta
|
|
15
19
|
```
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
That command detects the project and active coding agent, installs or safely updates Foundry, repairs the shared agent connection, validates its integration, starts the project when needed, and opens the visual session. On the first installation only, restart the coding agent once so it can load the shared MCP connection. A reviewed batch can be queued before the restart and will be claimed when the agent reconnects.
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
After the restart, reopen the same project folder and ask:
|
|
20
24
|
|
|
21
25
|
```text
|
|
22
26
|
Start Foundry for this project and keep listening for Apply with agent requests.
|
|
23
27
|
```
|
|
24
28
|
|
|
25
|
-
That is the normal workflow. Foundry
|
|
29
|
+
That is the normal workflow. Foundry resumes the most recent session for the current source revision and keeps all review and apply state local.
|
|
26
30
|
|
|
27
31
|
### Manual installation
|
|
28
32
|
|
|
29
|
-
From the project you want to inspect, run:
|
|
33
|
+
From the first project you want to inspect, run:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx foundry-design@beta setup --global
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For later projects, keep the shared agent connection and install only the development adapter:
|
|
30
40
|
|
|
31
41
|
```bash
|
|
32
|
-
npx foundry-design@beta setup
|
|
42
|
+
npx foundry-design@beta setup --agent none
|
|
33
43
|
```
|
|
34
44
|
|
|
35
45
|
Then restart the coding agent, reopen the same project folder, and ask:
|
|
@@ -38,7 +48,7 @@ Then restart the coding agent, reopen the same project folder, and ask:
|
|
|
38
48
|
Start Foundry for this project and keep listening for Apply with agent requests.
|
|
39
49
|
```
|
|
40
50
|
|
|
41
|
-
You do not need to run a second terminal command when the agent starts Foundry for you.
|
|
51
|
+
You do not need to run a second terminal command when the agent starts Foundry for you. Apply requests remain queued safely when the agent is offline. Run `npx foundry-design@beta doctor --repair` if the connection or generated integration needs repair.
|
|
42
52
|
|
|
43
53
|
Update an existing installation with:
|
|
44
54
|
|
|
@@ -56,13 +66,13 @@ npx foundry-design@beta uninstall
|
|
|
56
66
|
|
|
57
67
|
Supported automatic web integration currently includes Next.js App Router, Vite, and plain HTML. Generic web, SwiftUI, and React Native projects receive explicit setup guidance when a safe automatic edit is not available.
|
|
58
68
|
|
|
59
|
-
The
|
|
69
|
+
The npm setup above is the public beta installation path and includes the same portable skill and MCP connection used by the agent plugin bundle.
|
|
60
70
|
|
|
61
|
-
The beta supports Node.js 20 or newer. Read
|
|
71
|
+
The beta supports Node.js 20 or newer. Read the [local-first safety model](https://withfoundry.ai/#safety) before using it with sensitive work.
|
|
62
72
|
|
|
63
73
|
## Agent plugin
|
|
64
74
|
|
|
65
|
-
The portable plugin lives at `plugins/foundry-design-control`. The repository also includes marketplace manifests for Codex, Cursor, and Claude-compatible plugin import. Once installed, ask your agent:
|
|
75
|
+
The portable plugin lives at `plugins/foundry-design-control`. The repository also includes marketplace manifests for Codex, Cursor, and Claude-compatible plugin import. Until public marketplace review is complete, `setup --global` installs the same reusable skill and MCP connection from npm without requiring source-repository access. Once installed, ask your agent:
|
|
66
76
|
|
|
67
77
|
```text
|
|
68
78
|
Start Foundry for this project.
|
|
@@ -86,7 +96,9 @@ Foundry remains local-first. Installing the plugin does not create an account, e
|
|
|
86
96
|
- Persistent, coalescing change ledger with JSON and consolidated prompt export
|
|
87
97
|
- Compact in-preview review with editable approved batches and unresolved-target blocking
|
|
88
98
|
- Persistent Apply with agent runs across Codex, Cursor, and Claude Code through MCP
|
|
99
|
+
- Leased agent handoffs that safely return abandoned or interrupted claims to the queue
|
|
89
100
|
- Live source, rebuild, validation, retry, and rendered-verification progress
|
|
101
|
+
- Rendered verification that resumes after refresh and does not depend on Review remaining open
|
|
90
102
|
- Local MCP bridge for agent access
|
|
91
103
|
- Debug adapters for web, SwiftUI, and React Native on iOS Simulator
|
|
92
104
|
- Verification records that compare requested and rendered values
|
package/dist/adapter.js
CHANGED
|
@@ -1216,7 +1216,7 @@ var PANEL_CSS = `
|
|
|
1216
1216
|
.review-head strong { font-size:12px; }.review-summary { padding:12px 16px 12px;border-bottom:1px solid var(--fdc-line);background:#fcfcfc; }.review-summary strong { display:block;font-size:12px;font-weight:550;letter-spacing:-.01em; }.review-summary span { display:block;margin-top:4px;color:var(--fdc-muted);font-size:12px;line-height:1.45; }.review-summary.attention strong { color:#8b4d3d; }.review-toolbar button { height:28px;padding:0 8px;font-size:12px; }
|
|
1217
1217
|
.onboarding-card { bottom:84px;width:340px;padding:16px;border-radius:12px;box-shadow:0 16px 40px rgb(0 0 0 / 15%); }.onboarding-card-head { gap:8px; }.onboarding-card-head span { width:28px;height:28px;display:grid;place-items:center;color:#a75031;background:#fbf1ed;border-radius:8px; }.onboarding-card-head svg { width:16px;height:16px;color:inherit; }.onboarding-card-head strong { font-size:12px;letter-spacing:-.015em; }.onboarding-card>p { margin:8px 0 16px;font-size:12px;line-height:1.55; }.onboarding-steps { display:grid;grid-template-columns:1fr;gap:1px;border:1px solid var(--fdc-line);border-radius:8px;overflow:hidden;background:var(--fdc-line); }.onboarding-step { display:grid;grid-template-columns:24px 1fr;gap:8px;padding:8px 12px;background:white;text-align:left; }.onboarding-step b { color:#8a8a8a;font-size:8px;font-weight:500;letter-spacing:.04em; }.onboarding-step strong { display:block;font-size:12px;font-weight:550; }.onboarding-step small { display:block;margin-top:4px;color:var(--fdc-muted);font-size:8px;line-height:1.35; }.onboarding-actions { gap:8px;margin-top:12px; }.onboarding-actions button { height:32px;padding:0 12px;border-radius:8px;font-size:12px; }
|
|
1218
1218
|
.onboarding-card,.onboarding-step { color:var(--fdc-ink);background:var(--fdc-surface); }.onboarding-card-head span { color:#e7a68c;background:#36231d; }.onboarding-actions button { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.onboarding-actions .onboarding-start { color:#141416;background:#f0f1f3;border-color:#f0f1f3; }
|
|
1219
|
-
.status-popover { width:256px; }.status-popover-actions { display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-top:8px; }.status-popover .status-popover-actions button { height:32px;margin:0; }.status-popover .status-popover-actions [data-status-retry] { grid-column:1/-1; }
|
|
1219
|
+
.status-popover { width:256px; }.status-popover-actions { display:grid;grid-template-columns:1fr 1fr;gap:4px;margin-top:8px; }.status-popover .status-popover-actions button { height:32px;margin:0; }.status-popover .status-popover-actions [data-status-retry],.status-popover .status-popover-actions [data-status-repair] { grid-column:1/-1; }
|
|
1220
1220
|
.onboarding-card { width:360px; }.onboarding-card-head>strong { flex:1; }.onboarding-card-head .onboarding-close { width:28px;height:28px;display:grid;place-items:center;padding:0;border:0;border-radius:4px;background:transparent;color:var(--fdc-muted);cursor:pointer; }.onboarding-card-head .onboarding-close:hover { color:var(--fdc-ink);background:var(--fdc-subtle); }.onboarding-card-head .onboarding-close svg { width:12px;height:12px; }.onboarding-steps { gap:4px;border:0;overflow:visible;background:transparent; }.onboarding-step { min-height:40px;grid-template-columns:24px minmax(0,1fr);align-items:center;gap:8px;padding:8px;border:1px solid var(--fdc-line);border-radius:8px; }.onboarding-step b { width:20px;height:20px;display:grid;place-items:center;border:1px solid var(--fdc-line);border-radius:50%;color:var(--fdc-muted);font:500 8px/1 var(--fdc-font);letter-spacing:0; }.onboarding-step b svg { width:12px;height:12px; }.onboarding-step.complete>b { color:#141416;background:#8ae0c2;border-color:#8ae0c2; }.onboarding-step.current { border-color:var(--fdc-signal);box-shadow:0 0 0 4px rgb(59 130 246 / 10%); }
|
|
1221
1221
|
.review-summary { color:var(--fdc-ink);background:var(--fdc-paper); }.empty-state-icon { color:#9ec5ff;background:var(--fdc-signal-soft); }
|
|
1222
1222
|
.component-card,.health-card { color:var(--fdc-ink);background:var(--fdc-surface);border-color:var(--fdc-line); }.component-card.selected { color:var(--fdc-ink);background:var(--fdc-component-soft);border-color:#5c4b9e;box-shadow:0 0 0 4px rgb(155 135 245 / 10%); }.component-variants span,.component-actions button,.component-variants button { color:#c1b5f5;background:var(--fdc-component-soft);border-color:#4a406f; }.health-score::before { background:var(--fdc-surface); }.health-filters button { color:var(--fdc-muted); }.health-filters button:hover,.health-filters button.active { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }.health-card p,.health-evidence { color:var(--fdc-muted); }.mapping-chooser { color:#f0c9a8;background:#35291d;border-color:#665039; }.mapping-chooser>strong,.mapping-option,.mapping-option small { color:#e7c29f; }.review-card.locating { background:var(--fdc-signal-soft); }.baseline-badge { color:#83d8bb;background:#18352c; }
|
|
@@ -1399,6 +1399,7 @@ var PANEL_CSS = `
|
|
|
1399
1399
|
.property-control input,.property-control select,.compact-control input,.compact-control select { height:36px;font-size:12px;font-weight:400; }
|
|
1400
1400
|
.control-field .unit-select { width:44px;padding-right:24px!important;background-position:right 8px center!important; }
|
|
1401
1401
|
.section-grid { gap:8px;padding:0 16px 16px; }
|
|
1402
|
+
.inspector-category[data-category="position"]>.category-body>.property-section>.section-grid { padding-top:12px; }
|
|
1402
1403
|
@media (max-width:680px){.panel,.layers-panel{width:auto}.panel-resizer{display:none}.change-tray{right:8px;bottom:8px;left:auto;width:calc(100vw - 16px)}.review-takeover{padding:8px}.review-modal{width:calc(100vw - 16px);height:calc(100vh - 16px);border-radius:12px}.review-modal .review-actions{grid-template-columns:84px 1fr}.panel.change-summary-visible .inspector-scroll{padding-bottom:60px}}
|
|
1403
1404
|
@media (prefers-reduced-motion:reduce){*{transition-duration:.01ms!important}.layer-row.entering,.layer-branch{animation:none!important}}
|
|
1404
1405
|
`;
|
|
@@ -1912,7 +1913,7 @@ function installFoundryInspector(options = {}) {
|
|
|
1912
1913
|
statusPill.setAttribute("aria-label", "Foundry session status");
|
|
1913
1914
|
statusPill.insertAdjacentHTML(
|
|
1914
1915
|
"afterend",
|
|
1915
|
-
'<div class="status-popover" hidden><strong data-status-title>Session connected</strong><span data-status-detail>Changes are stored locally.</span><code data-status-project></code><code data-status-revision></code><div class="status-popover-actions"><button data-status-checklist>Getting started</button><button data-status-diagnostics>Copy diagnostics</button><button data-status-retry>Check connection</button></div></div>'
|
|
1916
|
+
'<div class="status-popover" hidden><strong data-status-title>Session connected</strong><span data-status-detail>Changes are stored locally.</span><code data-status-project></code><code data-status-revision></code><div class="status-popover-actions"><button data-status-checklist>Getting started</button><button data-status-diagnostics>Copy diagnostics</button><button data-status-retry>Check connection</button><button data-status-repair>Copy repair command</button></div></div>'
|
|
1916
1917
|
);
|
|
1917
1918
|
shadow.querySelector(".panel").insertAdjacentHTML(
|
|
1918
1919
|
"beforeend",
|
|
@@ -2122,6 +2123,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2122
2123
|
let reviewShowRejected = false;
|
|
2123
2124
|
const collapsedReviewGroups = /* @__PURE__ */ new Set();
|
|
2124
2125
|
let reviewPoll;
|
|
2126
|
+
let sessionPoll;
|
|
2125
2127
|
let lastReviewTrigger = null;
|
|
2126
2128
|
let reviewScrollTop = 0;
|
|
2127
2129
|
let reviewSuspended = false;
|
|
@@ -2189,8 +2191,8 @@ function installFoundryInspector(options = {}) {
|
|
|
2189
2191
|
},
|
|
2190
2192
|
{
|
|
2191
2193
|
id: "agent",
|
|
2192
|
-
title: "Agent
|
|
2193
|
-
detail: "Keep
|
|
2194
|
+
title: "Agent connection",
|
|
2195
|
+
detail: "Keep it listening while you design. Offline batches wait safely."
|
|
2194
2196
|
},
|
|
2195
2197
|
{
|
|
2196
2198
|
id: "selection",
|
|
@@ -2514,7 +2516,8 @@ function installFoundryInspector(options = {}) {
|
|
|
2514
2516
|
(change) => change.status !== "rejected" && String(change.before) !== String(change.after)
|
|
2515
2517
|
);
|
|
2516
2518
|
recordedChangeCount = activeChanges.length;
|
|
2517
|
-
|
|
2519
|
+
const latestRun = payload.applyRuns?.at(-1);
|
|
2520
|
+
latestApplyState = latestRun?.state ?? "none";
|
|
2518
2521
|
updateChangeCount(activeChanges.length, activeChanges.at(-1));
|
|
2519
2522
|
completeOnboardingStep("setup");
|
|
2520
2523
|
if (activeAgentPresence.connected) completeOnboardingStep("agent");
|
|
@@ -2524,6 +2527,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2524
2527
|
renderOnboardingChecklist();
|
|
2525
2528
|
setSessionStatus("live");
|
|
2526
2529
|
if (!libraryPanel.hidden) renderDesignMemory();
|
|
2530
|
+
if (latestRun?.state === "verifying") maybeVerifyRun(latestRun);
|
|
2527
2531
|
if (changeSet.changes.length === 0 && !hydratedOnce) {
|
|
2528
2532
|
showToast("Click any element. Shift-click builds a selection.");
|
|
2529
2533
|
}
|
|
@@ -2537,7 +2541,11 @@ function installFoundryInspector(options = {}) {
|
|
|
2537
2541
|
}
|
|
2538
2542
|
}
|
|
2539
2543
|
void hydrateSession();
|
|
2540
|
-
|
|
2544
|
+
function startSessionPolling() {
|
|
2545
|
+
clearInterval(sessionPoll);
|
|
2546
|
+
sessionPoll = setInterval(() => void hydrateSession(), 5e3);
|
|
2547
|
+
}
|
|
2548
|
+
startSessionPolling();
|
|
2541
2549
|
function showToast(message) {
|
|
2542
2550
|
const toast = shadow.querySelector(".toast");
|
|
2543
2551
|
toast.textContent = message;
|
|
@@ -3513,12 +3521,18 @@ function installFoundryInspector(options = {}) {
|
|
|
3513
3521
|
const count = group.querySelector(".included-count");
|
|
3514
3522
|
if (count) count.textContent = `${included} included`;
|
|
3515
3523
|
});
|
|
3516
|
-
applyButton.textContent =
|
|
3517
|
-
applyButton.disabled = selectedCount === 0
|
|
3524
|
+
applyButton.textContent = selectedCount ? activeAgentPresence.connected ? `Apply ${selectedCount} with agent` : `Queue ${selectedCount} for agent` : "Apply with agent";
|
|
3525
|
+
applyButton.disabled = selectedCount === 0;
|
|
3518
3526
|
}
|
|
3519
3527
|
function agentConnectionMarkup() {
|
|
3520
3528
|
const agentName = activeAgentPresence.presence?.agent?.name;
|
|
3521
|
-
return `<div class="review-agent ${activeAgentPresence.connected ? "connected" : "disconnected"}" aria-live="polite"><i></i><div><strong>${activeAgentPresence.connected ? `${escapeHtml(agentName ?? "Coding agent")} is ready` : "
|
|
3529
|
+
return `<div class="review-agent ${activeAgentPresence.connected ? "connected" : "disconnected"}" aria-live="polite"><i></i><div><strong>${activeAgentPresence.connected ? `${escapeHtml(agentName ?? "Coding agent")} is ready` : "Agent currently offline"}</strong><span>${activeAgentPresence.connected ? "Apply requests will be claimed automatically while this agent keeps listening." : "You can queue this batch now. Codex, Cursor, or Claude Code will claim it when the Foundry listener reconnects."}</span></div>${activeAgentPresence.connected ? "" : "<button data-copy-agent-listener>Copy reconnect instruction</button>"}</div>`;
|
|
3530
|
+
}
|
|
3531
|
+
function copyAgentListenerInstruction() {
|
|
3532
|
+
void navigator.clipboard.writeText(
|
|
3533
|
+
"Start Foundry for this project and keep listening for Apply with agent requests."
|
|
3534
|
+
);
|
|
3535
|
+
showToast("Agent instruction copied");
|
|
3522
3536
|
}
|
|
3523
3537
|
function updateAgentConnection() {
|
|
3524
3538
|
const current = reviewBody.querySelector(".review-agent");
|
|
@@ -3529,12 +3543,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3529
3543
|
const replacement = document.createElement("div");
|
|
3530
3544
|
replacement.innerHTML = agentConnectionMarkup();
|
|
3531
3545
|
current.replaceWith(replacement.firstElementChild);
|
|
3532
|
-
reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click",
|
|
3533
|
-
void navigator.clipboard.writeText(
|
|
3534
|
-
"Start Foundry for this project and keep listening for Apply with agent requests."
|
|
3535
|
-
);
|
|
3536
|
-
showToast("Agent instruction copied");
|
|
3537
|
-
});
|
|
3546
|
+
reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click", copyAgentListenerInstruction);
|
|
3538
3547
|
updateReviewSelection();
|
|
3539
3548
|
}
|
|
3540
3549
|
function renderReviewList(changes) {
|
|
@@ -3700,7 +3709,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3700
3709
|
}
|
|
3701
3710
|
const runStateLabels = {
|
|
3702
3711
|
queued: "Queued for agent",
|
|
3703
|
-
claimed: "
|
|
3712
|
+
claimed: "Handoff received",
|
|
3704
3713
|
applying: "Applying source changes",
|
|
3705
3714
|
rebuilding: "Rebuilding and checking",
|
|
3706
3715
|
verifying: "Verifying rendered values",
|
|
@@ -3709,6 +3718,19 @@ function installFoundryInspector(options = {}) {
|
|
|
3709
3718
|
failed: "Apply failed",
|
|
3710
3719
|
cancelled: "Apply cancelled"
|
|
3711
3720
|
};
|
|
3721
|
+
function maybeVerifyRun(run) {
|
|
3722
|
+
if (run.state !== "verifying" || verifyingRuns.has(run.id)) return;
|
|
3723
|
+
const reloadKey = "__foundry_verifying_run";
|
|
3724
|
+
if (sessionStorage.getItem(reloadKey) !== run.id) {
|
|
3725
|
+
sessionStorage.setItem(reloadKey, run.id);
|
|
3726
|
+
location.reload();
|
|
3727
|
+
return;
|
|
3728
|
+
}
|
|
3729
|
+
verifyingRuns.add(run.id);
|
|
3730
|
+
void verify(run.changeIds, run.id).then(() => sessionStorage.removeItem(reloadKey)).catch((error) => {
|
|
3731
|
+
showToast(error instanceof Error ? error.message : "Rendered verification was interrupted");
|
|
3732
|
+
}).finally(() => verifyingRuns.delete(run.id));
|
|
3733
|
+
}
|
|
3712
3734
|
function captureVerifiedRun(run) {
|
|
3713
3735
|
if (run.state !== "passed" || capturedBaselineRuns.has(run.id)) return;
|
|
3714
3736
|
const changes = (activeReviewPayload?.changeSet?.changes ?? []).filter(
|
|
@@ -3748,13 +3770,13 @@ function installFoundryInspector(options = {}) {
|
|
|
3748
3770
|
const attention = ["needs_attention", "failed"].includes(run.state);
|
|
3749
3771
|
const passed = run.state === "passed";
|
|
3750
3772
|
const active = ["queued", "claimed", "applying", "rebuilding", "verifying"].includes(run.state);
|
|
3751
|
-
const latestMessage = run.state === "queued" ? "The reviewed changes are queued
|
|
3773
|
+
const latestMessage = run.state === "queued" ? run.requeueCount > 0 ? "The previous agent did not begin source work, so Foundry safely returned this batch to the queue." : "The reviewed changes are queued and ready for an active coding agent." : run.state === "claimed" ? activeAgentPresence.connected ? "The agent received this batch. Waiting for source work to begin." : "The agent disconnected before source work began. Foundry will return this batch to the queue shortly." : run.messages.at(-1)?.message ?? run.error ?? "Apply run created.";
|
|
3752
3774
|
latestApplyState = run.state;
|
|
3753
3775
|
if (run.state === "passed") completeOnboardingStep("apply");
|
|
3754
3776
|
captureVerifiedRun(run);
|
|
3755
3777
|
reviewCount.textContent = `Attempt ${run.attempts}`;
|
|
3756
3778
|
reviewBody.innerHTML = `<div class="run-summary"><div class="run-state"><i class="${passed ? "passed" : attention ? "attention" : active ? "active" : ""}"></i><strong>${escapeHtml(runStateLabels[run.state] ?? run.state)}</strong></div><p>${escapeHtml(latestMessage)}</p></div><div class="run-steps">${run.messages.map(
|
|
3757
|
-
(message, index) => `<div class="run-step"><span>${String(index + 1).padStart(2, "0")}</span><div><strong>${escapeHtml(runStateLabels[message.state] ?? message.state)}</strong><p>${escapeHtml(message.
|
|
3779
|
+
(message, index) => `<div class="run-step"><span>${String(index + 1).padStart(2, "0")}</span><div><strong>${escapeHtml(runStateLabels[message.state] ?? message.state)}</strong><p>${escapeHtml(message.message)}</p></div></div>`
|
|
3758
3780
|
).join(
|
|
3759
3781
|
""
|
|
3760
3782
|
)}</div>${run.changedFiles.length ? `<div class="run-files"><strong>Changed files</strong>${run.changedFiles.map((file) => `<code>${escapeHtml(file)}</code>`).join("")}</div>` : ""}${run.validationResults.length ? `<div class="result-list">${run.validationResults.map((result) => `<div class="result-row ${result.passed ? "pass" : "fail"}"><span>${result.passed ? "Passed" : "Failed"} \xB7 ${escapeHtml(result.name)}</span><span>${escapeHtml(result.summary ?? "")}</span></div>`).join("")}</div>` : ""}${run.verificationResults.length ? `<div class="result-list">${run.verificationResults.map((result) => `<div class="result-row ${result.passed ? "pass" : "fail"}"><span>${result.passed ? "Matched" : "Mismatch"} \xB7 ${escapeHtml(result.property)}</span><span>${escapeHtml(reviewValue(result.requested))} \u2192 ${escapeHtml(reviewValue(result.rendered))}</span></div>`).join("")}</div>` : ""}`;
|
|
@@ -3762,6 +3784,10 @@ function installFoundryInspector(options = {}) {
|
|
|
3762
3784
|
applyButton.dataset.action = "retry";
|
|
3763
3785
|
applyButton.textContent = "Retry with agent";
|
|
3764
3786
|
applyButton.disabled = false;
|
|
3787
|
+
} else if (["queued", "claimed"].includes(run.state) && !activeAgentPresence.connected) {
|
|
3788
|
+
applyButton.dataset.action = "reconnect";
|
|
3789
|
+
applyButton.textContent = "Reconnect agent";
|
|
3790
|
+
applyButton.disabled = false;
|
|
3765
3791
|
} else {
|
|
3766
3792
|
applyButton.dataset.action = "status";
|
|
3767
3793
|
applyButton.textContent = passed ? "Verified" : active ? runStateLabels[run.state] ?? run.state : "Run complete";
|
|
@@ -3769,19 +3795,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3769
3795
|
}
|
|
3770
3796
|
reviewCancel.dataset.action = active ? "cancel" : "back";
|
|
3771
3797
|
reviewCancel.textContent = active ? "Cancel" : "Back";
|
|
3772
|
-
|
|
3773
|
-
const reloadKey = "__foundry_verifying_run";
|
|
3774
|
-
if (sessionStorage.getItem(reloadKey) !== run.id) {
|
|
3775
|
-
sessionStorage.setItem(reloadKey, run.id);
|
|
3776
|
-
location.reload();
|
|
3777
|
-
return;
|
|
3778
|
-
}
|
|
3779
|
-
verifyingRuns.add(run.id);
|
|
3780
|
-
void verify(run.changeIds, run.id).finally(() => {
|
|
3781
|
-
verifyingRuns.delete(run.id);
|
|
3782
|
-
sessionStorage.removeItem(reloadKey);
|
|
3783
|
-
});
|
|
3784
|
-
}
|
|
3798
|
+
maybeVerifyRun(run);
|
|
3785
3799
|
}
|
|
3786
3800
|
function renderReviewPayload(payload) {
|
|
3787
3801
|
const preservedScrollTop = reviewBody.scrollTop || reviewScrollTop;
|
|
@@ -3868,7 +3882,8 @@ function installFoundryInspector(options = {}) {
|
|
|
3868
3882
|
shadow.querySelector(".review-back")?.focus();
|
|
3869
3883
|
});
|
|
3870
3884
|
clearInterval(reviewPoll);
|
|
3871
|
-
clearInterval(
|
|
3885
|
+
clearInterval(sessionPoll);
|
|
3886
|
+
sessionPoll = void 0;
|
|
3872
3887
|
reviewPoll = setInterval(() => void refreshReview(), 1e3);
|
|
3873
3888
|
}
|
|
3874
3889
|
function closeReview(restoreFocus = true) {
|
|
@@ -3877,6 +3892,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3877
3892
|
reviewTakeover.hidden = true;
|
|
3878
3893
|
clearInterval(reviewPoll);
|
|
3879
3894
|
reviewPoll = void 0;
|
|
3895
|
+
startSessionPolling();
|
|
3880
3896
|
updateOutline();
|
|
3881
3897
|
if (restoreFocus) lastReviewTrigger?.focus();
|
|
3882
3898
|
}
|
|
@@ -3904,11 +3920,6 @@ function installFoundryInspector(options = {}) {
|
|
|
3904
3920
|
applyButton.disabled = true;
|
|
3905
3921
|
try {
|
|
3906
3922
|
activeAgentPresence = await sessionRequest("/agent-presence");
|
|
3907
|
-
if (!activeAgentPresence.connected) {
|
|
3908
|
-
updateAgentConnection();
|
|
3909
|
-
showToast("No coding agent is listening yet");
|
|
3910
|
-
return;
|
|
3911
|
-
}
|
|
3912
3923
|
const payload = await sessionRequest("/apply-runs", {
|
|
3913
3924
|
method: "POST",
|
|
3914
3925
|
body: JSON.stringify({
|
|
@@ -3918,6 +3929,8 @@ function installFoundryInspector(options = {}) {
|
|
|
3918
3929
|
});
|
|
3919
3930
|
clearReviewDraft();
|
|
3920
3931
|
renderReviewPayload(payload);
|
|
3932
|
+
if (!activeAgentPresence.connected)
|
|
3933
|
+
showToast("Queued. Your coding agent will claim this batch when it reconnects.");
|
|
3921
3934
|
} catch (error) {
|
|
3922
3935
|
showToast(error instanceof Error ? error.message : "Could not start apply run");
|
|
3923
3936
|
updateReviewSelection();
|
|
@@ -6221,6 +6234,10 @@ function installFoundryInspector(options = {}) {
|
|
|
6221
6234
|
void navigator.clipboard.writeText(JSON.stringify(diagnostics, null, 2));
|
|
6222
6235
|
showToast("Privacy-safe diagnostics copied");
|
|
6223
6236
|
});
|
|
6237
|
+
statusPopover.querySelector("[data-status-repair]").addEventListener("click", () => {
|
|
6238
|
+
void navigator.clipboard.writeText("npx foundry-design@beta doctor --repair");
|
|
6239
|
+
showToast("Repair command copied");
|
|
6240
|
+
});
|
|
6224
6241
|
interfaceThemeTrigger.addEventListener("click", () => {
|
|
6225
6242
|
if (interfaceThemeMenu.hidden) openInterfaceThemeMenu();
|
|
6226
6243
|
else closeInterfaceThemeMenu();
|
|
@@ -6243,7 +6260,7 @@ function installFoundryInspector(options = {}) {
|
|
|
6243
6260
|
void navigator.clipboard.writeText(
|
|
6244
6261
|
"Start Foundry for this project and keep listening for Apply with agent requests."
|
|
6245
6262
|
);
|
|
6246
|
-
showToast("
|
|
6263
|
+
showToast("Listener prompt copied");
|
|
6247
6264
|
return;
|
|
6248
6265
|
}
|
|
6249
6266
|
if (action === "apply" && recordedChangeCount > 0) {
|
|
@@ -6393,6 +6410,7 @@ function installFoundryInspector(options = {}) {
|
|
|
6393
6410
|
applyButton.addEventListener("click", () => {
|
|
6394
6411
|
if (applyButton.dataset.action === "apply") void submitReviewedRun();
|
|
6395
6412
|
if (applyButton.dataset.action === "retry") void retryRun();
|
|
6413
|
+
if (applyButton.dataset.action === "reconnect") copyAgentListenerInstruction();
|
|
6396
6414
|
});
|
|
6397
6415
|
function handleGlobalShortcuts(event) {
|
|
6398
6416
|
if (workspaceState.reviewOpen && event.key === "Tab") {
|
|
@@ -6504,6 +6522,7 @@ function installFoundryInspector(options = {}) {
|
|
|
6504
6522
|
systemDarkTheme.removeEventListener("change", handleSystemThemeChange);
|
|
6505
6523
|
document.removeEventListener("pointerdown", handleInterfaceThemeDismiss, true);
|
|
6506
6524
|
clearInterval(reviewPoll);
|
|
6525
|
+
clearInterval(sessionPoll);
|
|
6507
6526
|
document.removeEventListener("click", handlePointer, true);
|
|
6508
6527
|
document.removeEventListener("dblclick", handleTextEdit, true);
|
|
6509
6528
|
document.removeEventListener("pointermove", handleSelectionHover, true);
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,IAAI,IAAI,CAAC;IAChB,cAAc,IAAI,IAAI,CAAC;IACvB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,OAAO,IAAI,IAAI,CAAC;IAChB,cAAc,IAAI,IAAI,CAAC;IACvB,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;CACjB;AAw/BD,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,uBAA4B,GACpC,0BAA0B,CA++K5B"}
|