@senpi/runtime 3.0.150 → 3.0.154

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 (44) hide show
  1. package/dist/cli/guide-commands.d.ts.map +1 -1
  2. package/dist/cli/guide-commands.js +5 -0
  3. package/dist/cli/guide-commands.js.map +1 -1
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +24 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/prompt/session-context-seed-hook.d.ts +7 -0
  9. package/dist/prompt/session-context-seed-hook.d.ts.map +1 -1
  10. package/dist/prompt/session-context-seed-hook.js +1 -1
  11. package/dist/prompt/session-context-seed-hook.js.map +1 -1
  12. package/dist/prompt/skill-router-hook.d.ts +24 -0
  13. package/dist/prompt/skill-router-hook.d.ts.map +1 -0
  14. package/dist/prompt/skill-router-hook.js +386 -0
  15. package/dist/prompt/skill-router-hook.js.map +1 -0
  16. package/dist/skill-router/catalog.d.ts +30 -0
  17. package/dist/skill-router/catalog.d.ts.map +1 -0
  18. package/dist/skill-router/catalog.js +131 -0
  19. package/dist/skill-router/catalog.js.map +1 -0
  20. package/dist/skill-router/classify-client.d.ts +80 -0
  21. package/dist/skill-router/classify-client.d.ts.map +1 -0
  22. package/dist/skill-router/classify-client.js +283 -0
  23. package/dist/skill-router/classify-client.js.map +1 -0
  24. package/dist/skill-router/prompt.d.ts +36 -0
  25. package/dist/skill-router/prompt.d.ts.map +1 -0
  26. package/dist/skill-router/prompt.js +318 -0
  27. package/dist/skill-router/prompt.js.map +1 -0
  28. package/dist/skill-router/resolve.d.ts +41 -0
  29. package/dist/skill-router/resolve.d.ts.map +1 -0
  30. package/dist/skill-router/resolve.js +43 -0
  31. package/dist/skill-router/resolve.js.map +1 -0
  32. package/dist/skills-manager/version-manager.d.ts +14 -0
  33. package/dist/skills-manager/version-manager.d.ts.map +1 -1
  34. package/dist/skills-manager/version-manager.js +31 -3
  35. package/dist/skills-manager/version-manager.js.map +1 -1
  36. package/dist/telemetry/spans/span-hooks.d.ts.map +1 -1
  37. package/dist/telemetry/spans/span-hooks.js +9 -0
  38. package/dist/telemetry/spans/span-hooks.js.map +1 -1
  39. package/dist/utils/event-catalog.d.ts +84 -0
  40. package/dist/utils/event-catalog.d.ts.map +1 -1
  41. package/dist/utils/event-catalog.js +7 -0
  42. package/dist/utils/event-catalog.js.map +1 -1
  43. package/openclaw.plugin.json +1 -1
  44. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ export interface WarnLogger {
2
+ warn(message: string): void;
3
+ }
4
+ /**
5
+ * Resolve the classify URL from the value of `SENPI_SKILL_ROUTER_URL`.
6
+ *
7
+ * Unset or blank means prod. Otherwise the value must be an origin only: `https:`, no
8
+ * userinfo, no port, an empty or `/` path, no query or hash, and a hostname under `.senpi.ai`
9
+ * with at least one label in front. An invalid value returns `undefined` (the router stays off;
10
+ * it never falls back to prod) and logs one warning that names the variable, never its value.
11
+ */
12
+ export declare function resolveClassifyUrl(raw: string | undefined, logger?: WarnLogger): string | undefined;
13
+ /** A skill name as the server accepts it (ticket 01, "Request"). */
14
+ export declare const SKILL_NAME_PATTERN: RegExp;
15
+ /** The server's cap on `skills` and on the `fired` / `scores` it returns. */
16
+ export declare const MAX_SKILLS = 40;
17
+ export interface SkillRef {
18
+ name: string;
19
+ version?: string;
20
+ }
21
+ export interface ClassifyRequest {
22
+ /** The prepared prompt (`preparePromptForClassify`), never the raw hook prompt. */
23
+ prompt: string;
24
+ /** `skillsForRequest()`'s list. */
25
+ skills: readonly SkillRef[];
26
+ }
27
+ export interface ClassifyUsage {
28
+ inputTokens?: number;
29
+ outputTokens?: number;
30
+ costUsd?: number;
31
+ }
32
+ export interface ClassifySuccess {
33
+ ok: true;
34
+ decisionId?: string;
35
+ model?: string;
36
+ criteriaVersion?: string;
37
+ /** Validated: at most 40 pattern-matching names, each a finite number in [0, 1]. */
38
+ scores: Readonly<Record<string, number>>;
39
+ /** Validated: at most 40 pattern-matching names. The server's list; `resolve.ts` narrows it. */
40
+ fired: readonly string[];
41
+ unknownCount: number;
42
+ ignored: number;
43
+ unansweredCount: number;
44
+ usage: ClassifyUsage;
45
+ /** The server's own `latencyMs.total`. */
46
+ serverLatencyMs?: number;
47
+ /** The box's round trip. */
48
+ latencyMs: number;
49
+ }
50
+ export interface ClassifyFailure {
51
+ ok: false;
52
+ /** The HTTP status, or 0 for a timeout, a network error or a backoff. */
53
+ status: number;
54
+ /** The server's error code, or the client's: `timeout`, `network`, `bad_response`, `http_<status>`, `backoff`. */
55
+ code: string;
56
+ /** The server's 502 `reason`, when it is a plain code. */
57
+ reason?: string;
58
+ /** Seconds of the backoff window this result opened (or, for `backoff`, has left). */
59
+ retryAfterSec?: number;
60
+ latencyMs: number;
61
+ }
62
+ export type ClassifyResult = ClassifySuccess | ClassifyFailure;
63
+ export interface ClassifyClient {
64
+ /** Never throws. `signal` is linked to the client's own timeout. */
65
+ classify(request: ClassifyRequest, opts?: {
66
+ signal?: AbortSignal;
67
+ }): Promise<ClassifyResult>;
68
+ }
69
+ export interface ClassifyClientOptions {
70
+ /** From {@link resolveClassifyUrl}. */
71
+ url: string;
72
+ /** The box's per-user Senpi token. */
73
+ token: string;
74
+ /** Injectable for tests; defaults to the global `fetch`. */
75
+ fetch?: typeof fetch;
76
+ /** Injectable clock (ms) for latency and backoff windows; defaults to `Date.now`. */
77
+ now?: () => number;
78
+ }
79
+ export declare function createClassifyClient(options: ClassifyClientOptions): ClassifyClient;
80
+ //# sourceMappingURL=classify-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-client.d.ts","sourceRoot":"","sources":["../../src/skill-router/classify-client.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAWnG;AA+BD,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,QAA8B,CAAC;AAC9D,6EAA6E;AAC7E,eAAO,MAAM,UAAU,KAAK,CAAC;AAQ7B,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,MAAM,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,IAAI,CAAC;IACT,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzC,gGAAgG;IAChG,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,aAAa,CAAC;IACrB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,KAAK,CAAC;IACV,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,kHAAkH;IAClH,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,eAAe,CAAC;AAE/D,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9F;AAED,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,qFAAqF;IACrF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAuEnF"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Client for senpi-backend's skill-router classify endpoint (tickets skill-router/01, /02, /05).
3
+ *
4
+ * This is not a Jev client: the box never talks to OpenRouter and holds no Jev key (D2). It
5
+ * sends the user's prompt (envelope already stripped, see `prompt.ts`) and the names and
6
+ * versions of the skills installed on the box, and gets back the server's scores and `fired`
7
+ * list (D3 option A: the server holds the criteria).
8
+ *
9
+ * The bearer is the box's per-user Senpi token: 180 days long and also good for MCP trading
10
+ * calls. So it is only ever sent to a validated `https://*.senpi.ai` origin, with
11
+ * `redirect: "error"`, and never logged or put in a URL.
12
+ *
13
+ * Nothing here throws to its caller: every failure is a typed `{ ok: false }` result, which the
14
+ * hook treats as "no opinion" (no injection).
15
+ */
16
+ import { z } from "zod";
17
+ /** The fixed path on the classify origin. */
18
+ const CLASSIFY_PATH = "/v1/skill-router/classify";
19
+ /** Prod origin; dev is `https://moxie-backend.dev.senpi.ai`. */
20
+ const DEFAULT_CLASSIFY_ORIGIN = "https://moxie-backend.prod.senpi.ai";
21
+ const URL_ENV_NAME = "SENPI_SKILL_ROUTER_URL";
22
+ /**
23
+ * Resolve the classify URL from the value of `SENPI_SKILL_ROUTER_URL`.
24
+ *
25
+ * Unset or blank means prod. Otherwise the value must be an origin only: `https:`, no
26
+ * userinfo, no port, an empty or `/` path, no query or hash, and a hostname under `.senpi.ai`
27
+ * with at least one label in front. An invalid value returns `undefined` (the router stays off;
28
+ * it never falls back to prod) and logs one warning that names the variable, never its value.
29
+ */
30
+ export function resolveClassifyUrl(raw, logger) {
31
+ const value = raw?.trim() ?? "";
32
+ if (value.length === 0)
33
+ return `${DEFAULT_CLASSIFY_ORIGIN}${CLASSIFY_PATH}`;
34
+ const origin = validOrigin(value);
35
+ if (origin === undefined) {
36
+ logger?.warn(`[senpi-runtime][skill-router] ${URL_ENV_NAME} is invalid (it must be an origin like https://<host>.senpi.ai); the skill router is disabled`);
37
+ return undefined;
38
+ }
39
+ return `${origin}${CLASSIFY_PATH}`;
40
+ }
41
+ function validOrigin(value) {
42
+ let url;
43
+ try {
44
+ url = new URL(value);
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ if (url.protocol !== "https:")
50
+ return undefined;
51
+ if (url.username !== "" || url.password !== "")
52
+ return undefined;
53
+ if (url.port !== "")
54
+ return undefined;
55
+ if (url.pathname !== "/" || url.search !== "" || url.hash !== "")
56
+ return undefined;
57
+ // The WHATWG parser drops a default port (`:443`) and an empty query or hash (`?`, `#`), so
58
+ // check the text as well: any of them means the value is not a bare origin.
59
+ if (/[?#@]/.test(value) || hasExplicitPort(value))
60
+ return undefined;
61
+ const labels = url.hostname.toLowerCase().split(".");
62
+ if (labels.length < 3 || labels.some((l) => l.length === 0))
63
+ return undefined;
64
+ if (labels[labels.length - 2] !== "senpi" || labels[labels.length - 1] !== "ai")
65
+ return undefined;
66
+ return url.origin;
67
+ }
68
+ function hasExplicitPort(value) {
69
+ const start = value.indexOf("//");
70
+ if (start === -1)
71
+ return true;
72
+ const authority = value.slice(start + 2).split(/[/\\?#]/, 1)[0];
73
+ return authority.includes(":");
74
+ }
75
+ // ─── The classify call ──────────────────────────────────────────────────────
76
+ /** A skill name as the server accepts it (ticket 01, "Request"). */
77
+ export const SKILL_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
78
+ /** The server's cap on `skills` and on the `fired` / `scores` it returns. */
79
+ export const MAX_SKILLS = 40;
80
+ /** The box's budget for the whole round trip (DNS, connect, TLS, request, response body). */
81
+ const CLASSIFY_TIMEOUT_MS = 1500;
82
+ /** The most of a response body the client reads. */
83
+ const MAX_RESPONSE_BYTES = 64 * 1024;
84
+ /** The server drops a longer version; the box doesn't send one. */
85
+ const MAX_VERSION_CHARS = 32;
86
+ export function createClassifyClient(options) {
87
+ const doFetch = options.fetch ?? fetch;
88
+ const now = options.now ?? Date.now;
89
+ // The Retry-After window, in memory only: a restart clears it, which is also when a box-side
90
+ // mode change lands. One client per process, so this is per box.
91
+ let backoffUntilMs = 0;
92
+ return {
93
+ async classify(request, opts = {}) {
94
+ const remainingMs = backoffUntilMs - now();
95
+ if (remainingMs > 0) {
96
+ return { ok: false, status: 0, code: "backoff", retryAfterSec: Math.ceil(remainingMs / 1000), latencyMs: 0 };
97
+ }
98
+ const startedAt = now();
99
+ const elapsed = () => Math.max(0, now() - startedAt);
100
+ // One AbortController owns the whole round trip, body read included. A caller signal is
101
+ // linked to it (ported from senpi-jev-router `src/jev/client.ts:130-136`); the 2026.5.7
102
+ // `before_prompt_build` ctx carries none, so that link is for tests and future hosts.
103
+ const timer = new AbortController();
104
+ const timeout = setTimeout(() => timer.abort(), CLASSIFY_TIMEOUT_MS);
105
+ const signal = opts.signal && typeof AbortSignal.any === "function"
106
+ ? AbortSignal.any([timer.signal, opts.signal])
107
+ : timer.signal;
108
+ const failed = (status, code) => ({
109
+ ok: false,
110
+ status,
111
+ code,
112
+ latencyMs: elapsed(),
113
+ });
114
+ // A timer or caller abort is a timeout; anything else thrown on the wire is `network`.
115
+ // No error text is kept: it could carry the URL, and nothing here may carry the token.
116
+ const wireFailure = () => failed(0, signal.aborted ? "timeout" : "network");
117
+ try {
118
+ let res;
119
+ let text;
120
+ try {
121
+ res = await doFetch(options.url, {
122
+ method: "POST",
123
+ headers: { Authorization: `Bearer ${options.token}`, "Content-Type": "application/json" },
124
+ body: JSON.stringify(buildBody(request)),
125
+ redirect: "error",
126
+ signal,
127
+ });
128
+ text = await readCapped(res, MAX_RESPONSE_BYTES);
129
+ }
130
+ catch {
131
+ return wireFailure();
132
+ }
133
+ if (res.status !== 200) {
134
+ const body = errorBodySchema.parse(text === undefined ? undefined : parseJson(text));
135
+ const failure = failed(res.status, body.error ?? `http_${res.status}`);
136
+ if (res.status === 502 && body.reason !== undefined)
137
+ failure.reason = body.reason;
138
+ const windowSec = parseRetryAfter(res.headers.get("retry-after"), now()) ?? DEFAULT_BACKOFF_SEC[res.status];
139
+ if (windowSec !== undefined) {
140
+ backoffUntilMs = Math.max(backoffUntilMs, now() + windowSec * 1000);
141
+ failure.retryAfterSec = windowSec;
142
+ }
143
+ return failure;
144
+ }
145
+ const parsed = text === undefined ? undefined : parseSuccess(parseJson(text));
146
+ if (parsed === undefined)
147
+ return failed(200, "bad_response");
148
+ return { ok: true, ...parsed, latencyMs: elapsed() };
149
+ }
150
+ finally {
151
+ clearTimeout(timeout);
152
+ }
153
+ },
154
+ };
155
+ }
156
+ const MIN_BACKOFF_SEC = 1;
157
+ const MAX_BACKOFF_SEC = 86_400;
158
+ /**
159
+ * The box's own window when a non-200 carries no `Retry-After`: these statuses (a bad or
160
+ * unenrolled token, a wrong route) won't clear by retrying. Every other status opens none.
161
+ * Whatever `Retry-After` the server does send is honoured instead (ticket 01's table: 503
162
+ * `disabled` 3,600 / 900 s, 429 `rate_limited`, 503 `budget_exhausted` to 00:00Z, 502
163
+ * `breaker_open` = the breaker's remaining TTL).
164
+ */
165
+ const DEFAULT_BACKOFF_SEC = { 401: 3600, 403: 3600, 404: 3600, 405: 3600 };
166
+ /** `Retry-After` as delta-seconds or an HTTP-date, clamped to 1..86,400 s; `undefined` when absent or unparsable. */
167
+ function parseRetryAfter(header, nowMs) {
168
+ const value = header?.trim();
169
+ if (!value)
170
+ return undefined;
171
+ let seconds;
172
+ if (/^\d+$/.test(value)) {
173
+ seconds = Number(value);
174
+ }
175
+ else {
176
+ const at = Date.parse(value);
177
+ if (!Number.isFinite(at) || /^[+-]?\d/.test(value))
178
+ return undefined;
179
+ seconds = Math.ceil((at - nowMs) / 1000);
180
+ }
181
+ return Math.min(MAX_BACKOFF_SEC, Math.max(MIN_BACKOFF_SEC, seconds));
182
+ }
183
+ /** The body as UTF-8 text, or `undefined` when it is over `maxBytes` (the rest is not read). */
184
+ async function readCapped(res, maxBytes) {
185
+ const declared = Number(res.headers.get("content-length"));
186
+ if (Number.isFinite(declared) && declared > maxBytes) {
187
+ await res.body?.cancel().catch(() => undefined);
188
+ return undefined;
189
+ }
190
+ if (!res.body)
191
+ return "";
192
+ const reader = res.body.getReader();
193
+ const chunks = [];
194
+ let total = 0;
195
+ for (;;) {
196
+ const { done, value } = await reader.read();
197
+ if (done)
198
+ break;
199
+ total += value.byteLength;
200
+ if (total > maxBytes) {
201
+ await reader.cancel().catch(() => undefined);
202
+ return undefined;
203
+ }
204
+ chunks.push(value);
205
+ }
206
+ return Buffer.concat(chunks).toString("utf8");
207
+ }
208
+ function parseJson(text) {
209
+ try {
210
+ return JSON.parse(text);
211
+ }
212
+ catch {
213
+ return undefined;
214
+ }
215
+ }
216
+ /** Exactly `{prompt, skills: [{name, version?}]}`: the server answers 400 to any other key. */
217
+ function buildBody(request) {
218
+ return {
219
+ prompt: request.prompt,
220
+ skills: request.skills.map((s) => typeof s.version === "string" && s.version.length > 0 && s.version.length <= MAX_VERSION_CHARS
221
+ ? { name: s.name, version: s.version }
222
+ : { name: s.name }),
223
+ };
224
+ }
225
+ /** Ticket 01's codes are all of this shape; anything else becomes `http_<status>`. */
226
+ const ERROR_CODE_PATTERN = /^[a-z_]{1,32}$/;
227
+ /** A 502's Jev reason (`http_429`, `breaker_open`, ...); anything else is dropped. */
228
+ const REASON_PATTERN = /^[a-z0-9_]{1,32}$/;
229
+ const DECISION_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
230
+ const CRITERIA_VERSION_PATTERN = /^[A-Za-z0-9]{1,64}$/;
231
+ const MODEL_PATTERN = /^[A-Za-z0-9._/:-]{1,64}$/;
232
+ const skillName = z.string().regex(SKILL_NAME_PATTERN);
233
+ const optionalMatching = (pattern) => z.string().regex(pattern).optional().catch(undefined);
234
+ const optionalNonNegative = z.number().finite().nonnegative().optional().catch(undefined);
235
+ /** The length of an array, capped at 40; 0 for anything else. */
236
+ const cappedCount = z.unknown().transform((v) => (Array.isArray(v) ? Math.min(v.length, MAX_SKILLS) : 0));
237
+ /**
238
+ * A 200 body. `fired` and `scores` must be well-formed or the whole response is refused; every
239
+ * other field is dropped or zeroed when bad. Unlisted keys are stripped, so only these
240
+ * validated values ever leave the client.
241
+ */
242
+ const successBodySchema = z.object({
243
+ fired: z.array(skillName).max(MAX_SKILLS),
244
+ scores: z
245
+ .record(skillName, z.number().finite().min(0).max(1))
246
+ .refine((scores) => Object.keys(scores).length <= MAX_SKILLS),
247
+ decisionId: optionalMatching(DECISION_ID_PATTERN),
248
+ model: optionalMatching(MODEL_PATTERN),
249
+ criteriaVersion: optionalMatching(CRITERIA_VERSION_PATTERN),
250
+ unknown: cappedCount,
251
+ ignored: z.number().int().safe().nonnegative().catch(0),
252
+ unanswered: cappedCount,
253
+ usage: z
254
+ .object({ inputTokens: optionalNonNegative, outputTokens: optionalNonNegative, costUsd: optionalNonNegative })
255
+ .catch({}),
256
+ latencyMs: z.object({ total: optionalNonNegative }).catch({}),
257
+ });
258
+ /** A non-200 body: `{"error": "<code>", "reason": "<jev reason, 502 only>"}`, each kept only when plain. */
259
+ const errorBodySchema = z
260
+ .object({ error: optionalMatching(ERROR_CODE_PATTERN), reason: optionalMatching(REASON_PATTERN) })
261
+ .catch({});
262
+ function parseSuccess(raw) {
263
+ const parsed = successBodySchema.safeParse(raw);
264
+ if (!parsed.success)
265
+ return undefined;
266
+ const body = parsed.data;
267
+ return {
268
+ decisionId: body.decisionId,
269
+ model: body.model,
270
+ criteriaVersion: body.criteriaVersion,
271
+ scores: body.scores,
272
+ fired: body.fired,
273
+ unknownCount: body.unknown,
274
+ ignored: body.ignored,
275
+ unansweredCount: body.unanswered,
276
+ usage: dropUndefined(body.usage),
277
+ serverLatencyMs: body.latencyMs.total,
278
+ };
279
+ }
280
+ function dropUndefined(o) {
281
+ return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined));
282
+ }
283
+ //# sourceMappingURL=classify-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-client.js","sourceRoot":"","sources":["../../src/skill-router/classify-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Prompt hygiene for the skill-router classify call (ticket skill-router/05).
3
+ *
4
+ * On OpenClaw 2026.5.7 (the fleet version) the `before_prompt_build` hook receives get-reply's
5
+ * `prefixedCommandBody`, which wraps the user's message in an AI-facing envelope: a media note,
6
+ * a thread note, queued system events, the aborted-run hint, the inbound metadata blocks
7
+ * (`Sender (untrusted metadata):` and friends), the `chat.send` timestamp and a trailing
8
+ * Untrusted-context block. The owner approved sending user prompts to senpi-backend, OpenRouter
9
+ * and TypeSafe only with that envelope stripped, so this module removes it, in assembly order,
10
+ * before anything leaves the box. It is pure and never throws.
11
+ *
12
+ * Every literal below is copied from the openclaw@2026.5.7 dist (`npm pack openclaw@2026.5.7`);
13
+ * the file and line are named next to each. The vendored node_modules copy is 2026.6.9 and is
14
+ * not the reference.
15
+ */
16
+ export type PromptSkipReason = "reset_turn" | "inter_session" | "queued_batch" | "unknown_envelope" | "empty_prompt";
17
+ export type PreparedPrompt = {
18
+ ok: true;
19
+ /** The text to send: the user's message alone, at most {@link CLASSIFY_PROMPT_MAX_CHARS}. */
20
+ prompt: string;
21
+ /** `prompt.length`, the sent length. */
22
+ length: number;
23
+ truncated: boolean;
24
+ /** True when any envelope part was removed. */
25
+ envelopeStripped: boolean;
26
+ } | {
27
+ ok: false;
28
+ reason: PromptSkipReason;
29
+ envelopeStripped: boolean;
30
+ };
31
+ /**
32
+ * Turn a prompt into the text the classify endpoint may see, or say why the turn is not
33
+ * classified at all.
34
+ */
35
+ export declare function preparePromptForClassify(raw: string): PreparedPrompt;
36
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/skill-router/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,MAAM,MAAM,gBAAgB,GACxB,YAAY,GACZ,eAAe,GACf,cAAc,GACd,kBAAkB,GAClB,cAAc,CAAC;AAEnB,MAAM,MAAM,cAAc,GACtB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,6FAA6F;IAC7F,MAAM,EAAE,MAAM,CAAC;IACf,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,gBAAgB,EAAE,OAAO,CAAC;CAC3B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAC;AAsDvE;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAkEpE"}