@graphorin/core 0.6.0 → 0.7.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/CHANGELOG.md +88 -0
- package/README.md +14 -8
- package/dist/channels/channels.d.ts.map +1 -1
- package/dist/channels/index.d.ts +2 -2
- package/dist/channels/index.js +2 -2
- package/dist/channels/pause.d.ts +47 -2
- package/dist/channels/pause.d.ts.map +1 -1
- package/dist/channels/pause.js +62 -2
- package/dist/channels/pause.js.map +1 -1
- package/dist/contracts/checkpoint-store.d.ts +97 -1
- package/dist/contracts/checkpoint-store.d.ts.map +1 -1
- package/dist/contracts/checkpoint-store.js.map +1 -1
- package/dist/contracts/index.d.ts +5 -5
- package/dist/contracts/index.js +2 -1
- package/dist/contracts/memory-store.d.ts +59 -2
- package/dist/contracts/memory-store.d.ts.map +1 -1
- package/dist/contracts/provider.d.ts +20 -6
- package/dist/contracts/provider.d.ts.map +1 -1
- package/dist/contracts/session-store.d.ts +10 -2
- package/dist/contracts/session-store.d.ts.map +1 -1
- package/dist/contracts/tool.d.ts +75 -1
- package/dist/contracts/tool.d.ts.map +1 -1
- package/dist/contracts/tool.js +57 -0
- package/dist/contracts/tool.js.map +1 -0
- package/dist/contracts/tracer.d.ts +53 -5
- package/dist/contracts/tracer.d.ts.map +1 -1
- package/dist/contracts/tracer.js.map +1 -1
- package/dist/index.d.ts +14 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- package/dist/types/agent-event-wire.d.ts +74 -0
- package/dist/types/agent-event-wire.d.ts.map +1 -0
- package/dist/types/agent-event-wire.js +130 -0
- package/dist/types/agent-event-wire.js.map +1 -0
- package/dist/types/agent-event.d.ts +48 -6
- package/dist/types/agent-event.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.js +2 -1
- package/dist/types/memory.d.ts +11 -0
- package/dist/types/memory.d.ts.map +1 -1
- package/dist/types/run.d.ts +86 -4
- package/dist/types/run.d.ts.map +1 -1
- package/dist/types/run.js.map +1 -1
- package/dist/types/tool.d.ts +10 -0
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/types/usage.d.ts +11 -1
- package/dist/types/usage.d.ts.map +1 -1
- package/dist/types/usage.js.map +1 -1
- package/dist/utils/binary-json.d.ts +165 -0
- package/dist/utils/binary-json.d.ts.map +1 -0
- package/dist/utils/binary-json.js +240 -0
- package/dist/utils/binary-json.js.map +1 -0
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/validation.d.ts +10 -1
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +1 -1
- package/dist/utils/validation.js.map +1 -1
- package/package.json +9 -7
- package/src/channels/channels.ts +206 -0
- package/src/channels/directive.ts +41 -0
- package/src/channels/dispatch.ts +37 -0
- package/src/channels/durable.ts +151 -0
- package/src/channels/index.ts +62 -0
- package/src/channels/pause.ts +216 -0
- package/src/contracts/auth-token-store.ts +42 -0
- package/src/contracts/checkpoint-store.ts +256 -0
- package/src/contracts/embedder.ts +42 -0
- package/src/contracts/eval-scorer.ts +44 -0
- package/src/contracts/index.ts +112 -0
- package/src/contracts/local-provider-trust.ts +33 -0
- package/src/contracts/logger.ts +61 -0
- package/src/contracts/memory-store.ts +187 -0
- package/src/contracts/oauth-server-store.ts +78 -0
- package/src/contracts/preferred-model.ts +56 -0
- package/src/contracts/provider.ts +316 -0
- package/src/contracts/reasoning-retention.ts +52 -0
- package/src/contracts/redaction-validator.ts +56 -0
- package/src/contracts/sandbox.ts +70 -0
- package/src/contracts/secret-ref.ts +22 -0
- package/src/contracts/secret-value.ts +117 -0
- package/src/contracts/secrets-store.ts +90 -0
- package/src/contracts/session-store.ts +163 -0
- package/src/contracts/token-counter.ts +23 -0
- package/src/contracts/tool.ts +397 -0
- package/src/contracts/tracer.ts +219 -0
- package/src/contracts/trigger-store.ts +40 -0
- package/src/index.ts +23 -0
- package/src/types/agent-event-wire.ts +193 -0
- package/src/types/agent-event.ts +579 -0
- package/src/types/handoff.ts +111 -0
- package/src/types/index.ts +148 -0
- package/src/types/memory.ts +427 -0
- package/src/types/message.ts +174 -0
- package/src/types/run.ts +312 -0
- package/src/types/sensitivity.ts +35 -0
- package/src/types/session-scope.ts +18 -0
- package/src/types/stop-condition.ts +108 -0
- package/src/types/tool-call.ts +24 -0
- package/src/types/tool.ts +324 -0
- package/src/types/usage.ts +120 -0
- package/src/types/workflow-event.ts +132 -0
- package/src/utils/assert-never.ts +24 -0
- package/src/utils/async-context.ts +55 -0
- package/src/utils/binary-json.ts +425 -0
- package/src/utils/hash.ts +122 -0
- package/src/utils/index.ts +57 -0
- package/src/utils/streams.ts +233 -0
- package/src/utils/validation.ts +82 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import type { Message, ReasoningContentMeta } from '../types/message.js';
|
|
2
|
+
import type { Sensitivity } from '../types/sensitivity.js';
|
|
3
|
+
import type { ToolCall } from '../types/tool-call.js';
|
|
4
|
+
import type { Usage } from '../types/usage.js';
|
|
5
|
+
import type { ReasoningContract, ReasoningRetention } from './reasoning-retention.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Vendor-neutral LLM provider interface. Concrete adapters live in
|
|
9
|
+
* `@graphorin/provider` (and companion packages such as
|
|
10
|
+
* `@graphorin/provider-llamacpp-node`).
|
|
11
|
+
*
|
|
12
|
+
* Every provider exposes a `name` (used in spans / logs), the `modelId`
|
|
13
|
+
* it wraps, a static `capabilities` descriptor, and the two streaming /
|
|
14
|
+
* one-shot generation methods.
|
|
15
|
+
*
|
|
16
|
+
* @stable
|
|
17
|
+
*/
|
|
18
|
+
export interface Provider {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
readonly modelId: string;
|
|
21
|
+
readonly capabilities: ProviderCapabilities;
|
|
22
|
+
|
|
23
|
+
/** Returns an async stream of fine-grained provider events. */
|
|
24
|
+
stream(req: ProviderRequest): AsyncIterable<ProviderEvent>;
|
|
25
|
+
|
|
26
|
+
/** Convenience wrapper that consumes the stream into a single result. */
|
|
27
|
+
generate(req: ProviderRequest): Promise<ProviderResponse>;
|
|
28
|
+
|
|
29
|
+
/** Optional: provider-native input token counter. */
|
|
30
|
+
countTokens?(req: ProviderRequest): Promise<number>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Sensitivity tiers this provider is allowed to receive. Used by the
|
|
34
|
+
* ContextEngine sensitivity filter (D2) and the outbound redaction
|
|
35
|
+
* middleware (D3) to decide what content is safe to forward.
|
|
36
|
+
*/
|
|
37
|
+
readonly acceptsSensitivity?: ReadonlyArray<Sensitivity>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Static capability descriptor returned by `Provider.capabilities`.
|
|
42
|
+
*
|
|
43
|
+
* @stable
|
|
44
|
+
*/
|
|
45
|
+
export interface ProviderCapabilities {
|
|
46
|
+
readonly streaming: boolean;
|
|
47
|
+
readonly toolCalling: boolean;
|
|
48
|
+
readonly parallelToolCalls: boolean;
|
|
49
|
+
readonly multimodal: boolean;
|
|
50
|
+
readonly structuredOutput: boolean;
|
|
51
|
+
readonly reasoning: boolean;
|
|
52
|
+
/** Total context window in tokens. */
|
|
53
|
+
readonly contextWindow: number;
|
|
54
|
+
/** Maximum output tokens. */
|
|
55
|
+
readonly maxOutput: number;
|
|
56
|
+
/**
|
|
57
|
+
* How the provider treats reasoning content across consecutive
|
|
58
|
+
* `provider.stream(...)` calls. Drives the auto-detected default
|
|
59
|
+
* {@link ReasoningRetention} value when the caller does not pass
|
|
60
|
+
* an explicit override on the request.
|
|
61
|
+
*
|
|
62
|
+
* Adapters supplied with the framework declare this field; bespoke
|
|
63
|
+
* adapters that omit it are treated as `'optional'` (conservative
|
|
64
|
+
* `'strip'` default + WARN-once on first reasoning emission).
|
|
65
|
+
*/
|
|
66
|
+
readonly reasoningContract?: ReasoningContract;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Opt-in prompt-cache breakpoint policy (core-provider-02).
|
|
71
|
+
*
|
|
72
|
+
* `breakpoints: 'auto'` asks the adapter to place provider-native cache
|
|
73
|
+
* anchors around the stable request prefix: the Anthropic path (via the
|
|
74
|
+
* vercel adapter) marks the first and last conversation messages with
|
|
75
|
+
* `cache_control: { type: 'ephemeral' }` so tools + system + the stable
|
|
76
|
+
* prefix are written once and read at ~0.1x input price on subsequent
|
|
77
|
+
* steps. Providers with automatic caching (OpenAI) or no cache concept
|
|
78
|
+
* ignore the policy. `ttl` maps to Anthropic's extended cache TTL.
|
|
79
|
+
*
|
|
80
|
+
* @stable
|
|
81
|
+
*/
|
|
82
|
+
export interface ProviderCachePolicy {
|
|
83
|
+
readonly breakpoints: 'auto' | 'none';
|
|
84
|
+
readonly ttl?: '5m' | '1h';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Provider-call request payload.
|
|
89
|
+
*
|
|
90
|
+
* @stable
|
|
91
|
+
*/
|
|
92
|
+
export interface ProviderRequest {
|
|
93
|
+
readonly messages: ReadonlyArray<Message>;
|
|
94
|
+
readonly tools?: ReadonlyArray<ToolDefinition>;
|
|
95
|
+
readonly toolChoice?: ToolChoice;
|
|
96
|
+
readonly outputType?: OutputSpec;
|
|
97
|
+
readonly systemMessage?: string;
|
|
98
|
+
readonly temperature?: number;
|
|
99
|
+
readonly maxTokens?: number;
|
|
100
|
+
readonly signal?: AbortSignal;
|
|
101
|
+
readonly providerOptions?: Readonly<Record<string, unknown>>;
|
|
102
|
+
readonly cachePolicy?: ProviderCachePolicy;
|
|
103
|
+
/**
|
|
104
|
+
* C7: live parent span for the provider call. Like `signal`, this is a
|
|
105
|
+
* runtime handle (never serialized): `withTracing` parents its
|
|
106
|
+
* provider.generate/stream span under it so a run's traces form one
|
|
107
|
+
* tree instead of disconnected fragments.
|
|
108
|
+
*/
|
|
109
|
+
readonly parentSpan?: import('./tracer.js').AISpan;
|
|
110
|
+
readonly metadata?: ProviderRequestMetadata;
|
|
111
|
+
/**
|
|
112
|
+
* Per-request override of the provider's auto-detected
|
|
113
|
+
* {@link ReasoningRetention} default. Only honoured when the
|
|
114
|
+
* provider declares `reasoningContract` of `'round-trip-required'`
|
|
115
|
+
* or `'optional'`; hidden-chain-of-thought providers (e.g.
|
|
116
|
+
* `'hidden'`) always strip and emit one WARN per process when an
|
|
117
|
+
* incompatible override is supplied.
|
|
118
|
+
*/
|
|
119
|
+
readonly reasoningRetention?: ReasoningRetention;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Per-request metadata used by tracing and auditing layers.
|
|
124
|
+
*
|
|
125
|
+
* @stable
|
|
126
|
+
*/
|
|
127
|
+
export interface ProviderRequestMetadata {
|
|
128
|
+
readonly sessionId?: string;
|
|
129
|
+
readonly agentId?: string;
|
|
130
|
+
readonly userId?: string;
|
|
131
|
+
readonly runId?: string;
|
|
132
|
+
readonly stepNumber?: number;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* One-shot response shape returned by `Provider.generate(...)`.
|
|
137
|
+
*
|
|
138
|
+
* @stable
|
|
139
|
+
*/
|
|
140
|
+
export interface ProviderResponse {
|
|
141
|
+
readonly text?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Tool invocations the model requested. W-127: reuses the canonical
|
|
144
|
+
* {@link ToolCall} (the inline shape here was structurally identical
|
|
145
|
+
* and only invited drift).
|
|
146
|
+
*/
|
|
147
|
+
readonly toolCalls?: ReadonlyArray<ToolCall>;
|
|
148
|
+
readonly usage: Usage;
|
|
149
|
+
readonly finishReason: FinishReason;
|
|
150
|
+
readonly providerMetadata?: Readonly<Record<string, unknown>>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Reason a provider call ended.
|
|
155
|
+
*
|
|
156
|
+
* @stable
|
|
157
|
+
*/
|
|
158
|
+
export type FinishReason =
|
|
159
|
+
| 'stop'
|
|
160
|
+
| 'length'
|
|
161
|
+
| 'tool-calls'
|
|
162
|
+
| 'content-filter'
|
|
163
|
+
| 'error'
|
|
164
|
+
| 'aborted';
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Streamed provider event. Shape matches the wire-stable subset of the
|
|
168
|
+
* provider event union - adapters hide vendor specifics.
|
|
169
|
+
*
|
|
170
|
+
* @stable
|
|
171
|
+
*/
|
|
172
|
+
export type ProviderEvent =
|
|
173
|
+
| { readonly type: 'stream-start'; readonly metadata: ResponseMetadata }
|
|
174
|
+
| { readonly type: 'reasoning-delta'; readonly delta: string }
|
|
175
|
+
/**
|
|
176
|
+
* Closes the current reasoning block (W-024). Deltas stay textual;
|
|
177
|
+
* this terminator carries the provider's opaque round-trip metadata
|
|
178
|
+
* (e.g. the Anthropic thinking-block `signature`, or `data` for a
|
|
179
|
+
* redacted block) so multi-step tool use with extended thinking can
|
|
180
|
+
* replay the block byte-equal on the next request. Adapters without
|
|
181
|
+
* per-block structure simply never emit it - consumers fall back to
|
|
182
|
+
* collapsing the deltas.
|
|
183
|
+
*/
|
|
184
|
+
| { readonly type: 'reasoning-end'; readonly meta?: ReasoningContentMeta }
|
|
185
|
+
| { readonly type: 'text-delta'; readonly delta: string }
|
|
186
|
+
| { readonly type: 'tool-call-start'; readonly toolCallId: string; readonly toolName: string }
|
|
187
|
+
| {
|
|
188
|
+
readonly type: 'tool-call-input-delta';
|
|
189
|
+
readonly toolCallId: string;
|
|
190
|
+
readonly argsDelta: string;
|
|
191
|
+
}
|
|
192
|
+
| { readonly type: 'tool-call-end'; readonly toolCallId: string; readonly finalArgs: unknown }
|
|
193
|
+
| { readonly type: 'file'; readonly mimeType: string; readonly data: Uint8Array }
|
|
194
|
+
| { readonly type: 'source'; readonly uri: string; readonly title?: string }
|
|
195
|
+
| { readonly type: 'finish'; readonly finishReason: FinishReason; readonly usage: Usage }
|
|
196
|
+
| { readonly type: 'error'; readonly error: ProviderError };
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Metadata attached to the first `stream-start` event of a stream.
|
|
200
|
+
*
|
|
201
|
+
* @stable
|
|
202
|
+
*/
|
|
203
|
+
export interface ResponseMetadata {
|
|
204
|
+
readonly providerName: string;
|
|
205
|
+
readonly modelId: string;
|
|
206
|
+
readonly responseId?: string;
|
|
207
|
+
readonly createdAt?: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Provider-side error shape carried by `provider-error` events.
|
|
212
|
+
*
|
|
213
|
+
* @stable
|
|
214
|
+
*/
|
|
215
|
+
export interface ProviderError {
|
|
216
|
+
readonly kind: ProviderErrorKind;
|
|
217
|
+
readonly message: string;
|
|
218
|
+
readonly cause?: unknown;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** @stable */
|
|
222
|
+
export type ProviderErrorKind =
|
|
223
|
+
| 'rate-limit'
|
|
224
|
+
| 'capacity'
|
|
225
|
+
| 'context-length'
|
|
226
|
+
| 'transient'
|
|
227
|
+
| 'invalid-request'
|
|
228
|
+
| 'unauthorized'
|
|
229
|
+
| 'content-filter'
|
|
230
|
+
| 'unknown';
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Tool description shipped with a provider request. Implementations
|
|
234
|
+
* convert the user's Zod schema to a JSON Schema 7 fragment.
|
|
235
|
+
*
|
|
236
|
+
* @stable
|
|
237
|
+
*/
|
|
238
|
+
export interface ToolDefinition {
|
|
239
|
+
readonly name: string;
|
|
240
|
+
readonly description?: string;
|
|
241
|
+
readonly inputSchema: Readonly<Record<string, unknown>>;
|
|
242
|
+
/**
|
|
243
|
+
* A5: the tool's output schema (JSON Schema), when declared. The agent runtime
|
|
244
|
+
* populates it from `Tool.outputSchema`; structured-output providers and typed
|
|
245
|
+
* code-mode use it to validate / type the tool's result. Absent when the tool
|
|
246
|
+
* declares no output schema.
|
|
247
|
+
*/
|
|
248
|
+
readonly outputSchema?: Readonly<Record<string, unknown>>;
|
|
249
|
+
/**
|
|
250
|
+
* Worked examples surfaced to the provider alongside the schema. The
|
|
251
|
+
* agent runtime populates this from the tool's `examples` when they
|
|
252
|
+
* are eagerly rendered (see `Tool.examplesEagerlyRendered`); it is
|
|
253
|
+
* bounded to ≤5 and absent when the tool declares none or defers them.
|
|
254
|
+
* Implementations MAY fold these into the model-facing tool description.
|
|
255
|
+
*/
|
|
256
|
+
readonly examples?: ReadonlyArray<ToolDefinitionExample>;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* A single worked example as projected onto the provider wire contract -
|
|
261
|
+
* a serializable, schema-agnostic view of a `ToolExample`. `input` /
|
|
262
|
+
* `output` carry the example's already-parsed values; `comment` is the
|
|
263
|
+
* optional rationale shown to the model.
|
|
264
|
+
*
|
|
265
|
+
* @stable
|
|
266
|
+
*/
|
|
267
|
+
export interface ToolDefinitionExample {
|
|
268
|
+
readonly input: unknown;
|
|
269
|
+
readonly output: unknown;
|
|
270
|
+
readonly comment?: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Tool selection strategy.
|
|
275
|
+
*
|
|
276
|
+
* @stable
|
|
277
|
+
*/
|
|
278
|
+
export type ToolChoice = 'auto' | 'required' | 'none' | { readonly tool: string };
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Output type specification for structured / typed responses. Concrete
|
|
282
|
+
* Zod-based variants live in the runtime packages.
|
|
283
|
+
*
|
|
284
|
+
* @stable
|
|
285
|
+
*/
|
|
286
|
+
export interface OutputSpec {
|
|
287
|
+
readonly kind: 'text' | 'structured';
|
|
288
|
+
readonly description?: string;
|
|
289
|
+
readonly jsonSchema?: Readonly<Record<string, unknown>>;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Provider middleware: a function that wraps a `Provider` and returns a
|
|
294
|
+
* new `Provider` with extra behaviour (retry, fallback, redaction, …).
|
|
295
|
+
*
|
|
296
|
+
* Middleware ordering is enforced by the runtime per the documented
|
|
297
|
+
* inside-out chain (innermost adapter → ... → outermost retry / observer).
|
|
298
|
+
*
|
|
299
|
+
* @stable
|
|
300
|
+
*/
|
|
301
|
+
export type ProviderMiddleware = (next: Provider) => Provider;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Type signature for the canonical middleware composer (the runtime
|
|
305
|
+
* implementation lives in `@graphorin/provider`).
|
|
306
|
+
*
|
|
307
|
+
* The concrete composer guarantees a deterministic ordering - order of
|
|
308
|
+
* arguments mirrors order of execution from outermost to innermost - and
|
|
309
|
+
* is the only blessed entry point for chaining middleware in
|
|
310
|
+
* `@graphorin/*` code (per the security-first ordering rule).
|
|
311
|
+
*
|
|
312
|
+
* @stable
|
|
313
|
+
*/
|
|
314
|
+
export type ComposeProviderMiddleware = (
|
|
315
|
+
middlewares: ReadonlyArray<ProviderMiddleware>,
|
|
316
|
+
) => ProviderMiddleware;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a provider treats reasoning content across consecutive
|
|
3
|
+
* `provider.stream(...)` calls of the same agent + same model + same
|
|
4
|
+
* run.
|
|
5
|
+
*
|
|
6
|
+
* Three independent lifecycle operations exist for reasoning content
|
|
7
|
+
* in the provider layer:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Intra-loop transmission** - controlled by this enum. Default is
|
|
10
|
+
* auto-detected per provider:
|
|
11
|
+
* - Hidden chain-of-thought providers (e.g. OpenAI o1/o3, Google
|
|
12
|
+
* Gemini reasoning): `'strip'`.
|
|
13
|
+
* - Round-trip-required providers (e.g. Anthropic Claude tool-use
|
|
14
|
+
* with thinking blocks): `'pass-through-claude'`.
|
|
15
|
+
* 2. **Sub-agent handoff transmission** - always strips reasoning
|
|
16
|
+
* regardless of this setting; lives in
|
|
17
|
+
* `@graphorin/sessions` handoff filters.
|
|
18
|
+
* 3. **Prompt-cache key calculation** - reasoning blocks are excluded
|
|
19
|
+
* from cache-key hashes but included in outbound transmission.
|
|
20
|
+
*
|
|
21
|
+
* @stable
|
|
22
|
+
*/
|
|
23
|
+
export type ReasoningRetention =
|
|
24
|
+
/**
|
|
25
|
+
* Drop reasoning content from the next request body. Default for
|
|
26
|
+
* hidden-chain-of-thought providers and the conservative default
|
|
27
|
+
* for unknown providers.
|
|
28
|
+
*/
|
|
29
|
+
| 'strip'
|
|
30
|
+
/**
|
|
31
|
+
* Round-trip Anthropic-shaped thinking blocks
|
|
32
|
+
* (`signature` / `data` / `text` fields) byte-equal to the previous
|
|
33
|
+
* assistant message.
|
|
34
|
+
*/
|
|
35
|
+
| 'pass-through-claude'
|
|
36
|
+
/**
|
|
37
|
+
* Round-trip every reasoning content part the provider returns
|
|
38
|
+
* regardless of vendor shape. Useful for custom providers that
|
|
39
|
+
* declare `reasoningContract: 'optional'` and still benefit from
|
|
40
|
+
* preserving the chain.
|
|
41
|
+
*/
|
|
42
|
+
| 'pass-through-all';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Capability declaration on `ProviderCapabilities` describing how the
|
|
46
|
+
* provider treats reasoning content. The field is auto-populated per
|
|
47
|
+
* provider family by the adapter; consumers use it to infer the
|
|
48
|
+
* default {@link ReasoningRetention} value for a request.
|
|
49
|
+
*
|
|
50
|
+
* @stable
|
|
51
|
+
*/
|
|
52
|
+
export type ReasoningContract = 'hidden' | 'round-trip-required' | 'optional';
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Sensitivity } from '../types/sensitivity.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wraps every observability exporter (OTLP, console, JSONL replay log,
|
|
5
|
+
* …) and refuses to forward attributes that exceed the configured
|
|
6
|
+
* sensitivity floor or that contain matched secret / PII patterns.
|
|
7
|
+
*
|
|
8
|
+
* Concrete patterns and the default policy live in
|
|
9
|
+
* `@graphorin/observability`; the interface lives here so every package
|
|
10
|
+
* (server, agent, workflow, …) can require a `RedactionValidator` in its
|
|
11
|
+
* config without taking an observability dependency.
|
|
12
|
+
*
|
|
13
|
+
* @stable
|
|
14
|
+
*/
|
|
15
|
+
export interface RedactionValidator {
|
|
16
|
+
/** Identifier of the policy in use (`'default-deny-internal'`, …). */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
/** Lowest tier that may pass through the validator. */
|
|
19
|
+
readonly minTier: Sensitivity;
|
|
20
|
+
/**
|
|
21
|
+
* Validate (and optionally rewrite) an attribute payload. Returns the
|
|
22
|
+
* sanitized value or `null` if the entire record must be dropped.
|
|
23
|
+
*/
|
|
24
|
+
validate(input: RedactionInput): RedactionOutput | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Input handed to `RedactionValidator.validate(...)`.
|
|
29
|
+
*
|
|
30
|
+
* @stable
|
|
31
|
+
*/
|
|
32
|
+
export interface RedactionInput {
|
|
33
|
+
readonly value: unknown;
|
|
34
|
+
/** Tier declared by the upstream caller for this value. */
|
|
35
|
+
readonly tier: Sensitivity;
|
|
36
|
+
/** Optional context describing where the value originated. */
|
|
37
|
+
readonly context?: {
|
|
38
|
+
readonly attribute?: string;
|
|
39
|
+
readonly spanType?: string;
|
|
40
|
+
readonly origin?: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Result of `RedactionValidator.validate(...)` - either the sanitized
|
|
46
|
+
* payload (possibly equal to the input) or `null` if the value must be
|
|
47
|
+
* dropped entirely.
|
|
48
|
+
*
|
|
49
|
+
* @stable
|
|
50
|
+
*/
|
|
51
|
+
export interface RedactionOutput {
|
|
52
|
+
readonly value: unknown;
|
|
53
|
+
readonly tier: Sensitivity;
|
|
54
|
+
/** List of pattern names matched while validating. */
|
|
55
|
+
readonly matched?: ReadonlyArray<string>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pluggable sandbox interface for tool / skill execution. Concrete
|
|
3
|
+
* implementations live in `@graphorin/security` (worker-threads,
|
|
4
|
+
* isolated-vm, docker, none).
|
|
5
|
+
*
|
|
6
|
+
* @stable
|
|
7
|
+
*/
|
|
8
|
+
export interface Sandbox {
|
|
9
|
+
/** Identifier of the sandbox flavor (`'worker-threads'`, `'isolated-vm'`, …). */
|
|
10
|
+
readonly id: string;
|
|
11
|
+
run<TInput, TOutput>(
|
|
12
|
+
code: SandboxCode,
|
|
13
|
+
opts: SandboxRunOptions<TInput>,
|
|
14
|
+
): Promise<SandboxResult<TOutput>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Description of the code to run in the sandbox. Either a JS source
|
|
19
|
+
* string, a path to a JS file, or a fully-qualified handler reference
|
|
20
|
+
* resolved by the sandbox implementation.
|
|
21
|
+
*
|
|
22
|
+
* @stable
|
|
23
|
+
*/
|
|
24
|
+
export type SandboxCode =
|
|
25
|
+
| { readonly kind: 'source'; readonly source: string; readonly filename?: string }
|
|
26
|
+
| { readonly kind: 'file'; readonly path: string }
|
|
27
|
+
| { readonly kind: 'handler'; readonly module: string; readonly export: string };
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Per-call sandbox options.
|
|
31
|
+
*
|
|
32
|
+
* @stable
|
|
33
|
+
*/
|
|
34
|
+
export interface SandboxRunOptions<TInput = unknown> {
|
|
35
|
+
readonly input: TInput;
|
|
36
|
+
readonly timeoutMs?: number;
|
|
37
|
+
readonly maxMemoryMb?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Allowlist of environment variables visible inside the sandbox.
|
|
40
|
+
* Sandboxed code never inherits the host `process.env`; entries
|
|
41
|
+
* given here are the only ones defined.
|
|
42
|
+
*/
|
|
43
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
44
|
+
readonly allowNetwork?: boolean;
|
|
45
|
+
readonly allowFs?: boolean;
|
|
46
|
+
readonly signal?: AbortSignal;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Result of a sandboxed run. The shape mirrors the `ToolOutcome` union -
|
|
51
|
+
* the runtime maps `SandboxResult` to `ToolOutcome` after the call.
|
|
52
|
+
*
|
|
53
|
+
* @stable
|
|
54
|
+
*/
|
|
55
|
+
export type SandboxResult<TOutput = unknown> =
|
|
56
|
+
| { readonly ok: true; readonly output: TOutput; readonly durationMs: number }
|
|
57
|
+
| {
|
|
58
|
+
readonly ok: false;
|
|
59
|
+
readonly error: {
|
|
60
|
+
readonly kind:
|
|
61
|
+
| 'timeout'
|
|
62
|
+
| 'memory-exceeded'
|
|
63
|
+
| 'sandbox-violation'
|
|
64
|
+
| 'aborted'
|
|
65
|
+
| 'execution-failed';
|
|
66
|
+
readonly message: string;
|
|
67
|
+
readonly cause?: unknown;
|
|
68
|
+
};
|
|
69
|
+
readonly durationMs: number;
|
|
70
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parsed shape of a `SecretRef` URI (`scheme:[//authority]/path[?query][#fragment]`).
|
|
3
|
+
*
|
|
4
|
+
* The full grammar lives in `@graphorin/security`; the type lives here so
|
|
5
|
+
* downstream packages can carry parsed refs without a security dependency.
|
|
6
|
+
*
|
|
7
|
+
* @stable
|
|
8
|
+
*/
|
|
9
|
+
export interface SecretRef {
|
|
10
|
+
/** Original URI string as supplied by the caller. */
|
|
11
|
+
readonly raw: string;
|
|
12
|
+
/** Lowercased scheme (`'env'`, `'keyring'`, `'file'`, …). */
|
|
13
|
+
readonly scheme: string;
|
|
14
|
+
/** Optional authority component (e.g. `host[:port]`). */
|
|
15
|
+
readonly authority?: string;
|
|
16
|
+
/** Path component (without the leading slash for opaque schemes). */
|
|
17
|
+
readonly path: string;
|
|
18
|
+
/** Parsed query parameters (already percent-decoded). */
|
|
19
|
+
readonly query: Readonly<Record<string, string>>;
|
|
20
|
+
/** Optional fragment (e.g. JSON-Pointer for nested fields). */
|
|
21
|
+
readonly fragment?: string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-realm symbol used to brand `SecretValue` instances. Implementations
|
|
3
|
+
* (e.g. the wrapper class shipped from `@graphorin/security`) attach this
|
|
4
|
+
* symbol so that `isSecretValue(...)` works across realms (Worker threads,
|
|
5
|
+
* sandboxes, etc.).
|
|
6
|
+
*
|
|
7
|
+
* @stable
|
|
8
|
+
*/
|
|
9
|
+
export const SECRET_VALUE_BRAND: unique symbol = Symbol.for('graphorin.SecretValue');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Well-known symbol used by `node:util.inspect()` to format the wrapper.
|
|
13
|
+
* Re-exported here so downstream packages can reference it without taking
|
|
14
|
+
* an unconditional dependency on `node:util`.
|
|
15
|
+
*
|
|
16
|
+
* Equivalent to `Symbol.for('nodejs.util.inspect.custom')`.
|
|
17
|
+
*
|
|
18
|
+
* @stable
|
|
19
|
+
*/
|
|
20
|
+
export const NODEJS_INSPECT_CUSTOM: unique symbol = Symbol.for('nodejs.util.inspect.custom');
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Runtime-safe wrapper around an opaque secret (API key, token, password).
|
|
24
|
+
*
|
|
25
|
+
* The shape declared here is the **interface contract**: the concrete
|
|
26
|
+
* wrapper class lives in `@graphorin/security`. Downstream packages typing
|
|
27
|
+
* a parameter as `SecretValue` therefore avoid taking a security
|
|
28
|
+
* dependency.
|
|
29
|
+
*
|
|
30
|
+
* Note: `SecretValue` is **not** a TypeScript branded primitive - it is
|
|
31
|
+
* a full wrapper class with explicit leakage barriers
|
|
32
|
+
* (`Symbol.toPrimitive`, `toJSON`, `[nodejs.util.inspect.custom]`, …).
|
|
33
|
+
* Any conforming implementation must ensure that:
|
|
34
|
+
*
|
|
35
|
+
* - String coercion (`String(s)`, `` `${s}` ``, `s + ''`, …) yields a
|
|
36
|
+
* redacted placeholder, **not** the underlying value.
|
|
37
|
+
* - JSON serialization (`JSON.stringify({ apiKey: s })`) yields a
|
|
38
|
+
* redacted placeholder.
|
|
39
|
+
* - Inspector output (`util.inspect(s)`) yields
|
|
40
|
+
* `'SecretValue([REDACTED])'`.
|
|
41
|
+
* - The underlying value is only reachable through `.use(fn)`,
|
|
42
|
+
* `.useBuffer(fn)` or the audited `.reveal()` escape hatch.
|
|
43
|
+
*
|
|
44
|
+
* @stable
|
|
45
|
+
*/
|
|
46
|
+
export interface SecretValue {
|
|
47
|
+
/** Number of bytes in the wrapped value. Safe to log. */
|
|
48
|
+
readonly length: number;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Run `fn` with the unwrapped string and return its result. Preferred
|
|
52
|
+
* over `.reveal()` because it scopes the unwrapped value to a single
|
|
53
|
+
* synchronous / asynchronous turn.
|
|
54
|
+
*/
|
|
55
|
+
use<T>(fn: (raw: string) => T | Promise<T>): Promise<T>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Run `fn` with the unwrapped value as a `Buffer`. Useful for binary
|
|
59
|
+
* secrets (encryption keys, HMAC keys) where round-tripping through a
|
|
60
|
+
* V8 string would defeat the wrapper's hygiene.
|
|
61
|
+
*/
|
|
62
|
+
useBuffer<T>(fn: (buf: Buffer) => T | Promise<T>): Promise<T>;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* One-shot reveal as a string. Audited by the implementation. Prefer
|
|
66
|
+
* `.use(fn)` whenever possible.
|
|
67
|
+
*/
|
|
68
|
+
reveal(): string;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Best-effort zeroization of the underlying buffer. Does not affect
|
|
72
|
+
* derived V8 strings already created via `.use(fn)` / `.reveal()`.
|
|
73
|
+
*/
|
|
74
|
+
dispose(): void;
|
|
75
|
+
|
|
76
|
+
/** Cross-realm brand. Implementations set this to `SECRET_VALUE_BRAND`. */
|
|
77
|
+
readonly [SECRET_VALUE_BRAND]: true;
|
|
78
|
+
|
|
79
|
+
/** Leakage barrier for ToPrimitive coercion. Returns the placeholder. */
|
|
80
|
+
[Symbol.toPrimitive](hint: string): string | number;
|
|
81
|
+
|
|
82
|
+
/** Leakage barrier for `JSON.stringify(...)`. Returns the placeholder. */
|
|
83
|
+
toJSON(): string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Leakage barrier for `node:util.inspect(...)`. Returns the placeholder
|
|
87
|
+
* (`'SecretValue([REDACTED])'`) so that REPL / `console.log` /
|
|
88
|
+
* structured-logger output never reveals the underlying value.
|
|
89
|
+
*/
|
|
90
|
+
[NODEJS_INSPECT_CUSTOM](depth?: number, opts?: unknown, inspect?: unknown): string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Static helpers expected on every concrete `SecretValue` constructor.
|
|
95
|
+
*
|
|
96
|
+
* @stable
|
|
97
|
+
*/
|
|
98
|
+
export interface SecretValueStatic {
|
|
99
|
+
/** Cross-realm safe type guard. */
|
|
100
|
+
isSecretValue(value: unknown): value is SecretValue;
|
|
101
|
+
/** Constant-time equality. */
|
|
102
|
+
timingSafeEquals(a: SecretValue, b: SecretValue): boolean;
|
|
103
|
+
/** Construct from a plain string. */
|
|
104
|
+
fromString(raw: string, opts?: SecretValueOptions): SecretValue;
|
|
105
|
+
/** Construct from a Node.js `Buffer`. */
|
|
106
|
+
fromBuffer(buf: Buffer, opts?: SecretValueOptions): SecretValue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Optional metadata attached to a freshly constructed `SecretValue`.
|
|
111
|
+
*
|
|
112
|
+
* @stable
|
|
113
|
+
*/
|
|
114
|
+
export interface SecretValueOptions {
|
|
115
|
+
/** Free-form provenance string for the audit log. */
|
|
116
|
+
readonly source?: { readonly resolver?: string; readonly ref?: string };
|
|
117
|
+
}
|