@nifrajs/core 2.11.0 → 2.12.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/dist/assurance.d.ts +61 -3
- package/dist/assurance.d.ts.map +1 -1
- package/dist/assurance.js +152 -5
- package/dist/assurance.js.map +1 -1
- package/dist/capabilities.d.ts +9 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +5 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/diff.d.ts +2 -1
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +3 -1
- package/dist/diff.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/evidence.d.ts +89 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +170 -0
- package/dist/evidence.js.map +1 -0
- package/dist/execution-policy.d.ts +23 -0
- package/dist/execution-policy.d.ts.map +1 -0
- package/dist/execution-policy.js +28 -0
- package/dist/execution-policy.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/route-assurance.d.ts +19 -0
- package/dist/internal/route-assurance.d.ts.map +1 -1
- package/dist/internal/route-assurance.js +38 -5
- package/dist/internal/route-assurance.js.map +1 -1
- package/dist/internal/route-execution.d.ts +18 -0
- package/dist/internal/route-execution.d.ts.map +1 -1
- package/dist/internal/route-execution.js +67 -1
- package/dist/internal/route-execution.js.map +1 -1
- package/dist/manifest.d.ts +5 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +22 -4
- package/dist/manifest.js.map +1 -1
- package/dist/reflection.d.ts +5 -0
- package/dist/reflection.d.ts.map +1 -1
- package/dist/reflection.js +13 -4
- package/dist/reflection.js.map +1 -1
- package/dist/replay.d.ts +26 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +63 -0
- package/dist/replay.js.map +1 -0
- package/dist/schema/standard.d.ts +2 -0
- package/dist/schema/standard.d.ts.map +1 -1
- package/dist/schema/standard.js +13 -0
- package/dist/schema/standard.js.map +1 -1
- package/dist/server/body.d.ts +49 -6
- package/dist/server/body.d.ts.map +1 -1
- package/dist/server/body.js +226 -8
- package/dist/server/body.js.map +1 -1
- package/dist/server/context.d.ts +20 -3
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/contract.d.ts +15 -3
- package/dist/server/contract.d.ts.map +1 -1
- package/dist/server/contract.js +22 -0
- package/dist/server/contract.js.map +1 -1
- package/dist/server/cookies.d.ts +26 -5
- package/dist/server/cookies.d.ts.map +1 -1
- package/dist/server/cookies.js +76 -9
- package/dist/server/cookies.js.map +1 -1
- package/dist/server/edge.d.ts.map +1 -1
- package/dist/server/edge.js +11 -0
- package/dist/server/edge.js.map +1 -1
- package/dist/server/header-case.d.ts +9 -0
- package/dist/server/header-case.d.ts.map +1 -0
- package/dist/server/header-case.js +54 -0
- package/dist/server/header-case.js.map +1 -0
- package/dist/server/headers.d.ts +8 -0
- package/dist/server/headers.d.ts.map +1 -0
- package/dist/server/headers.js +13 -0
- package/dist/server/headers.js.map +1 -0
- package/dist/server/node-outcome-hook.d.ts.map +1 -1
- package/dist/server/node-outcome-hook.js +7 -11
- package/dist/server/node-outcome-hook.js.map +1 -1
- package/dist/server/node-outcome.d.ts +8 -1
- package/dist/server/node-outcome.d.ts.map +1 -1
- package/dist/server/node-outcome.js +10 -3
- package/dist/server/node-outcome.js.map +1 -1
- package/dist/server/plugin.d.ts +66 -7
- package/dist/server/plugin.d.ts.map +1 -1
- package/dist/server/plugin.js +14 -10
- package/dist/server/plugin.js.map +1 -1
- package/dist/server/proto-guard.d.ts +30 -0
- package/dist/server/proto-guard.d.ts.map +1 -0
- package/dist/server/proto-guard.js +116 -0
- package/dist/server/proto-guard.js.map +1 -0
- package/dist/server/registry.d.ts +6 -2
- package/dist/server/registry.d.ts.map +1 -1
- package/dist/server/request-context.d.ts +24 -6
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +157 -30
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/respond.d.ts +2 -2
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +34 -8
- package/dist/server/respond.js.map +1 -1
- package/dist/server/response-contract-lane.d.ts +1 -1
- package/dist/server/response-contract-lane.d.ts.map +1 -1
- package/dist/server/response-contract-lane.js +45 -13
- package/dist/server/response-contract-lane.js.map +1 -1
- package/dist/server/response-hooks.d.ts +10 -0
- package/dist/server/response-hooks.d.ts.map +1 -0
- package/dist/server/response-hooks.js +52 -0
- package/dist/server/response-hooks.js.map +1 -0
- package/dist/server/runtime-core.d.ts +12 -0
- package/dist/server/runtime-core.d.ts.map +1 -1
- package/dist/server/runtime-core.js +8 -0
- package/dist/server/runtime-core.js.map +1 -1
- package/dist/server/server-types.d.ts +60 -6
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +80 -23
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +429 -213
- package/dist/server/server.js.map +1 -1
- package/dist/server/static-headers.d.ts +14 -3
- package/dist/server/static-headers.d.ts.map +1 -1
- package/dist/server/static-headers.js +28 -6
- package/dist/server/static-headers.js.map +1 -1
- package/dist/server/transport-lane.d.ts +8 -0
- package/dist/server/transport-lane.d.ts.map +1 -1
- package/dist/server/transport-lane.js +12 -8
- package/dist/server/transport-lane.js.map +1 -1
- package/dist/server/websocket.d.ts +3 -0
- package/dist/server/websocket.d.ts.map +1 -1
- package/dist/server/websocket.js +14 -0
- package/dist/server/websocket.js.map +1 -1
- package/dist/server.d.ts +2 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/tool-catalog.d.ts +21 -0
- package/dist/tool-catalog.d.ts.map +1 -0
- package/dist/tool-catalog.js +16 -0
- package/dist/tool-catalog.js.map +1 -0
- package/dist/tool-contract.d.ts +238 -0
- package/dist/tool-contract.d.ts.map +1 -0
- package/dist/tool-contract.js +569 -0
- package/dist/tool-contract.js.map +1 -0
- package/package.json +26 -1
- package/src/assurance.ts +236 -6
- package/src/capabilities.ts +14 -1
- package/src/diff.ts +5 -2
- package/src/errors.ts +1 -0
- package/src/evidence.ts +319 -0
- package/src/execution-policy.ts +57 -0
- package/src/index.ts +1 -1
- package/src/internal/route-assurance.ts +67 -4
- package/src/internal/route-execution.ts +276 -1
- package/src/manifest.ts +27 -5
- package/src/reflection.ts +24 -4
- package/src/replay.ts +96 -0
- package/src/schema/standard.ts +16 -0
- package/src/server/body.ts +275 -7
- package/src/server/context.ts +23 -3
- package/src/server/contract.ts +43 -3
- package/src/server/cookies.ts +80 -10
- package/src/server/edge.ts +10 -0
- package/src/server/header-case.ts +54 -0
- package/src/server/headers.ts +11 -0
- package/src/server/node-outcome-hook.ts +6 -11
- package/src/server/node-outcome.ts +10 -2
- package/src/server/plugin.ts +87 -8
- package/src/server/proto-guard.ts +118 -0
- package/src/server/registry.ts +6 -2
- package/src/server/request-context.ts +242 -26
- package/src/server/respond.ts +35 -4
- package/src/server/response-contract-lane.ts +6 -17
- package/src/server/response-hooks.ts +51 -0
- package/src/server/runtime-core.ts +14 -0
- package/src/server/server-types.ts +66 -6
- package/src/server/server.ts +672 -287
- package/src/server/static-headers.ts +27 -3
- package/src/server/transport-lane.ts +19 -8
- package/src/server/websocket.ts +18 -2
- package/src/server.ts +7 -0
- package/src/tool-catalog.ts +40 -0
- package/src/tool-contract.ts +896 -0
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* hook) is applied later and therefore wins.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { markLowercaseHeaderKeys } from "./header-case.ts"
|
|
13
|
+
|
|
12
14
|
/** Valid HTTP field-name characters (RFC 9110 token). */
|
|
13
15
|
const HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/
|
|
14
16
|
|
|
@@ -118,25 +120,47 @@ function store<V>(record: Record<string, V>, name: string, value: V): void {
|
|
|
118
120
|
* than left alongside - one header name spelled two ways in a single record ships as a comma-joined
|
|
119
121
|
* value on the Web paths and as two lines on Node, so writing the static entry blind would change
|
|
120
122
|
* the wire instead of being overridden.
|
|
123
|
+
*
|
|
124
|
+
* `markLowercase` asks for the all-lowercase proof to be published on the result when it holds. The
|
|
125
|
+
* merge is the natural place to answer that: the static names were lowercased at registration, and
|
|
126
|
+
* the loop below already derives `lower` for every own name to decide the override, so `lower !==
|
|
127
|
+
* name` is the whole answer at no added cost. Only the Node-direct lane asks - its readers are the
|
|
128
|
+
* ones that would otherwise re-walk these keys - and only for an app with no raw native response
|
|
129
|
+
* twin, since such a twin writes the record past the case-normalizing view AFTER this runs.
|
|
121
130
|
*/
|
|
122
131
|
export function mergeStaticHeaderRecord<V>(
|
|
123
132
|
statics: Readonly<Record<string, string>>,
|
|
124
133
|
own: Readonly<Record<string, V>>,
|
|
134
|
+
markLowercase = false,
|
|
125
135
|
): Record<string, V | string> {
|
|
126
136
|
const merged: Record<string, V | string> = { ...statics }
|
|
137
|
+
let allLowercase = true
|
|
127
138
|
for (const name of Object.keys(own)) {
|
|
128
139
|
const value = own[name] as V
|
|
129
140
|
if (value === undefined) continue
|
|
130
141
|
const lower = name.toLowerCase()
|
|
131
|
-
if (lower !== name
|
|
142
|
+
if (lower !== name) {
|
|
143
|
+
allLowercase = false
|
|
144
|
+
if (Object.hasOwn(merged, lower)) delete merged[lower]
|
|
145
|
+
}
|
|
132
146
|
store(merged, name, value)
|
|
133
147
|
}
|
|
148
|
+
if (markLowercase && allLowercase) {
|
|
149
|
+
markLowercaseHeaderKeys(merged as Record<string, string | readonly string[]>)
|
|
150
|
+
}
|
|
134
151
|
return merged
|
|
135
152
|
}
|
|
136
153
|
|
|
137
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* A fresh, mutable copy of the static record - what the lanes whose writers mutate the record get.
|
|
156
|
+
* Every name in it was lowercased at registration, so `markLowercase` publishes a proof that needs no
|
|
157
|
+
* scan at all; the gate on it is the same one {@link mergeStaticHeaderRecord} documents.
|
|
158
|
+
*/
|
|
138
159
|
export function staticHeaderRecordCopy(
|
|
139
160
|
statics: StaticResponseHeaders,
|
|
161
|
+
markLowercase = false,
|
|
140
162
|
): Record<string, string | readonly string[]> {
|
|
141
|
-
|
|
163
|
+
const copy = { ...statics.record }
|
|
164
|
+
if (markLowercase) markLowercaseHeaderKeys(copy)
|
|
165
|
+
return copy
|
|
142
166
|
}
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import type { TransportCodec, TransportCodecRegistry } from "../transport-codec.ts"
|
|
3
3
|
import { readBoundedBytes } from "./body.ts"
|
|
4
4
|
import { jsonError } from "./http.ts"
|
|
5
|
-
import {
|
|
5
|
+
import { guardParsedValue, type ProtoPoisoning } from "./proto-guard.ts"
|
|
6
|
+
import { isResponseResult, PRE_DECODED_BODY, type PreDecodedBody } from "./runtime-core.ts"
|
|
6
7
|
import type { AnyServer, IdentityPlugin } from "./server.ts"
|
|
7
8
|
|
|
8
9
|
interface TransportBodySource {
|
|
@@ -28,6 +29,13 @@ export interface TransportRuntime {
|
|
|
28
29
|
export interface TransportCodecsOptions {
|
|
29
30
|
/** Maximum encoded request bytes. Keep aligned with `server({ maxBodyBytes })`. */
|
|
30
31
|
readonly maxBytes?: number
|
|
32
|
+
/**
|
|
33
|
+
* Prototype-poisoning policy for decoded request bodies, mirroring
|
|
34
|
+
* `server({ protoPoisoning })` - this lane parses with the codec's own decoder, so the body
|
|
35
|
+
* lane's guard never sees the raw text and the policy must be enforced here. Default `"reject"`:
|
|
36
|
+
* a poisoned payload answers the same flat 400 as an undecodable one.
|
|
37
|
+
*/
|
|
38
|
+
readonly protoPoisoning?: ProtoPoisoning
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
export function transportCodecs(
|
|
@@ -38,6 +46,7 @@ export function transportCodecs(
|
|
|
38
46
|
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
|
|
39
47
|
throw new RangeError("transport maxBytes must be a non-negative safe integer")
|
|
40
48
|
}
|
|
49
|
+
const protoPoisoning = options.protoPoisoning ?? "reject"
|
|
41
50
|
const runtime: TransportRuntime = Object.freeze({
|
|
42
51
|
responseCodec(accept: string | null): TransportCodec {
|
|
43
52
|
try {
|
|
@@ -70,9 +79,12 @@ export function transportCodecs(
|
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
81
|
try {
|
|
82
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(read.bytes)
|
|
83
|
+
// Same poisoning policy as the body lane, enforced on the codec's own decode - a rejected
|
|
84
|
+
// payload answers exactly like an undecodable one.
|
|
73
85
|
return {
|
|
74
86
|
matched: true,
|
|
75
|
-
value: codec.decode(
|
|
87
|
+
value: guardParsedValue(codec.decode(text), protoPoisoning),
|
|
76
88
|
}
|
|
77
89
|
} catch {
|
|
78
90
|
return {
|
|
@@ -103,9 +115,9 @@ export function transportCodecs(
|
|
|
103
115
|
if (!decoded.matched) return undefined
|
|
104
116
|
if ("response" in decoded) return decoded.response
|
|
105
117
|
|
|
106
|
-
//
|
|
107
|
-
//
|
|
108
|
-
//
|
|
118
|
+
// Re-frame as a plain JSON request whose already-decoded value rides the pre-decoded stash;
|
|
119
|
+
// the body lane takes the stash verbatim (this lane owns the cap and poisoning policy), so
|
|
120
|
+
// the placeholder body is never parsed and codec machinery stays out of the kernel.
|
|
109
121
|
const headers: Record<string, string> = {}
|
|
110
122
|
replacement.headers.forEach((value, name) => {
|
|
111
123
|
headers[name] = value
|
|
@@ -119,9 +131,8 @@ export function transportCodecs(
|
|
|
119
131
|
body: "{}",
|
|
120
132
|
signal: replacement.signal as never,
|
|
121
133
|
})
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
})
|
|
134
|
+
const stash: PreDecodedBody = { value: decoded.value }
|
|
135
|
+
Object.defineProperty(normalized, PRE_DECODED_BODY, { value: stash })
|
|
125
136
|
return normalized
|
|
126
137
|
})
|
|
127
138
|
app.afterHandle((result, context) => {
|
package/src/server/websocket.ts
CHANGED
|
@@ -207,6 +207,7 @@ export type WebSocketUpgradeOutcome =
|
|
|
207
207
|
* a standard socket without a static import of the WS implementation (which would defeat the
|
|
208
208
|
* `.use(websocket())` tree-shaking). `@nifrajs/workers` may import `attachWebSocket` directly instead. */
|
|
209
209
|
readonly attach: WsAttach
|
|
210
|
+
readonly maxPayloadBytes?: number
|
|
210
211
|
}
|
|
211
212
|
|
|
212
213
|
/** The socket-wiring signature the upgrade outcome carries (the installed runtime's `attach`). */
|
|
@@ -214,7 +215,7 @@ export type WsAttach = (
|
|
|
214
215
|
socket: StandardWebSocket,
|
|
215
216
|
handler: WebSocketHandler,
|
|
216
217
|
data: unknown,
|
|
217
|
-
options: { openNow: boolean; pubsub: TopicRegistry },
|
|
218
|
+
options: { openNow: boolean; pubsub: TopicRegistry; maxPayloadBytes?: number },
|
|
218
219
|
) => NifraWebSocket
|
|
219
220
|
|
|
220
221
|
/**
|
|
@@ -249,7 +250,7 @@ export function attachWebSocket(
|
|
|
249
250
|
socket: StandardWebSocket,
|
|
250
251
|
handler: WebSocketHandler,
|
|
251
252
|
data: unknown,
|
|
252
|
-
options: { openNow: boolean; pubsub: TopicRegistry },
|
|
253
|
+
options: { openNow: boolean; pubsub: TopicRegistry; maxPayloadBytes?: number },
|
|
253
254
|
): NifraWebSocket {
|
|
254
255
|
const { pubsub } = options
|
|
255
256
|
const ws: NifraWebSocket = {
|
|
@@ -282,9 +283,23 @@ export function attachWebSocket(
|
|
|
282
283
|
}
|
|
283
284
|
// Deliver binary as ArrayBuffer (→ Uint8Array) rather than Blob, where the runtime allows it.
|
|
284
285
|
if ("binaryType" in socket) socket.binaryType = "arraybuffer"
|
|
286
|
+
const maxPayloadBytes = options.maxPayloadBytes
|
|
285
287
|
socket.addEventListener("message", (event: { readonly data: unknown }) => {
|
|
286
288
|
const raw = event.data
|
|
287
289
|
const payload: WebSocketData = typeof raw === "string" ? raw : toBinary(raw)
|
|
290
|
+
// Measuring a text frame costs a full UTF-8 encode plus the buffer it allocates, so it happens
|
|
291
|
+
// only for a route that actually declared a cap. Reading `.byteLength` off an already-decoded
|
|
292
|
+
// binary frame is free, but the branch stays under the same guard to keep one shape here.
|
|
293
|
+
if (maxPayloadBytes !== undefined) {
|
|
294
|
+
const payloadBytes =
|
|
295
|
+
typeof raw === "string"
|
|
296
|
+
? WS_PAYLOAD_ENCODER.encode(raw).byteLength
|
|
297
|
+
: (payload as Uint8Array).byteLength
|
|
298
|
+
if (payloadBytes > maxPayloadBytes) {
|
|
299
|
+
socket.close(1009, "message too large")
|
|
300
|
+
return
|
|
301
|
+
}
|
|
302
|
+
}
|
|
288
303
|
safe(() => handler.message?.(ws, payload))
|
|
289
304
|
})
|
|
290
305
|
socket.addEventListener(
|
|
@@ -304,6 +319,7 @@ export function attachWebSocket(
|
|
|
304
319
|
}
|
|
305
320
|
|
|
306
321
|
const WS_MESSAGE_DECODER = new TextDecoder()
|
|
322
|
+
const WS_PAYLOAD_ENCODER = new TextEncoder()
|
|
307
323
|
|
|
308
324
|
/**
|
|
309
325
|
* If the handler declares a `messageSchema`, return a copy whose `message` validates each frame -
|
package/src/server.ts
CHANGED
|
@@ -31,6 +31,8 @@ export type {
|
|
|
31
31
|
} from "./server/context.ts"
|
|
32
32
|
export {
|
|
33
33
|
type CookieOptions,
|
|
34
|
+
type CookieSecret,
|
|
35
|
+
cookieNamePrefix,
|
|
34
36
|
parseCookies,
|
|
35
37
|
serializeCookie,
|
|
36
38
|
signValue,
|
|
@@ -73,6 +75,9 @@ export {
|
|
|
73
75
|
type AdmissionController,
|
|
74
76
|
type AdmissionDecision,
|
|
75
77
|
type AnyServer,
|
|
78
|
+
type ContextPlugin,
|
|
79
|
+
type DefinePluginResult,
|
|
80
|
+
defineContextPlugin,
|
|
76
81
|
defineIdentityPlugin,
|
|
77
82
|
definePlugin,
|
|
78
83
|
defineRouterPlugin,
|
|
@@ -81,6 +86,7 @@ export {
|
|
|
81
86
|
type McpPromptDescriptor,
|
|
82
87
|
type McpResourceDescriptor,
|
|
83
88
|
type Middleware,
|
|
89
|
+
type NifraFeatureVersion,
|
|
84
90
|
type NifraPlugin,
|
|
85
91
|
type NodeRequestContext,
|
|
86
92
|
type NodeRequestHook,
|
|
@@ -88,6 +94,7 @@ export {
|
|
|
88
94
|
type NodeResponseHook,
|
|
89
95
|
type NodeServeOutcome,
|
|
90
96
|
type OnRequestResult,
|
|
97
|
+
type PluginTypeCollapsed,
|
|
91
98
|
type PromptArgument,
|
|
92
99
|
type PromptMessage,
|
|
93
100
|
type ResponseBodyHook,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** Descriptive projections of typed tool contracts for model and transport catalogs. */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ToolAnnotations,
|
|
5
|
+
type ToolApprovalPolicy,
|
|
6
|
+
type ToolContract,
|
|
7
|
+
type ToolSensitivity,
|
|
8
|
+
toolInputJsonSchema,
|
|
9
|
+
} from "./tool-contract.ts"
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A read-only, transport-neutral view of a tool contract.
|
|
13
|
+
*
|
|
14
|
+
* This module is descriptive only. It never validates input, checks capabilities, requests approval,
|
|
15
|
+
* reserves idempotency, consumes cost, or executes the tool. Those policies stay in `executeTool`.
|
|
16
|
+
*/
|
|
17
|
+
export interface ToolCatalogEntry {
|
|
18
|
+
readonly name: string
|
|
19
|
+
readonly description: string
|
|
20
|
+
readonly inputSchema: Record<string, unknown>
|
|
21
|
+
readonly capability: string
|
|
22
|
+
readonly sensitivity: ToolSensitivity
|
|
23
|
+
readonly approval: ToolApprovalPolicy
|
|
24
|
+
readonly idempotent: boolean
|
|
25
|
+
readonly annotations: ToolAnnotations
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Build the single descriptive projection shared by agent, MCP, and test adapters. */
|
|
29
|
+
export function toCatalogEntry<Input, Output>(tool: ToolContract<Input, Output>): ToolCatalogEntry {
|
|
30
|
+
return Object.freeze({
|
|
31
|
+
name: tool.name,
|
|
32
|
+
description: tool.description,
|
|
33
|
+
inputSchema: Object.freeze({ ...toolInputJsonSchema(tool) }),
|
|
34
|
+
capability: tool.capability,
|
|
35
|
+
sensitivity: tool.sensitivity,
|
|
36
|
+
approval: tool.approval,
|
|
37
|
+
idempotent: tool.idempotency !== undefined,
|
|
38
|
+
annotations: tool.annotations,
|
|
39
|
+
})
|
|
40
|
+
}
|