@openclaw/typesafe 2026.9.6 → 2026.9.8

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 (52) hide show
  1. package/README.md +6 -3
  2. package/assets/icon.png +0 -0
  3. package/dist/.setup/client-CRLm45hB.mjs +395 -0
  4. package/dist/.setup/errors-BdIwQubl.mjs +83 -0
  5. package/dist/index.js +8 -506
  6. package/node_modules/typebox/build/compile/code.mjs +1 -2
  7. package/node_modules/typebox/build/compile/validator.mjs +5 -1
  8. package/node_modules/typebox/build/format/iri.mjs +16 -9
  9. package/node_modules/typebox/build/guard/emit.mjs +2 -2
  10. package/node_modules/typebox/build/guard/guard.d.mts +7 -5
  11. package/node_modules/typebox/build/guard/guard.mjs +14 -9
  12. package/node_modules/typebox/build/guard/index.mjs +6 -0
  13. package/node_modules/typebox/build/guard/unicode/unicode.d.mts +6 -0
  14. package/node_modules/typebox/build/guard/unicode/unicode.mjs +35 -0
  15. package/node_modules/typebox/build/guard/{string.mjs → unicode/unicode_segment.mjs} +16 -19
  16. package/node_modules/typebox/build/schema/build.mjs +2 -3
  17. package/node_modules/typebox/build/schema/engine/_pathing.d.mts +1 -0
  18. package/node_modules/typebox/build/schema/engine/_pathing.mjs +11 -0
  19. package/node_modules/typebox/build/schema/engine/_refine.mjs +13 -5
  20. package/node_modules/typebox/build/schema/engine/additionalProperties.mjs +2 -1
  21. package/node_modules/typebox/build/schema/engine/dependencies.mjs +2 -1
  22. package/node_modules/typebox/build/schema/engine/dependentSchemas.mjs +2 -1
  23. package/node_modules/typebox/build/schema/engine/dynamicRef.d.mts +1 -1
  24. package/node_modules/typebox/build/schema/engine/dynamicRef.mjs +2 -2
  25. package/node_modules/typebox/build/schema/engine/format.mjs +9 -2
  26. package/node_modules/typebox/build/schema/engine/patternProperties.mjs +3 -2
  27. package/node_modules/typebox/build/schema/engine/properties.mjs +3 -2
  28. package/node_modules/typebox/build/schema/engine/propertyNames.mjs +2 -1
  29. package/node_modules/typebox/build/schema/engine/recursiveRef.d.mts +1 -1
  30. package/node_modules/typebox/build/schema/engine/recursiveRef.mjs +2 -2
  31. package/node_modules/typebox/build/schema/engine/ref.d.mts +1 -1
  32. package/node_modules/typebox/build/schema/engine/ref.mjs +2 -2
  33. package/node_modules/typebox/build/schema/engine/schema.mjs +24 -24
  34. package/node_modules/typebox/build/schema/parse.mjs +3 -0
  35. package/node_modules/typebox/build/schema/pointer/pointer.d.mts +1 -6
  36. package/node_modules/typebox/build/schema/pointer/pointer.mjs +47 -64
  37. package/node_modules/typebox/build/system/settings/internal.d.mts +2 -0
  38. package/node_modules/typebox/build/system/settings/internal.mjs +20 -0
  39. package/node_modules/typebox/build/system/settings/settings.d.mts +11 -0
  40. package/node_modules/typebox/build/system/settings/settings.mjs +14 -0
  41. package/node_modules/typebox/build/type/extends/inference.d.mts +1 -1
  42. package/node_modules/typebox/build/type/extends/inference.mjs +15 -2
  43. package/node_modules/typebox/build/type/extends/tuple.d.mts +2 -1
  44. package/node_modules/typebox/build/type/extends/tuple.mjs +21 -1
  45. package/node_modules/typebox/build/value/parse/parse.mjs +10 -4
  46. package/node_modules/typebox/package.json +1 -1
  47. package/node_modules/typebox/readme.md +3 -1
  48. package/openclaw.plugin.json +37 -26
  49. package/package.json +7 -8
  50. package/skills/typesafe-evaluate/SKILL.md +0 -48
  51. package/skills/typesafe-evaluate/references/request-example.json +0 -65
  52. /package/node_modules/typebox/build/guard/{string.d.mts → unicode/unicode_segment.d.mts} +0 -0
package/dist/index.js CHANGED
@@ -1,486 +1,7 @@
1
+ import { i as ConfigSchema, n as decisionFailure, o as runtimeConfig } from "./.setup/errors-BdIwQubl.mjs";
1
2
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
- import { isDeepStrictEqual } from "node:util";
3
- import { Type } from "typebox";
4
- import { Compile } from "typebox/compile";
5
- import { Check } from "typebox/value";
6
- import { buildTimeoutAbortSignal } from "openclaw/plugin-sdk/extension-shared";
7
- import { responseWithRelease, shouldUseEnvHttpProxyForUrl, withTrustedEnvProxyGuardedFetchMode } from "openclaw/plugin-sdk/fetch-runtime";
8
- import { parseRetryAfterHeaderSeconds } from "openclaw/plugin-sdk/retry-runtime";
9
- import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
10
3
  import { getPreparedPluginSecretInput } from "openclaw/plugin-sdk/secret-input-runtime";
11
- //#region extensions/typesafe/src/errors.ts
12
- var EvaluationError = class extends Error {
13
- constructor(message, reason, retryAfterMs) {
14
- super(message);
15
- this.reason = reason;
16
- this.retryAfterMs = retryAfterMs;
17
- this.name = "EvaluationError";
18
- }
19
- };
20
- /** Only fixed plugin diagnostics cross the tool/provider boundary; raw causes stay discarded. */
21
- function evaluationError(error, aborted) {
22
- if (aborted) return new EvaluationError("TypeSafe evaluation cancelled.", "transport");
23
- if (error instanceof EvaluationError) return error;
24
- return new EvaluationError("TypeSafe evaluation failed or returned an invalid response.", "invalid-response");
25
- }
26
- /** Unexpected failures reject without retaining raw credentials or submitted state. */
27
- function decisionFailure(error) {
28
- if (error instanceof EvaluationError) return {
29
- status: "unavailable",
30
- reason: error.reason,
31
- ...error.retryAfterMs !== void 0 ? { retryAfterMs: error.retryAfterMs } : {}
32
- };
33
- throw new Error("TypeSafe decision adapter contract failure.");
34
- }
35
- const MAX_JSON_NODES = 262144;
36
- const MAX_JSON_DEPTH = 64;
37
- const MAX_CHOICE_OPTIONS = 255;
38
- const MAX_SCORE_LEVELS = 10;
39
- function map(value, options = {}) {
40
- return Type.Unsafe({
41
- type: "object",
42
- properties: {},
43
- additionalProperties: value,
44
- ...options
45
- });
46
- }
47
- const entry = Type.Union([
48
- Type.String(),
49
- map(Type.Unknown()),
50
- Type.Array(Type.Unknown()),
51
- Type.Null()
52
- ], { description: "Text, a JSON object or array, or null. Nested values must be finite JSON. Use structure for rules, examples, and exclusions." });
53
- const instructions = Type.Optional(Type.Union(entry.anyOf, { description: "The complete judgment to make; question IDs are not read by the model. Text, structured object/array, or null. May be omitted when criteria express the judgment." }));
54
- const model = Type.String({
55
- minLength: 1,
56
- maxLength: 128,
57
- pattern: "^[a-zA-Z0-9._/-]+$"
58
- });
59
- const probability = Type.Number({
60
- minimum: 0,
61
- maximum: 1
62
- });
63
- const objectOptions = { additionalProperties: false };
64
- const noulQuestion = Type.Object({
65
- type: Type.Literal("noul"),
66
- instructions,
67
- criteria: Type.Optional(Type.Union([Type.Object({
68
- true: Type.Optional(entry),
69
- false: Type.Optional(entry)
70
- }, objectOptions), Type.Null()], { description: "Optional true (yes) and false (no) outcome definitions; each accepts text, object, array, or null." }))
71
- }, {
72
- ...objectOptions,
73
- description: "Probability of yes (0–1), not intensity; no separate confidence. Use separate Nouls for independent labels."
74
- });
75
- const choiceQuestion = Type.Object({
76
- type: Type.Literal("choice"),
77
- instructions,
78
- criteria: map(entry, {
79
- minProperties: 2,
80
- maxProperties: MAX_CHOICE_OPTIONS,
81
- description: "2–255 competing labels mapped to descriptions. Labels may include spaces, punctuation, or Unicode. Null leaves a label undescribed. Include a no-match option when needed."
82
- })
83
- }, {
84
- ...objectOptions,
85
- description: "Choose one alternative; returns its label, full probability distribution, and confidence."
86
- });
87
- const scoreQuestion = Type.Object({
88
- type: Type.Literal("score"),
89
- instructions,
90
- criteria: Type.Array(entry, {
91
- minItems: 2,
92
- maxItems: MAX_SCORE_LEVELS,
93
- description: "2–10 ordered rubric levels, indexed from zero. Returns a fractional probability-weighted position, not an integer category or a normalized 0–1 score."
94
- })
95
- }, objectOptions);
96
- const question = Type.Union([
97
- noulQuestion,
98
- choiceQuestion,
99
- scoreQuestion
100
- ]);
101
- /** Explicit shared state; independently evaluated questions never see other answers. */
102
- const EvaluateInput = Type.Object({
103
- state: Type.Union(entry.anyOf, { description: "Shared evidence/context for every question. Only supplied state is sent; no ambient conversation is collected." }),
104
- questions: map(question, {
105
- minProperties: 1,
106
- description: "Nonempty map of question IDs to Choice, Score, or Noul questions. Mix types in one call. IDs only match answers; put all meaning in instructions/criteria. Questions are independent. The server enforces token limits; plugin JSON guard is 4 MiB."
107
- }),
108
- model: Type.Optional(Type.String({
109
- ...model,
110
- description: "Optional System One model ID or alias for this explicit tool call; defaults to the plugin’s evaluation-tool model. Native decisions use the host-selected model. A local Kev server uses its loaded checkpoint regardless of this label."
111
- }))
112
- }, objectOptions);
113
- const inputValidator = Compile(EvaluateInput);
114
- const distribution = map(probability, {
115
- minProperties: 2,
116
- maxProperties: MAX_CHOICE_OPTIONS
117
- });
118
- const Answer = Type.Union([
119
- Type.Object({
120
- type: Type.Literal("noul"),
121
- noul: probability
122
- }, objectOptions),
123
- Type.Object({
124
- type: Type.Literal("choice"),
125
- choice: Type.String(),
126
- confidence: probability,
127
- probabilities: distribution
128
- }, objectOptions),
129
- Type.Object({
130
- type: Type.Literal("score"),
131
- score: Type.Number({
132
- minimum: 0,
133
- maximum: 9
134
- }),
135
- confidence: probability,
136
- probabilities: distribution,
137
- legend: map(entry, {
138
- minProperties: 2,
139
- maxProperties: MAX_SCORE_LEVELS
140
- })
141
- }, objectOptions)
142
- ]);
143
- const VendorResult = Type.Object({
144
- model,
145
- answers: map(Answer, { minProperties: 1 }),
146
- usage: Type.Object({
147
- input_tokens: Type.Integer({
148
- minimum: 0,
149
- maximum: Number.MAX_SAFE_INTEGER
150
- }),
151
- output_tokens: Type.Integer({
152
- minimum: 0,
153
- maximum: Number.MAX_SAFE_INTEGER
154
- })
155
- }, objectOptions)
156
- }, objectOptions);
157
- const EvaluateOutput = Type.Object({ evaluation: VendorResult }, objectOptions);
158
- const resultValidator = Compile(VendorResult);
159
- /** Reject non-JSON values and excessive structure before schema walking or serialization. */
160
- function assertBoundedJson(value) {
161
- let nodes = 0;
162
- const visit = (node, depth) => {
163
- if (++nodes > MAX_JSON_NODES || depth > MAX_JSON_DEPTH) throw new EvaluationError("TypeSafe JSON exceeds resource limits (262144 nodes or depth 64).", "unsupported-input");
164
- if (node === null || typeof node === "string" || typeof node === "boolean") return;
165
- if (typeof node === "number" && Number.isFinite(node)) return;
166
- if (typeof node !== "object" || !node) throw new EvaluationError("TypeSafe input must be JSON.", "unsupported-input");
167
- const array = Array.isArray(node);
168
- const prototype = Object.getPrototypeOf(node);
169
- if (array ? prototype !== Array.prototype : prototype !== Object.prototype && prototype !== null) throw new EvaluationError("TypeSafe input must be plain JSON.", "unsupported-input");
170
- if (array) {
171
- if (node.length > MAX_JSON_NODES || Object.keys(node).length !== node.length || Object.hasOwn(node, "toJSON")) throw new EvaluationError("TypeSafe input must be a bounded JSON array.", "unsupported-input");
172
- for (let index = 0; index < node.length; index++) {
173
- const descriptor = Object.getOwnPropertyDescriptor(node, index);
174
- if (!descriptor?.enumerable || !("value" in descriptor)) throw new EvaluationError("TypeSafe input must be plain JSON.", "unsupported-input");
175
- visit(descriptor.value, depth + 1);
176
- }
177
- return;
178
- }
179
- for (const key of Object.getOwnPropertyNames(node)) {
180
- if ([
181
- "__proto__",
182
- "constructor",
183
- "prototype"
184
- ].includes(key)) throw new EvaluationError("TypeSafe input contains a reserved key.", "unsupported-input");
185
- const descriptor = Object.getOwnPropertyDescriptor(node, key);
186
- if (!descriptor?.enumerable || !("value" in descriptor)) throw new EvaluationError("TypeSafe input must be plain JSON.", "unsupported-input");
187
- visit(descriptor.value, depth + 1);
188
- }
189
- };
190
- visit(value, 0);
191
- if (Buffer.byteLength(JSON.stringify(value), "utf8") > 4194304) throw new EvaluationError("TypeSafe JSON exceeds the plugin resource limit of 4 MiB.", "unsupported-input");
192
- }
193
- /** Validate without including supplied state in diagnostics. */
194
- function parseInput(value) {
195
- assertBoundedJson(value);
196
- if (!inputValidator.Check(value)) {
197
- if (value && typeof value === "object" && "questions" in value && value.questions && typeof value.questions === "object" && !Array.isArray(value.questions)) {
198
- for (const [index, q] of Object.values(value.questions).entries()) if (!Check(question, q)) {
199
- const kind = q && typeof q === "object" && "type" in q ? q.type : void 0;
200
- const hint = kind === "choice" ? "Choice requires 2–255 criteria descriptions." : kind === "score" ? "Score requires 2–10 ordered criteria descriptions." : kind === "noul" ? "Noul criteria may contain only true/false descriptions, or null." : "type must be choice, score, or noul.";
201
- throw new EvaluationError(`Invalid TypeSafe questions entry #${index + 1}: ${hint} Instructions/descriptions accept text, object, array, or null; no extra question fields.`, "unsupported-input");
202
- }
203
- }
204
- throw new EvaluationError("Invalid TypeSafe evaluation input: supply state (text/object/array/null), a nonempty questions map, and optionally a valid model ID; no extra fields.", "unsupported-input");
205
- }
206
- return value;
207
- }
208
- /** Check the response schema and correspondence to this exact question batch. */
209
- function parseResult(value, input) {
210
- try {
211
- assertBoundedJson(value);
212
- if (!resultValidator.Check(value)) throw new Error();
213
- const questions = Object.entries(input.questions);
214
- if (Object.keys(value.answers).length !== questions.length) throw new Error();
215
- for (const [id, expected] of questions) {
216
- const answer = value.answers[id];
217
- if (!answer || answer.type !== expected.type) throw new Error();
218
- if (answer.type === "noul") continue;
219
- const labels = expected.type === "score" ? expected.criteria.map((_, index) => String(index)) : expected.type === "choice" ? Object.keys(expected.criteria) : [];
220
- if (Object.keys(answer.probabilities).length !== labels.length || labels.some((label) => !Object.hasOwn(answer.probabilities, label))) throw new Error();
221
- if (!(Object.values(answer.probabilities).reduce((sum, item) => sum + item, 0) > 0)) throw new Error();
222
- if (answer.type === "choice" && !labels.includes(answer.choice)) throw new Error();
223
- if (answer.type === "score" && expected.type === "score") {
224
- if (answer.score > labels.length - 1 || Object.keys(answer.legend).length !== labels.length || labels.some((label, index) => !isDeepStrictEqual(answer.legend[label], expected.criteria[index]))) throw new Error();
225
- }
226
- }
227
- return value;
228
- } catch {
229
- throw new Error("TypeSafe returned an invalid evaluation response.");
230
- }
231
- }
232
- //#endregion
233
- //#region extensions/typesafe/src/local.ts
234
- function localInput(input) {
235
- const questions = {};
236
- for (const [id, question] of Object.entries(input.questions)) {
237
- const instructions = question.instructions ?? null;
238
- if (question.type === "score") questions[id] = {
239
- ...question,
240
- instructions,
241
- criteria: question.criteria.map((level) => typeof level === "string" ? level : level === null ? "" : JSON.stringify(level))
242
- };
243
- else questions[id] = {
244
- ...question,
245
- instructions
246
- };
247
- }
248
- return {
249
- ...input,
250
- questions
251
- };
252
- }
253
- function parseLocalResult(value, wireInput, originalInput) {
254
- if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid local System One response.");
255
- let result = value;
256
- if ("latency_ms" in value) {
257
- const { latency_ms, ...payload } = value;
258
- if (typeof latency_ms !== "number" || !Number.isFinite(latency_ms) || latency_ms < 0) throw new Error("Invalid local System One latency metadata.");
259
- result = payload;
260
- }
261
- const evaluation = parseResult(result, wireInput);
262
- for (const [id, question] of Object.entries(originalInput.questions)) {
263
- const answer = evaluation.answers[id];
264
- if (question.type === "score" && answer?.type === "score") answer.legend = Object.fromEntries(question.criteria.map((level, index) => [String(index), level]));
265
- }
266
- return evaluation;
267
- }
268
- //#endregion
269
- //#region extensions/typesafe/src/config.ts
270
- const DEFAULT_MODEL = "jev-latest";
271
- const LOCAL_BASE_URL_PATTERN = "^https?://(?:localhost|127\\.0\\.0\\.1|\\[::1\\])(?::[0-9]{1,5})?/?$";
272
- const localBaseUrlPattern = new RegExp(LOCAL_BASE_URL_PATTERN);
273
- const ConfigSchema = Type.Object({
274
- baseUrl: Type.Optional(Type.String({
275
- maxLength: 128,
276
- pattern: LOCAL_BASE_URL_PATTERN
277
- })),
278
- apiKey: Type.Optional(Type.Object({
279
- source: Type.Union([
280
- Type.Literal("env"),
281
- Type.Literal("store"),
282
- Type.Literal("file"),
283
- Type.Literal("exec")
284
- ]),
285
- provider: Type.String({
286
- minLength: 1,
287
- maxLength: 128
288
- }),
289
- id: Type.String({
290
- minLength: 1,
291
- maxLength: 1024
292
- })
293
- }, { additionalProperties: false })),
294
- model: Type.Optional(Type.String({
295
- minLength: 1,
296
- maxLength: 128,
297
- pattern: "^[a-zA-Z0-9._/-]+$",
298
- description: "Tool default: jev-latest for hosted Jev, kev-latest for a local endpoint."
299
- })),
300
- timeoutMs: Type.Optional(Type.Integer({
301
- minimum: 1e3,
302
- maximum: 6e4,
303
- default: 3e4
304
- }))
305
- }, { additionalProperties: false });
306
- /** A configured endpoint grants access to one loopback origin, never arbitrary private hosts. */
307
- function localBaseUrl(value) {
308
- if (value === void 0) return;
309
- try {
310
- if (typeof value !== "string" || value !== value.trim() || !localBaseUrlPattern.test(value)) throw new Error();
311
- return new URL(value).origin;
312
- } catch {
313
- throw new Error("Invalid TypeSafe baseUrl; use an http(s) loopback origin without a path, credentials, query, or fragment.");
314
- }
315
- }
316
- /** Validate runtime settings and recognize materialized credentials without resolving inputs. */
317
- function runtimeConfig(config) {
318
- const baseUrl = localBaseUrl(config?.baseUrl);
319
- const model = config?.model ?? (baseUrl ? "kev-latest" : DEFAULT_MODEL);
320
- const timeoutMs = config?.timeoutMs ?? 3e4;
321
- if (typeof model !== "string" || !/^[a-zA-Z0-9._/-]{1,128}$/.test(model) || typeof timeoutMs !== "number" || !Number.isInteger(timeoutMs) || timeoutMs < 1e3 || timeoutMs > 6e4) throw new Error("Invalid TypeSafe configuration; check plugin Settings.");
322
- if (baseUrl) return {
323
- baseUrl,
324
- model,
325
- timeoutMs
326
- };
327
- const key = config?.apiKey;
328
- return {
329
- apiKey: typeof key === "string" && key.trim() ? key : void 0,
330
- model,
331
- timeoutMs
332
- };
333
- }
334
- //#endregion
335
- //#region extensions/typesafe/src/transport.ts
336
- const ENDPOINT = "https://api.typesafe.ai/v1/systemone";
337
- function httpError(response) {
338
- if (response.status === 401 || response.status === 403) return new EvaluationError("TypeSafe authentication failed; check the configured credential and account access.", "authentication");
339
- if (response.status === 429) {
340
- const milliseconds = response.headers.get("retry-after-ms");
341
- const parsedMilliseconds = milliseconds?.trim() ? Number(milliseconds) : NaN;
342
- const seconds = parseRetryAfterHeaderSeconds(response.headers.get("retry-after"));
343
- return new EvaluationError("TypeSafe rate limit reached; retry later.", "rate-limited", Number.isFinite(parsedMilliseconds) && parsedMilliseconds >= 0 ? parsedMilliseconds : seconds === void 0 ? void 0 : seconds * 1e3);
344
- }
345
- return new EvaluationError("TypeSafe service rejected the evaluation request.", "transport");
346
- }
347
- async function readBody(response, signal) {
348
- const reader = response.body?.getReader();
349
- if (!reader) {
350
- signal?.throwIfAborted();
351
- return Buffer.alloc(0);
352
- }
353
- let cancellation;
354
- const cancel = () => {
355
- cancellation ??= reader.cancel().catch(() => {});
356
- };
357
- signal?.addEventListener("abort", cancel, { once: true });
358
- const chunks = [];
359
- let length = 0;
360
- try {
361
- while (true) {
362
- signal?.throwIfAborted();
363
- const chunk = await reader.read();
364
- signal?.throwIfAborted();
365
- if (chunk.done) break;
366
- length += chunk.value.byteLength;
367
- if (length > 4194304) throw new EvaluationError("TypeSafe response exceeds its limit.", "invalid-response");
368
- chunks.push(chunk.value);
369
- }
370
- return Buffer.concat(chunks, length);
371
- } catch (error) {
372
- cancel();
373
- throw error;
374
- } finally {
375
- signal?.removeEventListener("abort", cancel);
376
- await cancellation;
377
- reader.releaseLock();
378
- }
379
- }
380
- async function requestEvaluation(params) {
381
- const baseUrl = localBaseUrl(params.baseUrl);
382
- const endpoint = baseUrl ? `${baseUrl}/v1/systemone` : ENDPOINT;
383
- const body = JSON.stringify(params.body);
384
- if (Buffer.byteLength(body) > 4194304) throw new EvaluationError("TypeSafe request exceeds its limit.", "unsupported-input");
385
- const timeoutMs = params.deadlineMonotonicMs === void 0 ? params.timeoutMs : Math.min(params.timeoutMs, params.deadlineMonotonicMs - performance.now());
386
- if (timeoutMs <= 0) throw new EvaluationError("TypeSafe evaluation timed out.", "transport");
387
- const { signal, cleanup } = buildTimeoutAbortSignal({
388
- signal: params.signal,
389
- timeoutMs,
390
- operation: "TypeSafe evaluation"
391
- });
392
- const assertActive = () => {
393
- signal?.throwIfAborted();
394
- if (params.deadlineMonotonicMs !== void 0 && performance.now() >= params.deadlineMonotonicMs) throw new EvaluationError("TypeSafe evaluation timed out.", "transport");
395
- };
396
- try {
397
- assertActive();
398
- const request = {
399
- url: endpoint,
400
- fetchImpl: globalThis.fetch,
401
- requireHttps: !baseUrl,
402
- ...baseUrl ? { policy: { allowedOrigins: [baseUrl] } } : {},
403
- ...baseUrl && new URL(baseUrl).hostname === "localhost" ? { lookupFn: async () => [{
404
- address: "127.0.0.1",
405
- family: 4
406
- }, {
407
- address: "::1",
408
- family: 6
409
- }] } : {},
410
- maxRedirects: 0,
411
- signal,
412
- beforeRequest: assertActive,
413
- init: {
414
- method: "POST",
415
- headers: {
416
- ...!baseUrl ? { Authorization: `Bearer ${params.apiKey}` } : {},
417
- Accept: "application/json",
418
- "Content-Type": "application/json"
419
- },
420
- body
421
- }
422
- };
423
- const guarded = await fetchWithSsrFGuard(!baseUrl && shouldUseEnvHttpProxyForUrl(endpoint) ? withTrustedEnvProxyGuardedFetchMode(request) : request);
424
- let releasePromise;
425
- const release = () => releasePromise ??= Promise.resolve().then(() => guarded.release());
426
- let payload;
427
- try {
428
- const response = responseWithRelease(guarded.response, release);
429
- if (!response.ok) {
430
- await response.body?.cancel();
431
- throw httpError(response);
432
- }
433
- const bytes = await readBody(response, signal);
434
- try {
435
- payload = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
436
- } catch {
437
- throw new EvaluationError("TypeSafe returned invalid JSON.", "invalid-response");
438
- }
439
- } finally {
440
- await release();
441
- }
442
- signal?.throwIfAborted();
443
- return payload;
444
- } catch (error) {
445
- if (params.signal?.aborted) throw new EvaluationError("TypeSafe evaluation cancelled.", "transport");
446
- if (signal?.aborted) throw new EvaluationError("TypeSafe evaluation timed out.", "transport");
447
- if (error instanceof EvaluationError) throw error;
448
- throw new EvaluationError("TypeSafe transport unavailable.", "transport");
449
- } finally {
450
- cleanup();
451
- }
452
- }
453
- //#endregion
454
- //#region extensions/typesafe/src/client.ts
455
- /** Evaluate explicit state without ambient credentials, retries, or vendor diagnostics. */
456
- async function evaluate(input, config, signal, deadlineMonotonicMs) {
457
- if (signal?.aborted) throw evaluationError(void 0, true);
458
- const parsed = parseInput(input);
459
- const model = parsed.model ?? config.model;
460
- if (model === "kev-latest" && !config.baseUrl) throw new EvaluationError("Kev requires a local System One server. Configure baseUrl in TypeSafe plugin Settings.", "unsupported-input");
461
- if (!config.baseUrl && !config.apiKey) throw new Error("TypeSafe API key is missing. Configure a SecretRef in plugin Settings.");
462
- try {
463
- const wireInput = config.baseUrl ? localInput(parsed) : parsed;
464
- const response = await requestEvaluation({
465
- body: {
466
- ...wireInput,
467
- model
468
- },
469
- apiKey: config.baseUrl ? void 0 : config.apiKey,
470
- baseUrl: config.baseUrl,
471
- timeoutMs: config.timeoutMs,
472
- signal,
473
- deadlineMonotonicMs
474
- });
475
- signal?.throwIfAborted();
476
- const evaluation = config.baseUrl ? parseLocalResult(response, wireInput, parsed) : parseResult(response, parsed);
477
- if (!config.baseUrl && config.apiKey && JSON.stringify(evaluation).includes(config.apiKey)) throw new Error("Invalid TypeSafe response.");
478
- return { evaluation };
479
- } catch (error) {
480
- throw evaluationError(error, signal?.aborted ?? false);
481
- }
482
- }
483
- //#endregion
4
+ import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
484
5
  //#region extensions/typesafe/src/credentials.ts
485
6
  /** Only host-prepared capability snapshots may supply a credential. Never resolve or cache refs. */
486
7
  function resolveRuntimeConfig(snapshot) {
@@ -495,7 +16,8 @@ function resolveRuntimeConfig(snapshot) {
495
16
  }
496
17
  //#endregion
497
18
  //#region extensions/typesafe/src/decisions.ts
498
- /** Transport and result validation are shared with the independently usable agent tool. */
19
+ const loadClient = createLazyRuntimeModule(() => import("./.setup/client-CRLm45hB.mjs"));
20
+ /** Translate the host-selected decision contract through the TypeSafe transport. */
499
21
  function createDecisionProvider(getConfig) {
500
22
  return {
501
23
  id: "typesafe",
@@ -505,6 +27,8 @@ function createDecisionProvider(getConfig) {
505
27
  return Boolean(config.baseUrl || config.apiKey);
506
28
  },
507
29
  async evaluate(batch, context) {
30
+ context.signal.throwIfAborted();
31
+ const { evaluate: evaluateTypeSafe } = await loadClient();
508
32
  context.signal.throwIfAborted();
509
33
  const config = getConfig();
510
34
  if (!config.baseUrl && !config.apiKey) return {
@@ -521,7 +45,7 @@ function createDecisionProvider(getConfig) {
521
45
  type: "noul"
522
46
  } : q]));
523
47
  try {
524
- const { evaluation } = await evaluate({
48
+ const { evaluation } = await evaluateTypeSafe({
525
49
  state: batch.state,
526
50
  questions,
527
51
  model: context.model
@@ -572,32 +96,10 @@ function createDecisionProvider(getConfig) {
572
96
  var typesafe_default = definePluginEntry({
573
97
  id: "typesafe",
574
98
  name: "TypeSafe AI",
575
- description: "Explicit typed evaluations, not a conversational model provider.",
99
+ description: "Typed decision provider for hosted Jev and local System One models.",
576
100
  configSchema: { jsonSchema: { ...ConfigSchema } },
577
101
  register(api) {
578
102
  api.registerDecisionProvider(createDecisionProvider(() => resolveRuntimeConfig(api.runtime.config.current())));
579
- api.registerTool({
580
- name: "typesafe_evaluate",
581
- label: "TypeSafe typed decisions",
582
- description: "Ask the configured System One model for typed decisions over explicit shared state: classify/select with Choice (2–255 options), rate with Score (2–10 ordered levels; fractional zero-based result), or estimate probability of yes with Noul (optional true/false criteria). Batch independent questions; they cannot see each other’s answers. Instructions and descriptions accept text, JSON objects/arrays, or null. Returns distributions, confidence for Choice/Score, model, and usage—not generated explanations or authorization. Hosted Jev requires credentials and may incur API charges; a configured local Kev endpoint receives supplied data without hosted credentials.",
583
- parameters: EvaluateInput,
584
- outputSchema: EvaluateOutput,
585
- resultContentSource: "network",
586
- async execute(_id, params, signal) {
587
- signal?.throwIfAborted();
588
- const config = resolveRuntimeConfig(api.runtime.config.current());
589
- if (!config.baseUrl && !config.apiKey) throw new Error("TypeSafe API key is missing. Configure a SecretRef in plugin Settings.");
590
- const details = await evaluate(params, config, signal);
591
- signal?.throwIfAborted();
592
- return {
593
- content: [{
594
- type: "text",
595
- text: JSON.stringify(details)
596
- }],
597
- details
598
- };
599
- }
600
- }, { optional: true });
601
103
  }
602
104
  });
603
105
  //#endregion
@@ -16,9 +16,8 @@ function Separator() {
16
16
  function ImportSection(build) {
17
17
  const context = build.UseUnevaluated() ? [`import { CheckContext } from "typebox/schema"`] : [];
18
18
  const hashing = `import { Hashing } from "typebox/system"`;
19
- const format = `import { Format } from "typebox/format"`;
20
19
  const guard = `import { Guard } from "typebox/guard"`;
21
- return [...context, hashing, format, guard];
20
+ return [...context, hashing, guard];
22
21
  }
23
22
  // ------------------------------------------------------------------
24
23
  // ExternalSection
@@ -1,4 +1,5 @@
1
1
  // deno-fmt-ignore-file
2
+ import { EnableParseErrors, DisableParseErrors } from '../system/settings/internal.mjs';
2
3
  import { Settings } from '../system/settings/index.mjs';
3
4
  import { Errors, Clean, Convert, Create, Default, Decode, Encode, HasCodec, Parser, ParseError } from '../value/index.mjs';
4
5
  import { Build } from '../schema/index.mjs';
@@ -51,7 +52,10 @@ export class Validator {
51
52
  return value;
52
53
  if (Settings.Get().correctiveParse)
53
54
  return Parser(this.Context(), this.Type(), value);
54
- throw new ParseError(value, this.Errors(value));
55
+ EnableParseErrors();
56
+ const errors = this.Errors(value);
57
+ DisableParseErrors();
58
+ throw new ParseError(value, errors);
55
59
  }
56
60
  /** Returns an array of validation errors for the given value. */
57
61
  Errors(value) {
@@ -1,9 +1,10 @@
1
1
  // deno-lint-ignore-file no-control-regex
2
- const IpvFutureMatchMaxLength = 2048;
3
- const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/; // Guarded By IpvFutureMatchMaxLength
4
- const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
5
- const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
6
2
  // ------------------------------------------------------------------
3
+ //
4
+ // Removed by the following PR
5
+ //
6
+ // https://github.com/json-schema-org/JSON-Schema-Test-Suite/pull/1176
7
+ //
7
8
  // NarrowIpvFuture
8
9
  //
9
10
  // Substitutes an IPvFuture address with a standard IPv6 loopback
@@ -13,12 +14,18 @@ const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
13
14
  // be expensive on large strings, this operation is strictly
14
15
  // limited to inputs under a defined length threshold.
15
16
  //
16
- // (review-optimization)
17
+ // ------------------------------------------------------------------
18
+ //
19
+ // const IpvFutureMatchMaxLength = 2048
20
+ // const IpvFutureMatch = /\[[vV][0-9a-fA-F]+\.[^\]]+\]/ // Guarded By IpvFutureMatchMaxLength
21
+ //
22
+ // function NarrowIpvFuture(value: string): string {
23
+ // return value.length < IpvFutureMatchMaxLength ? value.replace(IpvFutureMatch, '[::1]') : value
24
+ // }
17
25
  //
18
26
  // ------------------------------------------------------------------
19
- function NarrowIpvFuture(value) {
20
- return value.length < IpvFutureMatchMaxLength ? value.replace(IpvFutureMatch, '[::1]') : value;
21
- }
27
+ const InvalidIriChars = /[\x00-\x20<>\^`{|}\\]/;
28
+ const InvalidPercentEncoding = /%(?![0-9a-fA-F]{2})/;
22
29
  /**
23
30
  * Returns true if the value is a valid Internationalized Resource Identifier.
24
31
  * @specification https://datatracker.ietf.org/doc/html/rfc3987
@@ -31,5 +38,5 @@ export function IsIri(value) {
31
38
  if (InvalidPercentEncoding.test(value))
32
39
  return false;
33
40
  // 3. Delegate to the native URL parser, patching the IPvFuture edge case beforehand.
34
- return URL.canParse(NarrowIpvFuture(value));
41
+ return URL.canParse(value);
35
42
  }
@@ -97,10 +97,10 @@ export function IsGreaterEqualThan(left, right) {
97
97
  // String
98
98
  // --------------------------------------------------------------------------
99
99
  export function IsMinLength(value, length) {
100
- return `Guard.IsMinLength(${value}, ${length})`;
100
+ return `(${value}.length >= ${(+length) << 1} || (${value}.length >= ${length} && Guard.CodePointCount(${value}) >= ${length}))`;
101
101
  }
102
102
  export function IsMaxLength(value, length) {
103
- return `Guard.IsMaxLength(${value}, ${length})`;
103
+ return `(${value}.length <= ${length} || (${value}.length <= ${(+length) << 1} && Guard.CodePointCount(${value}) <= ${length}))`;
104
104
  }
105
105
  // --------------------------------------------------------------------------
106
106
  // Array
@@ -33,12 +33,14 @@ export declare function IsMultipleOf(dividend: bigint | number, divisor: bigint
33
33
  /** Returns true if the value appears to be an instance of a class. */
34
34
  export declare function IsClassInstance(value: unknown): boolean;
35
35
  export declare function IsValueLike(value: unknown): value is bigint | boolean | null | number | string | undefined;
36
- /** Returns the number of grapheme clusters in the string */
36
+ /** Returns the total number of visual grapheme clusters in the string. */
37
37
  export declare function GraphemeCount(value: string): number;
38
- /** Returns true if the string has at most the given number of graphemes */
39
- export declare function IsMaxLength(value: string, length: number): boolean;
40
- /** Returns true if the string has at least the given number of graphemes */
41
- export declare function IsMinLength(value: string, length: number): boolean;
38
+ /** Returns the total number of Unicode code points in the string. */
39
+ export declare function CodePointCount(value: string): number;
40
+ /** Returns true if the string length in Unicode code points does not exceed maxLength */
41
+ export declare function IsMaxLength(value: string, maxLength: number): boolean;
42
+ /** Returns true if the string length in Unicode code points is at least minLength */
43
+ export declare function IsMinLength(value: string, minLength: number): boolean;
42
44
  /** Returns true if every element from offset satisfies the callback, short-circuiting on the first failure */
43
45
  export declare function Every<T>(value: T[], offset: number, callback: (value: T, index: number) => boolean): boolean;
44
46
  /** Returns true if every element from offset satisfies the callback, using exhaustive enumeration */