@proxitor/plugin-api 0.1.0-beta.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/README.md +41 -0
- package/dist/index.d.ts +277 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @proxitor/plugin-api
|
|
2
|
+
|
|
3
|
+
Published plugin contract for proxitor v1. Plugins transform a `CanonicalRequest`
|
|
4
|
+
(IR) and observe/transform a `CanonicalEvent` stream; they are blind to
|
|
5
|
+
providers, wire formats and transport (spec D9).
|
|
6
|
+
|
|
7
|
+
## Mutations channels (and only these)
|
|
8
|
+
|
|
9
|
+
1. The typed IR: `CanonicalRequest` (mutate and return from `onRequest`).
|
|
10
|
+
2. `req.outboundHeaders` — upstream request headers. Protected (ignored on
|
|
11
|
+
conflict): `authorization`, `x-api-key`, `host`, `content-length`, and all
|
|
12
|
+
`provider.headers`.
|
|
13
|
+
3. Format-reserved `$proxitor.` keys inside `req.extensions[format]`. Declare
|
|
14
|
+
them in `reservedKeys`; config-time validation matches the provider's
|
|
15
|
+
wireFormat. Reserved keys per format:
|
|
16
|
+
|
|
17
|
+
| format | reserved keys |
|
|
18
|
+
| ------------------- | ------------------------------------------------------------------------------- |
|
|
19
|
+
| `openai-chat` | `$proxitor.provider`, `$proxitor.models`, `$proxitor.route`, `$proxitor.transforms` |
|
|
20
|
+
| `anthropic-messages` | — (none in v1) |
|
|
21
|
+
|
|
22
|
+
## ShortCircuit
|
|
23
|
+
|
|
24
|
+
`{ shortCircuit: true, status, headers? }` plus **at most one** of `error`
|
|
25
|
+
(CanonicalError, encoded to the client's wire-error format) or `events`
|
|
26
|
+
(CanonicalEvent[], encoded to the client's inbound format — works for both
|
|
27
|
+
streaming and non-streaming clients). Raw-body mocks are not supported.
|
|
28
|
+
|
|
29
|
+
## definePlugin
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { definePlugin } from '@proxitor/plugin-api';
|
|
33
|
+
import { z } from 'zod';
|
|
34
|
+
|
|
35
|
+
export default definePlugin(z.object({ ttl: z.enum(['5m', '1h']) }), {
|
|
36
|
+
name: 'cache-control',
|
|
37
|
+
onRequest(ctx, req) { /* mutate req, return it */ return req; },
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
zod is a peer dependency (`^4`).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import { ZodType } from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/canonical/request.d.ts
|
|
4
|
+
/** Per-node passthrough for fields the IR does not model (spec §4.1, D17). */
|
|
5
|
+
type NodeExtensions = Record<string, unknown>;
|
|
6
|
+
/** Request-level passthrough bag keyed by source format (spec §4.3). */
|
|
7
|
+
type ExtensionsBag = Record<string, Record<string, unknown>>;
|
|
8
|
+
type CacheControl = {
|
|
9
|
+
type: 'ephemeral';
|
|
10
|
+
ttl?: '5m' | '1h';
|
|
11
|
+
};
|
|
12
|
+
type CanonicalSystemBlock = {
|
|
13
|
+
type: 'text';
|
|
14
|
+
text: string;
|
|
15
|
+
cacheControl?: CacheControl;
|
|
16
|
+
extensions?: NodeExtensions;
|
|
17
|
+
};
|
|
18
|
+
type ImageSource = {
|
|
19
|
+
kind: 'base64';
|
|
20
|
+
mediaType: string;
|
|
21
|
+
data: string;
|
|
22
|
+
} | {
|
|
23
|
+
kind: 'url';
|
|
24
|
+
url: string;
|
|
25
|
+
};
|
|
26
|
+
type ResponseFormat = {
|
|
27
|
+
kind: 'json';
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'json_schema';
|
|
30
|
+
schema: Record<string, unknown>;
|
|
31
|
+
};
|
|
32
|
+
type CanonicalContentBlock = {
|
|
33
|
+
type: 'text';
|
|
34
|
+
text: string;
|
|
35
|
+
cacheControl?: CacheControl;
|
|
36
|
+
extensions?: NodeExtensions;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'image';
|
|
39
|
+
source: ImageSource;
|
|
40
|
+
cacheControl?: CacheControl;
|
|
41
|
+
extensions?: NodeExtensions;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'tool_use';
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
input: unknown;
|
|
47
|
+
cacheControl?: CacheControl;
|
|
48
|
+
extensions?: NodeExtensions;
|
|
49
|
+
} | {
|
|
50
|
+
type: 'tool_result';
|
|
51
|
+
toolUseId: string;
|
|
52
|
+
content: CanonicalContentBlock[] | string;
|
|
53
|
+
isError?: boolean;
|
|
54
|
+
cacheControl?: CacheControl;
|
|
55
|
+
extensions?: NodeExtensions;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'thinking';
|
|
58
|
+
thinking: string;
|
|
59
|
+
signature?: string;
|
|
60
|
+
cacheControl?: CacheControl;
|
|
61
|
+
extensions?: NodeExtensions;
|
|
62
|
+
};
|
|
63
|
+
type CanonicalMessage = {
|
|
64
|
+
role: 'user' | 'assistant';
|
|
65
|
+
content: CanonicalContentBlock[];
|
|
66
|
+
extensions?: NodeExtensions;
|
|
67
|
+
};
|
|
68
|
+
type CanonicalTool = {
|
|
69
|
+
name: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
inputSchema: Record<string, unknown>;
|
|
72
|
+
cacheControl?: CacheControl;
|
|
73
|
+
};
|
|
74
|
+
type CanonicalToolChoice = {
|
|
75
|
+
mode: 'auto' | 'any' | 'none';
|
|
76
|
+
} | {
|
|
77
|
+
mode: 'tool';
|
|
78
|
+
name: string;
|
|
79
|
+
};
|
|
80
|
+
/** Provenance-preserving max tokens (r2 P0-1): same-format encode re-emits the source field name. */
|
|
81
|
+
type MaxTokens = {
|
|
82
|
+
value: number;
|
|
83
|
+
source: 'max_tokens' | 'max_completion_tokens' | 'max_output_tokens';
|
|
84
|
+
};
|
|
85
|
+
type CanonicalParams = {
|
|
86
|
+
temperature?: number;
|
|
87
|
+
maxTokens?: MaxTokens;
|
|
88
|
+
topP?: number;
|
|
89
|
+
topK?: number;
|
|
90
|
+
stop?: string[];
|
|
91
|
+
seed?: number;
|
|
92
|
+
n?: number;
|
|
93
|
+
responseFormat?: ResponseFormat;
|
|
94
|
+
presencePenalty?: number;
|
|
95
|
+
frequencyPenalty?: number;
|
|
96
|
+
};
|
|
97
|
+
type CanonicalRequest = {
|
|
98
|
+
model: {
|
|
99
|
+
logical: string;
|
|
100
|
+
physical: string;
|
|
101
|
+
};
|
|
102
|
+
system: CanonicalSystemBlock[];
|
|
103
|
+
messages: CanonicalMessage[];
|
|
104
|
+
tools?: CanonicalTool[];
|
|
105
|
+
toolChoice?: CanonicalToolChoice;
|
|
106
|
+
params: CanonicalParams;
|
|
107
|
+
stream: boolean;
|
|
108
|
+
extensions: ExtensionsBag; /** Plugin → upstream header channel (D18); auth + provider.headers are protected. */
|
|
109
|
+
outboundHeaders?: Record<string, string>; /** Inbound client session hint, stamped by the pipeline from client headers; plugins may honor it instead of deriving their own id. */
|
|
110
|
+
clientSessionId?: string;
|
|
111
|
+
};
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/canonical/events.d.ts
|
|
114
|
+
type StopReason = 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use';
|
|
115
|
+
type Usage = {
|
|
116
|
+
inputTokens: number;
|
|
117
|
+
outputTokens: number;
|
|
118
|
+
cacheReadTokens?: number;
|
|
119
|
+
cacheCreateTokens?: number;
|
|
120
|
+
};
|
|
121
|
+
type PartialUsage = Partial<Usage>;
|
|
122
|
+
type TextDelta = {
|
|
123
|
+
type: 'text';
|
|
124
|
+
text: string;
|
|
125
|
+
};
|
|
126
|
+
type InputJsonDelta = {
|
|
127
|
+
type: 'input_json';
|
|
128
|
+
partialJson: string;
|
|
129
|
+
};
|
|
130
|
+
type ThinkingDelta = {
|
|
131
|
+
type: 'thinking';
|
|
132
|
+
thinking: string;
|
|
133
|
+
};
|
|
134
|
+
type CanonicalError = {
|
|
135
|
+
type: string;
|
|
136
|
+
message: string;
|
|
137
|
+
status: number;
|
|
138
|
+
providerError?: unknown;
|
|
139
|
+
};
|
|
140
|
+
type CanonicalEvent = {
|
|
141
|
+
type: 'message_start';
|
|
142
|
+
id: string;
|
|
143
|
+
model: string;
|
|
144
|
+
} | {
|
|
145
|
+
type: 'content_block_start';
|
|
146
|
+
index: number;
|
|
147
|
+
block: {
|
|
148
|
+
type: 'text' | 'tool_use' | 'thinking';
|
|
149
|
+
id?: string;
|
|
150
|
+
name?: string;
|
|
151
|
+
};
|
|
152
|
+
} | {
|
|
153
|
+
type: 'content_block_delta';
|
|
154
|
+
index: number;
|
|
155
|
+
delta: TextDelta | InputJsonDelta | ThinkingDelta;
|
|
156
|
+
} | {
|
|
157
|
+
type: 'signature_delta';
|
|
158
|
+
index: number;
|
|
159
|
+
signature: string;
|
|
160
|
+
} | {
|
|
161
|
+
type: 'content_block_stop';
|
|
162
|
+
index: number;
|
|
163
|
+
} | {
|
|
164
|
+
type: 'message_delta';
|
|
165
|
+
stopReason?: StopReason;
|
|
166
|
+
stopSequence?: string | null;
|
|
167
|
+
usage?: PartialUsage; /** Raw wire provenance the IR cannot express, e.g. openai `finish_reason` (spec §4.2). */
|
|
168
|
+
extensions?: NodeExtensions;
|
|
169
|
+
} | {
|
|
170
|
+
type: 'message_stop';
|
|
171
|
+
} | {
|
|
172
|
+
type: 'ping';
|
|
173
|
+
} | {
|
|
174
|
+
type: 'usage';
|
|
175
|
+
usage: Usage;
|
|
176
|
+
} | {
|
|
177
|
+
type: 'error';
|
|
178
|
+
error: CanonicalError;
|
|
179
|
+
};
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/ports.d.ts
|
|
182
|
+
type LoggerPort = {
|
|
183
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
184
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
185
|
+
error(message: string, context?: Record<string, unknown>): void;
|
|
186
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
187
|
+
};
|
|
188
|
+
type ClockPort = {
|
|
189
|
+
now(): number;
|
|
190
|
+
};
|
|
191
|
+
type RandomPort = {
|
|
192
|
+
uuid(): string;
|
|
193
|
+
};
|
|
194
|
+
//#endregion
|
|
195
|
+
//#region src/wire-format.d.ts
|
|
196
|
+
declare const WIRE_FORMATS: readonly ["anthropic-messages", "openai-chat"];
|
|
197
|
+
type WireFormat = (typeof WIRE_FORMATS)[number];
|
|
198
|
+
/**
|
|
199
|
+
* Format-reserved extension keys (spec §4.3): the only keys a plugin may write
|
|
200
|
+
* into `ir.extensions[format]`. Public contract — keep in sync with README.
|
|
201
|
+
*/
|
|
202
|
+
declare const RESERVED_KEYS: Readonly<Record<WireFormat, readonly string[]>>;
|
|
203
|
+
/**
|
|
204
|
+
* Endpoint path each wire format owns (spec §5.1): the format adapter owns the
|
|
205
|
+
* version path; a provider `baseUrl` is everything before it. Consumed by
|
|
206
|
+
* domain routing for baseUrl validation and upstream URL construction.
|
|
207
|
+
*/
|
|
208
|
+
declare const ENDPOINT_PATHS: Readonly<Record<WireFormat, string>>;
|
|
209
|
+
/**
|
|
210
|
+
* Inbound proxy-owned paths (spec §5.2): `/v1/models` is synthesized locally
|
|
211
|
+
* from the routing table; `/v1/responses` (openai-responses format) is
|
|
212
|
+
* deferred — classified to a 501 (§17), never a passthrough.
|
|
213
|
+
*/
|
|
214
|
+
declare const MODELS_PATH = "/v1/models";
|
|
215
|
+
declare const DEFERRED_RESPONSES_PATH = "/v1/responses";
|
|
216
|
+
/**
|
|
217
|
+
* Session headers (spec §10a): the pipeline stamps the first present value onto
|
|
218
|
+
* `CanonicalRequest.clientSessionId`; the session-id plugin forwards it upstream.
|
|
219
|
+
*/
|
|
220
|
+
declare const CLIENT_SESSION_ID_HEADER = "x-claude-code-session-id";
|
|
221
|
+
declare const SESSION_ID_HEADER = "x-session-id";
|
|
222
|
+
//#endregion
|
|
223
|
+
//#region src/plugin.d.ts
|
|
224
|
+
/**
|
|
225
|
+
* Plugin-initiated response without hitting upstream (spec §7).
|
|
226
|
+
* `error` XOR `events`: error is encoded to the client's wire-error format,
|
|
227
|
+
* events are encoded to the client's inbound format (format-agnostic mock).
|
|
228
|
+
* Raw-body mocks are intentionally NOT supported (D9).
|
|
229
|
+
*/
|
|
230
|
+
type ShortCircuit = {
|
|
231
|
+
shortCircuit: true;
|
|
232
|
+
status: number;
|
|
233
|
+
headers?: Record<string, string>;
|
|
234
|
+
error?: CanonicalError;
|
|
235
|
+
events?: CanonicalEvent[];
|
|
236
|
+
} & ({
|
|
237
|
+
error: CanonicalError;
|
|
238
|
+
events?: never;
|
|
239
|
+
} | {
|
|
240
|
+
events?: CanonicalEvent[];
|
|
241
|
+
error?: never;
|
|
242
|
+
});
|
|
243
|
+
type PluginContext<TConfig = unknown> = {
|
|
244
|
+
requestId: string;
|
|
245
|
+
logger: LoggerPort;
|
|
246
|
+
clock: ClockPort;
|
|
247
|
+
random: RandomPort;
|
|
248
|
+
config: TConfig;
|
|
249
|
+
};
|
|
250
|
+
type ProxyPlugin<TConfig = unknown> = {
|
|
251
|
+
/** Unique instance id: dedup across config layers. */name: string;
|
|
252
|
+
validateConfig?(raw: unknown): TConfig;
|
|
253
|
+
/**
|
|
254
|
+
* Declares which format-reserved `$proxitor.` keys this plugin writes (spec §4.3).
|
|
255
|
+
* Config-time validation matches these against the provider's wireFormat.
|
|
256
|
+
*/
|
|
257
|
+
reservedKeys?: Partial<Record<WireFormat, readonly string[]>>;
|
|
258
|
+
onRequest?(ctx: PluginContext<TConfig>, req: CanonicalRequest): Promise<CanonicalRequest | ShortCircuit> | CanonicalRequest | ShortCircuit;
|
|
259
|
+
onEvent?(ctx: PluginContext<TConfig>, event: CanonicalEvent): Promise<void> | void;
|
|
260
|
+
transformStream?(ctx: PluginContext<TConfig>, events: AsyncIterable<CanonicalEvent>): AsyncIterable<CanonicalEvent>;
|
|
261
|
+
onError?(ctx: PluginContext<TConfig>, error: CanonicalError): Promise<CanonicalError> | CanonicalError;
|
|
262
|
+
};
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region src/define-plugin.d.ts
|
|
265
|
+
type PluginWithoutValidate<TConfig> = Omit<ProxyPlugin<TConfig>, 'validateConfig'>;
|
|
266
|
+
/**
|
|
267
|
+
* The only runtime helper in the package: attaches a zod-backed validateConfig
|
|
268
|
+
* to a plugin (spec §7). Overload without a schema passes the plugin through.
|
|
269
|
+
*/
|
|
270
|
+
declare function definePlugin<TConfig>(plugin: ProxyPlugin<TConfig>): ProxyPlugin<TConfig>;
|
|
271
|
+
declare function definePlugin<TConfig>(schema: ZodType<TConfig>, plugin: PluginWithoutValidate<TConfig>): ProxyPlugin<TConfig>;
|
|
272
|
+
//#endregion
|
|
273
|
+
//#region src/index.d.ts
|
|
274
|
+
declare const PLUGIN_API_VERSION = "0.0.0";
|
|
275
|
+
//#endregion
|
|
276
|
+
export { CLIENT_SESSION_ID_HEADER, CacheControl, CanonicalContentBlock, CanonicalError, CanonicalEvent, CanonicalMessage, CanonicalParams, CanonicalRequest, CanonicalSystemBlock, CanonicalTool, CanonicalToolChoice, ClockPort, DEFERRED_RESPONSES_PATH, ENDPOINT_PATHS, ExtensionsBag, ImageSource, InputJsonDelta, LoggerPort, MODELS_PATH, MaxTokens, NodeExtensions, PLUGIN_API_VERSION, PartialUsage, PluginContext, ProxyPlugin, RESERVED_KEYS, RandomPort, ResponseFormat, SESSION_ID_HEADER, ShortCircuit, StopReason, TextDelta, ThinkingDelta, Usage, WIRE_FORMATS, WireFormat, definePlugin };
|
|
277
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/canonical/request.ts","../src/canonical/events.ts","../src/ports.ts","../src/wire-format.ts","../src/plugin.ts","../src/define-plugin.ts","../src/index.ts"],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//#region src/define-plugin.ts
|
|
2
|
+
function definePlugin(schemaOrPlugin, maybePlugin) {
|
|
3
|
+
if (maybePlugin === void 0) return schemaOrPlugin;
|
|
4
|
+
const schema = schemaOrPlugin;
|
|
5
|
+
return {
|
|
6
|
+
...maybePlugin,
|
|
7
|
+
validateConfig: (raw) => schema.parse(raw)
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/wire-format.ts
|
|
12
|
+
const WIRE_FORMATS = ["anthropic-messages", "openai-chat"];
|
|
13
|
+
/**
|
|
14
|
+
* Format-reserved extension keys (spec §4.3): the only keys a plugin may write
|
|
15
|
+
* into `ir.extensions[format]`. Public contract — keep in sync with README.
|
|
16
|
+
*/
|
|
17
|
+
const RESERVED_KEYS = {
|
|
18
|
+
"anthropic-messages": [],
|
|
19
|
+
"openai-chat": [
|
|
20
|
+
"$proxitor.provider",
|
|
21
|
+
"$proxitor.models",
|
|
22
|
+
"$proxitor.route",
|
|
23
|
+
"$proxitor.transforms"
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Endpoint path each wire format owns (spec §5.1): the format adapter owns the
|
|
28
|
+
* version path; a provider `baseUrl` is everything before it. Consumed by
|
|
29
|
+
* domain routing for baseUrl validation and upstream URL construction.
|
|
30
|
+
*/
|
|
31
|
+
const ENDPOINT_PATHS = {
|
|
32
|
+
"anthropic-messages": "/v1/messages",
|
|
33
|
+
"openai-chat": "/v1/chat/completions"
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Inbound proxy-owned paths (spec §5.2): `/v1/models` is synthesized locally
|
|
37
|
+
* from the routing table; `/v1/responses` (openai-responses format) is
|
|
38
|
+
* deferred — classified to a 501 (§17), never a passthrough.
|
|
39
|
+
*/
|
|
40
|
+
const MODELS_PATH = "/v1/models";
|
|
41
|
+
const DEFERRED_RESPONSES_PATH = "/v1/responses";
|
|
42
|
+
/**
|
|
43
|
+
* Session headers (spec §10a): the pipeline stamps the first present value onto
|
|
44
|
+
* `CanonicalRequest.clientSessionId`; the session-id plugin forwards it upstream.
|
|
45
|
+
*/
|
|
46
|
+
const CLIENT_SESSION_ID_HEADER = "x-claude-code-session-id";
|
|
47
|
+
const SESSION_ID_HEADER = "x-session-id";
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/index.ts
|
|
50
|
+
const PLUGIN_API_VERSION = "0.0.0";
|
|
51
|
+
//#endregion
|
|
52
|
+
export { CLIENT_SESSION_ID_HEADER, DEFERRED_RESPONSES_PATH, ENDPOINT_PATHS, MODELS_PATH, PLUGIN_API_VERSION, RESERVED_KEYS, SESSION_ID_HEADER, WIRE_FORMATS, definePlugin };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/define-plugin.ts","../src/wire-format.ts","../src/index.ts"],"sourcesContent":["import type { ZodType } from 'zod';\nimport type { ProxyPlugin } from './plugin.js';\n\ntype PluginWithoutValidate<TConfig> = Omit<ProxyPlugin<TConfig>, 'validateConfig'>;\n\n/**\n * The only runtime helper in the package: attaches a zod-backed validateConfig\n * to a plugin (spec §7). Overload without a schema passes the plugin through.\n */\nexport function definePlugin<TConfig>(plugin: ProxyPlugin<TConfig>): ProxyPlugin<TConfig>;\nexport function definePlugin<TConfig>(\n schema: ZodType<TConfig>,\n plugin: PluginWithoutValidate<TConfig>,\n): ProxyPlugin<TConfig>;\nexport function definePlugin<TConfig>(\n schemaOrPlugin: ZodType<TConfig> | ProxyPlugin<TConfig>,\n maybePlugin?: PluginWithoutValidate<TConfig>,\n): ProxyPlugin<TConfig> {\n if (maybePlugin === undefined) {\n return schemaOrPlugin as ProxyPlugin<TConfig>;\n }\n const schema = schemaOrPlugin as ZodType<TConfig>;\n return {\n ...maybePlugin,\n validateConfig: (raw: unknown): TConfig => schema.parse(raw),\n };\n}\n","export const WIRE_FORMATS = ['anthropic-messages', 'openai-chat'] as const;\n\nexport type WireFormat = (typeof WIRE_FORMATS)[number];\n\n/**\n * Format-reserved extension keys (spec §4.3): the only keys a plugin may write\n * into `ir.extensions[format]`. Public contract — keep in sync with README.\n */\nexport const RESERVED_KEYS: Readonly<Record<WireFormat, readonly string[]>> = {\n 'anthropic-messages': [],\n 'openai-chat': [\n '$proxitor.provider',\n '$proxitor.models',\n '$proxitor.route',\n '$proxitor.transforms',\n ],\n};\n\n/**\n * Endpoint path each wire format owns (spec §5.1): the format adapter owns the\n * version path; a provider `baseUrl` is everything before it. Consumed by\n * domain routing for baseUrl validation and upstream URL construction.\n */\nexport const ENDPOINT_PATHS: Readonly<Record<WireFormat, string>> = {\n 'anthropic-messages': '/v1/messages',\n 'openai-chat': '/v1/chat/completions',\n};\n\n/**\n * Inbound proxy-owned paths (spec §5.2): `/v1/models` is synthesized locally\n * from the routing table; `/v1/responses` (openai-responses format) is\n * deferred — classified to a 501 (§17), never a passthrough.\n */\nexport const MODELS_PATH = '/v1/models';\nexport const DEFERRED_RESPONSES_PATH = '/v1/responses';\n\n/**\n * Session headers (spec §10a): the pipeline stamps the first present value onto\n * `CanonicalRequest.clientSessionId`; the session-id plugin forwards it upstream.\n */\nexport const CLIENT_SESSION_ID_HEADER = 'x-claude-code-session-id';\nexport const SESSION_ID_HEADER = 'x-session-id';\n","export const PLUGIN_API_VERSION = '0.0.0';\n\nexport * from './canonical/events.js';\nexport * from './canonical/request.js';\nexport * from './define-plugin.js';\nexport * from './plugin.js';\nexport * from './ports.js';\nexport * from './wire-format.js';\n"],"mappings":";AAcA,SAAgB,aACd,gBACA,aACsB;CACtB,IAAI,gBAAgB,KAAA,GAClB,OAAO;CAET,MAAM,SAAS;CACf,OAAO;EACL,GAAG;EACH,iBAAiB,QAA0B,OAAO,MAAM,GAAG;CAC7D;AACF;;;AC1BA,MAAa,eAAe,CAAC,sBAAsB,aAAa;;;;;AAQhE,MAAa,gBAAiE;CAC5E,sBAAsB,CAAC;CACvB,eAAe;EACb;EACA;EACA;EACA;CACF;AACF;;;;;;AAOA,MAAa,iBAAuD;CAClE,sBAAsB;CACtB,eAAe;AACjB;;;;;;AAOA,MAAa,cAAc;AAC3B,MAAa,0BAA0B;;;;;AAMvC,MAAa,2BAA2B;AACxC,MAAa,oBAAoB;;;ACzCjC,MAAa,qBAAqB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proxitor/plugin-api",
|
|
3
|
+
"version": "0.1.0-beta.0",
|
|
4
|
+
"description": "Published proxitor plugin contract: Canonical IR, plugin hooks, ports",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"import": "./src/index.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsdown",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:types": "vitest run --typecheck",
|
|
20
|
+
"typecheck": "tsc --noEmit"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"tsdown": "^0.22.1",
|
|
24
|
+
"vitest": "^4.1.8",
|
|
25
|
+
"zod": "^4.4.3"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"zod": "^4.0.0"
|
|
29
|
+
},
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|