@dhzh/foundry 0.0.3-beta.2 → 0.0.3
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 +105 -108
- package/dist/index.js +1 -0
- package/package.json +1 -5
- package/bin/index.js +0 -2
- package/dist/cli/index.mjs +0 -25
- package/dist/web/index.html +0 -1
- package/dist/web/static/css/304.399a9465c7.css +0 -1
- package/dist/web/static/css/index.400108c990.css +0 -1
- package/dist/web/static/js/304.ae01979a4b.js +0 -3
- package/dist/web/static/js/index.93ad4f2a33.js +0 -1
- package/dist/web/static/js/lib-react.8689a73639.js +0 -2
- package/dist/web/static/js/lib-react.8689a73639.js.LICENSE.txt +0 -59
- package/dist/web/static/js/lib-router.7aa1b84d62.js +0 -2
- package/dist/web/static/js/lib-router.7aa1b84d62.js.LICENSE.txt +0 -10
package/README.md
CHANGED
|
@@ -1,139 +1,136 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Foundry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Foundry is an Electron desktop application for managing local AI agent Runtime configurations. The current release focuses on custom Provider management for Codex and Claude Code: define connection and model settings once, preview the resulting configuration changes, and apply them to the corresponding local Runtime.
|
|
4
4
|
|
|
5
|
-
Foundry is
|
|
6
|
-
serves the bundled React Web UI from `dist/web/`.
|
|
5
|
+
> Foundry is in an early stage. Provider and Runtime management are functional; the Skills area is currently a placeholder, and broader tools, agents, and workflows remain future work.
|
|
7
6
|
|
|
8
|
-
The
|
|
9
|
-
shell, including the Settings surface.
|
|
7
|
+
Tagged builds are published on the [GitHub Releases](https://github.com/tinywaves/foundry/releases) page. The current automated release workflow produces an unsigned, unnotarized macOS Universal DMG, so macOS may require explicit approval before opening it.
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## Current Features
|
|
12
10
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
11
|
+
- Manage separate custom Providers for Codex and Claude Code.
|
|
12
|
+
- Store Provider names, Base URLs, API keys, model mappings, remarks, websites, and optional avatars locally.
|
|
13
|
+
- Test Provider connectivity before or after saving.
|
|
14
|
+
- View Provider health and Runtime status from the dashboard.
|
|
15
|
+
- Select a Provider or restore Official Default settings for each Runtime.
|
|
16
|
+
- Preview every managed configuration field before writing to disk, with secrets redacted by default.
|
|
17
|
+
- Preserve settings outside Foundry's managed fields and keep a backup of the previous configuration.
|
|
18
|
+
- Automatically reapply an in-use Provider after a Runtime-effective edit.
|
|
19
|
+
- Show persistent restart guidance after every successful configuration write.
|
|
20
|
+
- On macOS, optionally restart an already-running ChatGPT desktop app so its hosted Codex experience reloads the configuration.
|
|
15
21
|
|
|
16
|
-
##
|
|
22
|
+
## Supported Runtimes
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
| Runtime | Configuration file | Managed configuration | Reload behavior |
|
|
25
|
+
| --- | --- | --- | --- |
|
|
26
|
+
| Codex | `~/.codex/config.toml` | Model selection and a Foundry-managed `model_providers` entry | Foundry can gracefully restart an already-running ChatGPT desktop app on macOS. Existing Codex CLI sessions must be restarted manually. |
|
|
27
|
+
| Claude Code | `~/.claude/settings.json` | Anthropic endpoint, token, model-role mappings, fallback model, and subagent model under `env` | Existing Claude Code CLI sessions must be restarted manually. |
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
Restoring Official Default removes the Runtime selection overrides managed by Foundry. It does not delete saved Provider records or unrelated Runtime settings.
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
## Typical Workflow
|
|
25
32
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
1. Open **Agent Runtime > Providers** and add a Provider for Codex or Claude Code.
|
|
34
|
+
2. Enter the endpoint, API key, and Runtime-specific model settings.
|
|
35
|
+
3. Run **Test Connection** to verify that the endpoint responds successfully.
|
|
36
|
+
4. Open **Agent Runtime > Runtimes**, select the desired Provider, and choose **Apply**.
|
|
37
|
+
5. Review the exact field-level changes in the preview dialog and confirm the write.
|
|
38
|
+
6. Follow the result dialog to restart the affected desktop application or CLI session.
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
When an in-use Provider is edited, Foundry saves the Provider first and reapplies it only when a Runtime-effective field changed. If the reapply fails, the saved Provider remains available and the dialog offers the existing Apply retry flow.
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
start the CLI in watch mode:
|
|
42
|
+
## Connection Tests
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
pnpm run build:web
|
|
37
|
-
pnpm run dev:cli
|
|
38
|
-
```
|
|
44
|
+
Provider tests run in the Electron main process with a 15-second timeout and do not follow redirects.
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
- Codex sends `GET <base-url>/models` and uses `Authorization: Bearer <api-key>` when a key is configured.
|
|
47
|
+
- Claude Code sends `GET <base-url>/v1/models`, or `GET <base-url>/models` when the Base URL already ends in `/v1`. It sends `anthropic-version: 2023-06-01` and uses `x-api-key` when configured.
|
|
48
|
+
- Any `2xx` response passes. Network, TLS, timeout, redirect, and non-`2xx` outcomes are recorded as sanitized connection failures.
|
|
41
49
|
|
|
42
|
-
##
|
|
50
|
+
## Configuration Safety
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
Foundry treats configuration writes as a previewed and recoverable operation:
|
|
45
53
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
- Existing TOML or JSON is parsed before any change is offered.
|
|
55
|
+
- Only the documented Runtime fields are modified; unrelated settings are preserved.
|
|
56
|
+
- The proposed output is generated, parsed again, and validated before replacing the active file.
|
|
57
|
+
- Writes use same-directory temporary files with restrictive `0600` permissions.
|
|
58
|
+
- The latest previous file content is stored beside the Runtime configuration as `<filename>.foundry-backup`.
|
|
59
|
+
- If the configuration is written but Foundry cannot record the new application state, it restores the previous file content.
|
|
60
|
+
- Concurrent writes to the same Runtime are rejected.
|
|
61
|
+
|
|
62
|
+
Provider records, including API keys and avatars, are stored in a local SQLite database named `foundry.sqlite` under Electron's platform-specific `userData` directory. Applied API keys are also written to the target Runtime configuration because the Runtime requires them. Treat both the Foundry user-data directory and Runtime configuration files as sensitive local data.
|
|
63
|
+
|
|
64
|
+
## ChatGPT Restart Behavior
|
|
65
|
+
|
|
66
|
+
Automatic restart is intentionally narrow and available only on macOS:
|
|
67
|
+
|
|
68
|
+
- ChatGPT is identified by the fixed bundle identifier `com.openai.codex`.
|
|
69
|
+
- Foundry offers restart only after confirming that ChatGPT is already running.
|
|
70
|
+
- Restart requests a normal application termination and never force-quits ChatGPT.
|
|
71
|
+
- Foundry waits up to 15 seconds for exit, reopens the same bundle, and waits up to another 15 seconds to confirm startup.
|
|
72
|
+
- If detection, quit, or reopen fails, the applied configuration remains intact and Foundry shows manual guidance without an automatic retry action.
|
|
73
|
+
- Foundry never launches ChatGPT when it was not already running and never starts or terminates Codex CLI or Claude Code CLI processes.
|
|
54
74
|
|
|
55
|
-
|
|
75
|
+
Restarting ChatGPT affects the entire desktop application and may interrupt work in its Chat, Work, and Codex views.
|
|
56
76
|
|
|
57
|
-
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
### Prerequisites
|
|
80
|
+
|
|
81
|
+
- Node.js `24.18.0`
|
|
82
|
+
- pnpm `11.9.0`
|
|
58
83
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
84
|
+
### Install and Run
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pnpm install
|
|
88
|
+
pnpm dev
|
|
62
89
|
```
|
|
63
90
|
|
|
64
|
-
|
|
91
|
+
### Verify Changes
|
|
65
92
|
|
|
66
|
-
```
|
|
67
|
-
pnpm
|
|
93
|
+
```bash
|
|
94
|
+
pnpm test
|
|
95
|
+
pnpm typecheck
|
|
96
|
+
pnpm lint
|
|
97
|
+
pnpm build
|
|
68
98
|
```
|
|
69
99
|
|
|
70
|
-
|
|
71
|
-
local URL when it starts.
|
|
100
|
+
### Package the Application
|
|
72
101
|
|
|
73
|
-
|
|
102
|
+
```bash
|
|
103
|
+
pnpm build:mac
|
|
104
|
+
pnpm build:win
|
|
105
|
+
pnpm build:linux
|
|
106
|
+
```
|
|
74
107
|
|
|
75
|
-
|
|
76
|
-
CLI command:
|
|
108
|
+
`pnpm build:unpack` creates an unpacked application directory for local packaging checks. Pushing a `v*` tag runs the release workflow, builds a macOS Universal DMG, and attaches it to a GitHub Release. Automated release artifacts are not currently signed or notarized.
|
|
77
109
|
|
|
78
|
-
|
|
110
|
+
## Architecture
|
|
79
111
|
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
```text
|
|
113
|
+
src/main/ Electron lifecycle, SQLite storage, configuration writes,
|
|
114
|
+
connection tests, and native ChatGPT control
|
|
115
|
+
src/preload/ Narrow contextBridge APIs for Provider and Runtime operations
|
|
116
|
+
src/renderer/ React UI, page workflows, and renderer-side response validation
|
|
117
|
+
src/shared/ Typed Provider and Runtime contracts shared across processes
|
|
118
|
+
resources/ Runtime packaging assets
|
|
119
|
+
build/ electron-builder resources and macOS entitlements
|
|
85
120
|
```
|
|
86
121
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
[`packages/web/src/index.tsx`](packages/web/src/index.tsx), which imports the
|
|
103
|
-
global Astryx reset and theme styles from
|
|
104
|
-
[`packages/web/src/index.css`](packages/web/src/index.css). The root component
|
|
105
|
-
lives in [`packages/web/src/app.tsx`](packages/web/src/app.tsx).
|
|
106
|
-
|
|
107
|
-
Rsbuild is configured in
|
|
108
|
-
[`packages/web/rsbuild.config.ts`](packages/web/rsbuild.config.ts). Production
|
|
109
|
-
assets are written directly to the repository-level `dist/web/` directory so
|
|
110
|
-
the CLI can serve them next to its bundled output.
|
|
111
|
-
|
|
112
|
-
## Project Layout
|
|
113
|
-
|
|
114
|
-
| Path | Role |
|
|
115
|
-
|------|------|
|
|
116
|
-
| `specs/plans/` | Numbered implementation plans and their naming convention |
|
|
117
|
-
| `src/cli/` | CLI entrypoint and Hono static server |
|
|
118
|
-
| `src/modules/settings/` | Settings registry, repository, service, routes, and CLI command |
|
|
119
|
-
| `skills/foundry-settings/` | Installable Skill wrapping the Settings CLI command |
|
|
120
|
-
| `packages/web/` | Rsbuild + React Web UI workspace |
|
|
121
|
-
| `packages/web/src/index.tsx` | Browser entrypoint |
|
|
122
|
-
| `packages/web/src/app.tsx` | Root React component |
|
|
123
|
-
| `packages/web/src/index.css` | Astryx reset and theme imports |
|
|
124
|
-
| `packages/web/rsbuild.config.ts` | React Compiler and Web build configuration |
|
|
125
|
-
| `bin/index.js` | Published `foundry` executable wrapper |
|
|
126
|
-
| `dist/cli/` | Bundled CLI output generated by tsdown |
|
|
127
|
-
| `dist/web/` | Web UI production output served by the CLI |
|
|
128
|
-
|
|
129
|
-
## Implementation Plans
|
|
130
|
-
|
|
131
|
-
See [`specs/plans/README.md`](specs/plans/README.md) for the canonical plan
|
|
132
|
-
location, naming, numbering, and content conventions.
|
|
133
|
-
|
|
134
|
-
## Learn More
|
|
135
|
-
|
|
136
|
-
- [Rsbuild documentation](https://rsbuild.rs)
|
|
137
|
-
- [Rspack documentation](https://rspack.rs)
|
|
138
|
-
- Run `pnpm exec astryx docs` for Astryx component and token guidance
|
|
139
|
-
- [Repository guidelines for agents](AGENTS.md)
|
|
122
|
+
The renderer does not receive arbitrary filesystem, process, shell, or IPC access. Native operations remain in the main process and are exposed through purpose-specific preload methods with constrained inputs and validated responses.
|
|
123
|
+
|
|
124
|
+
## Technology
|
|
125
|
+
|
|
126
|
+
- Electron and `electron-vite`
|
|
127
|
+
- React 19 and TypeScript
|
|
128
|
+
- Astryx Design System and StyleX
|
|
129
|
+
- TanStack Query
|
|
130
|
+
- SQLite through `better-sqlite3`
|
|
131
|
+
- Vitest and ESLint
|
|
132
|
+
- `electron-builder`
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
Foundry is licensed under the [Apache License 2.0](./LICENSE).
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function Test() {}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dhzh/foundry",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.3
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"devEngines": {
|
|
6
6
|
"packageManager": {
|
|
7
7
|
"name": "pnpm",
|
|
@@ -26,11 +26,7 @@
|
|
|
26
26
|
"cli",
|
|
27
27
|
"ai"
|
|
28
28
|
],
|
|
29
|
-
"bin": {
|
|
30
|
-
"foundry": "./bin/index.js"
|
|
31
|
-
},
|
|
32
29
|
"files": [
|
|
33
|
-
"bin",
|
|
34
30
|
"dist"
|
|
35
31
|
],
|
|
36
32
|
"repository": {
|
package/bin/index.js
DELETED
package/dist/cli/index.mjs
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import e from"cac";import t,{exit as n}from"node:process";import r from"terminal-link";import{z as i}from"zod";import{existsSync as a,mkdirSync as o}from"node:fs";import{DatabaseSync as s}from"node:sqlite";import{homedir as c}from"node:os";import l from"node:path";import u from"cli-table3";import{consola as d}from"consola";import{serve as f}from"@hono/node-server";import{serveStatic as p}from"@hono/node-server/serve-static";import{zValidator as m}from"@hono/zod-validator";import{Hono as h}from"hono";function g(){return l.join(c(),`.foundry`)}function _(){return l.join(g(),`foundry.sqlite`)}function v(){let e=g();return a(e)||o(e,{recursive:!0}),e}function y(){let e=_();return a(e)||new s(e).close(),e}function b(){return{storageRootPath:v(),databasePath:y()}}function x(e){let t=e.prepare(`PRAGMA integrity_check`).all().flatMap(e=>Object.values(e));if(t.length!==1||t[0]!==`ok`)throw Error(`SQLite database integrity check failed`)}function S(e,t){if(!e.isOpen)throw Error(`Cannot start a transaction on a closed database`);if(e.isTransaction)throw Error(`Nested SQLite transactions are not supported`);e.exec(`BEGIN`);try{let n=t();return e.exec(`COMMIT`),n}catch(t){throw e.exec(`ROLLBACK`),t}}function C(){let e=_(),t=new s(e,{enableForeignKeyConstraints:!0,timeout:5e3});t.exec(`
|
|
2
|
-
PRAGMA journal_mode = DELETE;
|
|
3
|
-
PRAGMA synchronous = FULL;
|
|
4
|
-
`);let n=!1;return{database:t,databasePath:e,assertIntegrity:()=>x(t),transaction:e=>S(t,e),close:()=>{n||=(t.close(),!0)}}}const w=[{group:`ui`,name:`theme`,defaultValue:`system`,schema:i.enum([`system`,`light`,`dark`]),secret:!1},{group:`ui`,name:`pointer`,defaultValue:!0,schema:i.boolean(),secret:!1}];function T(e,t){return w.find(n=>n.group===e&&n.name===t)}function E(e,t){return`${e}.${t}`}const D=`settings`;function O(e){e.database.exec(`
|
|
5
|
-
CREATE TABLE IF NOT EXISTS ${D} (
|
|
6
|
-
"group" TEXT NOT NULL,
|
|
7
|
-
name TEXT NOT NULL,
|
|
8
|
-
payload TEXT NOT NULL,
|
|
9
|
-
created_at INTEGER NOT NULL,
|
|
10
|
-
updated_at INTEGER NOT NULL,
|
|
11
|
-
PRIMARY KEY ("group", name)
|
|
12
|
-
)
|
|
13
|
-
`);let t=e.database.prepare(`
|
|
14
|
-
INSERT OR IGNORE INTO ${D} ("group", name, payload, created_at, updated_at)
|
|
15
|
-
VALUES (?, ?, ?, ?, ?)
|
|
16
|
-
`),n=Date.now();e.transaction(()=>{for(let e of w)t.run(e.group,e.name,JSON.stringify({value:e.defaultValue}),n,n)})}function k(e){let t=(e=[])=>`
|
|
17
|
-
SELECT * FROM ${D}
|
|
18
|
-
${e.length>0?`WHERE ${e.map(e=>`${e} = ?`).join(` AND `)}`:``}
|
|
19
|
-
`,n=e.database.prepare(t()),r=e.database.prepare(t([`"group"`,`name`])),i=e.database.prepare(`
|
|
20
|
-
INSERT INTO ${D} ("group", name, payload, created_at, updated_at)
|
|
21
|
-
VALUES (?, ?, ?, ?, ?)
|
|
22
|
-
ON CONFLICT("group", name) DO UPDATE SET
|
|
23
|
-
payload = excluded.payload,
|
|
24
|
-
updated_at = excluded.updated_at
|
|
25
|
-
`);return{get({group:e,name:t}){return r.get(e,t)},getAll(){return n.all()},upsert(e,t,n){let r=Date.now();return i.run(e,t,n,r,r).changes===1}}}function A(e,t){let n=T(e,t);if(!n)throw Error(`Unknown setting: ${e}.${t}`);return n}function j(e,t){let n;try{n=JSON.parse(e)}catch{return{structurallyValid:!1}}let r=i.object({value:t}).safeParse(n);return r.success?{value:r.data.value,structurallyValid:!0}:{structurallyValid:!1}}function M(e){O(e);let t=k(e);return{get(e,n){let r=t.get({group:e,name:n}),i=A(e,n),a=E(e,n);if(r){let t=j(r.payload,i.schema);if(t.structurallyValid)return{key:a,group:e,name:n,value:t.value}}return{key:a,group:e,name:n,value:i.defaultValue}},list(){return t.getAll().map(({group:e,name:t,payload:n})=>{let r=A(e,t),i=j(n,r.schema);return{key:E(e,t),group:e,name:t,value:i.structurallyValid?i.value:r.defaultValue}})},setMany(n){e.transaction(()=>{for(let{group:e,name:r,value:i}of n)t.upsert(e,r,JSON.stringify({value:i}))})},resetMany(n){let r=n.map(({group:e,name:t})=>A(e,t));e.transaction(()=>{for(let e of r)t.upsert(e.group,e.name,JSON.stringify({value:e.defaultValue}))})}}}function N(){let e=b(),t=C();try{return t.assertIntegrity(),{storage:t,storagePaths:e,settingsService:M(t),close:t.close}}catch(e){throw t.close(),e}}const P={log(...e){d.log(...e)},raw(...e){d.log.raw(...e)},table(e,t){let n=new u({head:[...e]});for(let e of t)n.push([...e]);d.log(n.toString())},info(...e){d.info(...e)},error(...e){d.error(...e)}},F=i.enum([`get`,`list`,`set`,`reset`]),I=[`Key`,`Value`];function L(e){return typeof e==`string`?e:JSON.stringify(e)}function R(e,t,n){if(e.length!==t)throw Error(`Usage: foundry settings ${n}`)}function z(e){let t=e.indexOf(`.`);if(t<=0||t>=e.length-1)throw Error(`Invalid setting key: ${e}`);return{group:e.slice(0,t),name:e.slice(t+1)}}function B(e){e.command(`settings <action> [...values]`,`Get, list, set, or reset Foundry settings`).option(`--raw`,`Print raw output`).action((e,t,n)=>{let r=F.safeParse(e);if(!r.success)throw Error(`Unknown settings action: ${e}, expected one of: ${F.options.join(`, `)}`);let{raw:i=!1}=n,a=N();try{switch(r.data){case`get`:{R(t,1,`get <key>`);let{group:e,name:n}=z(t[0]),r=a.settingsService.get(e,n);i?P.raw(L(r.value)):P.table(I,[[r.key,L(r.value)]]);return}case`list`:{R(t,0,`list`);let e=a.settingsService.list();if(i)for(let t of e)P.raw(L(t.value));else P.table(I,e.map(e=>[e.key,L(e.value)]));return}case`reset`:{R(t,1,`reset <key>`);let{group:e,name:n}=z(t[0]);try{a.settingsService.resetMany([{group:e,name:n}]),i?P.raw(`true`):P.log(!0)}catch{i?P.raw(`false`):P.log(!1)}return}case`set`:{R(t,2,`set <key> <value>`);let{group:e,name:n}=z(t[0]);try{a.settingsService.setMany([{group:e,name:n,value:t[1]}]),i?P.raw(`true`):P.log(!0)}catch{i?P.raw(`false`):P.log(!1)}}}}finally{a.close()}})}const V=e=>new h().get(`/api/settings`,t=>t.json(e.list())).post(`/api/settings`,m(`json`,i.array(i.object({group:i.string().min(1),name:i.string().min(1),value:i.json()})),(e,t)=>{if(!e.success)return t.json({error:`Invalid settings input`,issues:e.error.issues},400)}),t=>{let n=t.req.valid(`json`);try{return e.setMany(n),t.json(!0)}catch{return t.json({error:`Failed to update settings`},500)}}).post(`/api/settings/reset`,m(`json`,i.object({keys:i.array(i.object({group:i.string().min(1),name:i.string().min(1)}))}),(e,t)=>{if(!e.success)return t.json({error:`Invalid settings input`,issues:e.error.issues},400)}),t=>{let n=t.req.valid(`json`);try{return e.resetMany(n.keys),t.json(!0)}catch{return t.json({error:`Failed to reset settings`},500)}});function H(){let e=l.resolve(import.meta.dirname,`../web`);a(l.join(e,`index.html`))||(P.error(`Web UI assets missing. Please reinstall Foundry: npm install -g @dhzh/foundry`),n(1));let t=N(),r=V(t.settingsService);r.use(`/*`,p({root:e}));try{let e=f({fetch:r.fetch,hostname:`127.0.0.1`,port:7777});return{server:e,url:`http://127.0.0.1:7777`,close:()=>{e.close(),t.close()}}}catch(e){throw t.close(),e}}const U=e(`foundry`);B(U),U.command(`[...args]`,`Open a local Foundry workspace`).action(()=>{let e=H(),t=r(e.url,e.url,{fallback:!1});P.info(`Foundry workspace is running at ${t}`)}),U.help();try{U.parse()}catch(e){P.error(e instanceof Error?e.message:String(e)),t.exitCode=1}export{};
|
package/dist/web/index.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><title>Foundry</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/static/js/lib-react.8689a73639.js"></script><script defer src="/static/js/lib-router.7aa1b84d62.js"></script><script defer src="/static/js/304.ae01979a4b.js"></script><script defer src="/static/js/index.93ad4f2a33.js"></script><link href="/static/css/304.399a9465c7.css" rel="stylesheet"><link href="/static/css/index.400108c990.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
|