@skaile/transform-proxy 0.2.6 → 0.3.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 +4 -0
- package/README.md +3 -2
- package/dist/omp/index.d.mts +2 -1
- package/dist/omp/index.mjs +45 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
- omp extension, **behaviour change**: `/anon on` and `/anon off` switch only the omp process they run in (its subagents and its `/new`, `/resume`, `/fork` sessions included) and no longer save the default. Before, every `/anon on|off` wrote `~/.omp/agent/skaile-transform-proxy.json`, so turning anon off in one window turned it off for every omp started later. `/anon on --global` and `/anon off --global` also save the default. A saved `on` is applied at session start only until the first successful `/anon on|off` in that process, so a plain `/anon off` stays off across `/new`. An existing saved `enabled: true` still turns anon on in new omp processes; run `/anon off --global` to clear it.
|
|
6
|
+
|
|
3
7
|
## 0.2.6
|
|
4
8
|
|
|
5
9
|
- omp extension: while anon is on, in error or required, images are not sent. The extension sets omp's `images.blockImages` as a runtime override (never persisted), so omp replaces every image in the request, history included, with `Image reading is disabled.`; `/anon off` drops the override. Before, a screenshot from a browser tool made the proxy refuse every later request of the session with 400 `unsupported_content` ("Anthropic image content cannot be transformed"). `/anon status` lists `images: not sent`. An omp without the settings registry gets one warning, and the proxy keeps refusing images.
|
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ The package ships an [omp](https://omp.sh) extension (subpath `@skaile/transform
|
|
|
93
93
|
omp plugin install @skaile/transform-proxy
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
It adds the command `/anon on|off|status` and a compact status: `🟢A` (on), `🔴A` (off) or `🟠A` (error). The colour is in the emoji because omp strips ANSI colour from extension statuses and draws them in its accent colour. Unless `SKAILE_TRANSFORM_PROXY_URL` names a running proxy, it needs Node ≥ 22 on `PATH` (or its path in `SKAILE_TRANSFORM_PROXY_NODE`).
|
|
96
|
+
It adds the command `/anon on|off [--global] | status` and a compact status: `🟢A` (on), `🔴A` (off) or `🟠A` (error). The colour is in the emoji because omp strips ANSI colour from extension statuses and draws them in its accent colour. Unless `SKAILE_TRANSFORM_PROXY_URL` names a running proxy, it needs Node ≥ 22 on `PATH` (or its path in `SKAILE_TRANSFORM_PROXY_NODE`).
|
|
97
97
|
|
|
98
98
|
omp shows extension statuses on an extra line below the status line. To show the status in the status line itself, add the `status` segment and turn the extra line off in `~/.omp/agent/config.yml` (`showHookStatus: false` moves every extension status, not just this one, into the segment):
|
|
99
99
|
|
|
@@ -116,7 +116,8 @@ statusLine:
|
|
|
116
116
|
- The proxy session follows the root omp session: on `/new`, `/resume`, `/fork` (`session_switch`) and on a root `session_start` with a new session id, every provider is re-routed with the new `x-skaile-transform-session`. The proxy keeps the old session's state in memory until it exits; no request carries that id again. A `session_start` of a headless `print` session (how omp runs subagents) keeps the parent's id, so subagents share its pseudonyms.
|
|
117
117
|
- `/anon off` restores the original base URLs and headers.
|
|
118
118
|
- `/anon status` shows the state, the proxy URL and its source, the pipeline, the session id, whether images are blocked, and the routed and refused providers.
|
|
119
|
-
-
|
|
119
|
+
- `/anon on` and `/anon off` switch only the omp process they run in: that window, its subagents, and the sessions it opens with `/new`, `/resume` and `/fork`. Other omp windows are not touched, and the saved default does not change.
|
|
120
|
+
- `/anon on --global` and `/anon off --global` also save the default for omp processes started later, in `skaile-transform-proxy.json` in omp's agent dir (`~/.omp/agent`; `SKAILE_TRANSFORM_PROXY_OMP_STATE` overrides the path). A session start applies a saved `on` until the first successful `/anon on|off` in that process; from then on the process follows its own choice. A failed `/anon on --global` saves nothing.
|
|
120
121
|
- `SKAILE_TRANSFORM_PROXY_MODE=required` (set by a skaile session in required mode) turns routing on at session start and refuses `/anon off`.
|
|
121
122
|
|
|
122
123
|
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).
|
package/dist/omp/index.d.mts
CHANGED
|
@@ -117,7 +117,8 @@ interface AnonController {
|
|
|
117
117
|
command(args: string, ctx: OmpContext, session: OmpSessionActions): Promise<void>;
|
|
118
118
|
completions(prefix: string): OmpAutocompleteItem[] | null;
|
|
119
119
|
/**
|
|
120
|
-
* Applies the
|
|
120
|
+
* Applies the saved default (unless `/anon on|off` already decided in this process) or required
|
|
121
|
+
* mode, and refreshes the status bar. A root session
|
|
121
122
|
* whose omp session id changed rotates the proxy session; subagents keep the parent's id.
|
|
122
123
|
*/
|
|
123
124
|
sessionStart(ctx: OmpContext, session: OmpSessionActions): Promise<void>;
|
package/dist/omp/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ const TOKEN_ENV = "SKAILE_TRANSFORM_PROXY_TOKEN";
|
|
|
14
14
|
const NODE_ENV = "SKAILE_TRANSFORM_PROXY_NODE";
|
|
15
15
|
/** `required` (set by a skaile session in required mode): routing is forced on and `/anon off` is refused. */
|
|
16
16
|
const MODE_ENV = "SKAILE_TRANSFORM_PROXY_MODE";
|
|
17
|
-
/** Overrides the path of the
|
|
17
|
+
/** Overrides the path of the saved default (`/anon on|off --global`). */
|
|
18
18
|
const STATE_ENV = "SKAILE_TRANSFORM_PROXY_OMP_STATE";
|
|
19
19
|
/** The footer status key. */
|
|
20
20
|
const STATUS_KEY = "anon";
|
|
@@ -26,17 +26,29 @@ const SERVED_APIS = {
|
|
|
26
26
|
"openai-completions": true,
|
|
27
27
|
"openai-responses": true
|
|
28
28
|
};
|
|
29
|
-
|
|
29
|
+
/** `/anon on --global` / `/anon off --global` also save the default that new omp sessions start with. */
|
|
30
|
+
const GLOBAL_FLAG = "--global";
|
|
31
|
+
const USAGE = "usage: /anon on|off [--global] | status";
|
|
30
32
|
const VERBS = [
|
|
31
33
|
{
|
|
32
34
|
value: "on",
|
|
33
35
|
label: "on",
|
|
34
|
-
description: "route
|
|
36
|
+
description: "route this session through the transform proxy"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
value: "on --global",
|
|
40
|
+
label: "on --global",
|
|
41
|
+
description: "on, and the default for new sessions"
|
|
35
42
|
},
|
|
36
43
|
{
|
|
37
44
|
value: "off",
|
|
38
45
|
label: "off",
|
|
39
|
-
description: "restore
|
|
46
|
+
description: "restore this session's original provider base URLs"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
value: "off --global",
|
|
50
|
+
label: "off --global",
|
|
51
|
+
description: "off, and the default for new sessions"
|
|
40
52
|
},
|
|
41
53
|
{
|
|
42
54
|
value: "status",
|
|
@@ -44,6 +56,23 @@ const VERBS = [
|
|
|
44
56
|
description: "show the proxy, pipeline and routed providers"
|
|
45
57
|
}
|
|
46
58
|
];
|
|
59
|
+
/** A parsed `/anon` argument; `undefined` for anything else. */
|
|
60
|
+
function parseCommand(args) {
|
|
61
|
+
const [verb = "", ...flags] = args.trim().toLowerCase().split(/\s+/);
|
|
62
|
+
if (verb === "" || verb === "status") return flags.length === 0 ? {
|
|
63
|
+
verb: "status",
|
|
64
|
+
global: false
|
|
65
|
+
} : void 0;
|
|
66
|
+
if (verb !== "on" && verb !== "off") return void 0;
|
|
67
|
+
if (flags.length === 0) return {
|
|
68
|
+
verb,
|
|
69
|
+
global: false
|
|
70
|
+
};
|
|
71
|
+
return flags.length === 1 && flags[0] === GLOBAL_FLAG ? {
|
|
72
|
+
verb,
|
|
73
|
+
global: true
|
|
74
|
+
} : void 0;
|
|
75
|
+
}
|
|
47
76
|
/**
|
|
48
77
|
* The process-wide `/anon` state machine. omp builds one extension instance per session
|
|
49
78
|
* (subagents included) while they share one model registry, so one controller serves them all.
|
|
@@ -62,6 +91,8 @@ function createAnonController(deps) {
|
|
|
62
91
|
const registries = /* @__PURE__ */ new WeakMap();
|
|
63
92
|
let wanted = required;
|
|
64
93
|
let enabled = false;
|
|
94
|
+
/** The last successful `/anon on|off` in this omp process; once set, the saved default no longer applies here. */
|
|
95
|
+
let local;
|
|
65
96
|
/** Whether this controller holds the image block; only then does it release it. */
|
|
66
97
|
let imagesBlocked = false;
|
|
67
98
|
/** The host answered that it cannot block images; asked once, warned once. */
|
|
@@ -323,7 +354,7 @@ function createAnonController(deps) {
|
|
|
323
354
|
*/
|
|
324
355
|
async function start(ctx, session, root) {
|
|
325
356
|
enterSession(ctx, root);
|
|
326
|
-
if (!wanted && readEnabled(statePath)) wanted = true;
|
|
357
|
+
if (!wanted && local === void 0 && readEnabled(statePath)) wanted = true;
|
|
327
358
|
if (wanted) {
|
|
328
359
|
const failure = await activate(ctx, session);
|
|
329
360
|
if (failure !== void 0) {
|
|
@@ -338,15 +369,18 @@ function createAnonController(deps) {
|
|
|
338
369
|
required,
|
|
339
370
|
statePath,
|
|
340
371
|
async command(args, ctx, session) {
|
|
341
|
-
|
|
372
|
+
const parsed = parseCommand(args);
|
|
373
|
+
const scope = parsed?.global === true ? `this session; default for new sessions: ${parsed.verb}` : "this session";
|
|
374
|
+
switch (parsed?.verb) {
|
|
342
375
|
case "on": {
|
|
343
376
|
const before = wanted;
|
|
344
377
|
wanted = true;
|
|
345
378
|
const failure = await activate(ctx, session);
|
|
346
379
|
if (failure === void 0) {
|
|
347
|
-
|
|
380
|
+
local = true;
|
|
381
|
+
if (parsed.global) persist(ctx, true);
|
|
348
382
|
const count = stateOf(ctx.modelRegistry).routed.size;
|
|
349
|
-
ctx.ui.notify(`anon on: ${count} provider(s) routed through ${endpoint?.url}`, "info");
|
|
383
|
+
ctx.ui.notify(`anon on (${scope}): ${count} provider(s) routed through ${endpoint?.url}`, "info");
|
|
350
384
|
break;
|
|
351
385
|
}
|
|
352
386
|
wanted = before || required;
|
|
@@ -362,13 +396,13 @@ function createAnonController(deps) {
|
|
|
362
396
|
const lost = unroute(ctx);
|
|
363
397
|
wanted = false;
|
|
364
398
|
enabled = false;
|
|
399
|
+
local = false;
|
|
365
400
|
if (!await rebind(ctx, session)) ctx.ui.notify(`anon: could not rebind the active model ${ctx.model?.provider}/${ctx.model?.id}; select it again`, "warning");
|
|
366
|
-
persist(ctx, false);
|
|
367
|
-
ctx.ui.notify(
|
|
401
|
+
if (parsed.global) persist(ctx, false);
|
|
402
|
+
ctx.ui.notify(`anon off (${scope}): original provider base URLs restored`, "info");
|
|
368
403
|
if (lost.length > 0) ctx.ui.notify(`anon: ${lost.join(", ")} lost their runtime registration (registered by another extension); restart omp to restore them`, "warning");
|
|
369
404
|
break;
|
|
370
405
|
}
|
|
371
|
-
case "":
|
|
372
406
|
case "status":
|
|
373
407
|
ctx.ui.notify(statusText(ctx), "info");
|
|
374
408
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skaile/transform-proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Same-protocol passthrough proxy that runs model requests and replies through a chain of text transforms (Anthropic Messages, OpenAI chat, OpenAI responses)",
|
|
6
6
|
"license": "MIT",
|