gavio 0.1.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.
Files changed (196) hide show
  1. package/README.md +95 -0
  2. package/dist/cjs/context.js +47 -0
  3. package/dist/cjs/errors.js +57 -0
  4. package/dist/cjs/gateway.js +127 -0
  5. package/dist/cjs/ids.js +60 -0
  6. package/dist/cjs/index.js +49 -0
  7. package/dist/cjs/interceptors/audit/index.js +12 -0
  8. package/dist/cjs/interceptors/audit/interceptor.js +77 -0
  9. package/dist/cjs/interceptors/audit/record.js +107 -0
  10. package/dist/cjs/interceptors/audit/sink.js +3 -0
  11. package/dist/cjs/interceptors/audit/sinks/index.js +5 -0
  12. package/dist/cjs/interceptors/audit/sinks/stdout.js +33 -0
  13. package/dist/cjs/interceptors/base.js +7 -0
  14. package/dist/cjs/interceptors/cache/backend.js +9 -0
  15. package/dist/cjs/interceptors/cache/backends/index.js +5 -0
  16. package/dist/cjs/interceptors/cache/backends/memory.js +53 -0
  17. package/dist/cjs/interceptors/cache/index.js +9 -0
  18. package/dist/cjs/interceptors/chain.js +57 -0
  19. package/dist/cjs/interceptors/index.js +18 -0
  20. package/dist/cjs/interceptors/pii/context.js +25 -0
  21. package/dist/cjs/interceptors/pii/guard.js +161 -0
  22. package/dist/cjs/interceptors/pii/index.js +28 -0
  23. package/dist/cjs/interceptors/pii/match.js +21 -0
  24. package/dist/cjs/interceptors/pii/scanner.js +31 -0
  25. package/dist/cjs/interceptors/pii/scanners/bsn.js +41 -0
  26. package/dist/cjs/interceptors/pii/scanners/credit-card.js +51 -0
  27. package/dist/cjs/interceptors/pii/scanners/email.js +26 -0
  28. package/dist/cjs/interceptors/pii/scanners/iban.js +58 -0
  29. package/dist/cjs/interceptors/pii/scanners/index.js +45 -0
  30. package/dist/cjs/interceptors/pii/scanners/ip-address.js +36 -0
  31. package/dist/cjs/interceptors/pii/scanners/phone.js +37 -0
  32. package/dist/cjs/interceptors/pii/scanners/secret.js +46 -0
  33. package/dist/cjs/interceptors/pii/scanners/ssn.js +28 -0
  34. package/dist/cjs/interceptors/reliability/fallback.js +53 -0
  35. package/dist/cjs/interceptors/reliability/index.js +11 -0
  36. package/dist/cjs/interceptors/reliability/retry.js +69 -0
  37. package/dist/cjs/interceptors/reliability/timeout.js +41 -0
  38. package/dist/cjs/package.json +3 -0
  39. package/dist/cjs/pricing.js +70 -0
  40. package/dist/cjs/providers/anthropic.js +80 -0
  41. package/dist/cjs/providers/base.js +30 -0
  42. package/dist/cjs/providers/http.js +42 -0
  43. package/dist/cjs/providers/index.js +34 -0
  44. package/dist/cjs/providers/mock.js +54 -0
  45. package/dist/cjs/providers/openai.js +63 -0
  46. package/dist/cjs/request.js +60 -0
  47. package/dist/cjs/response.js +55 -0
  48. package/dist/cjs/testing/harness.js +70 -0
  49. package/dist/cjs/testing/index.js +8 -0
  50. package/dist/cjs/types.js +61 -0
  51. package/dist/esm/context.d.ts +33 -0
  52. package/dist/esm/context.js +43 -0
  53. package/dist/esm/errors.d.ts +36 -0
  54. package/dist/esm/errors.js +44 -0
  55. package/dist/esm/gateway.d.ts +54 -0
  56. package/dist/esm/gateway.js +123 -0
  57. package/dist/esm/ids.d.ts +11 -0
  58. package/dist/esm/ids.js +56 -0
  59. package/dist/esm/index.d.ts +25 -0
  60. package/dist/esm/index.js +20 -0
  61. package/dist/esm/interceptors/audit/index.d.ts +7 -0
  62. package/dist/esm/interceptors/audit/index.js +3 -0
  63. package/dist/esm/interceptors/audit/interceptor.d.ts +11 -0
  64. package/dist/esm/interceptors/audit/interceptor.js +72 -0
  65. package/dist/esm/interceptors/audit/record.d.ts +66 -0
  66. package/dist/esm/interceptors/audit/record.js +103 -0
  67. package/dist/esm/interceptors/audit/sink.d.ts +8 -0
  68. package/dist/esm/interceptors/audit/sink.js +2 -0
  69. package/dist/esm/interceptors/audit/sinks/index.d.ts +2 -0
  70. package/dist/esm/interceptors/audit/sinks/index.js +1 -0
  71. package/dist/esm/interceptors/audit/sinks/stdout.d.ts +8 -0
  72. package/dist/esm/interceptors/audit/sinks/stdout.js +30 -0
  73. package/dist/esm/interceptors/base.d.ts +37 -0
  74. package/dist/esm/interceptors/base.js +4 -0
  75. package/dist/esm/interceptors/cache/backend.d.ts +14 -0
  76. package/dist/esm/interceptors/cache/backend.js +8 -0
  77. package/dist/esm/interceptors/cache/backends/index.d.ts +2 -0
  78. package/dist/esm/interceptors/cache/backends/index.js +1 -0
  79. package/dist/esm/interceptors/cache/backends/memory.d.ts +7 -0
  80. package/dist/esm/interceptors/cache/backends/memory.js +50 -0
  81. package/dist/esm/interceptors/cache/index.d.ts +7 -0
  82. package/dist/esm/interceptors/cache/index.js +5 -0
  83. package/dist/esm/interceptors/chain.d.ts +17 -0
  84. package/dist/esm/interceptors/chain.js +53 -0
  85. package/dist/esm/interceptors/index.d.ts +8 -0
  86. package/dist/esm/interceptors/index.js +7 -0
  87. package/dist/esm/interceptors/pii/context.d.ts +15 -0
  88. package/dist/esm/interceptors/pii/context.js +21 -0
  89. package/dist/esm/interceptors/pii/guard.d.ts +30 -0
  90. package/dist/esm/interceptors/pii/guard.js +157 -0
  91. package/dist/esm/interceptors/pii/index.d.ts +10 -0
  92. package/dist/esm/interceptors/pii/index.js +7 -0
  93. package/dist/esm/interceptors/pii/match.d.ts +26 -0
  94. package/dist/esm/interceptors/pii/match.js +17 -0
  95. package/dist/esm/interceptors/pii/scanner.d.ts +32 -0
  96. package/dist/esm/interceptors/pii/scanner.js +26 -0
  97. package/dist/esm/interceptors/pii/scanners/bsn.d.ts +5 -0
  98. package/dist/esm/interceptors/pii/scanners/bsn.js +37 -0
  99. package/dist/esm/interceptors/pii/scanners/credit-card.d.ts +4 -0
  100. package/dist/esm/interceptors/pii/scanners/credit-card.js +47 -0
  101. package/dist/esm/interceptors/pii/scanners/email.d.ts +3 -0
  102. package/dist/esm/interceptors/pii/scanners/email.js +23 -0
  103. package/dist/esm/interceptors/pii/scanners/iban.d.ts +5 -0
  104. package/dist/esm/interceptors/pii/scanners/iban.js +54 -0
  105. package/dist/esm/interceptors/pii/scanners/index.d.ts +13 -0
  106. package/dist/esm/interceptors/pii/scanners/index.js +30 -0
  107. package/dist/esm/interceptors/pii/scanners/ip-address.d.ts +3 -0
  108. package/dist/esm/interceptors/pii/scanners/ip-address.js +33 -0
  109. package/dist/esm/interceptors/pii/scanners/phone.d.ts +6 -0
  110. package/dist/esm/interceptors/pii/scanners/phone.js +34 -0
  111. package/dist/esm/interceptors/pii/scanners/secret.d.ts +9 -0
  112. package/dist/esm/interceptors/pii/scanners/secret.js +43 -0
  113. package/dist/esm/interceptors/pii/scanners/ssn.d.ts +3 -0
  114. package/dist/esm/interceptors/pii/scanners/ssn.js +25 -0
  115. package/dist/esm/interceptors/reliability/fallback.d.ts +9 -0
  116. package/dist/esm/interceptors/reliability/fallback.js +50 -0
  117. package/dist/esm/interceptors/reliability/index.d.ts +7 -0
  118. package/dist/esm/interceptors/reliability/index.js +4 -0
  119. package/dist/esm/interceptors/reliability/retry.d.ts +13 -0
  120. package/dist/esm/interceptors/reliability/retry.js +66 -0
  121. package/dist/esm/interceptors/reliability/timeout.d.ts +9 -0
  122. package/dist/esm/interceptors/reliability/timeout.js +37 -0
  123. package/dist/esm/package.json +3 -0
  124. package/dist/esm/pricing.d.ts +19 -0
  125. package/dist/esm/pricing.js +65 -0
  126. package/dist/esm/providers/anthropic.d.ts +30 -0
  127. package/dist/esm/providers/anthropic.js +77 -0
  128. package/dist/esm/providers/base.d.ts +23 -0
  129. package/dist/esm/providers/base.js +28 -0
  130. package/dist/esm/providers/http.d.ts +8 -0
  131. package/dist/esm/providers/http.js +39 -0
  132. package/dist/esm/providers/index.d.ts +15 -0
  133. package/dist/esm/providers/index.js +25 -0
  134. package/dist/esm/providers/mock.d.ts +31 -0
  135. package/dist/esm/providers/mock.js +51 -0
  136. package/dist/esm/providers/openai.d.ts +26 -0
  137. package/dist/esm/providers/openai.js +60 -0
  138. package/dist/esm/request.d.ts +36 -0
  139. package/dist/esm/request.js +56 -0
  140. package/dist/esm/response.d.ts +38 -0
  141. package/dist/esm/response.js +51 -0
  142. package/dist/esm/testing/harness.d.ts +37 -0
  143. package/dist/esm/testing/harness.js +66 -0
  144. package/dist/esm/testing/index.d.ts +5 -0
  145. package/dist/esm/testing/index.js +3 -0
  146. package/dist/esm/types.d.ts +58 -0
  147. package/dist/esm/types.js +56 -0
  148. package/package.json +115 -0
  149. package/src/context.ts +57 -0
  150. package/src/errors.ts +47 -0
  151. package/src/gateway.ts +174 -0
  152. package/src/ids.ts +69 -0
  153. package/src/index.ts +52 -0
  154. package/src/interceptors/audit/index.ts +7 -0
  155. package/src/interceptors/audit/interceptor.ts +93 -0
  156. package/src/interceptors/audit/record.ts +138 -0
  157. package/src/interceptors/audit/sink.ts +10 -0
  158. package/src/interceptors/audit/sinks/index.ts +2 -0
  159. package/src/interceptors/audit/sinks/stdout.ts +42 -0
  160. package/src/interceptors/base.ts +58 -0
  161. package/src/interceptors/cache/backend.ts +15 -0
  162. package/src/interceptors/cache/backends/index.ts +2 -0
  163. package/src/interceptors/cache/backends/memory.ts +68 -0
  164. package/src/interceptors/cache/index.ts +8 -0
  165. package/src/interceptors/chain.ts +65 -0
  166. package/src/interceptors/index.ts +9 -0
  167. package/src/interceptors/pii/context.ts +24 -0
  168. package/src/interceptors/pii/guard.ts +201 -0
  169. package/src/interceptors/pii/index.ts +21 -0
  170. package/src/interceptors/pii/match.ts +43 -0
  171. package/src/interceptors/pii/scanner.ts +54 -0
  172. package/src/interceptors/pii/scanners/bsn.ts +44 -0
  173. package/src/interceptors/pii/scanners/credit-card.ts +52 -0
  174. package/src/interceptors/pii/scanners/email.ts +31 -0
  175. package/src/interceptors/pii/scanners/iban.ts +60 -0
  176. package/src/interceptors/pii/scanners/index.ts +35 -0
  177. package/src/interceptors/pii/scanners/ip-address.ts +41 -0
  178. package/src/interceptors/pii/scanners/phone.ts +46 -0
  179. package/src/interceptors/pii/scanners/secret.ts +51 -0
  180. package/src/interceptors/pii/scanners/ssn.ts +33 -0
  181. package/src/interceptors/reliability/fallback.ts +66 -0
  182. package/src/interceptors/reliability/index.ts +8 -0
  183. package/src/interceptors/reliability/retry.ts +97 -0
  184. package/src/interceptors/reliability/timeout.ts +53 -0
  185. package/src/pricing.ts +72 -0
  186. package/src/providers/anthropic.ts +113 -0
  187. package/src/providers/base.ts +52 -0
  188. package/src/providers/http.ts +50 -0
  189. package/src/providers/index.ts +39 -0
  190. package/src/providers/mock.ts +73 -0
  191. package/src/providers/openai.ts +94 -0
  192. package/src/request.ts +76 -0
  193. package/src/response.ts +73 -0
  194. package/src/testing/harness.ts +98 -0
  195. package/src/testing/index.ts +6 -0
  196. package/src/types.ts +83 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /** mockProvider — deterministic, offline provider for dev mode and tests. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.mockProvider = mockProvider;
5
+ const pricing_js_1 = require("../pricing.js");
6
+ const types_js_1 = require("../types.js");
7
+ const base_js_1 = require("./base.js");
8
+ /**
9
+ * Returns a canned response without any network call.
10
+ *
11
+ * If `response` is null/undefined, it echoes the last user message so the
12
+ * pipeline (including PII restore) is observable end to end.
13
+ */
14
+ class MockProvider extends base_js_1.BaseProviderAdapter {
15
+ response;
16
+ modelVersion;
17
+ constructor(options = {}) {
18
+ super(options.pricing);
19
+ this.response = options.response ?? null;
20
+ this.modelVersion = options.modelVersion ?? 'mock-1';
21
+ }
22
+ get providerName() {
23
+ return 'mock';
24
+ }
25
+ get reportedModelVersion() {
26
+ return this.modelVersion;
27
+ }
28
+ contentFor(request) {
29
+ if (this.response !== null)
30
+ return this.response;
31
+ const lastUser = [...request.messages]
32
+ .reverse()
33
+ .find((m) => m.role === 'user');
34
+ return `[mock reply] ${lastUser?.content ?? ''}`;
35
+ }
36
+ async complete(request) {
37
+ const started = performance.now();
38
+ const content = this.contentFor(request);
39
+ const usage = new types_js_1.TokenUsage((0, pricing_js_1.estimateTokens)(request.promptText()), (0, pricing_js_1.estimateTokens)(content));
40
+ return this.buildResponse(request, content, usage, this.modelVersion, started);
41
+ }
42
+ async *stream(request) {
43
+ for (const token of this.contentFor(request).split(' ')) {
44
+ yield token + ' ';
45
+ }
46
+ }
47
+ async healthCheck() {
48
+ return true;
49
+ }
50
+ }
51
+ /** Factory: build a mock provider adapter. */
52
+ function mockProvider(options = {}) {
53
+ return new MockProvider(options);
54
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ /** openaiAdapter — Chat Completions API (GPT-4o, o1, ...). */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.openaiAdapter = openaiAdapter;
5
+ const errors_js_1 = require("../errors.js");
6
+ const types_js_1 = require("../types.js");
7
+ const base_js_1 = require("./base.js");
8
+ const http_js_1 = require("./http.js");
9
+ const DEFAULT_BASE_URL = 'https://api.openai.com/v1';
10
+ class OpenAIAdapter extends base_js_1.BaseProviderAdapter {
11
+ apiKey;
12
+ baseUrl;
13
+ timeoutSeconds;
14
+ organization;
15
+ constructor(options = {}) {
16
+ super(options.pricing);
17
+ this.apiKey = options.apiKey ?? process.env['OPENAI_API_KEY'];
18
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
19
+ this.timeoutSeconds = (options.timeoutMs ?? 30_000) / 1000;
20
+ this.organization = options.organization;
21
+ }
22
+ get providerName() {
23
+ return 'openai';
24
+ }
25
+ headers() {
26
+ if (!this.apiKey) {
27
+ throw new errors_js_1.ConfigurationError('OPENAI_API_KEY not set (pass apiKey or set the env var)');
28
+ }
29
+ const headers = { Authorization: `Bearer ${this.apiKey}` };
30
+ if (this.organization)
31
+ headers['OpenAI-Organization'] = this.organization;
32
+ return headers;
33
+ }
34
+ async complete(request) {
35
+ const started = performance.now();
36
+ const payload = {
37
+ model: request.model,
38
+ messages: request.messages,
39
+ temperature: request.temperature,
40
+ max_tokens: request.maxTokens,
41
+ };
42
+ const data = await (0, http_js_1.postJson)(`${this.baseUrl}/chat/completions`, payload, this.headers(), this.timeoutSeconds);
43
+ const choices = data['choices'] ?? [];
44
+ const message = choices[0]?.['message'] ?? {};
45
+ const content = message['content'] ?? '';
46
+ const usageData = data['usage'] ?? {};
47
+ const usage = new types_js_1.TokenUsage(usageData['prompt_tokens'] ?? 0, usageData['completion_tokens'] ?? 0);
48
+ return this.buildResponse(request, content, usage, data['model'] ?? request.model, started);
49
+ }
50
+ async healthCheck() {
51
+ try {
52
+ this.headers();
53
+ return true;
54
+ }
55
+ catch {
56
+ return false;
57
+ }
58
+ }
59
+ }
60
+ /** Factory: build an OpenAI provider adapter. */
61
+ function openaiAdapter(options = {}) {
62
+ return new OpenAIAdapter(options);
63
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ /** GavioRequest — the canonical, provider-agnostic request model. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.GavioRequest = void 0;
5
+ const ids_js_1 = require("./ids.js");
6
+ const types_js_1 = require("./types.js");
7
+ /**
8
+ * A single gateway call. A `traceId` (UUID v7, time-sortable) is assigned
9
+ * automatically if not supplied. `parentTraceId` links calls into a
10
+ * multi-agent DAG.
11
+ */
12
+ class GavioRequest {
13
+ messages;
14
+ model;
15
+ provider;
16
+ traceId;
17
+ agentId;
18
+ parentTraceId;
19
+ sessionId;
20
+ options;
21
+ metadata;
22
+ constructor(init) {
23
+ this.messages = init.messages;
24
+ this.model = init.model;
25
+ this.provider = (0, types_js_1.coerceProvider)(init.provider);
26
+ this.traceId = init.traceId ?? (0, ids_js_1.newTraceId)();
27
+ this.agentId = init.agentId ?? null;
28
+ this.parentTraceId = init.parentTraceId ?? null;
29
+ this.sessionId = init.sessionId ?? null;
30
+ this.options = init.options ?? {};
31
+ this.metadata = init.metadata ?? {};
32
+ }
33
+ get temperature() {
34
+ const t = this.options['temperature'];
35
+ return typeof t === 'number' ? t : 0.7;
36
+ }
37
+ get maxTokens() {
38
+ const m = this.options['maxTokens'] ?? this.options['max_tokens'];
39
+ return typeof m === 'number' ? m : 1024;
40
+ }
41
+ /** Concatenate message contents — used for hashing and token estimation. */
42
+ promptText() {
43
+ return this.messages.map((m) => m.content ?? '').join('\n');
44
+ }
45
+ /** Return a shallow copy with replaced messages (interceptors mutate via this). */
46
+ copyWithMessages(messages) {
47
+ return new GavioRequest({
48
+ messages,
49
+ model: this.model,
50
+ provider: this.provider,
51
+ traceId: this.traceId,
52
+ agentId: this.agentId,
53
+ parentTraceId: this.parentTraceId,
54
+ sessionId: this.sessionId,
55
+ options: { ...this.options },
56
+ metadata: { ...this.metadata },
57
+ });
58
+ }
59
+ }
60
+ exports.GavioRequest = GavioRequest;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ /** GavioResponse — the canonical response returned to the caller. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.GavioResponse = void 0;
5
+ const types_js_1 = require("./types.js");
6
+ /** Result of a gateway call, enriched by the post-interceptor pipeline. */
7
+ class GavioResponse {
8
+ traceId;
9
+ content;
10
+ model;
11
+ provider;
12
+ modelVersion;
13
+ usage;
14
+ costUsd;
15
+ latencyMs;
16
+ cacheHit;
17
+ cacheType;
18
+ interceptorsFired;
19
+ audit;
20
+ metadata;
21
+ constructor(init) {
22
+ this.traceId = init.traceId;
23
+ this.content = init.content;
24
+ this.model = init.model;
25
+ this.provider = init.provider;
26
+ this.modelVersion = init.modelVersion ?? '';
27
+ this.usage = init.usage ?? new types_js_1.TokenUsage();
28
+ this.costUsd = init.costUsd ?? 0.0;
29
+ this.latencyMs = init.latencyMs ?? 0;
30
+ this.cacheHit = init.cacheHit ?? false;
31
+ this.cacheType = init.cacheType ?? null;
32
+ this.interceptorsFired = init.interceptorsFired ?? [];
33
+ this.audit = init.audit ?? null;
34
+ this.metadata = init.metadata ?? {};
35
+ }
36
+ /** Return a copy with replaced content (used by PII restore, guardrails). */
37
+ copyWithContent(content) {
38
+ return new GavioResponse({
39
+ traceId: this.traceId,
40
+ content,
41
+ model: this.model,
42
+ provider: this.provider,
43
+ modelVersion: this.modelVersion,
44
+ usage: this.usage,
45
+ costUsd: this.costUsd,
46
+ latencyMs: this.latencyMs,
47
+ cacheHit: this.cacheHit,
48
+ cacheType: this.cacheType,
49
+ interceptorsFired: [...this.interceptorsFired],
50
+ audit: this.audit,
51
+ metadata: { ...this.metadata },
52
+ });
53
+ }
54
+ }
55
+ exports.GavioResponse = GavioResponse;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * GavioTestKit — run interceptor chains in isolation for unit tests.
4
+ *
5
+ * This v0.1.0 kit drives a chain against a {@link mockProvider} and lets you
6
+ * assert on PII detection, the redacted request, and the resulting audit record.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.GavioTestKit = void 0;
10
+ const context_js_1 = require("../context.js");
11
+ const base_js_1 = require("../interceptors/base.js");
12
+ const chain_js_1 = require("../interceptors/chain.js");
13
+ const mock_js_1 = require("../providers/mock.js");
14
+ const request_js_1 = require("../request.js");
15
+ const types_js_1 = require("../types.js");
16
+ /** Records the request as it reaches the provider (post-redaction). */
17
+ class CaptureInterceptor {
18
+ name = '_capture';
19
+ captured = null;
20
+ before(request) {
21
+ this.captured = request;
22
+ return request;
23
+ }
24
+ }
25
+ class GavioTestKit {
26
+ interceptors;
27
+ provider;
28
+ model;
29
+ constructor(options = {}) {
30
+ this.interceptors = [...(options.interceptors ?? [])];
31
+ this.provider = options.provider ?? (0, mock_js_1.mockProvider)();
32
+ this.model = options.model ?? 'mock';
33
+ }
34
+ async run(input) {
35
+ const request = new request_js_1.GavioRequest({
36
+ messages: input.messages,
37
+ model: this.model,
38
+ provider: (0, types_js_1.coerceProvider)(this.provider.providerName),
39
+ options: input.options ?? {},
40
+ });
41
+ const ctx = new context_js_1.InterceptorContext({ traceId: request.traceId });
42
+ const capture = new CaptureInterceptor();
43
+ const all = [...this.interceptors, capture];
44
+ const policies = all.filter(base_js_1.isExecutorPolicy);
45
+ const regular = all.filter((i) => !(0, base_js_1.isExecutorPolicy)(i));
46
+ const chain = new chain_js_1.InterceptorChain(regular);
47
+ let executor = (req) => this.provider.complete(req);
48
+ for (let i = policies.length - 1; i >= 0; i--) {
49
+ executor = wrap(policies[i], executor, ctx);
50
+ }
51
+ const response = await chain.execute(request, ctx, executor);
52
+ return {
53
+ response,
54
+ ctx,
55
+ preRequestText: () => capture.captured?.promptText() ?? '',
56
+ piiDetected: (entityType) => {
57
+ if (entityType === undefined)
58
+ return ctx.piiEntityTypes.length > 0;
59
+ return ctx.piiEntityTypes.includes(entityType);
60
+ },
61
+ get auditRecord() {
62
+ return response.audit;
63
+ },
64
+ };
65
+ }
66
+ }
67
+ exports.GavioTestKit = GavioTestKit;
68
+ function wrap(policy, inner, ctx) {
69
+ return (req) => policy.around(req, ctx, inner);
70
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /** Gavio test utilities. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.mockProvider = exports.GavioTestKit = void 0;
5
+ var harness_js_1 = require("./harness.js");
6
+ Object.defineProperty(exports, "GavioTestKit", { enumerable: true, get: function () { return harness_js_1.GavioTestKit; } });
7
+ var mock_js_1 = require("../providers/mock.js");
8
+ Object.defineProperty(exports, "mockProvider", { enumerable: true, get: function () { return mock_js_1.mockProvider; } });
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /** Shared enums (as string unions / const objects) and utility types. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.TokenUsage = exports.GuardrailOutcome = exports.Sensitivity = exports.PiiMode = exports.CacheType = exports.Provider = void 0;
5
+ exports.coerceProvider = coerceProvider;
6
+ /** Supported LLM providers. String-valued for easy config + logging. */
7
+ exports.Provider = {
8
+ OPENAI: 'openai',
9
+ ANTHROPIC: 'anthropic',
10
+ GEMINI: 'gemini',
11
+ AZURE_OPENAI: 'azure_openai',
12
+ OLLAMA: 'ollama',
13
+ BEDROCK: 'bedrock',
14
+ COHERE: 'cohere',
15
+ MOCK: 'mock',
16
+ };
17
+ /** Accept either a known provider value or any string and normalise to lowercase. */
18
+ function coerceProvider(value) {
19
+ return value.toLowerCase();
20
+ }
21
+ exports.CacheType = {
22
+ EXACT: 'exact',
23
+ SEMANTIC: 'semantic',
24
+ };
25
+ /** What PiiGuard does with a detected entity. */
26
+ exports.PiiMode = {
27
+ REDACT: 'redact', // replace with a typed placeholder token
28
+ MASK: 'mask', // replace characters with asterisks
29
+ TAG: 'tag', // annotate inline but keep the value
30
+ BLOCK: 'block', // raise and refuse the request
31
+ };
32
+ exports.Sensitivity = {
33
+ STRICT: 'strict',
34
+ BALANCED: 'balanced',
35
+ PERMISSIVE: 'permissive',
36
+ };
37
+ exports.GuardrailOutcome = {
38
+ PASS: 'PASS',
39
+ FAIL: 'FAIL',
40
+ HITL: 'HITL',
41
+ };
42
+ /** Token accounting for a single completion. */
43
+ class TokenUsage {
44
+ promptTokens;
45
+ completionTokens;
46
+ constructor(promptTokens = 0, completionTokens = 0) {
47
+ this.promptTokens = promptTokens;
48
+ this.completionTokens = completionTokens;
49
+ }
50
+ get totalTokens() {
51
+ return this.promptTokens + this.completionTokens;
52
+ }
53
+ toJSON() {
54
+ return {
55
+ promptTokens: this.promptTokens,
56
+ completionTokens: this.completionTokens,
57
+ totalTokens: this.totalTokens,
58
+ };
59
+ }
60
+ }
61
+ exports.TokenUsage = TokenUsage;
@@ -0,0 +1,33 @@
1
+ /** Per-request context passed through the interceptor pipeline. */
2
+ export interface InterceptorContextInit {
3
+ traceId: string;
4
+ agentId?: string | null;
5
+ parentTraceId?: string | null;
6
+ sessionId?: string | null;
7
+ dryRun?: boolean;
8
+ }
9
+ /**
10
+ * Mutable scratch space shared by all interceptors within one request. One
11
+ * instance per request — never shared across requests. Interceptors stash
12
+ * signals here (PII findings, cache decisions, risk scores) for the audit
13
+ * interceptor to collect at the end of the chain.
14
+ */
15
+ export declare class InterceptorContext {
16
+ traceId: string;
17
+ agentId: string | null;
18
+ parentTraceId: string | null;
19
+ sessionId: string | null;
20
+ dryRun: boolean;
21
+ interceptorsFired: string[];
22
+ piiEntityTypes: string[];
23
+ piiEntityCounts: Record<string, number>;
24
+ cacheHit: boolean;
25
+ cacheType: string | null;
26
+ riskScore: number | null;
27
+ guardrailOutcome: string | null;
28
+ /** Arbitrary inter-interceptor state (e.g. PII replacement map for restore). */
29
+ state: Record<string, unknown>;
30
+ constructor(init: InterceptorContextInit);
31
+ markFired(name: string): void;
32
+ recordPii(entityTypes: string[]): void;
33
+ }
@@ -0,0 +1,43 @@
1
+ /** Per-request context passed through the interceptor pipeline. */
2
+ /**
3
+ * Mutable scratch space shared by all interceptors within one request. One
4
+ * instance per request — never shared across requests. Interceptors stash
5
+ * signals here (PII findings, cache decisions, risk scores) for the audit
6
+ * interceptor to collect at the end of the chain.
7
+ */
8
+ export class InterceptorContext {
9
+ traceId;
10
+ agentId;
11
+ parentTraceId;
12
+ sessionId;
13
+ dryRun;
14
+ interceptorsFired = [];
15
+ piiEntityTypes = [];
16
+ piiEntityCounts = {};
17
+ cacheHit = false;
18
+ cacheType = null;
19
+ riskScore = null;
20
+ guardrailOutcome = null;
21
+ /** Arbitrary inter-interceptor state (e.g. PII replacement map for restore). */
22
+ state = {};
23
+ constructor(init) {
24
+ this.traceId = init.traceId;
25
+ this.agentId = init.agentId ?? null;
26
+ this.parentTraceId = init.parentTraceId ?? null;
27
+ this.sessionId = init.sessionId ?? null;
28
+ this.dryRun = init.dryRun ?? false;
29
+ }
30
+ markFired(name) {
31
+ if (!this.interceptorsFired.includes(name)) {
32
+ this.interceptorsFired.push(name);
33
+ }
34
+ }
35
+ recordPii(entityTypes) {
36
+ for (const et of entityTypes) {
37
+ this.piiEntityCounts[et] = (this.piiEntityCounts[et] ?? 0) + 1;
38
+ if (!this.piiEntityTypes.includes(et)) {
39
+ this.piiEntityTypes.push(et);
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Gavio error hierarchy. All Gavio errors derive from {@link GavioError} so
3
+ * callers can catch the whole family with a single check.
4
+ */
5
+ export declare class GavioError extends Error {
6
+ constructor(message?: string);
7
+ }
8
+ /** Raised when the gateway is misconfigured (e.g. no provider set). */
9
+ export declare class ConfigurationError extends GavioError {
10
+ }
11
+ /** Base class for provider-adapter failures. */
12
+ export declare class ProviderError extends GavioError {
13
+ }
14
+ /** The provider could not be reached (network / health-check failure). */
15
+ export declare class ProviderUnavailableError extends ProviderError {
16
+ }
17
+ /** The provider returned a rate-limit (HTTP 429) signal. */
18
+ export declare class RateLimitError extends ProviderError {
19
+ }
20
+ /** The provider returned a 5xx server error. */
21
+ export declare class ServerError extends ProviderError {
22
+ }
23
+ /** A request exceeded its configured timeout. */
24
+ export declare class TimeoutError extends ProviderError {
25
+ }
26
+ /** PiiGuard is in BLOCK mode and detected PII in the request. */
27
+ export declare class PiiBlockedError extends GavioError {
28
+ readonly entityTypes: string[];
29
+ constructor(entityTypes: string[]);
30
+ }
31
+ /** A hard budget cap was exceeded. Never swallow this — surface to user. */
32
+ export declare class BudgetExceededError extends GavioError {
33
+ }
34
+ /** Output failed a guardrail validator with onFailure='error'. */
35
+ export declare class GuardrailViolationError extends GavioError {
36
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Gavio error hierarchy. All Gavio errors derive from {@link GavioError} so
3
+ * callers can catch the whole family with a single check.
4
+ */
5
+ export class GavioError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = new.target.name;
9
+ Object.setPrototypeOf(this, new.target.prototype);
10
+ }
11
+ }
12
+ /** Raised when the gateway is misconfigured (e.g. no provider set). */
13
+ export class ConfigurationError extends GavioError {
14
+ }
15
+ /** Base class for provider-adapter failures. */
16
+ export class ProviderError extends GavioError {
17
+ }
18
+ /** The provider could not be reached (network / health-check failure). */
19
+ export class ProviderUnavailableError extends ProviderError {
20
+ }
21
+ /** The provider returned a rate-limit (HTTP 429) signal. */
22
+ export class RateLimitError extends ProviderError {
23
+ }
24
+ /** The provider returned a 5xx server error. */
25
+ export class ServerError extends ProviderError {
26
+ }
27
+ /** A request exceeded its configured timeout. */
28
+ export class TimeoutError extends ProviderError {
29
+ }
30
+ /** PiiGuard is in BLOCK mode and detected PII in the request. */
31
+ export class PiiBlockedError extends GavioError {
32
+ entityTypes;
33
+ constructor(entityTypes) {
34
+ const sorted = Array.from(new Set(entityTypes)).sort();
35
+ super(`Request blocked: PII detected (${sorted.join(', ')})`);
36
+ this.entityTypes = entityTypes;
37
+ }
38
+ }
39
+ /** A hard budget cap was exceeded. Never swallow this — surface to user. */
40
+ export class BudgetExceededError extends GavioError {
41
+ }
42
+ /** Output failed a guardrail validator with onFailure='error'. */
43
+ export class GuardrailViolationError extends GavioError {
44
+ }
@@ -0,0 +1,54 @@
1
+ /** Gateway — the entry point. Wires interceptors around a provider adapter. */
2
+ import type { Interceptor } from './interceptors/base.js';
3
+ import { PricingProvider } from './pricing.js';
4
+ import type { ProviderAdapter } from './providers/base.js';
5
+ import type { GavioResponse } from './response.js';
6
+ import { Provider } from './types.js';
7
+ import type { Message } from './types.js';
8
+ export interface GatewayOptions {
9
+ provider?: Provider | string;
10
+ model?: string;
11
+ adapter?: ProviderAdapter;
12
+ devMode?: boolean;
13
+ dryRun?: boolean;
14
+ pricing?: PricingProvider;
15
+ }
16
+ export interface CompleteOptions {
17
+ messages: Message[];
18
+ model?: string;
19
+ agentId?: string | null;
20
+ parentTraceId?: string | null;
21
+ sessionId?: string | null;
22
+ metadata?: Record<string, unknown>;
23
+ /** Provider sampling options (temperature, maxTokens, etc.). */
24
+ options?: Record<string, unknown>;
25
+ }
26
+ /**
27
+ * Routes a request through the interceptor pipeline to a provider.
28
+ *
29
+ * Construct with `new Gateway({ provider, model })` then chain `.use(...)` and
30
+ * `.withAdapter(...)`. A single instance is safe to reuse — per-request state
31
+ * lives in an {@link InterceptorContext} created fresh for every call.
32
+ */
33
+ export declare class Gateway {
34
+ private readonly providerHint;
35
+ private modelHint;
36
+ private adapterOverride;
37
+ private readonly devMode;
38
+ private readonly dryRunMode;
39
+ private readonly pricing;
40
+ private readonly interceptors;
41
+ constructor(options?: GatewayOptions);
42
+ /** Register an interceptor or executor policy. First-registered = outermost. */
43
+ use(interceptor: Interceptor): this;
44
+ /** Supply a provider adapter explicitly (overrides `provider`). */
45
+ withAdapter(adapter: ProviderAdapter): this;
46
+ get model(): string;
47
+ get providerName(): string;
48
+ complete(opts: CompleteOptions): Promise<GavioResponse>;
49
+ healthCheck(): Promise<boolean>;
50
+ private buildPipeline;
51
+ private wrapPolicy;
52
+ private resolveAdapter;
53
+ private resolveModel;
54
+ }