@finalai/agent-definition 0.1.2 → 0.1.4
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/HOSTING.md +234 -0
- package/README.md +7 -0
- package/dist/compiler-assets/{chunk-TATN3PYK.ts → chunk-2ZRYQO4Q.ts} +4 -4
- package/dist/compiler-assets/{chunk-HGW4YHAY.ts → chunk-3K4C4SVG.ts} +9 -0
- package/dist/compiler-assets/{chunk-7VSSVZM4.ts → chunk-4A66SVBJ.ts} +4 -4
- package/dist/compiler-assets/{chunk-CWWRTRWW.ts → chunk-4E5HECVD.ts} +1 -1
- package/dist/compiler-assets/{chunk-7QP2CKPI.ts → chunk-4X2DS5BR.ts} +1 -1
- package/dist/compiler-assets/{chunk-ZDLVA6XF.ts → chunk-5NTKRRMC.ts} +112 -21
- package/dist/compiler-assets/{chunk-2CZRHOLL.ts → chunk-7XUPKRZU.ts} +1 -1
- package/dist/compiler-assets/{chunk-OWC6SFFF.ts → chunk-APU2VKLW.ts} +52 -12
- package/dist/compiler-assets/{chunk-HFS4KLEL.ts → chunk-D3SB4CCB.ts} +1 -1
- package/dist/compiler-assets/{chunk-HNPUTP35.ts → chunk-GCFSHHH2.ts} +2 -2
- package/dist/compiler-assets/{chunk-5BK6FVRE.ts → chunk-IF6MR7JF.ts} +2 -2
- package/dist/compiler-assets/{chunk-LUSAAV4L.ts → chunk-IZGOMT7K.ts} +2 -2
- package/dist/compiler-assets/{chunk-GTUZOATD.ts → chunk-JGQ2KAN7.ts} +1 -1
- package/dist/compiler-assets/{chunk-NYTOYKKF.ts → chunk-K6D7ZK74.ts} +3 -3
- package/dist/compiler-assets/{chunk-WMXMVFHM.ts → chunk-K7V4IMOB.ts} +3 -3
- package/dist/compiler-assets/{chunk-VHXHUU7L.ts → chunk-LHMUAIYJ.ts} +1 -1
- package/dist/compiler-assets/{chunk-SKTNMUO7.ts → chunk-MSE7X5YG.ts} +25 -2
- package/dist/compiler-assets/chunk-PFLSBTJA.ts +39 -0
- package/dist/compiler-assets/{chunk-XHKPWT3G.ts → chunk-QJ26GEUM.ts} +1 -1
- package/dist/compiler-assets/{chunk-JPY4L2UJ.ts → chunk-RIEMTCTV.ts} +12 -8
- package/dist/compiler-assets/chunk-RMIQJHSL.ts +0 -0
- package/dist/compiler-assets/chunk-TJ536HI4.ts +61 -0
- package/dist/compiler-assets/{chunk-QMWTDPNT.ts → chunk-TJZS457N.ts} +3 -3
- package/dist/compiler-assets/{chunk-JIPNTA56.ts → chunk-TM36NO3C.ts} +1 -1
- package/dist/compiler-assets/{chunk-MZMSKIKU.ts → chunk-UBR53WBH.ts} +33 -8
- package/dist/compiler-assets/chunk-ULI5WWRR.ts +40 -0
- package/dist/compiler-assets/chunk-W6DOJA4W.ts +3763 -0
- package/dist/compiler-assets/{chunk-EVQIK62B.ts → chunk-YW7HDGQA.ts} +11 -7
- package/dist/compiler-assets/{chunk-BLB6JGLO.ts → chunk-YWFGIPHD.ts} +27 -24
- package/dist/compiler-assets/{chunk-QMKWAFVZ.ts → chunk-Z5TO7RSJ.ts} +5 -3
- package/dist/compiler-assets/src/authoring/agent.ts +4 -4
- package/dist/compiler-assets/src/authoring/approval.ts +7 -7
- package/dist/compiler-assets/src/authoring/brand.ts +3 -3
- package/dist/compiler-assets/src/authoring/channels.ts +6 -6
- package/dist/compiler-assets/src/authoring/connections.ts +14 -4
- package/dist/compiler-assets/src/authoring/credentials.ts +7 -6
- package/dist/compiler-assets/src/authoring/dynamic.ts +9 -4
- package/dist/compiler-assets/src/authoring/harness.ts +9 -9
- package/dist/compiler-assets/src/authoring/hooks.ts +10 -8
- package/dist/compiler-assets/src/authoring/index.ts +33 -26
- package/dist/compiler-assets/src/authoring/instructions.ts +10 -5
- package/dist/compiler-assets/src/authoring/sandbox.ts +10 -10
- package/dist/compiler-assets/src/authoring/schedules.ts +4 -4
- package/dist/compiler-assets/src/authoring/skills.ts +4 -4
- package/dist/compiler-assets/src/authoring/tools.ts +10 -8
- package/dist/compiler-assets/src/compatibility.ts +11 -11
- package/dist/compiler-assets/src/hosted-bindings.ts +15 -0
- package/dist/compiler-assets/src/index.ts +54 -41
- package/dist/compiler-assets/src/manifest.ts +8 -4
- package/dist/compiler-assets/src/resolve.ts +5 -5
- package/dist/compiler-assets/src/runtime/bundle.ts +22 -20
- package/dist/compiler-assets/src/runtime/describe.ts +14 -12
- package/dist/compiler-assets/src/runtime/described.ts +19 -12
- package/dist/compiler-assets/src/runtime/isolate.ts +18 -16
- package/dist/compiler-assets/src/runtime/lower.ts +13 -11
- package/dist/compiler-assets/src/runtime/schema-validation.ts +4 -4
- package/dist/compiler-assets/src/runtime/values.ts +2 -2
- package/dist/modules/authoring/agent.d.mts +3 -2
- package/dist/modules/authoring/agent.mjs.map +2 -2
- package/dist/modules/authoring/connections.d.mts +15 -2
- package/dist/modules/authoring/connections.mjs +36 -0
- package/dist/modules/authoring/connections.mjs.map +2 -2
- package/dist/modules/authoring/context.d.mts +3 -1
- package/dist/modules/authoring/context.mjs.map +2 -2
- package/dist/modules/authoring/dynamic.d.mts +3 -1
- package/dist/modules/authoring/dynamic.mjs +19 -1
- package/dist/modules/authoring/dynamic.mjs.map +2 -2
- package/dist/modules/authoring/harness.mjs +2 -0
- package/dist/modules/authoring/harness.mjs.map +2 -2
- package/dist/modules/authoring/hooks.d.mts +2 -1
- package/dist/modules/authoring/hooks.mjs.map +2 -2
- package/dist/modules/authoring/index.d.mts +4 -2
- package/dist/modules/authoring/index.mjs +4 -1
- package/dist/modules/authoring/index.mjs.map +2 -2
- package/dist/modules/authoring/sandbox.d.mts +2 -1
- package/dist/modules/authoring/sandbox.mjs.map +2 -2
- package/dist/modules/compiler/assemble.mjs +6 -1
- package/dist/modules/compiler/assemble.mjs.map +2 -2
- package/dist/modules/compiler/index.d.mts +2 -1
- package/dist/modules/compiler/index.mjs +18 -0
- package/dist/modules/compiler/index.mjs.map +2 -2
- package/dist/modules/compiler/local-isolate.d.mts +2 -1
- package/dist/modules/compiler/local-isolate.mjs +6 -1
- package/dist/modules/compiler/local-isolate.mjs.map +2 -2
- package/dist/modules/hosted-bindings.d.mts +10 -0
- package/dist/modules/hosted-bindings.mjs +36 -0
- package/dist/modules/hosted-bindings.mjs.map +7 -0
- package/dist/modules/index.d.mts +2 -0
- package/dist/modules/index.mjs +2 -0
- package/dist/modules/index.mjs.map +2 -2
- package/dist/modules/manifest.d.mts +2 -2
- package/dist/modules/manifest.mjs +4 -0
- package/dist/modules/manifest.mjs.map +2 -2
- package/dist/modules/resolve.mjs +4 -0
- package/dist/modules/resolve.mjs.map +2 -2
- package/dist/modules/runtime/describe.mjs +25 -4
- package/dist/modules/runtime/describe.mjs.map +2 -2
- package/dist/modules/runtime/described.d.mts +40 -4
- package/dist/modules/runtime/described.mjs +7 -2
- package/dist/modules/runtime/described.mjs.map +2 -2
- package/dist/modules/runtime/isolate.d.mts +2 -0
- package/dist/modules/runtime/isolate.mjs +7 -4
- package/dist/modules/runtime/isolate.mjs.map +2 -2
- package/dist/modules/runtime/lower.mjs +76 -14
- package/dist/modules/runtime/lower.mjs.map +2 -2
- package/dist/modules/runtime/schema-validation.mjs +19 -2
- package/dist/modules/runtime/schema-validation.mjs.map +2 -2
- package/fixtures/assistant/agent/agent.ts +7 -0
- package/package.json +4 -3
- package/dist/compiler-assets/chunk-GNR7XBPN.ts +0 -3364
- package/dist/compiler-assets/chunk-JNJE72EH.ts +0 -10
- package/dist/compiler-assets/chunk-T6WG4L4M.ts +0 -19
- /package/dist/compiler-assets/{chunk-6WR3PGNF.ts → chunk-CIWWFQHL.ts} +0 -0
package/HOSTING.md
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Portable agent definitions and hosted bindings
|
|
2
|
+
|
|
3
|
+
An agent declares behavior and logical resources. Hosting supplies endpoints,
|
|
4
|
+
resource identifiers, and credential references. The same compiled source can
|
|
5
|
+
resolve against dev and production configuration without source edits.
|
|
6
|
+
|
|
7
|
+
## Selecting a deployment
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
export FINAL_API_HOST=https://agent-session.primary-dev.final.ai/api
|
|
11
|
+
export FINAL_API_KEY=<dev-organization-key>
|
|
12
|
+
pnpm exec final-agents build ./agent
|
|
13
|
+
pnpm exec final-agents publish ./agent --agent my-agent
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Choose production by changing the host and organization key. `--host` overrides
|
|
17
|
+
`FINAL_API_HOST`; without either, the existing production default remains. Build
|
|
18
|
+
compiles locally and optionally checks installed-harness compatibility. Publish
|
|
19
|
+
compiles again and sends source/release requests to the selected deployment.
|
|
20
|
+
Neither rewrites authored URLs. A GitHub-backed definition uses remote source;
|
|
21
|
+
push edits before explicitly publishing a ref. Caller API keys never become agent
|
|
22
|
+
credentials merely because they were used to publish.
|
|
23
|
+
|
|
24
|
+
## Hosted connections
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { defineHostedConnection } from '@finalai/agents';
|
|
28
|
+
|
|
29
|
+
export default defineHostedConnection({
|
|
30
|
+
binding: 'issue-tracker',
|
|
31
|
+
tools: { allow: ['read_issue'], deny: ['delete_issue'] },
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`issue-tracker` is an example configuration name, not a built-in service.
|
|
36
|
+
Hosting configures it with non-secret JSON:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"url": "https://issues.dev.example/mcp",
|
|
41
|
+
"auth": { "secretKey": "ISSUE_TRACKER_TOKEN", "headerName": null },
|
|
42
|
+
"headers": { "X-Workspace": "development" }
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Production supplies another value under the same name. The helper uses an ordinary
|
|
47
|
+
`defineDynamic` connection at `session.started`, then the usual HTTP MCP lowering,
|
|
48
|
+
validation, permissions, and credential broker. Hosting supplies transport settings,
|
|
49
|
+
not tool policies. URL, authentication references, transport headers belong to hosting; the hosted helper does
|
|
50
|
+
not accept authored overrides for these fields. Referenced secrets still need the agent's secret allowlist and normal
|
|
51
|
+
authorization. Actual tokens must not be returned in configuration headers.
|
|
52
|
+
|
|
53
|
+
Final uses the same generic helper:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { defineFinalConnection } from '@finalai/agents';
|
|
57
|
+
|
|
58
|
+
export default defineFinalConnection({
|
|
59
|
+
tools: { deny: ['create_agent_session'] },
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
This resolves the `final` binding. Hosting supplies its URL and
|
|
64
|
+
`auth: { kind: 'final-session' }`, just as it supplies authentication for any
|
|
65
|
+
other hosted connection. `binding`
|
|
66
|
+
selects another name. Existing explicit `url` calls remain static and compatible;
|
|
67
|
+
they always point at that URL. There is no Final-specific compiler rewrite.
|
|
68
|
+
|
|
69
|
+
## Connection tool policy
|
|
70
|
+
|
|
71
|
+
`tools.allow`, `tools.deny` and `tools.approval` keys are tool names or `*`
|
|
72
|
+
patterns, so a definition can scope a connection whose tool list it does not know:
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
export default defineFinalConnection({
|
|
76
|
+
tools: {
|
|
77
|
+
allow: ['github.*', 'list_goals'],
|
|
78
|
+
deny: ['github.delete_repo'],
|
|
79
|
+
approval: { 'github.delete_*': always() },
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`*` matches any run of characters; everything else matches literally. `deny` wins
|
|
85
|
+
over `allow`. The most specific key governs a tool: an exact name, else the matching
|
|
86
|
+
pattern with the most literal characters, with ties resolved toward `ask`. Hosts
|
|
87
|
+
enforce this through `isToolExposed` and `toolApprovalOf` from
|
|
88
|
+
`@finalai/agent-provider`, and look up a tool's input-approval predicate under the
|
|
89
|
+
key `resolveToolApprovalKey` returns.
|
|
90
|
+
|
|
91
|
+
## Loaded and searchable tools
|
|
92
|
+
|
|
93
|
+
A connection that can expose many tools, such as Final's with every service the
|
|
94
|
+
person has connected, can name the ones the harness should list up front:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
export default defineFinalConnection({
|
|
98
|
+
tools: { load: ['list_goals', 'get_goal', 'draft_goal', 'notify_user'] },
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Without `load`, the harness lists every exposed tool, as before. With it, the host
|
|
103
|
+
lists only the loaded tools and must keep every other exposed tool reachable: it
|
|
104
|
+
serves a search over the connection's remaining exposed tools (name, description,
|
|
105
|
+
input schema) and a call that runs a found tool by its real name, with the same
|
|
106
|
+
exposure and approval checks as a direct call. A host may instead add a found tool
|
|
107
|
+
to the list and send `notifications/tools/list_changed`; harnesses that ignore that
|
|
108
|
+
notification still need the call path. `load: []` leaves every tool to search.
|
|
109
|
+
Entries are tool names or `*` patterns. `isToolLoaded` from `@finalai/agent-provider`
|
|
110
|
+
applies the rule after exposure.
|
|
111
|
+
|
|
112
|
+
## Selecting tools by annotation
|
|
113
|
+
|
|
114
|
+
`tools.allow` and `tools.deny` entries can be MCP annotation selectors as well as
|
|
115
|
+
tool names, so a definition can scope tools it cannot name in advance:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
export default defineFinalConnection({
|
|
119
|
+
tools: {
|
|
120
|
+
allow: ['list_goals', 'draft_goal', { readOnlyHint: true }],
|
|
121
|
+
deny: [{ destructiveHint: true, readOnlyHint: false }],
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
A selector matches when every hint it sets equals the tool's hint, reading hints the
|
|
127
|
+
tool omits as the MCP spec's defaults (not read-only, destructive, not idempotent,
|
|
128
|
+
open world). The annotations come from the connection's server, so select on them
|
|
129
|
+
only for servers trusted to classify their own tools.
|
|
130
|
+
|
|
131
|
+
Selectors lower to `allowAnnotations` (each with the connection default approval and
|
|
132
|
+
input predicate) and `denyAnnotations`. A host exposes a tool when nothing in `deny`
|
|
133
|
+
or `denyAnnotations` matches it and either an `approvals` key (name or pattern)
|
|
134
|
+
governs it, `approvals` is null, or `toolAnnotationRuleFor` finds a rule; a tool an
|
|
135
|
+
`approvals` key governs keeps that approval, otherwise it runs under the rule's. `tools.approval` overrides apply only to
|
|
136
|
+
named tools.
|
|
137
|
+
|
|
138
|
+
## Resources and provider packages
|
|
139
|
+
|
|
140
|
+
`HostedBindingsIface` is the shared `@finalai/agent-provider` contract. Hosting
|
|
141
|
+
implements `get(name)` to return scoped JSON or null. `requireHostedBinding` rejects
|
|
142
|
+
missing hosting, absent names, and invalid JSON without an environment fallback.
|
|
143
|
+
Names are configuration keys, not global permissions or inferred URLs.
|
|
144
|
+
|
|
145
|
+
Tools, hooks, dynamic resolvers, sandbox selectors, and harness/sandbox/channel
|
|
146
|
+
provider contexts expose an optional `bindings` reader. A third-party resolver can
|
|
147
|
+
use the same reader for model or resource configuration:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { defineDynamic, requireHostedBinding } from '@finalai/agents';
|
|
151
|
+
|
|
152
|
+
export const model = defineDynamic({
|
|
153
|
+
requiredBindings: [{ name: 'primary-model', schema: { type: 'string', minLength: 1 } }],
|
|
154
|
+
description: 'The deployment model',
|
|
155
|
+
preview: 'Resolved from primary-model',
|
|
156
|
+
events: {
|
|
157
|
+
'session.started': async (_event, ctx) =>
|
|
158
|
+
requireHostedBinding({ bindings: ctx.bindings, name: 'primary-model' }),
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Use that value in a harness configuration supporting dynamic models. A resource
|
|
164
|
+
binding can similarly contain a repository, guide slug, device ID, or non-secret
|
|
165
|
+
SDK base URL; the consumer validates the resource-specific schema. Literal IDs,
|
|
166
|
+
custom URLs, and external credential choices are never silently rewritten.
|
|
167
|
+
|
|
168
|
+
Installed providers already accept factory configuration injected by hosting.
|
|
169
|
+
Keep supplying deployment service URLs there. Computer/WebSocket clients retain
|
|
170
|
+
explicit configuration; a hosted provider can obtain it through this shared reader.
|
|
171
|
+
Package versions stay pinned. Packages do not read a global DEV/PROD flag.
|
|
172
|
+
|
|
173
|
+
## Declared requirements and user experience
|
|
174
|
+
|
|
175
|
+
`defineHostedConnection` declares its binding name and JSON configuration schema
|
|
176
|
+
in the compiled dynamic slot automatically. Other dynamic consumers declare
|
|
177
|
+
`requiredBindings` as in the model example. Hosts can inspect these requirements
|
|
178
|
+
without running authored resolvers. Repeated names must satisfy every declared
|
|
179
|
+
schema; names are looked up once per preflight.
|
|
180
|
+
|
|
181
|
+
Before accepting a release, hosting calls
|
|
182
|
+
`validateHostedBindings({ manifest, bindings })` with a reader scoped to the
|
|
183
|
+
selected deployment, organization, and agent. Hosts compiling source can instead
|
|
184
|
+
pass `hostedBindings` to `compile`; failed preflight returns error diagnostics and
|
|
185
|
+
no manifest or bundle. An offline build can still compile and expose requirements
|
|
186
|
+
without accessing deployment configuration. The CLI does not yet fetch binding
|
|
187
|
+
configuration itself: server-side publication must enable this preflight.
|
|
188
|
+
|
|
189
|
+
When dev is selected, lookups use only dev configuration. A missing dev binding
|
|
190
|
+
fails even if production has the same name; never retry against production or
|
|
191
|
+
substitute a production default. Changing the CLI host selects where to publish;
|
|
192
|
+
the runtime reader comes from that deployment, not from the author's environment.
|
|
193
|
+
Explicit authored URLs retain their literal destination.
|
|
194
|
+
|
|
195
|
+
Authors keep one source definition. Operators configure its named connections
|
|
196
|
+
and resources once in each deployment. End users start the agent as usual; an
|
|
197
|
+
unconfigured required resource produces a configuration failure instead of a
|
|
198
|
+
session silently missing tools. Dynamic handlers validate declared requirements
|
|
199
|
+
before running. Shared manifest resolution rejects null results for required slots,
|
|
200
|
+
even if a host catches a resolver exception and returns null. Hosts must propagate
|
|
201
|
+
that failure to startup. Session-started values stay pinned across turns and resume.
|
|
202
|
+
|
|
203
|
+
This PR adds no configuration UI. A host can use the compiled requirements to show
|
|
204
|
+
which names need configuration and return an actionable deployment-specific error.
|
|
205
|
+
|
|
206
|
+
## Host integration
|
|
207
|
+
|
|
208
|
+
These packages implement contracts and authored runtime behavior, not a deployment
|
|
209
|
+
configuration store or RPC service. Existing hosting needs to:
|
|
210
|
+
|
|
211
|
+
1. Resolve names within the authorized deployment, organization, and agent; never
|
|
212
|
+
expose the process environment or an unrestricted cross-tenant registry.
|
|
213
|
+
2. Inject `bindings` into lifecycle resolution and the tool/hook/selector/provider
|
|
214
|
+
contexts using it. Dynamic approval evaluation and tool reconstruction after
|
|
215
|
+
isolate eviction need the same reader. Readers and tokens are not persisted in
|
|
216
|
+
boundary snapshots.
|
|
217
|
+
3. Configure `final` with that deployment's approved MCP endpoint. The ordinary
|
|
218
|
+
broker continues restricting `final-session` grants to that endpoint.
|
|
219
|
+
4. Return non-secret configuration and credential references, with normal provider,
|
|
220
|
+
secret, resource, and organization authorization.
|
|
221
|
+
5. Run the release preflight above and validate again before starting a new
|
|
222
|
+
session. Treat failed required-binding resolution as a startup/configuration error, not
|
|
223
|
+
an omitted connection or a fallback to production. Preserve existing runtime
|
|
224
|
+
revisions when publication fails.
|
|
225
|
+
6. Retain session-started resolved values across turns/resume; resolve new sessions
|
|
226
|
+
against their own deployment.
|
|
227
|
+
|
|
228
|
+
Optional readers preserve source compatibility with existing hosts. Definitions
|
|
229
|
+
requesting bindings fail clearly if hosting does not provide them. Installing these
|
|
230
|
+
packages alone does not change Final's deployed service wiring or provision secrets.
|
|
231
|
+
|
|
232
|
+
New compiles emit manifest version 3, so older hosts reject them rather than
|
|
233
|
+
stripping required-binding metadata. Updated readers still accept persisted
|
|
234
|
+
version 2 revisions. Upgrade hosting before publishing newly compiled agents.
|
package/README.md
CHANGED
|
@@ -14,3 +14,10 @@ resolves those convenience entrypoints for the generic compiler.
|
|
|
14
14
|
|
|
15
15
|
Custom provider contracts and sandbox implementation helpers are available directly
|
|
16
16
|
from `@finalai/agent-provider` and `@finalai/agent-provider/sandbox`.
|
|
17
|
+
|
|
18
|
+
`defineHostedConnection` resolves a named transport through the existing dynamic
|
|
19
|
+
connection lifecycle. `DynamicResolveContextIface.bindings` is the optional shared
|
|
20
|
+
host reader; use `requireHostedBinding` for configuration and logical resource
|
|
21
|
+
references. Missing required bindings reject resolution. No environment URLs are
|
|
22
|
+
chosen by the compiler. Dynamic approval/tool reconstruction must receive the same
|
|
23
|
+
reader from hosting. See the repository's [hosting guide](HOSTING.md).
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resultMatchesSchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-W6DOJA4W.ts";
|
|
4
4
|
import {
|
|
5
5
|
stamp
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QJ26GEUM.ts";
|
|
7
7
|
import {
|
|
8
8
|
callableSchema,
|
|
9
9
|
isObjectLike,
|
|
10
10
|
optionalValueSchema
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-TM36NO3C.ts";
|
|
12
12
|
import {
|
|
13
13
|
array,
|
|
14
14
|
boolean,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
object,
|
|
17
17
|
string,
|
|
18
18
|
union
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-3K4C4SVG.ts";
|
|
20
20
|
|
|
21
21
|
// src/authoring/tools.ts
|
|
22
22
|
var toolLabelSchema = union([
|
|
@@ -6449,6 +6449,14 @@ function object(shape, params) {
|
|
|
6449
6449
|
};
|
|
6450
6450
|
return new ZodObject(def);
|
|
6451
6451
|
}
|
|
6452
|
+
function strictObject(shape, params) {
|
|
6453
|
+
return new ZodObject({
|
|
6454
|
+
type: "object",
|
|
6455
|
+
shape,
|
|
6456
|
+
catchall: never(),
|
|
6457
|
+
...util_exports.normalizeParams(params)
|
|
6458
|
+
});
|
|
6459
|
+
}
|
|
6452
6460
|
function looseObject(shape, params) {
|
|
6453
6461
|
return new ZodObject({
|
|
6454
6462
|
type: "object",
|
|
@@ -6851,6 +6859,7 @@ export {
|
|
|
6851
6859
|
unknown,
|
|
6852
6860
|
array,
|
|
6853
6861
|
object,
|
|
6862
|
+
strictObject,
|
|
6854
6863
|
looseObject,
|
|
6855
6864
|
union,
|
|
6856
6865
|
discriminatedUnion,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ToolApproval
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-APU2VKLW.ts";
|
|
4
4
|
import {
|
|
5
5
|
authoredKindOf,
|
|
6
6
|
stamp
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QJ26GEUM.ts";
|
|
8
8
|
import {
|
|
9
9
|
callableSchema
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-TM36NO3C.ts";
|
|
11
11
|
import {
|
|
12
12
|
nativeEnum,
|
|
13
13
|
object,
|
|
14
14
|
string
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-3K4C4SVG.ts";
|
|
16
16
|
|
|
17
17
|
// src/authoring/approval.ts
|
|
18
18
|
var policy = (value, note = null) => stamp({ policy: value, note }, "approval" /* Approval */);
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toolLabelSchema
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
jsonSchemaDeclarationError
|
|
6
|
-
} from "./chunk-GNR7XBPN.ts";
|
|
3
|
+
} from "./chunk-2ZRYQO4Q.ts";
|
|
7
4
|
import {
|
|
8
5
|
lowerApproval
|
|
9
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4A66SVBJ.ts";
|
|
7
|
+
import {
|
|
8
|
+
toolAnnotationSelectorSchema
|
|
9
|
+
} from "./chunk-APU2VKLW.ts";
|
|
10
|
+
import {
|
|
11
|
+
jsonSchemaDeclarationError
|
|
12
|
+
} from "./chunk-W6DOJA4W.ts";
|
|
10
13
|
import {
|
|
11
14
|
authoredKindOf,
|
|
12
15
|
pendingExportName,
|
|
13
16
|
pendingIndexOf
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QJ26GEUM.ts";
|
|
15
18
|
import {
|
|
16
19
|
authoredRecordSchema,
|
|
17
20
|
authoredValueSchema,
|
|
@@ -26,7 +29,7 @@ import {
|
|
|
26
29
|
isString,
|
|
27
30
|
messageOf,
|
|
28
31
|
optionalValueSchema
|
|
29
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-TM36NO3C.ts";
|
|
30
33
|
import {
|
|
31
34
|
ZodType,
|
|
32
35
|
array,
|
|
@@ -38,8 +41,38 @@ import {
|
|
|
38
41
|
string,
|
|
39
42
|
toJSONSchema,
|
|
40
43
|
union,
|
|
44
|
+
unknown,
|
|
41
45
|
url
|
|
42
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-3K4C4SVG.ts";
|
|
47
|
+
|
|
48
|
+
// ../agent-provider/src/tool-patterns.ts
|
|
49
|
+
var TOOL_PATTERN_WILDCARD = "*";
|
|
50
|
+
var toolPatternMatches = (pattern, name) => {
|
|
51
|
+
let patternIndex = 0;
|
|
52
|
+
let nameIndex = 0;
|
|
53
|
+
let starIndex = -1;
|
|
54
|
+
let resumeIndex = 0;
|
|
55
|
+
while (nameIndex < name.length) {
|
|
56
|
+
const char = pattern[patternIndex];
|
|
57
|
+
if (char === TOOL_PATTERN_WILDCARD) {
|
|
58
|
+
starIndex = patternIndex;
|
|
59
|
+
resumeIndex = nameIndex;
|
|
60
|
+
patternIndex += 1;
|
|
61
|
+
} else if (char != null && char === name[nameIndex]) {
|
|
62
|
+
patternIndex += 1;
|
|
63
|
+
nameIndex += 1;
|
|
64
|
+
} else if (starIndex !== -1) {
|
|
65
|
+
patternIndex = starIndex + 1;
|
|
66
|
+
resumeIndex += 1;
|
|
67
|
+
nameIndex = resumeIndex;
|
|
68
|
+
} else {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
while (pattern[patternIndex] === TOOL_PATTERN_WILDCARD) patternIndex += 1;
|
|
73
|
+
return patternIndex === pattern.length;
|
|
74
|
+
};
|
|
75
|
+
var isToolDenied = (deny, name) => deny?.some((pattern) => toolPatternMatches(pattern, name)) === true;
|
|
43
76
|
|
|
44
77
|
// src/runtime/lower.ts
|
|
45
78
|
var IssueSeverity = /* @__PURE__ */ ((IssueSeverity2) => {
|
|
@@ -236,9 +269,10 @@ var authoredConnectionSchema = looseObject({
|
|
|
236
269
|
approval: optionalValueSchema,
|
|
237
270
|
toolCall: optionalValueSchema,
|
|
238
271
|
tools: looseObject({
|
|
239
|
-
allow: array(
|
|
240
|
-
deny: array(
|
|
241
|
-
approval: authoredRecordSchema.optional()
|
|
272
|
+
allow: array(unknown()).optional(),
|
|
273
|
+
deny: array(unknown()).optional(),
|
|
274
|
+
approval: authoredRecordSchema.optional(),
|
|
275
|
+
load: array(string()).optional()
|
|
242
276
|
}).optional()
|
|
243
277
|
});
|
|
244
278
|
var connectionAuthSchema = union([
|
|
@@ -263,6 +297,25 @@ var lowerAuth = (value, path, issues) => {
|
|
|
263
297
|
);
|
|
264
298
|
return null;
|
|
265
299
|
};
|
|
300
|
+
var splitToolEntries = (args) => {
|
|
301
|
+
const names = [];
|
|
302
|
+
const selectors = [];
|
|
303
|
+
for (const entry of args.entries) {
|
|
304
|
+
if (isString(entry)) {
|
|
305
|
+
names.push(entry);
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const parsed = toolAnnotationSelectorSchema.safeParse(entry);
|
|
309
|
+
if (parsed.success) selectors.push(parsed.data);
|
|
310
|
+
else
|
|
311
|
+
args.issues.push(
|
|
312
|
+
error(
|
|
313
|
+
`${args.label} entries must be tool names, * patterns, or annotation selectors such as { readOnlyHint: true }`
|
|
314
|
+
)
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
return { names, selectors };
|
|
318
|
+
};
|
|
266
319
|
var lowerConnection = (args) => {
|
|
267
320
|
const issues = [];
|
|
268
321
|
const path = `connection ${args.key}`;
|
|
@@ -301,12 +354,29 @@ var lowerConnection = (args) => {
|
|
|
301
354
|
const overrides = Object.fromEntries(overrideEntries);
|
|
302
355
|
const inputApprovals = Object.fromEntries(inputApprovalEntries);
|
|
303
356
|
for (const key of staticOverrideKeys) delete inputApprovals[key];
|
|
304
|
-
const defaultPolicy = overrides[
|
|
305
|
-
const
|
|
357
|
+
const defaultPolicy = overrides[TOOL_PATTERN_WILDCARD] ?? defaultApproval.policy;
|
|
358
|
+
const allowEntries = tools?.allow == null ? null : splitToolEntries({ entries: tools.allow, label: `${path} tools.allow`, issues });
|
|
359
|
+
const allow = allowEntries?.names ?? null;
|
|
360
|
+
const allowSelectors = allowEntries?.selectors ?? [];
|
|
361
|
+
const denyEntries = splitToolEntries({
|
|
362
|
+
entries: tools?.deny ?? [],
|
|
363
|
+
label: `${path} tools.deny`,
|
|
364
|
+
issues
|
|
365
|
+
});
|
|
366
|
+
const deny = denyEntries.names;
|
|
367
|
+
const authoredEntries = {
|
|
368
|
+
allow: allow ?? [],
|
|
369
|
+
deny,
|
|
370
|
+
approval: Object.keys(overrides)
|
|
371
|
+
};
|
|
372
|
+
for (const [field, entries] of Object.entries(authoredEntries)) {
|
|
373
|
+
if (entries.some((entry) => entry.trim().length === 0))
|
|
374
|
+
issues.push(error(`${path} tools.${field} entries must be tool names or * patterns`));
|
|
375
|
+
}
|
|
376
|
+
const inherited = Object.hasOwn(inputApprovals, "*") ? inputApprovals["*"] : void 0;
|
|
306
377
|
let approvals = null;
|
|
307
378
|
if (allow != null) {
|
|
308
379
|
approvals = Object.fromEntries(allow.map((tool) => [tool, overrides[tool] ?? defaultPolicy]));
|
|
309
|
-
const inherited = Object.hasOwn(inputApprovals, "*") ? inputApprovals["*"] : void 0;
|
|
310
380
|
if (inherited != null) {
|
|
311
381
|
for (const tool of allow) {
|
|
312
382
|
if (!Object.hasOwn(overrides, tool))
|
|
@@ -319,20 +389,33 @@ var lowerConnection = (args) => {
|
|
|
319
389
|
}
|
|
320
390
|
}
|
|
321
391
|
for (const tool of Object.keys(overrides)) {
|
|
322
|
-
if (
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
392
|
+
if (tool === TOOL_PATTERN_WILDCARD || allow.includes(tool)) continue;
|
|
393
|
+
if (allow.some((pattern) => toolPatternMatches(pattern, tool))) {
|
|
394
|
+
approvals[tool] = overrides[tool] ?? defaultPolicy;
|
|
395
|
+
continue;
|
|
326
396
|
}
|
|
397
|
+
issues.push(
|
|
398
|
+
warning(
|
|
399
|
+
allowSelectors.length > 0 ? `${path} sets an approval for ${tool}, which tools.allow does not name; approvals apply only to named tools` : `${path} sets an approval for ${tool}, which tools.allow does not expose`
|
|
400
|
+
)
|
|
401
|
+
);
|
|
327
402
|
}
|
|
328
403
|
} else if (defaultApproval.policy === "ask" /* Ask */ || Object.keys(overrides).length > 0) {
|
|
329
404
|
approvals = { "*": defaultApproval.policy, ...overrides };
|
|
330
405
|
}
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
if (Object.hasOwn(overrides, tool))
|
|
406
|
+
for (const tool of Object.keys(overrides)) {
|
|
407
|
+
if (tool !== TOOL_PATTERN_WILDCARD && isToolDenied(deny, tool))
|
|
334
408
|
issues.push(warning(`${path} sets an approval for ${tool}, which tools.deny hides`));
|
|
335
409
|
}
|
|
410
|
+
const load = tools?.load ?? null;
|
|
411
|
+
if (load?.some((tool) => tool.trim().length === 0) === true)
|
|
412
|
+
issues.push(error(`${path} tools.load entries must be tool names or * patterns`));
|
|
413
|
+
for (const tool of load ?? []) {
|
|
414
|
+
if (isToolDenied(deny, tool))
|
|
415
|
+
issues.push(warning(`${path} loads ${tool}, which tools.deny hides`));
|
|
416
|
+
else if (allow != null && allowSelectors.length === 0 && !allow.some((pattern) => toolPatternMatches(pattern, tool)))
|
|
417
|
+
issues.push(warning(`${path} loads ${tool}, which tools.allow does not expose`));
|
|
418
|
+
}
|
|
336
419
|
if (connection?.toolCall != null)
|
|
337
420
|
issues.push(error(`${path} uses toolCall.providedArguments, which is not supported`));
|
|
338
421
|
const binding = {
|
|
@@ -344,6 +427,14 @@ var lowerConnection = (args) => {
|
|
|
344
427
|
approvals
|
|
345
428
|
};
|
|
346
429
|
if (deny.length > 0) binding.deny = [...new Set(deny)];
|
|
430
|
+
if (load != null) binding.load = [...new Set(load)];
|
|
431
|
+
if (allowSelectors.length > 0)
|
|
432
|
+
binding.allowAnnotations = allowSelectors.map((match) => ({
|
|
433
|
+
match,
|
|
434
|
+
approval: defaultPolicy,
|
|
435
|
+
...inherited == null ? {} : { inputApproval: inherited }
|
|
436
|
+
}));
|
|
437
|
+
if (denyEntries.selectors.length > 0) binding.denyAnnotations = denyEntries.selectors;
|
|
347
438
|
if (Object.keys(inputApprovals).length > 0) binding.inputApprovals = inputApprovals;
|
|
348
439
|
return { binding, issues };
|
|
349
440
|
};
|