@skaile/transform-proxy 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1
4
+
5
+ - Anthropic walker: the pipeline `instruction` is appended after the host's system prompt (last text block, or after a blank line for a string `system`) instead of being prepended. Claude Code gateways such as TeamClaude answer 429 `rate_limit_error` for Sonnet when the system prompt does not start with the Claude Code blocks; with the instruction first, omp and Claude Code requests for `claude-sonnet-4-5` through the proxy were refused.
6
+
7
+ ## 0.2.0
8
+
9
+ - OpenAI chat completions (`/chat/completions`) and OpenAI responses (`/responses`) walkers: text leaves, tool-call arguments and reasoning summaries are transformed outbound and restored in JSON and SSE replies; `image_url`, `input_audio`, `file`, `input_image` and `input_file` parts are refused with 400 `unsupported_content`. Responses reasoning summaries are cached by item id so a replayed reasoning item is sent back byte for byte.
10
+ - omp extension (`@skaile/transform-proxy/omp`, manifest `omp.extensions`): `/anon on|off|status` routes every provider of omp's model registry through the proxy (an external one from `SKAILE_TRANSFORM_PROXY_URL`, or one started in-process from the CLI config lookup), shows `anon on` / `anon off` in the footer, persists the flag in omp's agent dir and refuses `off` under `SKAILE_TRANSFORM_PROXY_MODE=required`.
11
+
3
12
  ## 0.1.0
4
13
 
5
14
  - First release: transform contract, chain composition, per-session state and facts, the HTTP proxy with the Anthropic Messages walker, and the `skaile-transform-proxy` CLI.
package/README.md CHANGED
@@ -21,10 +21,12 @@ The proxy strips all four headers before forwarding. Every other header, includi
21
21
  |---|---|
22
22
  | `POST …/messages` | Anthropic request and response: request rewritten, JSON reply and SSE stream restored. |
23
23
  | `POST …/messages/count_tokens` | Request rewritten; the response passes through untouched. |
24
+ | `POST …/chat/completions` | OpenAI chat request and response: request rewritten, JSON reply and SSE stream restored. |
25
+ | `POST …/responses` | OpenAI responses request and response: request rewritten, JSON reply and SSE stream restored. |
24
26
  | `GET …/models` | Passthrough. |
25
- | anything else (chat completions, responses, embeddings) | 404 `unsupported_route`. |
27
+ | anything else (embeddings included) | 404 `unsupported_route`. |
26
28
 
27
- OpenAI chat and responses walkers are not implemented yet. Embeddings are refused on purpose: a vector of pseudonymized input cannot be restored.
29
+ Embeddings are refused on purpose: a vector of pseudonymized input cannot be restored.
28
30
 
29
31
  ## Refusals
30
32
 
@@ -81,6 +83,28 @@ await proxy.dropSession('s1')
81
83
  await proxy.close()
82
84
  ```
83
85
 
86
+ ## omp extension
87
+
88
+ The package ships an [omp](https://omp.sh) extension (subpath `@skaile/transform-proxy/omp`, declared in the package manifest under `omp.extensions`):
89
+
90
+ ```sh
91
+ omp plugin install @skaile/transform-proxy
92
+ ```
93
+
94
+ It adds the command `/anon on|off|status` and the footer status `anon on` / `anon off`.
95
+
96
+ - `/anon on` routes every provider of omp's model registry through the proxy: the provider's `baseUrl` becomes the proxy URL, and the original base URL travels in `x-skaile-transform-upstream`, next to `x-skaile-transform-session` (the omp session id) and the token. The provider's own headers and auth stay in place and are relayed.
97
+ - With `SKAILE_TRANSFORM_PROXY_URL` (and `SKAILE_TRANSFORM_PROXY_TOKEN`) set, it uses that running proxy, and the proxy applies its `defaultPipeline`.
98
+ - Otherwise it starts one proxy inside the omp process, from the config lookup of the CLI (`./.skaile/transform-proxy.yaml`, then `~/.config/skaile/transform-proxy.yaml`). That config must set `defaultPipeline`. Without a config, `/anon on` refuses and says where to put one.
99
+ - Providers on a wire the proxy does not rewrite (Bedrock, Vertex, Gemini, agent bridges, providers without a base URL) are routed too, so the proxy refuses their requests: the setup fails closed. `/anon status` lists them as refused.
100
+ - The session's active model is rebound to the re-routed one, so the next request already uses the new base URL.
101
+ - `/anon off` restores the original base URLs and headers.
102
+ - `/anon status` shows the state, the proxy URL and its source, the pipeline, the session id, and the routed and refused providers.
103
+ - The enabled flag is saved in `skaile-transform-proxy.json` in omp's agent dir (`~/.omp/agent`; `SKAILE_TRANSFORM_PROXY_OMP_STATE` overrides the path) and re-applied when a session starts.
104
+ - `SKAILE_TRANSFORM_PROXY_MODE=required` (set by a skaile session in required mode) turns routing on at session start and refuses `/anon off`.
105
+
106
+ The overrides are registered under the model-registry source `skaile-transform-proxy`, so `/anon off` clears them in one catalog reload. A provider that another extension registered at runtime is taken over while anon is on; `/anon off` restores its base URL and headers, and a provider that existed only at runtime is reported as lost (restart omp to restore it).
107
+
84
108
  ## Writing a transform module
85
109
 
86
110
  A module default-exports a `TransformModule`:
@@ -89,6 +113,8 @@ A module default-exports a `TransformModule`:
89
113
  - It returns a `TransformFactory`, which runs once per `(session, pipeline)`: `(ctx: { sessionId, facts, log }) => Transform`.
90
114
  - A `Transform` has `instruction?`, `outbound(text, leaf)`, `inbound(text)`, `inboundStream()` and `dispose?()`.
91
115
 
116
+ The Anthropic walker appends the pipeline `instruction` after the host's system prompt: a string `system` gets it after a blank line, a block array gets it as one more text block at the end, and an absent `system` becomes the instruction. The host's leading blocks stay first, because Claude Code gateways (TeamClaude) refuse Sonnet requests with 429 `rate_limit_error` when the system prompt does not start with the Claude Code blocks. The OpenAI walkers still put the instruction first: a leading `system` message in chat completions, a prefix of `instructions` in responses.
117
+
92
118
  `inboundStream().push(c1) + … + flush()` must equal `inbound(c1 + … + cn)` for every chunking.
93
119
 
94
120
  Connectors publish facts through `proxy.session(id).publisher(source)`. Facts are in-process only.
package/dist/cli.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as TransformProxy } from "./server-D5nBnO7T.mjs";
1
+ import { i as TransformProxy } from "./server-C_eKyCTV.mjs";
2
2
  /** Environment variable that supplies the client token when `--token` is absent. */
3
3
  export declare const TOKEN_ENV = "SKAILE_TRANSFORM_PROXY_TOKEN";
4
4
  export interface CliEnvironment {
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { d as createTransformProxy, g as errorMessage, o as resolveProxyConfig } from "./config-BKD-ILIz.mjs";
2
+ import { d as createTransformProxy, o as resolveProxyConfig, v as errorMessage } from "./config-Xdn_LYpZ.mjs";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { homedir } from "node:os";