@agentproto/app-kit 1.3.0 → 1.4.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.
- package/README.md +133 -1
- package/dist/define-app.d.ts.map +1 -1
- package/dist/emit.d.ts +6 -1
- package/dist/emit.d.ts.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +417 -12
- package/dist/index.mjs.map +1 -1
- package/dist/load-app.d.ts +23 -1
- package/dist/load-app.d.ts.map +1 -1
- package/dist/manifest-fields.d.ts +30 -0
- package/dist/manifest-fields.d.ts.map +1 -0
- package/dist/pack.d.ts +90 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/types.d.ts +99 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -91,6 +91,37 @@ An app may also declare `requires: ["@acme/shared", ...]` — app ids that must
|
|
|
91
91
|
applied to the same scope before this one can run. The runtime validates the
|
|
92
92
|
graph when mounting apps via `app_apply`.
|
|
93
93
|
|
|
94
|
+
### Placement, requirements, and A2A exposure
|
|
95
|
+
|
|
96
|
+
Four optional `APP.md` keys describe where an app can run and what it exposes.
|
|
97
|
+
They are **semantics only** — nothing schedules or serves on them yet. All are
|
|
98
|
+
validated by `defineApp` (`AppDefinitionError`) and `loadAppHandle`
|
|
99
|
+
(`AppLoadError`), surfaced on `AppHandle`, and written by `emit` only when they
|
|
100
|
+
differ from the default.
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
placement: any # "local" | "box" | "any" | "split" (default "any")
|
|
104
|
+
requires:
|
|
105
|
+
browser: false # needs the user's real browser (Bureau / local-browser)
|
|
106
|
+
fs: false # needs the user's local filesystem beyond app data
|
|
107
|
+
gpu: false
|
|
108
|
+
secrets: [] # env/secret names the app needs
|
|
109
|
+
apps: [] # other app ids this app depends on
|
|
110
|
+
exposes: # A2A-visible surfaces (default: none exposed)
|
|
111
|
+
agents: [] # ids from `agents:`
|
|
112
|
+
workflows: [] # ids from `workflows:`
|
|
113
|
+
accepts:
|
|
114
|
+
tasks: false # accept A2A tasks (default false)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- An unknown `placement`, or an `exposes.*` id that isn't one of the app's own
|
|
118
|
+
agents/workflows, is a validation error.
|
|
119
|
+
- `requires` also still accepts the legacy flat array (`requires: ["@acme/shared"]`,
|
|
120
|
+
equivalent to `requires: { apps: [...] }`).
|
|
121
|
+
- On the handle: `placement`, `exposes`, `accepts` and `requirements` (every key
|
|
122
|
+
resolved to its default) are always present. `handle.requires` stays the flat
|
|
123
|
+
list of app ids (absent when none) so existing dependency checks keep working.
|
|
124
|
+
|
|
94
125
|
## UI surfaces, artifacts, dev-launch, and the artifact surface
|
|
95
126
|
|
|
96
127
|
Beyond agents and workflows, an app can declare four optional surfaces that
|
|
@@ -99,7 +130,20 @@ runtime app registry:
|
|
|
99
130
|
|
|
100
131
|
- **`ui`** — an HTML dashboard/panel. `html` is written to
|
|
101
132
|
`.agentproto/ui/index.html`; `APP.md` frontmatter carries the relative path
|
|
102
|
-
plus optional `title`, `description`, `tools`, and `
|
|
133
|
+
plus optional `title`, `description`, `tools`, `csp`, and `build`.
|
|
134
|
+
- **`ui.build`** — how to (re)build `ui.path` when it's missing or stale,
|
|
135
|
+
so the bundle doesn't have to be committed. `{ command, cwd?, sources? }`:
|
|
136
|
+
`command` is a shell command line run with cwd `cwd` (default: the app
|
|
137
|
+
dir); `sources` is a list of globs (relative to `cwd`, default
|
|
138
|
+
`["src/**"]`) whose newest mtime is compared against `ui.path`'s to decide
|
|
139
|
+
staleness. The daemon/CLI run it — `app_install`, the first `GET
|
|
140
|
+
/apps/:appId/ui`, the MCP panel cache, and `agentproto app serve` all call
|
|
141
|
+
the same `ensureAppUiBuilt` (`@agentproto/runtime/app-ui-build`) before
|
|
142
|
+
serving, single-flight per bundle path so concurrent first requests only
|
|
143
|
+
build once. Output is captured to `<appDir>/.agentproto/ui-build.log`; a
|
|
144
|
+
failing build surfaces that log's tail as the tool/route error instead of
|
|
145
|
+
a bare 404. No `ui.build` declared ⇒ today's behavior: the bundle must
|
|
146
|
+
already exist on disk.
|
|
103
147
|
- **`artifact`** — a persistent HTML dashboard (Cowork artifact). The app
|
|
104
148
|
provides a path to an HTML file on disk; `emit` copies it to
|
|
105
149
|
`.agentproto/artifact/index.html`. The daemon never writes the host manifest
|
|
@@ -225,6 +269,14 @@ export const dashboardApp = defineApp({
|
|
|
225
269
|
html: "<!doctype html><html>…</html>",
|
|
226
270
|
title: "Ops Dashboard",
|
|
227
271
|
tools: ["terminal_start", "agent_start"],
|
|
272
|
+
// Only needed when `ui.path`'s bundle isn't committed to the repo —
|
|
273
|
+
// the daemon/CLI build it on demand before serving. See the APP.md
|
|
274
|
+
// frontmatter equivalent below.
|
|
275
|
+
build: {
|
|
276
|
+
command: "pnpm run build",
|
|
277
|
+
cwd: "ui",
|
|
278
|
+
sources: ["ui/src/**", "ui/index.html", "ui/vite.config.ts"],
|
|
279
|
+
},
|
|
228
280
|
},
|
|
229
281
|
artifact: {
|
|
230
282
|
path: "/path/to/dashboard.html",
|
|
@@ -321,6 +373,86 @@ const app = await loadAppHandle("/path/to/emitted/app")
|
|
|
321
373
|
app.agents.map((e) => e.agent.id) // ["@agentik/reviewer", "fixer"]
|
|
322
374
|
```
|
|
323
375
|
|
|
376
|
+
### `ui.build` — don't commit the generated bundle
|
|
377
|
+
|
|
378
|
+
Add a `build` block under `ui` in `APP.md`'s frontmatter and gitignore
|
|
379
|
+
`.agentproto/ui/index.html` — the daemon builds it on demand instead:
|
|
380
|
+
|
|
381
|
+
```yaml
|
|
382
|
+
ui:
|
|
383
|
+
path: .agentproto/ui/index.html
|
|
384
|
+
build:
|
|
385
|
+
command: pnpm run build
|
|
386
|
+
cwd: ui
|
|
387
|
+
sources:
|
|
388
|
+
- ui/src/**
|
|
389
|
+
- ui/index.html
|
|
390
|
+
- ui/vite.config.ts
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
`app_install`, the first `GET /apps/:appId/ui`, the MCP panel, and
|
|
394
|
+
`agentproto app serve` all resolve this the same way (`peekAppUi` +
|
|
395
|
+
`ensureAppUiBuilt` from `@agentproto/runtime/app-ui-build`): missing or
|
|
396
|
+
older than the newest matching source → run `command` once (single-flight
|
|
397
|
+
per bundle path, output captured to `.agentproto/ui-build.log`) → serve.
|
|
398
|
+
Omit `build` to keep committing the bundle, unchanged from before this
|
|
399
|
+
existed.
|
|
400
|
+
|
|
401
|
+
## Boundaries — fs zones for app-spawned sessions
|
|
402
|
+
|
|
403
|
+
Set `boundaries: { enforce: "required" | "best-effort" }` on `defineApp` (or
|
|
404
|
+
`boundaries:` in `APP.md`'s frontmatter) to declare how strictly the daemon
|
|
405
|
+
must confine sessions the app spawns — `app_run`, and workflow agent steps
|
|
406
|
+
whose workflow carries this app's `appId`:
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
defineApp({
|
|
410
|
+
id: "@acme/transcriber",
|
|
411
|
+
boundaries: { enforce: "required" },
|
|
412
|
+
// ...
|
|
413
|
+
})
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
For every such session the daemon builds one **boundary** with three zones:
|
|
417
|
+
|
|
418
|
+
| Zone | Contents | Access |
|
|
419
|
+
| --- | --- | --- |
|
|
420
|
+
| read-only | the installed app dir (source, `.agentproto/`, `scripts/`) | read |
|
|
421
|
+
| writable | the app's `data/` dir, and the workflow run's `$run.workspace` (`app_run` has no run workspace: writable is `data/` only) | read + write |
|
|
422
|
+
| everything else | including the daemon's own workspace and any host monorepo the app happens to be installed inside | denied |
|
|
423
|
+
|
|
424
|
+
The boundary is enforced on two independent surfaces:
|
|
425
|
+
|
|
426
|
+
1. **Daemon file/command tools** (`file_read`, `file_write`, `directory_*`,
|
|
427
|
+
`command_execute`, …) — always enforced, identity-based: the daemon
|
|
428
|
+
recovers the caller's boundary from its own session record, resolves
|
|
429
|
+
relative paths against the app dir, and rejects reads/writes outside the
|
|
430
|
+
zones (including through symlinks). This does not depend on the harness.
|
|
431
|
+
2. **The harness's own native tools** (a claude-code session's Bash, Write,
|
|
432
|
+
Edit, …) — enforced by wrapping the harness in an OS sandbox
|
|
433
|
+
(`@agentproto/command-sandbox`: macOS Seatbelt or Linux bubblewrap) built
|
|
434
|
+
from the same zones, plus, on adapters that support it, excluding the host
|
|
435
|
+
repository's `CLAUDE.md`/`AGENTS.md` from context so an app session never
|
|
436
|
+
inherits instructions from the monorepo it's installed inside.
|
|
437
|
+
|
|
438
|
+
Surface 2 needs an adapter that supports fs zones and an available OS sandbox
|
|
439
|
+
backend. When it can't be enforced:
|
|
440
|
+
|
|
441
|
+
- `boundaries.enforce: "best-effort"` (the default) still spawns the session
|
|
442
|
+
— daemon tools remain confined — and emits a `session:harness-warning`
|
|
443
|
+
naming the reason (no sandbox backend on this platform, the adapter doesn't
|
|
444
|
+
support `fsZones`, or `commandSandbox: "off"` was requested explicitly).
|
|
445
|
+
- `boundaries.enforce: "required"` refuses the spawn instead of downgrading
|
|
446
|
+
silently (`app_boundary_unenforceable`).
|
|
447
|
+
|
|
448
|
+
**Deferred:** the `AGENT.md` `tools:` allowlist becoming an *enforced*
|
|
449
|
+
allowlist on adapters that support it (today it's advisory — an agent can
|
|
450
|
+
still reach native Bash next to an allowlisted `command_execute`). Also out
|
|
451
|
+
of scope for this phase: a network-capable sandboxed process reaching the
|
|
452
|
+
daemon's HTTP API directly (bypasses the identity-based check the MCP path
|
|
453
|
+
uses), and boundary enforcement on daemon-wide MCP tools other than
|
|
454
|
+
file/command/terminal.
|
|
455
|
+
|
|
324
456
|
## Runtime note
|
|
325
457
|
|
|
326
458
|
`toMastraAgents` is the path where a `body` becomes a **true** model
|
package/dist/define-app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAEV,aAAa,EACb,SAAS,EACT,aAAa,EAGd,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"define-app.d.ts","sourceRoot":"","sources":["../src/define-app.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAEV,aAAa,EACb,SAAS,EACT,aAAa,EAGd,MAAM,YAAY,CAAA;AAKnB,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,SAAS,CAyKvD;AAiID,YAAY,EAAE,aAAa,EAAE,CAAA"}
|
package/dist/emit.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
import type { WorkflowHandle } from "@agentproto/workflow";
|
|
34
34
|
import type { WorkspaceHandle } from "@agentproto/workspace";
|
|
35
|
-
import type { AgentEntry, AppArtifactDecl, AppArtifactSurface, AppDataDefinition, AppDevDefinition, AppSkillSurface, AppUiDefinition, EmittedApp } from "./types.js";
|
|
35
|
+
import type { AgentEntry, AppAccepts, AppArtifactDecl, AppArtifactSurface, AppBoundariesDefinition, AppDataDefinition, AppDevDefinition, AppExposes, AppPlacement, AppRequirements, AppSkillSurface, AppUiDefinition, EmittedApp } from "./types.js";
|
|
36
36
|
interface EmitInput {
|
|
37
37
|
readonly agents: readonly AgentEntry[];
|
|
38
38
|
readonly workflows: readonly WorkflowHandle[];
|
|
@@ -42,6 +42,10 @@ interface EmitInput {
|
|
|
42
42
|
readonly version?: string;
|
|
43
43
|
readonly description?: string;
|
|
44
44
|
readonly requires?: readonly string[];
|
|
45
|
+
readonly requirements?: AppRequirements;
|
|
46
|
+
readonly placement?: AppPlacement;
|
|
47
|
+
readonly exposes?: AppExposes;
|
|
48
|
+
readonly accepts?: AppAccepts;
|
|
45
49
|
readonly ui?: AppUiDefinition;
|
|
46
50
|
readonly artifact?: AppArtifactSurface;
|
|
47
51
|
readonly skill?: AppSkillSurface;
|
|
@@ -49,6 +53,7 @@ interface EmitInput {
|
|
|
49
53
|
readonly dev?: AppDevDefinition;
|
|
50
54
|
readonly data?: AppDataDefinition;
|
|
51
55
|
readonly externalReadRoots?: readonly string[];
|
|
56
|
+
readonly boundaries?: AppBoundariesDefinition;
|
|
52
57
|
readonly category?: string;
|
|
53
58
|
}
|
|
54
59
|
export declare function emitApp(app: EmitInput, dir: string): Promise<EmittedApp>;
|
package/dist/emit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAGpP,UAAU,SAAS;IACjB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAA;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAA;IACpC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,eAAe,CAAA;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,YAAY,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,EAAE,eAAe,CAAA;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,uBAAuB,CAAA;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAuH9E"}
|
package/dist/index.d.ts
CHANGED
|
@@ -38,8 +38,11 @@
|
|
|
38
38
|
*/
|
|
39
39
|
export { defineApp, AppDefinitionError } from "./define-app.js";
|
|
40
40
|
export { emitApp } from "./emit.js";
|
|
41
|
-
export { loadAppHandle, AppLoadError, resolveAppUIRoot } from "./load-app.js";
|
|
41
|
+
export { loadAppHandle, AppLoadError, resolveAppUIRoot, peekAppUi } from "./load-app.js";
|
|
42
|
+
export type { AppUiPeek } from "./load-app.js";
|
|
42
43
|
export { loadAppBundledTools } from "./load-app-tools.js";
|
|
44
|
+
export { packApp, unpackApp, aggregateSha256, collectFiles, isManifest, safeId, AGENTAPP_FORMAT, AgentAppPackError, } from "./pack.js";
|
|
45
|
+
export type { AgentAppManifest, BundleFile, AgentAppPackErrorCode } from "./pack.js";
|
|
43
46
|
export { refKey, stripOwner } from "./refs.js";
|
|
44
|
-
export type { AppDefinition, AppHandle, AgentEntry, DoctypeHandle, WorkspaceShorthand, WorkspaceInput, AppUiDefinition, AppArtifactSurface, AppSkillSurface, AppArtifactDecl, AppDevLaunchConfig, AppDataDefinition, AppDevDefinition, ToMastraAgentOptions, EmittedApp, } from "./types.js";
|
|
47
|
+
export type { AppDefinition, AppHandle, AgentEntry, DoctypeHandle, WorkspaceShorthand, WorkspaceInput, AppUiDefinition, AppUiBuildConfig, AppArtifactSurface, AppSkillSurface, AppArtifactDecl, AppDevLaunchConfig, AppBoundariesDefinition, AppDataDefinition, AppDevDefinition, AppPlacement, AppRequirements, AppExposes, AppAccepts, ToMastraAgentOptions, EmittedApp, } from "./types.js";
|
|
45
48
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACxF,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,YAAY,EACZ,UAAU,EACV,MAAM,EACN,eAAe,EACf,iBAAiB,GAClB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAA;AACpF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC9C,YAAY,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,UAAU,GACX,MAAM,YAAY,CAAA"}
|