glove-foundry 0.4.1 → 0.5.0

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.
@@ -0,0 +1,97 @@
1
+ # Execution daemon, browsers and sandboxes
2
+
3
+ Foundry's control process owns agent definitions, instances, conversations, applications, policy and inspection. Agent jobs now execute through Station 3 in a **separate managed daemon process**. Foundry no longer constructs a `SignalRunner` in its control process.
4
+
5
+ ```text
6
+ Foundry control process
7
+ definitions / instances / conversations / approvals / observability
8
+ │ private process transport
9
+ ▼
10
+ Managed Station daemon
11
+ ├─ execution queue / schedules → agent job subprocesses
12
+ └─ optional resource adapters ← scoped mounts in agent jobs
13
+ ├─ browser provider (for example Steel)
14
+ └─ sandbox provider (for example Docker)
15
+ ```
16
+
17
+ An application can host resources on this same Station or connect its mounts to external workers. Hosting resources is optional.
18
+
19
+ Node 22+ is required by Station 3 (22.13+ for SQLite memory). Existing `glove foundry dev` and `start` commands start the managed execution daemon automatically. Its API uses ephemeral host credentials, and generated signal entrypoints live in a private temporary directory. Keys and backend configuration do not enter agent manifests. The independent Station dashboard is not embedded in Foundry; Foundry retains its inspector.
20
+
21
+ The daemon owns job processes, queue access and recurring schedule execution. Foundry receives lifecycle/log events across the process boundary and retains its existing run IDs, cancellation, approvals, callbacks, sleep and schedule semantics. Agent identity is passed explicitly when loading definitions, so discovery of several agents does not race on environment variables.
22
+
23
+ ## Lifecycle and current boundary
24
+
25
+ This implementation manages a local daemon per Foundry runtime. Stopping Foundry gracefully stops its daemon and agent jobs; losing the parent connection also shuts down the managed daemon. It does **not** yet attach agent jobs to an independently administered remote daemon or leave jobs running after the Foundry control process exits. Approvals and core callbacks still use private shared local files. Do not treat this as distributed control-plane failover.
26
+
27
+ The execution queue remains in-memory, as before. Persist instances, conversations, activations and workspace state through the application adapters. Foundry reconstructs persisted activations on startup; it does not restore an interrupted live agent process. Browser/sandbox workers configured through adapters have independent persistence and ownership. Scope cleanup does not shut down those external daemons.
28
+
29
+ Station 3 owns its idle polling backoff; Foundry's legacy `idlePollIntervalMs` option is retained for source compatibility but is not forwarded by Station's daemon API. `pollIntervalMs`, concurrency, attempts and retry backoff are forwarded.
30
+
31
+ ## One Station for jobs and resources
32
+
33
+ Configure the managed daemon in `foundry.application.ts`. Resource providers are optional, application-owned adapters; they do not become agent definition fields or core dependencies.
34
+
35
+ ```ts
36
+ import { defineApplication } from "glove-foundry";
37
+ import { stationDaemon } from "glove-foundry/station";
38
+
39
+ export default defineApplication({
40
+ name: "Assistant",
41
+ daemon: stationDaemon({
42
+ stationId: "assistant",
43
+ // Optional: omit port to allocate a free loopback port.
44
+ port: 4244,
45
+ resources: async () => ({
46
+ browser: await createBrowserManager(),
47
+ sandbox: await createSandboxAdapter(),
48
+ }),
49
+ onReady: connection => savePrivateConnection(connection),
50
+ }),
51
+ });
52
+ ```
53
+
54
+ The factory helpers and private connection storage above belong to the application. See [Operator's application](../../../examples/foundry-operator/foundry.application.ts) and [resource factory](../../../examples/foundry-operator/lib/resources.ts) for a complete Steel/Docker implementation.
55
+
56
+ `glove foundry start` loads the application file inside the managed execution process, invokes the resource factory once, and starts **one** Station with agent jobs and resource endpoints. Agent runs continue using `mountBrowser` and `mountSandbox` with scoped adapters. Configuring providers on the daemon does not automatically grant agents access. Omit `daemon` to retain the jobs-only default, or supply either resource provider independently. Existing mounts can still connect to external workers.
57
+
58
+ `onReady` receives `{ url, stationId, token }` after Station starts. The callback runs inside the daemon; use private storage or another application-owned channel when the host needs the connection. This is a trusted operator connection: Station 3 requires admin scope for its operator resource API. Keep it out of model context, manifests, observability and client-side code. Provider credentials stay in the resource adapters. The callback should overwrite stale connection state on each startup.
59
+
60
+ Foundry stops Station and its resource adapters on shutdown, and cleans up on failed startup or a failed `onReady` callback. Resource factories must release partially acquired resources if they throw before returning. Mount cleanup retains its existing independent semantics; retaining a run scope does not promise a browser survives daemon shutdown. Persistent files and profiles depend on the chosen provider adapters.
61
+
62
+ Programmatic `FoundryRuntime.discover` calls using a daemon adapter must supply `applicationFilePath`; closures are loaded in the child process, never serialized from the parent. Each Foundry runtime owns its Station instance. A fixed port must be unique per instance; omitting it avoids manual port allocation.
63
+
64
+ ## Optional capability mounts
65
+
66
+ Browser and sandbox support is opt-in through `glove-execution`. Neither `glove-core` nor Foundry depends on that package. Use the same explicit mounting pattern as other Glove extensions, inside Foundry's existing `configure` hook:
67
+
68
+ ```ts
69
+ import { defineAgent } from "glove-foundry";
70
+ import { mountBrowser } from "glove-execution";
71
+ import { stationBrowserClient } from "glove-execution/station";
72
+
73
+ export default defineAgent({
74
+ model: () => createConfiguredModel(),
75
+ description: "Browser researcher",
76
+ configure(agent, context) {
77
+ const adapter = stationBrowserClient(
78
+ browserConnectionFor(context.agentId),
79
+ { maxSessions: 1, allowEvaluate: true },
80
+ );
81
+ let close = () => adapter.close();
82
+ context.onCleanup(() => close());
83
+ const browser = mountBrowser(agent, { adapter });
84
+ close = () => browser.close();
85
+ },
86
+ });
87
+ ```
88
+
89
+ The host supplies the model factory and credential-bearing connection resolver. `mountBrowser` attaches tools and a transient context provider that delivers native screenshots after tool results, without wrapping or replacing the agent’s model. Mounting creates a workflow scope; it does not automatically open a browser. Models get `execute_browser`, a persistent, bounded script surface for composing observation, actions, browser evaluation and verification in one model call. `mountSandbox` similarly installs `execute_sandbox`. Existing `repl` selection sees tools mounted during `configure`.
90
+
91
+ The generic `context.onCleanup` hook registers teardown for any mounted capability. Callbacks run in reverse order on success, failure and cancellation, even if configuration fails. Keep returned mount handles in host code; browser/sandbox handles and fields are not part of Foundry's context or manifest. The portable mount entrypoint has no Node or Station imports; the separate Station adapter entrypoint owns backend integration.
92
+
93
+ See [glove-execution](../../glove-execution/README.md) for worker connections, resource grants, retained sandbox ownership, scripting, page evaluation, mounting outside Foundry and custom adapters.
94
+
95
+ ## Station 2 consumers
96
+
97
+ Station retired `station-kit`. Existing room examples now import `defineConfig` from `station-daemon`, start with `stationd`, and use Station 3 dependency ranges. Run the dashboard separately using `station-dashboard@3`, `STATION_DAEMON_URL` and a separate `PORT`. Existing API consumers continue to target the daemon port.
@@ -1,4 +1,6 @@
1
- # Foundry production integration — release handoff
1
+ # Historical Foundry production integration — release handoff
2
+
3
+ > This is the September 9 snapshot. See [the execution release handoff](./execution-release.md) for the current Station 3, browser/sandbox and shared-daemon candidate.
2
4
 
3
5
  Verified on 9 September 2026 with Node 22.18. This is a **tested release candidate, not a published release or a guarantee for an untested production application**.
4
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glove-foundry",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "An Effect-native, file-routed framework for typed, observable Glove agent applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,7 +35,11 @@
35
35
  "types": "./dist/eslint.d.ts",
36
36
  "import": "./dist/eslint.js"
37
37
  },
38
- "./package.json": "./package.json"
38
+ "./package.json": "./package.json",
39
+ "./station": {
40
+ "types": "./dist/station.d.ts",
41
+ "import": "./dist/station.js"
42
+ }
39
43
  },
40
44
  "files": [
41
45
  "dist",
@@ -54,25 +58,29 @@
54
58
  "agent-applications"
55
59
  ],
56
60
  "engines": {
57
- "node": ">=20.12.0"
61
+ "node": ">=22"
58
62
  },
59
63
  "dependencies": {
60
64
  "@clack/prompts": "^1.8.0",
61
65
  "effect": "^3.22.1",
62
- "station-env": "^2.3.0",
63
- "station-signal": "^2.3.0",
64
- "station-schedules": "^2.3.0",
66
+ "station-env": "^3.0.0",
67
+ "station-signal": "^3.0.0",
68
+ "station-schedules": "^3.0.0",
65
69
  "tsx": "^4.21.0",
66
70
  "zod": "^4.3.6",
67
- "glove-core": "4.1.0",
68
- "glove-js": "0.5.0",
69
- "glove-mcp": "1.2.0",
70
- "glove-lisp": "0.5.0",
71
- "glove-facts": "0.1.2",
72
- "glove-memory": "2.2.0",
73
- "glove-mesh": "0.1.5",
74
- "glove-python": "0.4.0",
75
- "glove-working-environment": "0.6.1"
71
+ "station-daemon": "^3.0.0",
72
+ "station-client": "^3.0.0",
73
+ "station-beacon": "^3.0.0",
74
+ "station-broadcast": "^3.0.0",
75
+ "glove-core": "4.2.0",
76
+ "glove-facts": "0.1.3",
77
+ "glove-memory": "2.2.1",
78
+ "glove-lisp": "0.5.1",
79
+ "glove-js": "0.5.1",
80
+ "glove-mesh": "0.1.6",
81
+ "glove-python": "0.4.1",
82
+ "glove-working-environment": "0.7.0",
83
+ "glove-mcp": "1.2.1"
76
84
  },
77
85
  "devDependencies": {
78
86
  "@types/node": "^25.2.3",
@@ -4,7 +4,7 @@ A [Glove Foundry](https://github.com/porkytheblack/glove/tree/main/packages/glov
4
4
 
5
5
  ## First run
6
6
 
7
- Use Node.js 22.13+ (recommended; minimum 20.12). This minimal starter needs an
7
+ Use Node.js 22.13+ (recommended; minimum 22). This minimal starter needs an
8
8
  OpenRouter key. For a keyless first look, choose the guided travel-concierge
9
9
  template instead. Run these commands from this project's directory; skip
10
10
  installation if you already accepted it in the setup wizard.
@@ -6,7 +6,7 @@ It runs before you configure anything — there is a built-in demo model, so you
6
6
 
7
7
  ## First run, step by step
8
8
 
9
- Use Node.js 22.13+ (recommended); the CLI requires Node 20.12 or newer. Open a
9
+ Use Node.js 22.13+ (recommended); the CLI requires Node 22 or newer. Open a
10
10
  terminal in this project's directory. If the setup wizard already installed
11
11
  dependencies, you can skip the install command below.
12
12