glove-foundry 0.3.3 → 0.4.1

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 CHANGED
@@ -6,16 +6,94 @@ Glove Foundry is an Effect-native application framework for typed, observable Gl
6
6
 
7
7
  The development server includes a hierarchical inspector for definitions, instances, runs, automations, integrations, and shared workspaces. See the [inspector guide](./docs/inspector.md).
8
8
 
9
+ Build guided conversations with first-class, lazy `goals`, `facts`, `forms`, and
10
+ `contextProviders`. Native runners own behavior; adapters own saved progress,
11
+ evidence and answers. See [the guidance handbook](./docs/guidance.md) for scope,
12
+ durable SQLite setup, preparation, and a runnable example.
13
+
14
+ ## Your first agent application
15
+
16
+ Dependency installation is selected by default in the setup wizard. Foundry runs
17
+ your chosen package manager's `install` command in the generated project and waits
18
+ for it to finish before showing next steps. In non-interactive commands, add
19
+ `--install` to install automatically; use `--no-install` to defer it explicitly.
20
+
21
+ Use Node.js 22.13+ (recommended, including SQLite memory support); the CLI requires
22
+ at least Node 20.12. Run this in a terminal:
23
+
24
+ ```bash
25
+ npx glove-foundry init
26
+ ```
27
+
28
+ The Clack-powered setup guides you through a project directory, standalone or
29
+ Next.js integration, a starter, and your package manager. Review the plan before
30
+ any files are created. Arrow keys move, Enter selects, and Ctrl+C cancels. It never
31
+ asks for API keys. Installing dependencies is an explicit choice.
32
+
33
+ Choose **Guided example** for a first look: its travel concierge works without a
34
+ provider key. Choose **Minimal agent** when you want one agent and one tool and are
35
+ ready to configure OpenRouter. These are development starters, not durable storage
36
+ or preconfigured Telegram/Discord deployments.
37
+
38
+ For a repeatable, non-interactive setup:
39
+
9
40
  ```bash
10
- npx glove-foundry init my-agent-app
41
+ npx glove-foundry init my-agent-app --template travel-concierge --package-manager pnpm --yes
11
42
  cd my-agent-app
12
43
  pnpm install
13
44
  pnpm dev
14
45
  ```
15
46
 
47
+ Open `http://127.0.0.1:4141`, choose **Start a run**, select the concierge, and ask
48
+ “Find a flight to Nairobi.” Open that run to follow its model and tool events. Edit
49
+ `agents/concierge/agent.ts` to change behavior; the development server reloads it.
50
+ Run `pnpm typecheck` and `pnpm lint` after changes.
51
+
52
+ For live model responses, copy `.env.example` to `.env.local`, set
53
+ `OPENROUTER_API_KEY`, and restart `pnpm dev`. Keep that file out of version control.
54
+ The guided example stays in deterministic demo mode until a key is configured.
55
+
56
+ ### Initializer options
57
+
58
+ | Option | Meaning |
59
+ | --- | --- |
60
+ | `--template travel-concierge\|minimal` | Choose a worked example or small starting point |
61
+ | `--target standalone\|nextjs` | Create a project or add agents to an existing app; Next.js is detected |
62
+ | `--package-manager pnpm\|npm\|yarn\|bun` | Choose install commands; existing lockfiles are detected |
63
+ | `--yes` or `--no-interactive` | Accept defaults without prompts; does not install unless `--install` is supplied |
64
+ | `--interactive` | Require a terminal; useful when accidental piping should fail |
65
+ | `--install` or `--no-install` | Install dependencies now, or print the command for later |
66
+ | `--help` | Show create and runtime command help |
67
+
68
+ Piped commands never wait for a prompt. Existing standalone directories must be
69
+ empty; Next.js integration preserves existing app files and refuses collisions.
70
+ If installation fails, your generated project remains available with retry steps.
71
+
72
+ ### Before deploying
73
+
74
+ Persist **three separate things**: Foundry instance/activation data, Glove
75
+ conversation history, and structured memory/VFS state. The demo's in-memory
76
+ adapters intentionally reset and must not be mistaken for production persistence.
77
+ Use `FileFoundryDataAdapter` for single-host runtime data, a durable conversation
78
+ store, and `glove-memory/sqlite` or your own native memory adapters. Add VFS
79
+ persistence when agents work on documents. Multi-host deployments need shared,
80
+ transactional adapters. See [Building with Foundry](./docs/building-with-foundry.md).
81
+
82
+ **Troubleshooting:** check `node --version` for engine errors, add a provider key
83
+ for the minimal starter, choose another `--port` if 4141 is occupied, and inspect a
84
+ failed run's events for provider failures. With npm, use `npm run dev` instead of
85
+ `pnpm dev`; generated README commands follow your selected package manager.
86
+
16
87
  Inside an installed project, the framework binary also supports `glove foundry dev`
17
88
  and `glove foundry start`.
18
89
 
90
+ Foundry binds to loopback by default. A non-loopback host fails closed unless the
91
+ application supplies `requestAuthorization`, an Effect-native adapter that returns
92
+ only an authorization decision. It may validate bearer/basic credentials, cookies,
93
+ or an identity from a trusted proxy; Foundry never stores or observes the credential.
94
+ The typed client accepts a matching per-request `authorization` adapter. Terminate
95
+ TLS and apply rate/network policy at the deployment boundary.
96
+
19
97
  ## The mental model
20
98
 
21
99
  Foundry keeps code and data deliberately separate.
@@ -116,7 +194,7 @@ Definition config is followed through the imported value. Zod config schemas inf
116
194
 
117
195
  ## Applications, transmissions, and connections
118
196
 
119
- Applications are headless, installable capability definitions. They may own multiple inbound and outbound transmissions. Outbound transmissions become tools only when the application is installed on an instance.
197
+ Applications are headless, installable capability definitions. They may own multiple inbound and outbound transmissions. Outbound transmissions become tools only when the application is installed on an instance. Calling one of those tools awaits and returns the outbound adapter's schema-validated result; grants, credentials, and adapter execution remain in the parent runtime. Set `outbound.requiresPermission` to a boolean or payload predicate for exact-input approval. `outbound.project` can remove presentation-only material from model-visible data, while `outbound.render` retains a UI-only projection in tool history—for example, a browser screenshot can render without copying its base64 bytes into model context. Framework-authored fire-and-forget transmissions keep their asynchronous command semantics.
120
198
 
121
199
  ```ts
122
200
  // connections/provider-events.connection.ts
@@ -130,6 +208,7 @@ export default defineConnection({
130
208
  route: chooseRoute(ctx.routes, event),
131
209
  eventId: event.id,
132
210
  threadKey: event.threadId,
211
+ awaitCompletion: true,
133
212
  raw: event,
134
213
  }))
135
214
  }),
@@ -138,6 +217,13 @@ export default defineConnection({
138
217
 
139
218
  Foundry supervises connection lifetime and retry, but never acquires or refreshes credentials. Account references contain only metadata and an opaque `accessRef`. Your `accountSessions` or provider adapter owns credential material and refresh.
140
219
 
220
+ `receive()` resolves after durable dispatch by default. A stateful consumer that
221
+ awaits each event in order can set `awaitCompletion: true`; its Effect then remains
222
+ open until every matching run is terminal, preventing successive chat turns from
223
+ racing one transcript. Leave it unset for dispatch-oriented streams or manage a
224
+ per-conversation queue in a transport that needs unrelated threads to proceed in
225
+ parallel.
226
+
141
227
  Connections are desired only when:
142
228
 
143
229
  - an instance has installed the application and has a matching inbound playbook; or
@@ -145,6 +231,31 @@ Connections are desired only when:
145
231
 
146
232
  This covers webhook/socket ingestion and long-lived provider bots without exposing the execution backend as a framework primitive.
147
233
 
234
+ MCP entries can resolve lazily from typed installation data in the same way. The instance owns the selected URL, metadata, and tool exclusions; the agent-owned `mcpAdapter` receives the decoded selections and resolves fresh auth headers only when `glove-mcp` connects.
235
+
236
+ ```ts
237
+ const projectMcp = defineMcp({
238
+ description: "Instance-selected project MCP",
239
+ config: z.object({
240
+ serverUrl: z.string().url(),
241
+ tokenEnvironment: z.string(),
242
+ }),
243
+ entry: ({ config }) => ({
244
+ name: "Project tools",
245
+ description: "Project-specific capabilities",
246
+ url: config.serverUrl,
247
+ }),
248
+ })
249
+
250
+ export default defineAgent({
251
+ // ...
252
+ mcpAdapter: ({ resolved, conversationId }) =>
253
+ Effect.succeed(mcpAdapterFor(conversationId, resolved)),
254
+ })
255
+ ```
256
+
257
+ Credential acquisition and refresh still belong to `mcpAdapterFor`; persisted installation config should contain only a reference such as an environment-variable or vault-record name.
258
+
148
259
  ## Background playbooks and lazy provisioning
149
260
 
150
261
  A playbook is serializable runtime policy. It is composed by an agent resolver or frontend from transmission primitives, then persisted on the instance. Executable normalization, authentication, predicates, serialization, and delivery live on the transmission definition.
@@ -174,7 +285,80 @@ The data adapter atomically enforces `provisioningKey`. Inbound delivery claims
174
285
 
175
286
  ## Conversations and shared work
176
287
 
177
- One agent instance can own many conversations. Foundry also provides adapter-backed workspace entries, shared inbox items, tasks, and scoped environment values. These are data primitives, not prompt conventions, so agents can pass documents and work records by reference instead of copying context.
288
+ One agent instance can own many conversations. Messages use native Glove content parts,
289
+ and media parts may retain an optional human-facing filename. The server keeps JSON at
290
+ a conservative 1 MB by default; a trusted multimodal deployment can set the typed
291
+ `server.messageBodyBytes` bound for larger base64 messages. Foundry also provides
292
+ adapter-backed workspace entries, shared inbox items, tasks, and scoped environment
293
+ values. These are data primitives, not prompt conventions, so agents can pass documents
294
+ and work records by reference instead of copying context.
295
+
296
+ The built-in **Chat** page is a durable WebChat surface over those same primitives.
297
+ It lists conversations per runtime instance, reloads exact native Glove history from
298
+ the configured `store`/`conversationStore`, accepts text and file content parts, and
299
+ supports cancel plus interrupt-and-restart steering. The typed client exposes the
300
+ same read boundary:
301
+
302
+ ```ts
303
+ const transcript = await foundry.conversationTranscript(agent.id, conversation.id, {
304
+ limit: 100,
305
+ })
306
+ ```
307
+
308
+ `transcript.persisted` is `false` when the agent has no configured conversation
309
+ store. Foundry does not fabricate history from retained runs or UI state.
310
+
311
+ ## Least-privilege subagents
312
+
313
+ Subagents may declare fixed tools or project an invocation-time subset from the
314
+ fully assembled parent. That lets a delegate inherit an installed application or
315
+ MCP read operation without receiving the parent's write/admin surface. The
316
+ projection is resolved only when the subagent is called, after instance
317
+ installations and message-dependent assembly have completed.
318
+
319
+ ```ts
320
+ defineSubagent({
321
+ name: "researcher",
322
+ description: "Research one bounded question",
323
+ systemPrompt: "Return evidence, uncertainty, and a concise conclusion.",
324
+ tools: ({ parent }) => projectTools(parent, [
325
+ webSearchToolName,
326
+ webReadToolName,
327
+ "workspace_read_file",
328
+ ]),
329
+ })
330
+ ```
331
+
332
+ The child keeps its isolated store, compaction policy, model, prompt, skills,
333
+ layers, and subscribers. Parent subscribers still receive the subagent lifecycle
334
+ bracket, so delegation remains visible in the same run trace.
335
+
336
+ ## Programmatic tool workflows
337
+
338
+ `defineRepl` can expose an explicit projection of the fully assembled agent as
339
+ sandbox functions. This lets an agent use one Python, JavaScript, or Lisp program
340
+ to read, filter, loop, branch, and invoke several approved capabilities while
341
+ only the final value enters its conversation context:
342
+
343
+ ```ts
344
+ defineRepl({
345
+ language: "python",
346
+ session: PySession.create({ actor: agentId }),
347
+ mount: { frame: "workflow", discovery: "auto" },
348
+ programmaticTools: {
349
+ maxCalls: 50,
350
+ select: ({ tools }) => tools
351
+ .filter((tool) => tool.name.startsWith("workspace_"))
352
+ .map((tool) => ({ tool, server: "workspace" })),
353
+ },
354
+ })
355
+ ```
356
+
357
+ Selection happens after dynamic installations and `configure`; returned entries
358
+ carry direct live tool references rather than parallel ids. The surface is empty
359
+ unless the definition opts in. Foundry revalidates Zod inputs, propagates aborts,
360
+ records safe per-call events, and refuses permission-gated calls inside the
361
+ program so an interactive approval cannot be bypassed.
178
362
 
179
363
  ## Immediate work, future work, and sleep
180
364
 
@@ -209,12 +393,19 @@ Useful endpoints:
209
393
  GET /api/manifest
210
394
  GET /api/agent-instances
211
395
  PATCH /api/agent-instances/:id
396
+ GET /api/conversations/:id/messages?agent=:agentId
397
+ POST /api/conversations/:id/messages
398
+ PATCH /api/conversations/:id
212
399
  GET /api/playbook-subscriptions
213
400
  PUT /api/playbook-subscriptions
214
401
  GET /api/application-connections
215
402
  POST /api/transmissions/:routeId/fire
216
403
  GET /api/runs
217
404
  GET /api/events
405
+ GET /v1/models
406
+ POST /v1/chat/completions
218
407
  ```
219
408
 
220
- See [Building with Foundry](./docs/building-with-foundry.md), [Architecture](./docs/architecture.md), and the runnable [`examples/foundry-agent`](../../examples/foundry-agent).
409
+ The `/v1/chat/completions` endpoint accepts an agent instance id as `model`, supports SSE streaming, and returns `x-foundry-conversation-id`. Reuse `user`, `conversation_id`, or that header to continue the same durable Foundry conversation from an OpenAI-compatible client.
410
+
411
+ See [Building with Foundry](./docs/building-with-foundry.md), [Architecture](./docs/architecture.md), the compact [`examples/foundry-agent`](../../examples/foundry-agent), and the [Braind Storm workforce](../../examples/foundry-braind-storm).