foundry-design 0.2.0-beta.11 → 0.2.0-beta.14
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 +63 -10
- package/dist/companion.d.ts +22 -0
- package/dist/companion.d.ts.map +1 -0
- package/dist/companion.js +51 -0
- package/dist/companion.js.map +1 -0
- package/dist/doctor.d.ts +24 -0
- package/dist/doctor.d.ts.map +1 -0
- package/dist/doctor.js +182 -0
- package/dist/doctor.js.map +1 -0
- package/dist/index.js +162 -87
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +28 -3
- package/dist/installer.js.map +1 -1
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +46 -1
- package/dist/project.js.map +1 -1
- package/dist/release.d.ts +3 -3
- package/dist/release.js +1 -1
- package/dist/skill/foundry-design-control/SKILL.md +1 -1
- package/dist/skill/foundry-design-control/references/apply-run-contract.md +5 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -6,11 +6,19 @@ 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
|
+
> **Release candidate:** `0.2.0-beta.14`. The commands below are prepared for this release and must not be promoted to npm `latest` until the full installation matrix passes.
|
|
10
10
|
|
|
11
11
|
Full documentation is available at [withfoundry.ai](https://withfoundry.ai).
|
|
12
12
|
|
|
13
|
-
### Recommended:
|
|
13
|
+
### Recommended: install once, use in every project
|
|
14
|
+
|
|
15
|
+
Install Foundry's shared connection for Codex, Cursor, and Claude once:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx foundry-design install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Restart the selected coding agents once. Then open any project and run:
|
|
14
22
|
|
|
15
23
|
Open a terminal in the project, or ask Codex, Cursor, or Claude Code to run:
|
|
16
24
|
|
|
@@ -18,7 +26,7 @@ Open a terminal in the project, or ask Codex, Cursor, or Claude Code to run:
|
|
|
18
26
|
npx foundry-design
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
That command
|
|
29
|
+
That command finds the nearest real project, detects its framework, installs or safely updates only the development adapter and lightweight project connection, validates it, starts the project when needed, and opens the visual session. The agent bridge and skill remain installed once at machine level. Foundry refuses to treat a home folder as a project and prints the exact CLI and MCP bridge versions before changing configuration.
|
|
22
30
|
|
|
23
31
|
After the restart, reopen the same project folder and ask:
|
|
24
32
|
|
|
@@ -30,16 +38,16 @@ That is the normal workflow. Foundry resumes the most recent session for the cur
|
|
|
30
38
|
|
|
31
39
|
### Manual installation
|
|
32
40
|
|
|
33
|
-
|
|
41
|
+
Install the shared connection for selected agents:
|
|
34
42
|
|
|
35
43
|
```bash
|
|
36
|
-
npx foundry-design
|
|
44
|
+
npx foundry-design install --agent codex,cursor,claude
|
|
37
45
|
```
|
|
38
46
|
|
|
39
|
-
|
|
47
|
+
Connect any project with only its development adapter and local project metadata:
|
|
40
48
|
|
|
41
49
|
```bash
|
|
42
|
-
npx foundry-design
|
|
50
|
+
npx foundry-design connect
|
|
43
51
|
```
|
|
44
52
|
|
|
45
53
|
Then restart the coding agent, reopen the same project folder, and ask:
|
|
@@ -48,7 +56,23 @@ Then restart the coding agent, reopen the same project folder, and ask:
|
|
|
48
56
|
Start Foundry for this project and keep listening for Apply with agent requests.
|
|
49
57
|
```
|
|
50
58
|
|
|
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. After an active agent claims a batch, the MCP bridge keeps that handoff alive
|
|
59
|
+
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. After an active agent claims a batch, the MCP bridge keeps that handoff alive through source edits, rebuilding, and verification. A claim abandoned before source work begins returns to the queue. If the agent disappears during source work, Foundry preserves the same run in **Needs attention** and waits for you to choose **Resume with agent**. It never guesses whether a half-finished edit is safe to repeat.
|
|
60
|
+
|
|
61
|
+
Check the complete connection at any time with:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx foundry-design status
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Foundry reports project integration, the exact MCP package version, runtime health, and the live agent listener separately. Run `npx foundry-design doctor --repair` if configuration or generated integration needs repair.
|
|
68
|
+
|
|
69
|
+
If an older project has stale or conflicting project-scoped agent configuration, run:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx foundry-design reset
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Reset migrates Foundry-owned project MCP files and skills to the shared connection, preserves customized files, and reports anything it could not replace safely.
|
|
52
76
|
|
|
53
77
|
Update an existing installation with:
|
|
54
78
|
|
|
@@ -56,7 +80,13 @@ Update an existing installation with:
|
|
|
56
80
|
npx foundry-design update
|
|
57
81
|
```
|
|
58
82
|
|
|
59
|
-
The updater refreshes checksum-matched
|
|
83
|
+
The updater refreshes checksum-matched project files and the shared machine connection. It removes only Foundry-owned legacy project agent files, preserves customized files, validates the project, and rolls back if Foundry introduces a TypeScript or lint failure. Restart the coding agent only when its shared bridge version changes.
|
|
84
|
+
|
|
85
|
+
Remove a project from Foundry's recent-project list without removing its adapter:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npx foundry-design disconnect
|
|
89
|
+
```
|
|
60
90
|
|
|
61
91
|
Remove only Foundry-managed integration with:
|
|
62
92
|
|
|
@@ -64,15 +94,31 @@ Remove only Foundry-managed integration with:
|
|
|
64
94
|
npx foundry-design uninstall
|
|
65
95
|
```
|
|
66
96
|
|
|
97
|
+
Remove the shared machine connection separately:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx foundry-design uninstall --global
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Project-scoped MCP configuration remains available only as an explicit compatibility mode:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npx foundry-design setup --project-agent --agent codex
|
|
107
|
+
```
|
|
108
|
+
|
|
67
109
|
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.
|
|
68
110
|
|
|
69
111
|
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.
|
|
70
112
|
|
|
113
|
+
### Claude Desktop extension
|
|
114
|
+
|
|
115
|
+
The repository also produces a validated `.mcpb` extension for Claude Desktop. It bundles the local Foundry MCP bridge and can be installed through **Settings → Extensions → Advanced → Install Extension**. This provides a host-native alternative when a Claude Desktop surface does not merge the normal user-level Claude Code MCP configuration. Project instrumentation is still installed with `npx foundry-design`.
|
|
116
|
+
|
|
71
117
|
If an npm mirror or existing `npx` cache reports an old tag, bypass it with a temporary cache and the exact current release:
|
|
72
118
|
|
|
73
119
|
```bash
|
|
74
120
|
FOUNDRY_NPX_CACHE="$(mktemp -d)"
|
|
75
|
-
npx --yes --prefer-online --registry=https://registry.npmjs.org --cache "$FOUNDRY_NPX_CACHE" --package=foundry-design@0.2.0-beta.
|
|
121
|
+
npx --yes --prefer-online --registry=https://registry.npmjs.org --cache "$FOUNDRY_NPX_CACHE" --package=foundry-design@0.2.0-beta.14 foundry-design
|
|
76
122
|
```
|
|
77
123
|
|
|
78
124
|
The beta supports Node.js 20 or newer. Read the [local-first safety model](https://withfoundry.ai/#safety) before using it with sensitive work.
|
|
@@ -87,6 +133,10 @@ Start Foundry for this project.
|
|
|
87
133
|
|
|
88
134
|
Foundry remains local-first. Installing the plugin does not create an account, enable telemetry, or send project data to a Foundry service.
|
|
89
135
|
|
|
136
|
+
### Cursor one-click connection
|
|
137
|
+
|
|
138
|
+
[Add the Foundry MCP bridge to Cursor](https://cursor.com/link/mcp/install?name=foundry-design-control&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIi0tcHJlZmVyLW9ubGluZSIsImZvdW5kcnktZGVzaWduLW1jcC1zZXJ2ZXJAMC4yLjAtYmV0YS4xNCJdfQ%3D%3D), then run `npx foundry-design` inside the project. The repository's Cursor plugin additionally bundles the Foundry skill and session-start hook for marketplace distribution.
|
|
139
|
+
|
|
90
140
|
## Current capabilities
|
|
91
141
|
|
|
92
142
|
- A dedicated local design workspace with a live product canvas, equal Layers and Inspector docks, and a direct-overlay fallback when a product blocks framing
|
|
@@ -105,6 +155,7 @@ Foundry remains local-first. Installing the plugin does not create an account, e
|
|
|
105
155
|
- Center-workspace review with editable approved batches, grouped targets, and unresolved-target blocking
|
|
106
156
|
- Persistent Apply with agent runs across Codex, Cursor, and Claude Code through MCP
|
|
107
157
|
- Automatically renewed agent handoffs that remain claimed during source inspection and safely return abandoned work to the queue
|
|
158
|
+
- Explicit same-run recovery when an agent disappears during source editing, rebuilding, or verification
|
|
108
159
|
- Live source, rebuild, validation, retry, and rendered-verification progress
|
|
109
160
|
- Rendered verification that resumes after refresh and does not depend on Review remaining open
|
|
110
161
|
- Local MCP bridge for agent access
|
|
@@ -123,6 +174,8 @@ pnpm check
|
|
|
123
174
|
pnpm release:check
|
|
124
175
|
pnpm release:pack
|
|
125
176
|
pnpm release:test-install
|
|
177
|
+
pnpm test:e2e
|
|
178
|
+
pnpm mcpb:build
|
|
126
179
|
pnpm build
|
|
127
180
|
pnpm foundry setup --project /path/to/project --agent codex --local-mcp
|
|
128
181
|
pnpm foundry index --project /path/to/project --output /tmp/foundry-design-graph.json
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Agent } from './installer.js';
|
|
2
|
+
export interface CompanionProject {
|
|
3
|
+
root: string;
|
|
4
|
+
targetUrl?: string;
|
|
5
|
+
lastOpenedAt: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CompanionState {
|
|
8
|
+
version: 1;
|
|
9
|
+
foundryVersion: string;
|
|
10
|
+
agents: Agent[];
|
|
11
|
+
projects: CompanionProject[];
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class CompanionStore {
|
|
15
|
+
readonly path: string;
|
|
16
|
+
constructor(home: string);
|
|
17
|
+
read(): Promise<CompanionState>;
|
|
18
|
+
recordInstallation(agents: Agent[]): Promise<CompanionState>;
|
|
19
|
+
registerProject(root: string, targetUrl?: string): Promise<CompanionState>;
|
|
20
|
+
private write;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=companion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companion.d.ts","sourceRoot":"","sources":["../src/companion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAG5C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAc;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,IAAI,EAAE,MAAM;IAIlB,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;IAY/B,kBAAkB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAU5D,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;YAelE,KAAK;CAOpB"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, resolve } from 'node:path';
|
|
3
|
+
import { FOUNDRY_VERSION } from './release.js';
|
|
4
|
+
export class CompanionStore {
|
|
5
|
+
path;
|
|
6
|
+
constructor(home) {
|
|
7
|
+
this.path = join(home, '.foundry', 'companion.json');
|
|
8
|
+
}
|
|
9
|
+
async read() {
|
|
10
|
+
return readFile(this.path, 'utf8')
|
|
11
|
+
.then((content) => JSON.parse(content))
|
|
12
|
+
.catch(() => ({
|
|
13
|
+
version: 1,
|
|
14
|
+
foundryVersion: FOUNDRY_VERSION,
|
|
15
|
+
agents: [],
|
|
16
|
+
projects: [],
|
|
17
|
+
updatedAt: new Date(0).toISOString(),
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
async recordInstallation(agents) {
|
|
21
|
+
const state = await this.read();
|
|
22
|
+
return this.write({
|
|
23
|
+
...state,
|
|
24
|
+
foundryVersion: FOUNDRY_VERSION,
|
|
25
|
+
agents: [...new Set([...state.agents, ...agents])],
|
|
26
|
+
updatedAt: new Date().toISOString(),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async registerProject(root, targetUrl) {
|
|
30
|
+
const state = await this.read();
|
|
31
|
+
const project = {
|
|
32
|
+
root: resolve(root),
|
|
33
|
+
...(targetUrl ? { targetUrl } : {}),
|
|
34
|
+
lastOpenedAt: new Date().toISOString(),
|
|
35
|
+
};
|
|
36
|
+
return this.write({
|
|
37
|
+
...state,
|
|
38
|
+
foundryVersion: FOUNDRY_VERSION,
|
|
39
|
+
projects: [project, ...state.projects.filter((candidate) => candidate.root !== project.root)],
|
|
40
|
+
updatedAt: new Date().toISOString(),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async write(state) {
|
|
44
|
+
await mkdir(dirname(this.path), { recursive: true });
|
|
45
|
+
const temporary = `${this.path}.${process.pid}.tmp`;
|
|
46
|
+
await writeFile(temporary, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
47
|
+
await rename(temporary, this.path);
|
|
48
|
+
return state;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=companion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"companion.js","sourceRoot":"","sources":["../src/companion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAgB/C,MAAM,OAAO,cAAc;IAChB,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;aAC/B,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;aACxD,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,cAAc,EAAE,eAAe;YAC/B,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC,CAAC;IACR,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,MAAe;QACtC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC;YAChB,GAAG,KAAK;YACR,cAAc,EAAE,eAAe;YAC/B,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;YAClD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAY,EAAE,SAAkB;QACpD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,OAAO,GAAqB;YAChC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;YACnB,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACvC,CAAC;QACF,OAAO,IAAI,CAAC,KAAK,CAAC;YAChB,GAAG,KAAK;YACR,cAAc,EAAE,eAAe;YAC/B,QAAQ,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7F,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,KAAqB;QACvC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QACpD,MAAM,SAAS,CAAC,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnF,MAAM,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SessionStore } from 'foundry-design-runtime';
|
|
2
|
+
export type DoctorStatus = 'passed' | 'warning' | 'failed';
|
|
3
|
+
export interface DoctorCheck {
|
|
4
|
+
id: 'project' | 'platform' | 'config' | 'integration' | 'instrumentation' | 'agent-configured' | 'agent-config-valid' | 'agent-version' | 'preview' | 'runtime' | 'agent-listening';
|
|
5
|
+
label: string;
|
|
6
|
+
status: DoctorStatus;
|
|
7
|
+
detail: string;
|
|
8
|
+
}
|
|
9
|
+
export interface DoctorReport {
|
|
10
|
+
version: string;
|
|
11
|
+
projectRoot: string;
|
|
12
|
+
checkedAt: string;
|
|
13
|
+
ready: boolean;
|
|
14
|
+
checks: DoctorCheck[];
|
|
15
|
+
configuredAgentFiles: string[];
|
|
16
|
+
activeSessionId?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DoctorOptions {
|
|
19
|
+
home?: string;
|
|
20
|
+
store?: SessionStore;
|
|
21
|
+
fetcher?: typeof fetch;
|
|
22
|
+
}
|
|
23
|
+
export declare function collectDoctorReport(projectRoot: string, options?: DoctorOptions): Promise<DoctorReport>;
|
|
24
|
+
//# sourceMappingURL=doctor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAItD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE3D,MAAM,WAAW,WAAW;IAC1B,EAAE,EACE,SAAS,GACT,UAAU,GACV,QAAQ,GACR,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,oBAAoB,GACpB,eAAe,GACf,SAAS,GACT,SAAS,GACT,iBAAiB,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAaD,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CA0LvB"}
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { SessionStore } from 'foundry-design-runtime';
|
|
5
|
+
import { detectPlatform } from './project.js';
|
|
6
|
+
import { FOUNDRY_MCP_PACKAGE_SPEC, FOUNDRY_VERSION } from './release.js';
|
|
7
|
+
async function text(path) {
|
|
8
|
+
return readFile(path, 'utf8').catch(() => '');
|
|
9
|
+
}
|
|
10
|
+
async function available(fetcher, url) {
|
|
11
|
+
if (!url)
|
|
12
|
+
return false;
|
|
13
|
+
return fetcher(url)
|
|
14
|
+
.then((response) => response.ok)
|
|
15
|
+
.catch(() => false);
|
|
16
|
+
}
|
|
17
|
+
export async function collectDoctorReport(projectRoot, options = {}) {
|
|
18
|
+
const root = resolve(projectRoot);
|
|
19
|
+
const home = options.home ?? homedir();
|
|
20
|
+
const fetcher = options.fetcher ?? fetch;
|
|
21
|
+
const store = options.store ?? new SessionStore();
|
|
22
|
+
const platform = await detectPlatform(root);
|
|
23
|
+
const configPath = join(root, '.foundry', 'foundry.config.json');
|
|
24
|
+
const config = await text(configPath).then((content) => {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(content);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
const manifest = await text(join(root, '.foundry', 'install-manifest.json')).then((content) => {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(content);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
const candidateAgentFiles = [
|
|
41
|
+
...new Set([
|
|
42
|
+
join(root, '.codex', 'config.toml'),
|
|
43
|
+
join(root, '.cursor', 'mcp.json'),
|
|
44
|
+
join(root, '.mcp.json'),
|
|
45
|
+
join(home, '.codex', 'config.toml'),
|
|
46
|
+
join(home, '.cursor', 'mcp.json'),
|
|
47
|
+
join(home, '.claude.json'),
|
|
48
|
+
join(home, '.mcp.json'),
|
|
49
|
+
]),
|
|
50
|
+
];
|
|
51
|
+
const schemaCheckedAgentFiles = [
|
|
52
|
+
...new Set([
|
|
53
|
+
join(root, '.cursor', 'mcp.json'),
|
|
54
|
+
join(root, '.mcp.json'),
|
|
55
|
+
join(home, '.cursor', 'mcp.json'),
|
|
56
|
+
join(home, '.mcp.json'),
|
|
57
|
+
]),
|
|
58
|
+
];
|
|
59
|
+
const invalidAgentFiles = (await Promise.all(schemaCheckedAgentFiles.map(async (path) => {
|
|
60
|
+
const content = await text(path);
|
|
61
|
+
if (!content)
|
|
62
|
+
return undefined;
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(content);
|
|
65
|
+
return parsed.mcpServers && typeof parsed.mcpServers === 'object' ? undefined : path;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return path;
|
|
69
|
+
}
|
|
70
|
+
}))).filter((path) => Boolean(path));
|
|
71
|
+
const agentFiles = (await Promise.all(candidateAgentFiles.map(async (path) => ({ path, content: await text(path) })))).filter(({ content }) => content.includes('foundry-design-control'));
|
|
72
|
+
const exactAgentFiles = agentFiles.filter(({ content }) => content.includes(FOUNDRY_MCP_PACKAGE_SPEC));
|
|
73
|
+
const staleAgentFiles = agentFiles.filter(({ content }) => !content.includes(FOUNDRY_MCP_PACKAGE_SPEC));
|
|
74
|
+
const runtimeHealthy = await available(fetcher, 'http://127.0.0.1:4387/v1/health');
|
|
75
|
+
const sessions = await store.list().catch(() => []);
|
|
76
|
+
const activeSession = [...sessions]
|
|
77
|
+
.filter((session) => session.changeSet.context.projectRoot === root)
|
|
78
|
+
.sort((left, right) => right.changeSet.updatedAt.localeCompare(left.changeSet.updatedAt))[0];
|
|
79
|
+
let listening = false;
|
|
80
|
+
let listenerDetail = 'No live agent listener for this project session.';
|
|
81
|
+
if (runtimeHealthy && activeSession) {
|
|
82
|
+
const stored = await store.read(activeSession.changeSet.sessionId).catch(() => undefined);
|
|
83
|
+
if (stored) {
|
|
84
|
+
const response = await fetcher(`http://127.0.0.1:4387/v1/sessions/${activeSession.changeSet.sessionId}/agent-presence`, { headers: { 'x-foundry-token': stored.token } }).catch(() => undefined);
|
|
85
|
+
const presence = response?.ok
|
|
86
|
+
? (await response.json())
|
|
87
|
+
: undefined;
|
|
88
|
+
listening = presence?.connected === true;
|
|
89
|
+
if (listening) {
|
|
90
|
+
listenerDetail = `${presence?.presence?.agent?.name ?? 'Agent'} is listening until ${presence?.presence?.expiresAt ?? 'the current lease expires'}.`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const checks = [
|
|
95
|
+
{ id: 'project', label: 'Project', status: 'passed', detail: root },
|
|
96
|
+
{ id: 'platform', label: 'Detected platform', status: 'passed', detail: platform },
|
|
97
|
+
{
|
|
98
|
+
id: 'config',
|
|
99
|
+
label: 'Foundry configuration',
|
|
100
|
+
status: config ? 'passed' : 'failed',
|
|
101
|
+
detail: config ? configPath : 'Not configured.',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'integration',
|
|
105
|
+
label: 'Managed integration',
|
|
106
|
+
status: manifest?.generatorVersion === FOUNDRY_VERSION
|
|
107
|
+
? 'passed'
|
|
108
|
+
: manifest?.generatorVersion
|
|
109
|
+
? 'warning'
|
|
110
|
+
: 'failed',
|
|
111
|
+
detail: manifest?.generatorVersion ?? 'Not installed.',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: 'instrumentation',
|
|
115
|
+
label: 'Instrumentation',
|
|
116
|
+
status: config?.instrumented ? 'passed' : 'warning',
|
|
117
|
+
detail: config?.instrumented
|
|
118
|
+
? `${config.framework ?? config.platform}`
|
|
119
|
+
: 'Integration pending.',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'agent-configured',
|
|
123
|
+
label: 'Agent configured',
|
|
124
|
+
status: agentFiles.length ? 'passed' : 'failed',
|
|
125
|
+
detail: agentFiles.length ? agentFiles.map(({ path }) => path).join(', ') : 'Not configured.',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'agent-config-valid',
|
|
129
|
+
label: 'Agent configuration schema',
|
|
130
|
+
status: invalidAgentFiles.length ? 'failed' : 'passed',
|
|
131
|
+
detail: invalidAgentFiles.length
|
|
132
|
+
? `Invalid MCP configuration: ${invalidAgentFiles.join(', ')}.`
|
|
133
|
+
: 'All detected MCP configuration files have an mcpServers record.',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'agent-version',
|
|
137
|
+
label: 'Agent package version',
|
|
138
|
+
status: exactAgentFiles.length === agentFiles.length && agentFiles.length
|
|
139
|
+
? 'passed'
|
|
140
|
+
: agentFiles.length
|
|
141
|
+
? 'warning'
|
|
142
|
+
: 'failed',
|
|
143
|
+
detail: staleAgentFiles.length
|
|
144
|
+
? `Expected ${FOUNDRY_MCP_PACKAGE_SPEC}. Update: ${staleAgentFiles.map(({ path }) => path).join(', ')}`
|
|
145
|
+
: exactAgentFiles.length
|
|
146
|
+
? FOUNDRY_MCP_PACKAGE_SPEC
|
|
147
|
+
: `Expected ${FOUNDRY_MCP_PACKAGE_SPEC}.`,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'preview',
|
|
151
|
+
label: 'Project preview',
|
|
152
|
+
status: platform !== 'web' || (config?.targetUrl && (await available(fetcher, config.targetUrl)))
|
|
153
|
+
? 'passed'
|
|
154
|
+
: config?.targetUrl
|
|
155
|
+
? 'warning'
|
|
156
|
+
: 'failed',
|
|
157
|
+
detail: config?.targetUrl ?? (platform === 'web' ? 'Not configured.' : 'Not required.'),
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'runtime',
|
|
161
|
+
label: 'Runtime',
|
|
162
|
+
status: runtimeHealthy ? 'passed' : 'warning',
|
|
163
|
+
detail: runtimeHealthy ? 'Healthy on 127.0.0.1:4387.' : 'Not running.',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'agent-listening',
|
|
167
|
+
label: 'Active agent listener',
|
|
168
|
+
status: listening ? 'passed' : 'warning',
|
|
169
|
+
detail: listenerDetail,
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
return {
|
|
173
|
+
version: FOUNDRY_VERSION,
|
|
174
|
+
projectRoot: root,
|
|
175
|
+
checkedAt: new Date().toISOString(),
|
|
176
|
+
ready: checks.every((check) => check.status !== 'failed') && listening,
|
|
177
|
+
checks,
|
|
178
|
+
configuredAgentFiles: agentFiles.map(({ path }) => path),
|
|
179
|
+
activeSessionId: activeSession?.changeSet.sessionId,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|