@vinaverse/server 0.0.0-stage → 0.1.0-alpha.2
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/LICENSE +202 -0
- package/README.md +165 -2
- package/dist/api.cjs +528 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +453 -0
- package/dist/api.d.ts +453 -0
- package/dist/api.js +516 -0
- package/dist/api.js.map +1 -0
- package/dist/chunk-FEEJNQXV.js +64 -0
- package/dist/chunk-FEEJNQXV.js.map +1 -0
- package/dist/chunk-GTPMQKGX.js +277 -0
- package/dist/chunk-GTPMQKGX.js.map +1 -0
- package/dist/chunk-NPXO6SMZ.js +84 -0
- package/dist/chunk-NPXO6SMZ.js.map +1 -0
- package/dist/chunk-SDJFZPHJ.js +141 -0
- package/dist/chunk-SDJFZPHJ.js.map +1 -0
- package/dist/express.cjs +397 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +43 -0
- package/dist/express.d.ts +43 -0
- package/dist/express.js +87 -0
- package/dist/express.js.map +1 -0
- package/dist/fastify.cjs +363 -0
- package/dist/fastify.cjs.map +1 -0
- package/dist/fastify.d.cts +62 -0
- package/dist/fastify.d.ts +62 -0
- package/dist/fastify.js +54 -0
- package/dist/fastify.js.map +1 -0
- package/dist/hono.cjs +421 -0
- package/dist/hono.cjs.map +1 -0
- package/dist/hono.d.cts +21 -0
- package/dist/hono.d.ts +21 -0
- package/dist/hono.js +34 -0
- package/dist/hono.js.map +1 -0
- package/dist/index.cjs +1481 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +196 -0
- package/dist/index.d.ts +196 -0
- package/dist/index.js +920 -0
- package/dist/index.js.map +1 -0
- package/dist/lambda.cjs +405 -0
- package/dist/lambda.cjs.map +1 -0
- package/dist/lambda.d.cts +53 -0
- package/dist/lambda.d.ts +53 -0
- package/dist/lambda.js +86 -0
- package/dist/lambda.js.map +1 -0
- package/dist/nonces-scwljZwl.d.cts +92 -0
- package/dist/nonces-scwljZwl.d.ts +92 -0
- package/dist/provider-BqfTvF3g.d.ts +2016 -0
- package/dist/provider-Miaa9V7I.d.cts +2016 -0
- package/dist/stores.cjs +315 -0
- package/dist/stores.cjs.map +1 -0
- package/dist/stores.d.cts +52 -0
- package/dist/stores.d.ts +52 -0
- package/dist/stores.js +306 -0
- package/dist/stores.js.map +1 -0
- package/dist/testing.cjs +135 -0
- package/dist/testing.cjs.map +1 -0
- package/dist/testing.d.cts +29 -0
- package/dist/testing.d.ts +29 -0
- package/dist/testing.js +49 -0
- package/dist/testing.js.map +1 -0
- package/dist/vinaverse-v1.d-BVc4uyUd.d.cts +3460 -0
- package/dist/vinaverse-v1.d-BVc4uyUd.d.ts +3460 -0
- package/package.json +225 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { T as ToolProvider, W as WebhookHandlerOptions, C as ConversationEvent, a as WebhookError, R as ReadBody } from './provider-BqfTvF3g.js';
|
|
2
|
+
export { b as ConversationEventType, c as ConversationState, K as KEEP_SECONDS, L as LeaseLostError, M as MAX_REQUEST_BYTES, d as ResultTooLargeError, e as TOOL_OPERATIONS, f as ToolBody, g as ToolCall, h as ToolContractComponents, o as ToolContractOperations, i as ToolHandlers, j as ToolOperationId, k as ToolProviderOptions, l as ToolRequest, m as ToolResponse, n as ToolResult, p as ToolSignatureError, q as ToolSignatureErrorCode, r as WEBHOOK_EVENT_TYPES, s as WebhookEnvelope, t as WebhookErrorCode, u as WebhookEvent, v as WebhookEventOf, w as WebhookEventType, x as WebhookResponse, y as createToolProvider, z as isConversationEvent, A as verifyToolCall } from './provider-BqfTvF3g.js';
|
|
3
|
+
export { c as ContractComponents, w as ContractWebhooks } from './vinaverse-v1.d-BVc4uyUd.js';
|
|
4
|
+
export { I as IdempotencyRecord, a as IdempotencyStore, M as MemoryIdempotencyStore, b as MemoryNonceStore, N as NONCE_KEEP_SECONDS, c as NonceStore, d as canonicalJson, f as fingerprint } from './nonces-scwljZwl.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `(request) => Promise<Response>` for a Vinaverse webhook endpoint. It reads
|
|
8
|
+
* the raw body itself, so mount it where nothing has parsed the body:
|
|
9
|
+
*
|
|
10
|
+
* export const POST = createFetchWebhookHandler({ secret, onEvent });
|
|
11
|
+
*/
|
|
12
|
+
declare function createFetchWebhookHandler(options: WebhookHandlerOptions): (request: Request) => Promise<Response>;
|
|
13
|
+
/**
|
|
14
|
+
* `(request) => Promise<Response>` serving a tenant's tools: every tool route
|
|
15
|
+
* under the provider's `basePath`, with the contract enforced. The target is
|
|
16
|
+
* the request URL's path and query as received.
|
|
17
|
+
*
|
|
18
|
+
* const handle = createFetchToolHandler(createToolProvider({ … }));
|
|
19
|
+
*/
|
|
20
|
+
declare function createFetchToolHandler(provider: ToolProvider, options?: {
|
|
21
|
+
maxBodyBytes?: number;
|
|
22
|
+
}): (request: Request) => Promise<Response>;
|
|
23
|
+
|
|
24
|
+
declare const CONTRACT: {
|
|
25
|
+
readonly api: "v1-draft.17";
|
|
26
|
+
readonly commit: "fe4fb7d2945e1ced2bce7d44e85a4b28005e46df";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
type ProblemCode = 'not_found' | 'forbidden' | 'invalid_argument' | 'unavailable' | 'token_expired';
|
|
30
|
+
/** The codes a refused flow submission carries (`FlowSubmissionRefusal`). */
|
|
31
|
+
type FlowRefusalCode = 'REQUIRED_MISSING' | 'UNKNOWN_VALUE' | 'TOO_LONG' | 'VERSION_NOT_ACCEPTED' | 'TOO_MANY' | 'TOO_FEW' | 'BAD_DATE' | 'UPLOAD_NOT_FOUND' | 'OUT_OF_RANGE';
|
|
32
|
+
interface ProblemBody {
|
|
33
|
+
readonly status: number;
|
|
34
|
+
readonly code: string;
|
|
35
|
+
readonly detail?: string;
|
|
36
|
+
readonly field?: string;
|
|
37
|
+
readonly example?: string;
|
|
38
|
+
readonly question_id?: string;
|
|
39
|
+
}
|
|
40
|
+
/** A refusal the toolkit sends as the contract's problem details. */
|
|
41
|
+
declare class ToolRefusal extends Error {
|
|
42
|
+
#private;
|
|
43
|
+
readonly problem: ProblemBody;
|
|
44
|
+
constructor(problem: ProblemBody);
|
|
45
|
+
get status(): number;
|
|
46
|
+
/** The record does not exist, or the person may not see it (both are the same 404). */
|
|
47
|
+
static notFound(detail?: string): ToolRefusal;
|
|
48
|
+
static forbidden(detail?: string): ToolRefusal;
|
|
49
|
+
/**
|
|
50
|
+
* A value the tenant does not accept. `field` is a JSON Pointer into the
|
|
51
|
+
* body (`/changes/address/postal_code`); `example` is a valid value the
|
|
52
|
+
* agent offers when it asks again.
|
|
53
|
+
*/
|
|
54
|
+
static invalidArgument(options?: {
|
|
55
|
+
field?: string;
|
|
56
|
+
example?: string;
|
|
57
|
+
detail?: string;
|
|
58
|
+
}): ToolRefusal;
|
|
59
|
+
/** A temporary failure; a read is retried. */
|
|
60
|
+
static unavailable(detail?: string): ToolRefusal;
|
|
61
|
+
/** The delegated token is not valid (expired, revoked, unknown): a 401, which ends the session's tool access. */
|
|
62
|
+
static tokenExpired(detail?: string): ToolRefusal;
|
|
63
|
+
/** `get_flow_definition` with a `version` the tenant no longer accepts: `410 VERSION_GONE`. */
|
|
64
|
+
static versionGone(detail?: string): ToolRefusal;
|
|
65
|
+
/**
|
|
66
|
+
* `submit_flow` refused: `422` with a flow code and the question to ask
|
|
67
|
+
* again (none only for `VERSION_NOT_ACCEPTED`). Stored like an acceptance,
|
|
68
|
+
* so the same submission gets the same refusal again.
|
|
69
|
+
*/
|
|
70
|
+
static flowRefused(code: FlowRefusalCode, questionId?: string, detail?: string): ToolRefusal;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** No Web Crypto in this runtime: the package cannot verify anything here. */
|
|
74
|
+
declare class WebCryptoUnavailableError extends Error {
|
|
75
|
+
constructor();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** The fields of a conversation state the rule reads. */
|
|
79
|
+
interface SequencedState {
|
|
80
|
+
readonly conversation_id: string;
|
|
81
|
+
readonly sequence: number;
|
|
82
|
+
readonly answers_omitted?: boolean;
|
|
83
|
+
readonly answers?: unknown;
|
|
84
|
+
readonly remarks?: unknown;
|
|
85
|
+
}
|
|
86
|
+
/** What a tenant keeps per conversation: the state held, and what it knows about the deliveries. */
|
|
87
|
+
interface ConversationRecord<S extends SequencedState = SequencedState> {
|
|
88
|
+
/** The newest state, with the answers and remarks merged in when a delivery left them out. */
|
|
89
|
+
readonly state: S;
|
|
90
|
+
/** Every `sequence` a delivery carried for this conversation, ascending. */
|
|
91
|
+
readonly seen: readonly number[];
|
|
92
|
+
/** The last applied state left out its answers: read the full state. */
|
|
93
|
+
readonly fullReadNeeded: boolean;
|
|
94
|
+
}
|
|
95
|
+
type SequenceAction = 'apply' | 'stale';
|
|
96
|
+
type DeliveryAction = SequenceAction | 'duplicate' | 'skip_test';
|
|
97
|
+
/** Apply a state only above the one held: an equal or lower `sequence` is stale. */
|
|
98
|
+
declare function sequenceVerdict(held: Pick<SequencedState, 'conversation_id' | 'sequence'> | null | undefined, incoming: Pick<SequencedState, 'conversation_id' | 'sequence'>): SequenceAction;
|
|
99
|
+
/**
|
|
100
|
+
* Applies one conversation state to the record held for its conversation (or
|
|
101
|
+
* none) and returns the record to keep and what happened. A stale state
|
|
102
|
+
* changes nothing but `seen`. An applied state with `answers_omitted: true` is
|
|
103
|
+
* kept without that flag, with the `answers` and `remarks` held (or none), and
|
|
104
|
+
* `fullReadNeeded` set.
|
|
105
|
+
*/
|
|
106
|
+
declare function applyConversationState<S extends SequencedState>(record: ConversationRecord<S> | null | undefined, incoming: S): {
|
|
107
|
+
record: ConversationRecord<S>;
|
|
108
|
+
action: SequenceAction;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* The sequences still to come for a conversation: above the lowest one a
|
|
112
|
+
* delivery carried and below the one held, that no delivery has carried yet.
|
|
113
|
+
* Wait for them, or read the full state.
|
|
114
|
+
*/
|
|
115
|
+
declare function missingSequences(record: ConversationRecord): number[];
|
|
116
|
+
type ConversationData = ConversationEvent['data'];
|
|
117
|
+
/**
|
|
118
|
+
* The rule over a stream of verified deliveries, in memory: envelope ids seen,
|
|
119
|
+
* and a record per conversation. For one process and for tests; a tenant
|
|
120
|
+
* behind several instances keeps the ids and the records in its database and
|
|
121
|
+
* calls `applyConversationState` itself.
|
|
122
|
+
*/
|
|
123
|
+
declare class ConversationReceiver {
|
|
124
|
+
#private;
|
|
125
|
+
/**
|
|
126
|
+
* One verified delivery (an event, or a Studio test delivery's envelope):
|
|
127
|
+
* what to do with it. The record for its conversation is then `record(id)`.
|
|
128
|
+
*/
|
|
129
|
+
receive(delivery: {
|
|
130
|
+
readonly id: string;
|
|
131
|
+
readonly data: unknown;
|
|
132
|
+
}): DeliveryAction;
|
|
133
|
+
record(conversationId: string): ConversationRecord<ConversationData> | undefined;
|
|
134
|
+
conversations(): string[];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
declare const SIGNATURE_HEADER = "Vinaverse-Signature";
|
|
138
|
+
declare const TOLERANCE_SECONDS = 300;
|
|
139
|
+
interface ParsedSignature {
|
|
140
|
+
/** The signed timestamp, in Unix seconds. */
|
|
141
|
+
readonly timestamp: bigint;
|
|
142
|
+
/** Each `v1` signature, decoded. */
|
|
143
|
+
readonly signatures: readonly Uint8Array[];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Reads the header the way the API's own verifier does: comma-separated
|
|
147
|
+
* `key=value` parts (a space around a part changes nothing), exactly one `t`
|
|
148
|
+
* of digits, and the `v1` values. A `v1`
|
|
149
|
+
* that is not 64 lowercase hex digits can never match, so it is left out; a
|
|
150
|
+
* header left with no `v1` is malformed.
|
|
151
|
+
*/
|
|
152
|
+
declare function parseSignatureHeader(header: string): ParsedSignature | WebhookError;
|
|
153
|
+
|
|
154
|
+
interface VerifyWebhookOptions {
|
|
155
|
+
/**
|
|
156
|
+
* The request body exactly as received, before any JSON parsing: a string,
|
|
157
|
+
* or bytes (`Uint8Array`, which a Node `Buffer` is, or `ArrayBuffer`). A
|
|
158
|
+
* body parsed and serialized again never verifies.
|
|
159
|
+
*/
|
|
160
|
+
rawBody: string | Uint8Array | ArrayBuffer;
|
|
161
|
+
/** The `Vinaverse-Signature` header (a framework's string array is accepted). */
|
|
162
|
+
header: string | readonly string[] | null | undefined;
|
|
163
|
+
/**
|
|
164
|
+
* The endpoint's signing secret (`vv_whsec_…`), whole. Pass two while you
|
|
165
|
+
* roll a new one out: a delivery verifies if either matches.
|
|
166
|
+
*/
|
|
167
|
+
secret: string | readonly string[];
|
|
168
|
+
/** The time to check the signature's timestamp against; default now. */
|
|
169
|
+
now?: Date;
|
|
170
|
+
/** How far from `now` a signature may be: whole seconds, 0 to 300 (the contract's window, the default). */
|
|
171
|
+
toleranceSeconds?: number;
|
|
172
|
+
}
|
|
173
|
+
type VerifyWebhookResult = ({
|
|
174
|
+
ok: true;
|
|
175
|
+
} & ReadBody) | {
|
|
176
|
+
ok: false;
|
|
177
|
+
error: WebhookError;
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Verifies a Vinaverse webhook delivery and reads it, in one call:
|
|
181
|
+
*
|
|
182
|
+
* - `{ ok: true, kind: 'event', event }`: a verified event; narrow it on `event.type`.
|
|
183
|
+
* - `{ ok: true, kind: 'test', envelope }`: a test delivery from Studio; answer 2xx, do nothing.
|
|
184
|
+
* - `{ ok: true, kind: 'unrecognized', envelope }`: verified, but a type newer than this
|
|
185
|
+
* package; answer 2xx, and upgrade to handle it.
|
|
186
|
+
* - `{ ok: false, error }`: refused (`error.code` says why); answer 400.
|
|
187
|
+
*
|
|
188
|
+
* Deliveries are at least once: deduplicate on `event.id`, and order a
|
|
189
|
+
* conversation's states with `sequenceVerdict` or `applyConversationState`.
|
|
190
|
+
* It never throws for a bad delivery; it throws a `TypeError` for a missing
|
|
191
|
+
* secret or a tolerance that is not a whole number of seconds from 0 to 300,
|
|
192
|
+
* and `WebCryptoUnavailableError` in a runtime without Web Crypto.
|
|
193
|
+
*/
|
|
194
|
+
declare function verifyWebhook(options: VerifyWebhookOptions): Promise<VerifyWebhookResult>;
|
|
195
|
+
|
|
196
|
+
export { CONTRACT, ConversationEvent, ConversationReceiver, type ConversationRecord, type DeliveryAction, type FlowRefusalCode, type ProblemBody, type ProblemCode, SIGNATURE_HEADER, type SequenceAction, type SequencedState, TOLERANCE_SECONDS, ToolProvider, ToolRefusal, type VerifyWebhookOptions, type VerifyWebhookResult, WebCryptoUnavailableError, WebhookError, WebhookHandlerOptions, applyConversationState, createFetchToolHandler, createFetchWebhookHandler, missingSequences, parseSignatureHeader, sequenceVerdict, verifyWebhook };
|