foundry-design-web-adapter 0.2.0-beta.3 → 0.2.0-beta.4
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 +32 -8
- package/dist/adapter.js +57 -5
- package/dist/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,27 +4,51 @@ Foundry is a local-first precision design workbench for Codex, Cursor, and Claud
|
|
|
4
4
|
|
|
5
5
|
## Beta installation
|
|
6
6
|
|
|
7
|
-
Foundry is distributed through npm, so testers do not need
|
|
7
|
+
Foundry is distributed through npm, so testers do not need GitHub access.
|
|
8
|
+
|
|
9
|
+
### Recommended: let your coding agent install it
|
|
10
|
+
|
|
11
|
+
Open the project in Codex, Cursor, or Claude Code and paste:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Install Foundry for this project by running npx foundry-design@beta setup --yes. Check the result and tell me when I need to restart.
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Setup detects the project and active coding agent, installs development-only instrumentation, configures the local agent connection, validates the integration, and records everything it owns for safe updates or removal.
|
|
18
|
+
|
|
19
|
+
Restart the coding agent once, reopen the same project folder, and paste:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
Start Foundry for this project and keep listening for Apply with agent requests.
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
That is the normal workflow. Foundry starts the project when needed, opens an authenticated local preview, and shows **Agent is ready** before it allows an apply request.
|
|
26
|
+
|
|
27
|
+
### Manual installation
|
|
28
|
+
|
|
29
|
+
From the project you want to inspect, run:
|
|
8
30
|
|
|
9
31
|
```bash
|
|
10
32
|
npx foundry-design@beta setup
|
|
11
33
|
```
|
|
12
34
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Restart the coding agent after setup, then ask:
|
|
35
|
+
Then restart the coding agent, reopen the same project folder, and ask:
|
|
16
36
|
|
|
17
37
|
```text
|
|
18
|
-
Start Foundry for this project.
|
|
38
|
+
Start Foundry for this project and keep listening for Apply with agent requests.
|
|
19
39
|
```
|
|
20
40
|
|
|
21
|
-
|
|
41
|
+
You do not need to run a second terminal command when the agent starts Foundry for you. For a manual-only preview, run `npx foundry-design@beta start`, but Apply with agent still requires a restarted and actively listening coding agent.
|
|
42
|
+
|
|
43
|
+
Update an existing installation with:
|
|
22
44
|
|
|
23
45
|
```bash
|
|
24
|
-
npx foundry-design@beta
|
|
46
|
+
npx foundry-design@beta update
|
|
25
47
|
```
|
|
26
48
|
|
|
27
|
-
Foundry
|
|
49
|
+
The updater refreshes checksum-matched Foundry files, agent connections, and skill bundles. It preserves and reports files changed since setup, validates the project, and rolls back the update if Foundry introduces a TypeScript or lint failure. Restart the coding agent after updating.
|
|
50
|
+
|
|
51
|
+
Remove only Foundry-managed integration with:
|
|
28
52
|
|
|
29
53
|
```bash
|
|
30
54
|
npx foundry-design@beta uninstall
|
package/dist/adapter.js
CHANGED
|
@@ -1264,6 +1264,14 @@ var PANEL_CSS = `
|
|
|
1264
1264
|
.review-overview .review-toolbar { position:static;z-index:auto;flex:none;padding:0;border:0;background:transparent;backdrop-filter:none; }
|
|
1265
1265
|
.review-overview .review-toolbar button { height:28px;padding:0 8px;border-color:transparent;background:transparent;color:var(--fdc-muted);font-size:8px; }
|
|
1266
1266
|
.review-overview .review-toolbar button:hover { color:var(--fdc-ink);background:var(--fdc-elevated);border-color:var(--fdc-line); }
|
|
1267
|
+
.review-agent { display:grid;grid-template-columns:8px minmax(0,1fr) auto;align-items:center;gap:12px;margin:12px 16px 0;padding:12px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-paper); }
|
|
1268
|
+
.review-agent>i { width:8px;height:8px;border-radius:50%;background:#d16d51; }
|
|
1269
|
+
.review-agent.connected>i { background:#2ca67f;box-shadow:0 0 0 4px rgb(44 166 127 / 12%); }
|
|
1270
|
+
.review-agent strong,.review-agent span { display:block; }
|
|
1271
|
+
.review-agent strong { font-size:12px;font-weight:600; }
|
|
1272
|
+
.review-agent span { margin-top:4px;color:var(--fdc-muted);font-size:12px;line-height:1.45; }
|
|
1273
|
+
.review-agent button { height:32px;padding:0 12px;border:1px solid var(--fdc-line);border-radius:8px;background:var(--fdc-elevated);color:var(--fdc-ink);font-size:12px;cursor:pointer; }
|
|
1274
|
+
.review-agent button:hover { border-color:var(--fdc-muted); }
|
|
1267
1275
|
.change-tray .review-group { border-right:0;border-bottom:1px solid var(--fdc-line); }
|
|
1268
1276
|
.change-tray .review-group-title { position:sticky;top:52px;z-index:2;min-height:40px;padding:0 12px;background:rgb(28 28 31 / 98%); }
|
|
1269
1277
|
.review-group-title .included-count { font-size:8px; }
|
|
@@ -2081,6 +2089,7 @@ function installFoundryInspector(options = {}) {
|
|
|
2081
2089
|
let selectedControls = [];
|
|
2082
2090
|
let resizeObserver;
|
|
2083
2091
|
let activeReviewPayload = null;
|
|
2092
|
+
let activeAgentPresence = { connected: false, presence: null };
|
|
2084
2093
|
const reviewDraftKey = `__foundry_review_draft:${sessionId || "local"}`;
|
|
2085
2094
|
let reviewDraft = (() => {
|
|
2086
2095
|
try {
|
|
@@ -3394,8 +3403,29 @@ function installFoundryInspector(options = {}) {
|
|
|
3394
3403
|
const count = group.querySelector(".included-count");
|
|
3395
3404
|
if (count) count.textContent = `${included} included`;
|
|
3396
3405
|
});
|
|
3397
|
-
applyButton.textContent = selectedCount ? `Apply ${selectedCount} with agent` : "Apply with agent";
|
|
3398
|
-
applyButton.disabled = selectedCount === 0;
|
|
3406
|
+
applyButton.textContent = !activeAgentPresence.connected ? "Connect agent to apply" : selectedCount ? `Apply ${selectedCount} with agent` : "Apply with agent";
|
|
3407
|
+
applyButton.disabled = selectedCount === 0 || !activeAgentPresence.connected;
|
|
3408
|
+
}
|
|
3409
|
+
function agentConnectionMarkup() {
|
|
3410
|
+
const agentName = activeAgentPresence.presence?.agent?.name;
|
|
3411
|
+
return `<div class="review-agent ${activeAgentPresence.connected ? "connected" : "disconnected"}" aria-live="polite"><i></i><div><strong>${activeAgentPresence.connected ? `${escapeHtml(agentName ?? "Coding agent")} is ready` : "Connect your coding agent"}</strong><span>${activeAgentPresence.connected ? "Apply requests will be claimed automatically while this agent keeps listening." : "In the same project, ask your agent to start Foundry and keep listening for Apply requests."}</span></div>${activeAgentPresence.connected ? "" : "<button data-copy-agent-listener>Copy instruction</button>"}</div>`;
|
|
3412
|
+
}
|
|
3413
|
+
function updateAgentConnection() {
|
|
3414
|
+
const current = reviewBody.querySelector(".review-agent");
|
|
3415
|
+
if (!current) {
|
|
3416
|
+
updateReviewSelection();
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3419
|
+
const replacement = document.createElement("div");
|
|
3420
|
+
replacement.innerHTML = agentConnectionMarkup();
|
|
3421
|
+
current.replaceWith(replacement.firstElementChild);
|
|
3422
|
+
reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click", () => {
|
|
3423
|
+
void navigator.clipboard.writeText(
|
|
3424
|
+
"Start Foundry for this project and keep listening for Apply with agent requests."
|
|
3425
|
+
);
|
|
3426
|
+
showToast("Agent instruction copied");
|
|
3427
|
+
});
|
|
3428
|
+
updateReviewSelection();
|
|
3399
3429
|
}
|
|
3400
3430
|
function renderReviewList(changes) {
|
|
3401
3431
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -3409,7 +3439,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3409
3439
|
const unresolvedCount = changes.filter(
|
|
3410
3440
|
(change) => change.confidence === "unresolved" || change.mappingCandidates?.length > 1 && !change.selectedMappingId
|
|
3411
3441
|
).length;
|
|
3412
|
-
reviewBody.innerHTML = changes.length || rejectedCount ? `<div class="review-overview"><div class="review-summary" data-unresolved="${unresolvedCount}" aria-live="polite"><strong>Preparing review\u2026</strong><span>Only included, exactly mapped changes will be sent to your agent.</span></div><div class="review-toolbar"><button data-review-compare>Compare</button><button data-review-approve-exact>Include all</button><button data-review-toggle-rejected>${reviewShowRejected ? "Hide removed" : rejectedCount ? `${rejectedCount} removed` : "Removed"}</button></div></div>${[
|
|
3442
|
+
reviewBody.innerHTML = changes.length || rejectedCount ? `<div class="review-overview"><div class="review-summary" data-unresolved="${unresolvedCount}" aria-live="polite"><strong>Preparing review\u2026</strong><span>Only included, exactly mapped changes will be sent to your agent.</span></div><div class="review-toolbar"><button data-review-compare>Compare</button><button data-review-approve-exact>Include all</button><button data-review-toggle-rejected>${reviewShowRejected ? "Hide removed" : rejectedCount ? `${rejectedCount} removed` : "Removed"}</button></div></div>${agentConnectionMarkup()}${[
|
|
3413
3443
|
...groups.values()
|
|
3414
3444
|
].map((group) => {
|
|
3415
3445
|
const target = group[0].target;
|
|
@@ -3443,6 +3473,12 @@ function installFoundryInspector(options = {}) {
|
|
|
3443
3473
|
reviewCancel.dataset.action = "back";
|
|
3444
3474
|
reviewCancel.textContent = "Back";
|
|
3445
3475
|
renderIcons(reviewBody);
|
|
3476
|
+
reviewBody.querySelector("[data-copy-agent-listener]")?.addEventListener("click", () => {
|
|
3477
|
+
void navigator.clipboard.writeText(
|
|
3478
|
+
"Start Foundry for this project and keep listening for Apply with agent requests."
|
|
3479
|
+
);
|
|
3480
|
+
showToast("Agent instruction copied");
|
|
3481
|
+
});
|
|
3446
3482
|
reviewBody.querySelectorAll("[data-review-change]").forEach(
|
|
3447
3483
|
(field) => field.addEventListener("change", () => {
|
|
3448
3484
|
reviewDraft.selections[field.dataset.reviewChange] = field.checked;
|
|
@@ -3668,7 +3704,11 @@ function installFoundryInspector(options = {}) {
|
|
|
3668
3704
|
async function refreshReview() {
|
|
3669
3705
|
if (!workspaceState.reviewOpen || !sessionId || !token) return;
|
|
3670
3706
|
try {
|
|
3671
|
-
const payload = await
|
|
3707
|
+
const [payload, presence] = await Promise.all([
|
|
3708
|
+
sessionRequest(),
|
|
3709
|
+
sessionRequest("/agent-presence")
|
|
3710
|
+
]);
|
|
3711
|
+
activeAgentPresence = presence;
|
|
3672
3712
|
const latestRun = payload.applyRuns?.at(-1);
|
|
3673
3713
|
const runNeedsRefresh = latestRun && [
|
|
3674
3714
|
"queued",
|
|
@@ -3681,6 +3721,7 @@ function installFoundryInspector(options = {}) {
|
|
|
3681
3721
|
].includes(latestRun.state);
|
|
3682
3722
|
if (applyButton.dataset.action === "apply" && !runNeedsRefresh) {
|
|
3683
3723
|
activeReviewPayload = payload;
|
|
3724
|
+
updateAgentConnection();
|
|
3684
3725
|
return;
|
|
3685
3726
|
}
|
|
3686
3727
|
renderReviewPayload(payload);
|
|
@@ -3702,7 +3743,12 @@ function installFoundryInspector(options = {}) {
|
|
|
3702
3743
|
workspaceState = updateWorkspace(workspaceState, { type: "set-review", open: true });
|
|
3703
3744
|
reviewTakeover.hidden = false;
|
|
3704
3745
|
outline.hidden = true;
|
|
3705
|
-
|
|
3746
|
+
const [payload, presence] = await Promise.all([
|
|
3747
|
+
sessionRequest(),
|
|
3748
|
+
sessionRequest("/agent-presence")
|
|
3749
|
+
]);
|
|
3750
|
+
activeAgentPresence = presence;
|
|
3751
|
+
renderReviewPayload(payload);
|
|
3706
3752
|
requestAnimationFrame(() => {
|
|
3707
3753
|
reviewBody.scrollTop = reviewScrollTop;
|
|
3708
3754
|
shadow.querySelector(".review-back")?.focus();
|
|
@@ -3743,6 +3789,12 @@ function installFoundryInspector(options = {}) {
|
|
|
3743
3789
|
);
|
|
3744
3790
|
applyButton.disabled = true;
|
|
3745
3791
|
try {
|
|
3792
|
+
activeAgentPresence = await sessionRequest("/agent-presence");
|
|
3793
|
+
if (!activeAgentPresence.connected) {
|
|
3794
|
+
updateAgentConnection();
|
|
3795
|
+
showToast("No coding agent is listening yet");
|
|
3796
|
+
return;
|
|
3797
|
+
}
|
|
3746
3798
|
const payload = await sessionRequest("/apply-runs", {
|
|
3747
3799
|
method: "POST",
|
|
3748
3800
|
body: JSON.stringify({
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6DA,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":"AA6DA,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;AAq/BD,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,uBAA4B,GACpC,0BAA0B,CA4yK5B"}
|