@wrongstack/runtime 0.284.0 → 0.285.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/dist/clipboard.d.ts +4 -5
- package/dist/clipboard.d.ts.map +1 -0
- package/dist/clipboard.js +10 -10
- package/dist/clipboard.js.map +7 -1
- package/dist/container.d.ts +36 -0
- package/dist/container.d.ts.map +1 -0
- package/dist/fleet/light-subagent-factory.d.ts +25 -0
- package/dist/fleet/light-subagent-factory.d.ts.map +1 -0
- package/dist/host.d.ts +10 -12
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +5 -3
- package/dist/host.js.map +7 -1
- package/dist/index.d.ts +23 -62
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +99 -28
- package/dist/index.js.map +7 -1
- package/dist/local-llm-probe.d.ts +59 -0
- package/dist/local-llm-probe.d.ts.map +1 -0
- package/dist/pack.d.ts +3 -5
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +0 -2
- package/dist/pack.js.map +7 -1
- package/dist/probe.d.ts +1 -62
- package/dist/probe.js +3 -3
- package/dist/probe.js.map +7 -1
- package/dist/vision.d.ts +16 -18
- package/dist/vision.d.ts.map +1 -0
- package/dist/vision.js +14 -8
- package/dist/vision.js.map +7 -1
- package/package.json +5 -5
package/dist/probe.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/local-llm-probe.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Local-LLM health probe \u2014 `GET <baseUrl>/v1/models`.\n *\n * This module lives in `@wrongstack/runtime` (not `@wrongstack/cli` or\n * `@wrongstack/providers`) so the WebUI server can reuse it without\n * pulling in the entire CLI dependency graph. The function is\n * identical to the one in `@wrongstack/cli/src/auth-menu/local.ts` \u2014\n * we keep a single canonical implementation here and have the CLI\n * re-export from this one.\n *\n * The probe:\n * - Hits `GET <baseUrl>/models` (OpenAI-compatible)\n * - Sends an optional `Authorization: Bearer <key>` header\n * - Scrubs every result through the `SecretScrubber` so a Bearer\n * token accidentally captured in an error page never reaches\n * the renderer\n * - Returns a `ProbeResult` (never throws) so the caller can\n * decide how to react to each `status`\n */\nimport type { SecretScrubber } from '@wrongstack/core';\n\n/** Default probe timeout. Local servers should respond in < 100ms. */\nconst PROBE_TIMEOUT_MS = 3_000;\n\nexport interface ProbeOptions {\n baseUrl: string;\n apiKey: string | undefined;\n noAuth: boolean;\n /**\n * Display label for the probed server \u2014 the CLI uses this in the\n * rendered probe result (\"Ollama health probe ok\"). Optional; the\n * probe itself doesn't care.\n */\n presetLabel?: string | undefined;\n /** Used to scrub error-page bodies and network error messages. */\n scrubber: SecretScrubber;\n fetchImpl?: typeof fetch | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport interface ProbeResult {\n ok: boolean;\n status:\n | 'ok'\n | 'unreachable'\n | 'timeout'\n | 'http_error'\n | 'invalid_response'\n | 'skipped'\n | 'no_provider'\n | 'no_base_url';\n httpStatus?: number | undefined;\n elapsedMs?: number | undefined;\n modelCount?: number | undefined;\n /**\n * The actual model ids returned by the server, deduplicated, in\n * server-reported order. Empty (not undefined) when the server\n * returned a valid empty list.\n */\n modelIds?: string[] | undefined;\n /** Redactable error detail (e.g. ECONNREFUSED). */\n detail?: string | undefined;\n}\n\n/**\n * Probe a local LLM server by hitting the OpenAI-compatible\n * `GET /v1/models` endpoint.\n *\n * The probe is fully isolated from the config layer \u2014 it only\n * returns a `ProbeResult` and never throws.\n */\nexport async function probeLocalLlm(opts: ProbeOptions): Promise<ProbeResult> {\n const { baseUrl, apiKey, noAuth, scrubber, fetchImpl, timeoutMs } = opts;\n const fetchFn = fetchImpl ?? fetch;\n const timeout = timeoutMs ?? PROBE_TIMEOUT_MS;\n\n // Normalize the URL: append `/models` if the user gave us the chat\n // completions base. Strip trailing slashes so we can just concatenate.\n const base = baseUrl.replace(/\\/+$/, '');\n const url = /\\/models$/.test(base) ? base : `${base}/models`;\n\n const headers: Record<string, string> = { accept: 'application/json' };\n if (!noAuth && apiKey) {\n headers['authorization'] = `Bearer ${apiKey}`;\n }\n\n const started = Date.now();\n let res: Response;\n try {\n res = await fetchFn(url, {\n method: 'GET',\n headers,\n signal: AbortSignal.timeout(timeout),\n });\n } catch (err) {\n const elapsed = Date.now() - started;\n const name = (err as { name?: string } | null)?.name;\n if (name === 'TimeoutError' || name === 'AbortError') {\n return { ok: false, status: 'timeout', elapsedMs: elapsed, detail: `> ${timeout}ms` };\n }\n const detail = scrubber.scrub((err as Error)?.message ?? String(err));\n return { ok: false, status: 'unreachable', elapsedMs: elapsed, detail };\n }\n\n const elapsed = Date.now() - started;\n\n if (!res.ok) {\n let bodySlice = '';\n try {\n const txt = await res.text();\n bodySlice = txt.slice(0, 200);\n } catch {\n // ignore\n }\n return {\n ok: false,\n status: 'http_error',\n httpStatus: res.status,\n elapsedMs: elapsed,\n detail: scrubber.scrub(bodySlice) || undefined,\n };\n }\n\n const modelIds: string[] = [];\n try {\n const parsed = (await res.json()) as unknown;\n if (!parsed || typeof parsed !== 'object') {\n return {\n ok: false,\n status: 'invalid_response',\n httpStatus: res.status,\n elapsedMs: elapsed,\n detail: 'response is not a JSON object',\n };\n }\n const obj = parsed as Record<string, unknown>;\n const dataList = obj['data'];\n const modelsList = obj['models'];\n const rawList: unknown[] | null = Array.isArray(dataList)\n ? (dataList as unknown[])\n : Array.isArray(modelsList)\n ? (modelsList as unknown[])\n : null;\n if (rawList === null) {\n return {\n ok: false,\n status: 'invalid_response',\n httpStatus: res.status,\n elapsedMs: elapsed,\n detail: 'no `data` or `models` array in response',\n };\n }\n const seen = new Set<string>();\n for (const entry of rawList) {\n if (!entry || typeof entry !== 'object') continue;\n const e = entry as Record<string, unknown>;\n const raw =\n typeof e['id'] === 'string' ? e['id'] : typeof e['name'] === 'string' ? e['name'] : null;\n if (raw === null) continue;\n const id = scrubber.scrub(raw).trim();\n if (id.length === 0) continue;\n if (seen.has(id)) continue;\n seen.add(id);\n modelIds.push(id);\n }\n } catch (err) {\n return {\n ok: false,\n status: 'invalid_response',\n httpStatus: res.status,\n elapsedMs: elapsed,\n detail: scrubber.scrub((err as Error)?.message ?? 'parse failed'),\n };\n }\n\n return {\n ok: true,\n status: 'ok',\n httpStatus: res.status,\n elapsedMs: elapsed,\n modelCount: modelIds.length,\n modelIds,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["elapsed"]
|
|
7
|
+
}
|
package/dist/vision.d.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
interface VisionAdapterInput {
|
|
1
|
+
import type { ContentBlock, Context, ImageBlock, ToolRegistry } from '@wrongstack/core';
|
|
2
|
+
export interface VisionAdapterInput {
|
|
4
3
|
image: ImageBlock;
|
|
5
4
|
prompt?: string | undefined;
|
|
6
5
|
ctx: Context;
|
|
7
6
|
signal: AbortSignal;
|
|
8
7
|
}
|
|
9
|
-
interface VisionAdapter {
|
|
8
|
+
export interface VisionAdapter {
|
|
10
9
|
name: string;
|
|
11
10
|
describe(input: VisionAdapterInput): Promise<string>;
|
|
12
11
|
}
|
|
13
|
-
type VisionAdapters = readonly VisionAdapter[] | (() => readonly VisionAdapter[] | Promise<readonly VisionAdapter[]>);
|
|
14
|
-
interface VisionRoutingOptions {
|
|
12
|
+
export type VisionAdapters = readonly VisionAdapter[] | (() => readonly VisionAdapter[] | Promise<readonly VisionAdapter[]>);
|
|
13
|
+
export interface VisionRoutingOptions {
|
|
15
14
|
supportsVision: boolean;
|
|
16
15
|
adapters?: VisionAdapters | undefined;
|
|
17
16
|
ctx: Context;
|
|
@@ -20,13 +19,13 @@ interface VisionRoutingOptions {
|
|
|
20
19
|
providerId?: string | undefined;
|
|
21
20
|
model?: string | undefined;
|
|
22
21
|
}
|
|
23
|
-
interface VisionRoutingResult {
|
|
22
|
+
export interface VisionRoutingResult {
|
|
24
23
|
blocks: ContentBlock[];
|
|
25
24
|
route: 'native' | 'adapter' | 'none';
|
|
26
25
|
convertedImages: number;
|
|
27
26
|
adapterName?: string | undefined;
|
|
28
27
|
}
|
|
29
|
-
declare class ImageInputUnsupportedError extends Error {
|
|
28
|
+
export declare class ImageInputUnsupportedError extends Error {
|
|
30
29
|
constructor(opts: {
|
|
31
30
|
providerId?: string | undefined;
|
|
32
31
|
model?: string | undefined;
|
|
@@ -43,21 +42,20 @@ declare class ImageInputUnsupportedError extends Error {
|
|
|
43
42
|
* Carries the rejected URL so callers can log / surface it without parsing
|
|
44
43
|
* the message.
|
|
45
44
|
*/
|
|
46
|
-
declare class VisionUrlBlockedError extends Error {
|
|
45
|
+
export declare class VisionUrlBlockedError extends Error {
|
|
47
46
|
readonly url: string;
|
|
48
47
|
constructor(opts: {
|
|
49
48
|
url: string;
|
|
50
49
|
reason: string;
|
|
51
50
|
});
|
|
52
51
|
}
|
|
53
|
-
declare function routeImagesForModel(blocks: ContentBlock[], opts: VisionRoutingOptions): Promise<VisionRoutingResult>;
|
|
54
|
-
interface ToolVisionAdapterOptions {
|
|
52
|
+
export declare function routeImagesForModel(blocks: ContentBlock[], opts: VisionRoutingOptions): Promise<VisionRoutingResult>;
|
|
53
|
+
export interface ToolVisionAdapterOptions {
|
|
55
54
|
prompt?: string | undefined;
|
|
56
55
|
}
|
|
57
|
-
declare function createToolVisionAdapters(registry: ToolRegistry, opts?: ToolVisionAdapterOptions): VisionAdapter[];
|
|
58
|
-
declare const VISION_IMAGE_KEYS: readonly [
|
|
59
|
-
declare const VISION_PATH_KEYS: readonly [
|
|
60
|
-
declare const VISION_MEDIA_TYPE_KEYS: readonly [
|
|
61
|
-
declare const VISION_PROMPT_KEYS: readonly [
|
|
62
|
-
|
|
63
|
-
export { ImageInputUnsupportedError, type ToolVisionAdapterOptions, VISION_IMAGE_KEYS, VISION_MEDIA_TYPE_KEYS, VISION_PATH_KEYS, VISION_PROMPT_KEYS, type VisionAdapter, type VisionAdapterInput, type VisionAdapters, type VisionRoutingOptions, type VisionRoutingResult, VisionUrlBlockedError, createToolVisionAdapters, routeImagesForModel };
|
|
56
|
+
export declare function createToolVisionAdapters(registry: ToolRegistry, opts?: ToolVisionAdapterOptions): VisionAdapter[];
|
|
57
|
+
export declare const VISION_IMAGE_KEYS: readonly ['image', 'base64', 'data', 'url', 'image_url', 'imageUrl', 'path', 'image_path', 'imagePath', 'file_path', 'filePath', 'filename', 'file', 'mediaType', 'mimeType'];
|
|
58
|
+
export declare const VISION_PATH_KEYS: readonly ['path', 'image_path', 'imagePath', 'image_url', 'imageUrl', 'file_path', 'filePath', 'filename', 'file'];
|
|
59
|
+
export declare const VISION_MEDIA_TYPE_KEYS: readonly ['mediaType', 'mimeType', 'media_type'];
|
|
60
|
+
export declare const VISION_PROMPT_KEYS: readonly ['prompt', 'query', 'instruction'];
|
|
61
|
+
//# sourceMappingURL=vision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision.d.ts","sourceRoot":"","sources":["../src/vision.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAQ,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG9F,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACtD;AAED,MAAM,MAAM,cAAc,GACtB,SAAS,aAAa,EAAE,GACxB,CAAC,MAAM,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACtC,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,YAAY,IAAI,EAAE;QAChB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAChC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC3B,UAAU,EAAE,MAAM,CAAC;KACpB,EAMA;CACF;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB,YAAY,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAIhD;CACF;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,YAAY,EAAE,EACtB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,mBAAmB,CAAC,CAsE9B;AASD,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,EACtB,IAAI,GAAE,wBAA6B,GAClC,aAAa,EAAE,CA2BjB;AAED,eAAO,MAAM,iBAAiB,YAC5B,OAAO,EACP,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAAW,EACX,UAAU,EACV,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,MAAM,EACN,WAAW,EACX,UAAU,CACF,CAAC;AAEX,eAAO,MAAM,gBAAgB,YAC3B,MAAM,EACN,YAAY,EACZ,WAAW,EACX,WAAW,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,MAAM,CACE,CAAC;AAEX,eAAO,MAAM,sBAAsB,YAAI,WAAW,EAAE,UAAU,EAAE,YAAY,CAAU,CAAC;AACvF,eAAO,MAAM,kBAAkB,YAAI,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAU,CAAC"}
|
package/dist/vision.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import * as fs from 'fs/promises';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import { assertNotPrivateHost } from '@wrongstack/core';
|
|
5
|
-
|
|
6
1
|
// src/vision.ts
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { assertNotPrivateHost } from "@wrongstack/core";
|
|
7
6
|
var ImageInputUnsupportedError = class extends Error {
|
|
8
7
|
constructor(opts) {
|
|
9
8
|
const target = [opts.providerId, opts.model].filter(Boolean).join("/") || "current model";
|
|
@@ -231,7 +230,14 @@ function stringifyToolResult(value) {
|
|
|
231
230
|
}
|
|
232
231
|
return JSON.stringify(value);
|
|
233
232
|
}
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
export {
|
|
234
|
+
ImageInputUnsupportedError,
|
|
235
|
+
VISION_IMAGE_KEYS,
|
|
236
|
+
VISION_MEDIA_TYPE_KEYS,
|
|
237
|
+
VISION_PATH_KEYS,
|
|
238
|
+
VISION_PROMPT_KEYS,
|
|
239
|
+
VisionUrlBlockedError,
|
|
240
|
+
createToolVisionAdapters,
|
|
241
|
+
routeImagesForModel
|
|
242
|
+
};
|
|
236
243
|
//# sourceMappingURL=vision.js.map
|
|
237
|
-
//# sourceMappingURL=vision.js.map
|
package/dist/vision.js.map
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vision.ts"],"names":[],"mappings":"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","file":"vision.js","sourcesContent":["import * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ContentBlock, Context, ImageBlock, Tool, ToolRegistry } from '@wrongstack/core';\nimport { assertNotPrivateHost } from '@wrongstack/core';\n\nexport interface VisionAdapterInput {\n image: ImageBlock;\n prompt?: string | undefined;\n ctx: Context;\n signal: AbortSignal;\n}\n\nexport interface VisionAdapter {\n name: string;\n describe(input: VisionAdapterInput): Promise<string>;\n}\n\nexport type VisionAdapters =\n | readonly VisionAdapter[]\n | (() => readonly VisionAdapter[] | Promise<readonly VisionAdapter[]>);\n\nexport interface VisionRoutingOptions {\n supportsVision: boolean;\n adapters?: VisionAdapters | undefined;\n ctx: Context;\n signal: AbortSignal;\n prompt?: string | undefined;\n providerId?: string | undefined;\n model?: string | undefined;\n}\n\nexport interface VisionRoutingResult {\n blocks: ContentBlock[];\n route: 'native' | 'adapter' | 'none';\n convertedImages: number;\n adapterName?: string | undefined;\n}\n\nexport class ImageInputUnsupportedError extends Error {\n constructor(opts: {\n providerId?: string | undefined;\n model?: string | undefined;\n imageCount: number;\n }) {\n const target = [opts.providerId, opts.model].filter(Boolean).join('/') || 'current model';\n super(\n `${target} does not support image input, and no image-understanding adapter is available for ${opts.imageCount} image${opts.imageCount === 1 ? '' : 's'}. Switch to a vision model or enable an MCP/tool adapter that can describe images.`,\n );\n this.name = 'ImageInputUnsupportedError';\n }\n}\n\n/**\n * Thrown when an image URL targets a private / loopback / IMDS address.\n * Vision adapters forward URLs straight to the underlying tool, so without\n * this check a malicious (or accidentally-malformed) `image.source.url`\n * could turn image analysis into an SSRF vector hitting localhost, RFC1918\n * ranges, or the cloud metadata endpoint.\n *\n * Carries the rejected URL so callers can log / surface it without parsing\n * the message.\n */\nexport class VisionUrlBlockedError extends Error {\n readonly url: string;\n\n constructor(opts: { url: string; reason: string }) {\n super(`vision: blocked unsafe image URL \"${opts.url}\" (${opts.reason})`);\n this.name = 'VisionUrlBlockedError';\n this.url = opts.url;\n }\n}\n\nexport async function routeImagesForModel(\n blocks: ContentBlock[],\n opts: VisionRoutingOptions,\n): Promise<VisionRoutingResult> {\n const images = blocks.filter((b): b is ImageBlock => b.type === 'image');\n if (images.length === 0) {\n return { blocks, route: 'none', convertedImages: 0 };\n }\n if (opts.supportsVision) {\n // Native vision providers typically fetch image URLs server-side, so\n // enforce the same SSRF guard used for adapter routes.\n for (const img of images) {\n if (img.source.type === 'url' && img.source.url) {\n try {\n await assertNotPrivateHost(new URL(img.source.url).hostname);\n } catch (err) {\n const reason =\n err instanceof Error && err.message.startsWith('fetch:')\n ? err.message.slice('fetch:'.length).trim()\n : 'unresolvable host';\n throw new VisionUrlBlockedError({ url: img.source.url, reason });\n }\n }\n }\n return { blocks, route: 'native', convertedImages: 0 };\n }\n\n const adapters = await resolveAdapters(opts.adapters);\n if (adapters.length === 0) {\n throw new ImageInputUnsupportedError({\n providerId: opts.providerId,\n model: opts.model,\n imageCount: images.length,\n });\n }\n\n const out: ContentBlock[] = [];\n let convertedImages = 0;\n let lastErr: unknown;\n let adapterName: string | undefined;\n for (const block of blocks) {\n if (block.type !== 'image') {\n out.push(block);\n continue;\n }\n let description: string | undefined;\n for (const adapter of adapters) {\n try {\n description = await adapter.describe({\n image: block,\n prompt: opts.prompt,\n ctx: opts.ctx,\n signal: opts.signal,\n });\n adapterName = adapter.name;\n break;\n } catch (err) {\n lastErr = err;\n }\n }\n if (!description?.trim()) {\n throw new Error(\n `No image-understanding adapter could process an image.${lastErr instanceof Error ? ` Last error: ${lastErr.message}` : ''}`,\n );\n }\n convertedImages++;\n out.push({\n type: 'text',\n text: `[Image ${convertedImages} analyzed via ${adapterName ?? 'vision adapter'}]\\n${description.trim()}`,\n });\n }\n\n return { blocks: out, route: 'adapter', convertedImages, adapterName };\n}\n\nasync function resolveAdapters(\n adapters: VisionAdapters | undefined,\n): Promise<readonly VisionAdapter[]> {\n if (!adapters) return [];\n return typeof adapters === 'function' ? await adapters() : adapters;\n}\n\nexport interface ToolVisionAdapterOptions {\n prompt?: string | undefined;\n}\n\nexport function createToolVisionAdapters(\n registry: ToolRegistry,\n opts: ToolVisionAdapterOptions = {},\n): VisionAdapter[] {\n return registry\n .list()\n .filter(isLikelyVisionTool)\n .map((tool) => ({\n name: tool.name,\n async describe(input: VisionAdapterInput): Promise<string> {\n const currentTool = registry.get(tool.name);\n if (!currentTool) {\n throw new Error(`Tool \"${tool.name}\" is no longer registered`);\n }\n const built = await buildToolPayload(currentTool, input.image, input.prompt ?? opts.prompt);\n if (!built) {\n throw new Error(\n `Tool \"${currentTool.name}\" does not expose a supported image input schema`,\n );\n }\n try {\n const result = await currentTool.execute(built.payload, input.ctx, {\n signal: input.signal,\n });\n return stringifyToolResult(result);\n } finally {\n await built.cleanup?.();\n }\n },\n }));\n}\n\nexport const VISION_IMAGE_KEYS = [\n 'image',\n 'base64',\n 'data',\n 'url',\n 'image_url',\n 'imageUrl',\n 'path',\n 'image_path',\n 'imagePath',\n 'file_path',\n 'filePath',\n 'filename',\n 'file',\n 'mediaType',\n 'mimeType',\n] as const;\n\nexport const VISION_PATH_KEYS = [\n 'path',\n 'image_path',\n 'imagePath',\n 'image_url',\n 'imageUrl',\n 'file_path',\n 'filePath',\n 'filename',\n 'file',\n] as const;\n\nexport const VISION_MEDIA_TYPE_KEYS = ['mediaType', 'mimeType', 'media_type'] as const;\nexport const VISION_PROMPT_KEYS = ['prompt', 'query', 'instruction'] as const;\n\nfunction isLikelyVisionTool(tool: Tool): boolean {\n if (tool.permission !== 'auto' || tool.mutating) return false;\n const haystack = `${tool.name} ${tool.description ?? ''} ${tool.usageHint ?? ''}`.toLowerCase();\n if (/(generate|create|draw|paint|edit|upscale|remove|write|delete)/.test(haystack)) return false;\n if (!/(vision|image|screenshot|ocr|describe|analy[sz]e)/.test(haystack)) return false;\n const props = schemaProperties(tool);\n return VISION_IMAGE_KEYS.some((key) => key in props);\n}\n\nasync function buildToolPayload(\n tool: Tool,\n image: ImageBlock,\n prompt = 'Describe this image for a coding agent. Include visible text, UI state, errors, layout, and any details needed to answer the user.',\n): Promise<{ payload: Record<string, unknown>; cleanup?: () => Promise<void> } | null> {\n const props = schemaProperties(tool);\n const payload: Record<string, unknown> = {};\n const mediaType = image.source.media_type ?? 'image/png';\n const data = image.source.data;\n const url = image.source.url;\n let cleanup: (() => Promise<void>) | undefined;\n\n // SSRF guard: when the image is referenced by URL, validate the host\n // BEFORE forwarding it to the underlying vision tool. The tool may\n // itself fetch the URL (the typical case for an MCP image-understanding\n // adapter), so a URL pointing at localhost / 127.0.0.1 / 169.254.169.254\n // / RFC1918 ranges would otherwise become an SSRF vector. Without this\n // gate, vision is a back-door around the fetch.ts SSRF guard (which\n // only applies when the explicit `fetch` tool is invoked).\n if (image.source.type === 'url' && url) {\n try {\n await assertNotPrivateHost(new URL(url).hostname);\n } catch (err) {\n const reason =\n err instanceof Error && err.message.startsWith('fetch:')\n ? err.message.slice('fetch:'.length).trim()\n : 'unresolvable host';\n throw new VisionUrlBlockedError({ url, reason });\n }\n }\n\n const pathKey = firstPresent(props, [...VISION_PATH_KEYS]);\n if (pathKey && image.source.type === 'base64' && data) {\n const p = await writeTempImage(data, mediaType);\n payload[pathKey] = p;\n cleanup = async () => {\n await fs.unlink(p).catch(() => undefined);\n await fs.rmdir(path.dirname(p)).catch(() => undefined);\n };\n } else if ('image' in props) {\n payload.image =\n image.source.type === 'base64'\n ? { type: 'base64', mediaType, media_type: mediaType, data }\n : { type: 'url', url };\n } else if (image.source.type === 'base64' && 'base64' in props) {\n payload.base64 = data;\n } else if (image.source.type === 'base64' && 'data' in props) {\n payload.data = data;\n } else if (image.source.type === 'url' && 'url' in props) {\n payload.url = url;\n } else if (image.source.type === 'url' && 'image_url' in props) {\n payload.image_url = url;\n } else if (image.source.type === 'url' && 'imageUrl' in props) {\n payload.imageUrl = url;\n } else {\n return null;\n }\n\n for (const key of VISION_MEDIA_TYPE_KEYS) {\n if (key in props) payload[key] = mediaType;\n }\n for (const key of VISION_PROMPT_KEYS) {\n if (key in props) payload[key] = prompt;\n }\n const built: { payload: Record<string, unknown>; cleanup?: () => Promise<void> } = { payload };\n if (cleanup !== undefined) built.cleanup = cleanup;\n return built;\n}\n\nfunction firstPresent(props: Record<string, unknown>, keys: string[]): string | undefined {\n return keys.find((key) => key in props);\n}\n\nasync function writeTempImage(data: string, mediaType: string): Promise<string> {\n const ext = mediaType.includes('jpeg') || mediaType.includes('jpg') ? 'jpg' : 'png';\n const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'wstack-vision-'));\n const file = path.join(dir, `image.${ext}`);\n await fs.writeFile(file, data, 'base64');\n return file;\n}\n\nfunction schemaProperties(tool: Tool): Record<string, unknown> {\n const schema = tool.inputSchema;\n if (!schema || typeof schema !== 'object') return {};\n const props = (schema as { properties?: unknown | undefined }).properties;\n return props && typeof props === 'object' ? (props as Record<string, unknown>) : {};\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n return value\n .map((item) => {\n if (item && typeof item === 'object' && 'text' in item) {\n return String((item as { text?: unknown | undefined }).text ?? '');\n }\n return typeof item === 'string' ? item : JSON.stringify(item);\n })\n .join('\\n');\n }\n if (value && typeof value === 'object' && 'text' in value) {\n return String((value as { text?: unknown | undefined }).text ?? '');\n }\n return JSON.stringify(value);\n}\n"]}
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/vision.ts"],
|
|
4
|
+
"sourcesContent": ["import * as fs from 'node:fs/promises';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ContentBlock, Context, ImageBlock, Tool, ToolRegistry } from '@wrongstack/core';\nimport { assertNotPrivateHost } from '@wrongstack/core';\n\nexport interface VisionAdapterInput {\n image: ImageBlock;\n prompt?: string | undefined;\n ctx: Context;\n signal: AbortSignal;\n}\n\nexport interface VisionAdapter {\n name: string;\n describe(input: VisionAdapterInput): Promise<string>;\n}\n\nexport type VisionAdapters =\n | readonly VisionAdapter[]\n | (() => readonly VisionAdapter[] | Promise<readonly VisionAdapter[]>);\n\nexport interface VisionRoutingOptions {\n supportsVision: boolean;\n adapters?: VisionAdapters | undefined;\n ctx: Context;\n signal: AbortSignal;\n prompt?: string | undefined;\n providerId?: string | undefined;\n model?: string | undefined;\n}\n\nexport interface VisionRoutingResult {\n blocks: ContentBlock[];\n route: 'native' | 'adapter' | 'none';\n convertedImages: number;\n adapterName?: string | undefined;\n}\n\nexport class ImageInputUnsupportedError extends Error {\n constructor(opts: {\n providerId?: string | undefined;\n model?: string | undefined;\n imageCount: number;\n }) {\n const target = [opts.providerId, opts.model].filter(Boolean).join('/') || 'current model';\n super(\n `${target} does not support image input, and no image-understanding adapter is available for ${opts.imageCount} image${opts.imageCount === 1 ? '' : 's'}. Switch to a vision model or enable an MCP/tool adapter that can describe images.`,\n );\n this.name = 'ImageInputUnsupportedError';\n }\n}\n\n/**\n * Thrown when an image URL targets a private / loopback / IMDS address.\n * Vision adapters forward URLs straight to the underlying tool, so without\n * this check a malicious (or accidentally-malformed) `image.source.url`\n * could turn image analysis into an SSRF vector hitting localhost, RFC1918\n * ranges, or the cloud metadata endpoint.\n *\n * Carries the rejected URL so callers can log / surface it without parsing\n * the message.\n */\nexport class VisionUrlBlockedError extends Error {\n readonly url: string;\n\n constructor(opts: { url: string; reason: string }) {\n super(`vision: blocked unsafe image URL \"${opts.url}\" (${opts.reason})`);\n this.name = 'VisionUrlBlockedError';\n this.url = opts.url;\n }\n}\n\nexport async function routeImagesForModel(\n blocks: ContentBlock[],\n opts: VisionRoutingOptions,\n): Promise<VisionRoutingResult> {\n const images = blocks.filter((b): b is ImageBlock => b.type === 'image');\n if (images.length === 0) {\n return { blocks, route: 'none', convertedImages: 0 };\n }\n if (opts.supportsVision) {\n // Native vision providers typically fetch image URLs server-side, so\n // enforce the same SSRF guard used for adapter routes.\n for (const img of images) {\n if (img.source.type === 'url' && img.source.url) {\n try {\n await assertNotPrivateHost(new URL(img.source.url).hostname);\n } catch (err) {\n const reason =\n err instanceof Error && err.message.startsWith('fetch:')\n ? err.message.slice('fetch:'.length).trim()\n : 'unresolvable host';\n throw new VisionUrlBlockedError({ url: img.source.url, reason });\n }\n }\n }\n return { blocks, route: 'native', convertedImages: 0 };\n }\n\n const adapters = await resolveAdapters(opts.adapters);\n if (adapters.length === 0) {\n throw new ImageInputUnsupportedError({\n providerId: opts.providerId,\n model: opts.model,\n imageCount: images.length,\n });\n }\n\n const out: ContentBlock[] = [];\n let convertedImages = 0;\n let lastErr: unknown;\n let adapterName: string | undefined;\n for (const block of blocks) {\n if (block.type !== 'image') {\n out.push(block);\n continue;\n }\n let description: string | undefined;\n for (const adapter of adapters) {\n try {\n description = await adapter.describe({\n image: block,\n prompt: opts.prompt,\n ctx: opts.ctx,\n signal: opts.signal,\n });\n adapterName = adapter.name;\n break;\n } catch (err) {\n lastErr = err;\n }\n }\n if (!description?.trim()) {\n throw new Error(\n `No image-understanding adapter could process an image.${lastErr instanceof Error ? ` Last error: ${lastErr.message}` : ''}`,\n );\n }\n convertedImages++;\n out.push({\n type: 'text',\n text: `[Image ${convertedImages} analyzed via ${adapterName ?? 'vision adapter'}]\\n${description.trim()}`,\n });\n }\n\n return { blocks: out, route: 'adapter', convertedImages, adapterName };\n}\n\nasync function resolveAdapters(\n adapters: VisionAdapters | undefined,\n): Promise<readonly VisionAdapter[]> {\n if (!adapters) return [];\n return typeof adapters === 'function' ? await adapters() : adapters;\n}\n\nexport interface ToolVisionAdapterOptions {\n prompt?: string | undefined;\n}\n\nexport function createToolVisionAdapters(\n registry: ToolRegistry,\n opts: ToolVisionAdapterOptions = {},\n): VisionAdapter[] {\n return registry\n .list()\n .filter(isLikelyVisionTool)\n .map((tool) => ({\n name: tool.name,\n async describe(input: VisionAdapterInput): Promise<string> {\n const currentTool = registry.get(tool.name);\n if (!currentTool) {\n throw new Error(`Tool \"${tool.name}\" is no longer registered`);\n }\n const built = await buildToolPayload(currentTool, input.image, input.prompt ?? opts.prompt);\n if (!built) {\n throw new Error(\n `Tool \"${currentTool.name}\" does not expose a supported image input schema`,\n );\n }\n try {\n const result = await currentTool.execute(built.payload, input.ctx, {\n signal: input.signal,\n });\n return stringifyToolResult(result);\n } finally {\n await built.cleanup?.();\n }\n },\n }));\n}\n\nexport const VISION_IMAGE_KEYS = [\n 'image',\n 'base64',\n 'data',\n 'url',\n 'image_url',\n 'imageUrl',\n 'path',\n 'image_path',\n 'imagePath',\n 'file_path',\n 'filePath',\n 'filename',\n 'file',\n 'mediaType',\n 'mimeType',\n] as const;\n\nexport const VISION_PATH_KEYS = [\n 'path',\n 'image_path',\n 'imagePath',\n 'image_url',\n 'imageUrl',\n 'file_path',\n 'filePath',\n 'filename',\n 'file',\n] as const;\n\nexport const VISION_MEDIA_TYPE_KEYS = ['mediaType', 'mimeType', 'media_type'] as const;\nexport const VISION_PROMPT_KEYS = ['prompt', 'query', 'instruction'] as const;\n\nfunction isLikelyVisionTool(tool: Tool): boolean {\n if (tool.permission !== 'auto' || tool.mutating) return false;\n const haystack = `${tool.name} ${tool.description ?? ''} ${tool.usageHint ?? ''}`.toLowerCase();\n if (/(generate|create|draw|paint|edit|upscale|remove|write|delete)/.test(haystack)) return false;\n if (!/(vision|image|screenshot|ocr|describe|analy[sz]e)/.test(haystack)) return false;\n const props = schemaProperties(tool);\n return VISION_IMAGE_KEYS.some((key) => key in props);\n}\n\nasync function buildToolPayload(\n tool: Tool,\n image: ImageBlock,\n prompt = 'Describe this image for a coding agent. Include visible text, UI state, errors, layout, and any details needed to answer the user.',\n): Promise<{ payload: Record<string, unknown>; cleanup?: () => Promise<void> } | null> {\n const props = schemaProperties(tool);\n const payload: Record<string, unknown> = {};\n const mediaType = image.source.media_type ?? 'image/png';\n const data = image.source.data;\n const url = image.source.url;\n let cleanup: (() => Promise<void>) | undefined;\n\n // SSRF guard: when the image is referenced by URL, validate the host\n // BEFORE forwarding it to the underlying vision tool. The tool may\n // itself fetch the URL (the typical case for an MCP image-understanding\n // adapter), so a URL pointing at localhost / 127.0.0.1 / 169.254.169.254\n // / RFC1918 ranges would otherwise become an SSRF vector. Without this\n // gate, vision is a back-door around the fetch.ts SSRF guard (which\n // only applies when the explicit `fetch` tool is invoked).\n if (image.source.type === 'url' && url) {\n try {\n await assertNotPrivateHost(new URL(url).hostname);\n } catch (err) {\n const reason =\n err instanceof Error && err.message.startsWith('fetch:')\n ? err.message.slice('fetch:'.length).trim()\n : 'unresolvable host';\n throw new VisionUrlBlockedError({ url, reason });\n }\n }\n\n const pathKey = firstPresent(props, [...VISION_PATH_KEYS]);\n if (pathKey && image.source.type === 'base64' && data) {\n const p = await writeTempImage(data, mediaType);\n payload[pathKey] = p;\n cleanup = async () => {\n await fs.unlink(p).catch(() => undefined);\n await fs.rmdir(path.dirname(p)).catch(() => undefined);\n };\n } else if ('image' in props) {\n payload.image =\n image.source.type === 'base64'\n ? { type: 'base64', mediaType, media_type: mediaType, data }\n : { type: 'url', url };\n } else if (image.source.type === 'base64' && 'base64' in props) {\n payload.base64 = data;\n } else if (image.source.type === 'base64' && 'data' in props) {\n payload.data = data;\n } else if (image.source.type === 'url' && 'url' in props) {\n payload.url = url;\n } else if (image.source.type === 'url' && 'image_url' in props) {\n payload.image_url = url;\n } else if (image.source.type === 'url' && 'imageUrl' in props) {\n payload.imageUrl = url;\n } else {\n return null;\n }\n\n for (const key of VISION_MEDIA_TYPE_KEYS) {\n if (key in props) payload[key] = mediaType;\n }\n for (const key of VISION_PROMPT_KEYS) {\n if (key in props) payload[key] = prompt;\n }\n const built: { payload: Record<string, unknown>; cleanup?: () => Promise<void> } = { payload };\n if (cleanup !== undefined) built.cleanup = cleanup;\n return built;\n}\n\nfunction firstPresent(props: Record<string, unknown>, keys: string[]): string | undefined {\n return keys.find((key) => key in props);\n}\n\nasync function writeTempImage(data: string, mediaType: string): Promise<string> {\n const ext = mediaType.includes('jpeg') || mediaType.includes('jpg') ? 'jpg' : 'png';\n const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'wstack-vision-'));\n const file = path.join(dir, `image.${ext}`);\n await fs.writeFile(file, data, 'base64');\n return file;\n}\n\nfunction schemaProperties(tool: Tool): Record<string, unknown> {\n const schema = tool.inputSchema;\n if (!schema || typeof schema !== 'object') return {};\n const props = (schema as { properties?: unknown | undefined }).properties;\n return props && typeof props === 'object' ? (props as Record<string, unknown>) : {};\n}\n\nfunction stringifyToolResult(value: unknown): string {\n if (typeof value === 'string') return value;\n if (Array.isArray(value)) {\n return value\n .map((item) => {\n if (item && typeof item === 'object' && 'text' in item) {\n return String((item as { text?: unknown | undefined }).text ?? '');\n }\n return typeof item === 'string' ? item : JSON.stringify(item);\n })\n .join('\\n');\n }\n if (value && typeof value === 'object' && 'text' in value) {\n return String((value as { text?: unknown | undefined }).text ?? '');\n }\n return JSON.stringify(value);\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,YAAY,UAAU;AAEtB,SAAS,4BAA4B;AAmC9B,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,MAIT;AACD,UAAM,SAAS,CAAC,KAAK,YAAY,KAAK,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KAAK;AAC1E;AAAA,MACE,GAAG,MAAM,sFAAsF,KAAK,UAAU,SAAS,KAAK,eAAe,IAAI,KAAK,GAAG;AAAA,IACzJ;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAYO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACtC;AAAA,EAET,YAAY,MAAuC;AACjD,UAAM,qCAAqC,KAAK,GAAG,MAAM,KAAK,MAAM,GAAG;AACvE,SAAK,OAAO;AACZ,SAAK,MAAM,KAAK;AAAA,EAClB;AACF;AAEA,eAAsB,oBACpB,QACA,MAC8B;AAC9B,QAAM,SAAS,OAAO,OAAO,CAAC,MAAuB,EAAE,SAAS,OAAO;AACvE,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,EAAE,QAAQ,OAAO,QAAQ,iBAAiB,EAAE;AAAA,EACrD;AACA,MAAI,KAAK,gBAAgB;AAGvB,eAAW,OAAO,QAAQ;AACxB,UAAI,IAAI,OAAO,SAAS,SAAS,IAAI,OAAO,KAAK;AAC/C,YAAI;AACF,gBAAM,qBAAqB,IAAI,IAAI,IAAI,OAAO,GAAG,EAAE,QAAQ;AAAA,QAC7D,SAAS,KAAK;AACZ,gBAAM,SACJ,eAAe,SAAS,IAAI,QAAQ,WAAW,QAAQ,IACnD,IAAI,QAAQ,MAAM,SAAS,MAAM,EAAE,KAAK,IACxC;AACN,gBAAM,IAAI,sBAAsB,EAAE,KAAK,IAAI,OAAO,KAAK,OAAO,CAAC;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,QAAQ,OAAO,UAAU,iBAAiB,EAAE;AAAA,EACvD;AAEA,QAAM,WAAW,MAAM,gBAAgB,KAAK,QAAQ;AACpD,MAAI,SAAS,WAAW,GAAG;AACzB,UAAM,IAAI,2BAA2B;AAAA,MACnC,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,YAAY,OAAO;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,QAAM,MAAsB,CAAC;AAC7B,MAAI,kBAAkB;AACtB,MAAI;AACJ,MAAI;AACJ,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,SAAS,SAAS;AAC1B,UAAI,KAAK,KAAK;AACd;AAAA,IACF;AACA,QAAI;AACJ,eAAW,WAAW,UAAU;AAC9B,UAAI;AACF,sBAAc,MAAM,QAAQ,SAAS;AAAA,UACnC,OAAO;AAAA,UACP,QAAQ,KAAK;AAAA,UACb,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK;AAAA,QACf,CAAC;AACD,sBAAc,QAAQ;AACtB;AAAA,MACF,SAAS,KAAK;AACZ,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,QAAI,CAAC,aAAa,KAAK,GAAG;AACxB,YAAM,IAAI;AAAA,QACR,yDAAyD,mBAAmB,QAAQ,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAAA,MAC5H;AAAA,IACF;AACA;AACA,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,MAAM,UAAU,eAAe,iBAAiB,eAAe,gBAAgB;AAAA,EAAM,YAAY,KAAK,CAAC;AAAA,IACzG,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,QAAQ,KAAK,OAAO,WAAW,iBAAiB,YAAY;AACvE;AAEA,eAAe,gBACb,UACmC;AACnC,MAAI,CAAC,SAAU,QAAO,CAAC;AACvB,SAAO,OAAO,aAAa,aAAa,MAAM,SAAS,IAAI;AAC7D;AAMO,SAAS,yBACd,UACA,OAAiC,CAAC,GACjB;AACjB,SAAO,SACJ,KAAK,EACL,OAAO,kBAAkB,EACzB,IAAI,CAAC,UAAU;AAAA,IACd,MAAM,KAAK;AAAA,IACX,MAAM,SAAS,OAA4C;AACzD,YAAM,cAAc,SAAS,IAAI,KAAK,IAAI;AAC1C,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,SAAS,KAAK,IAAI,2BAA2B;AAAA,MAC/D;AACA,YAAM,QAAQ,MAAM,iBAAiB,aAAa,MAAM,OAAO,MAAM,UAAU,KAAK,MAAM;AAC1F,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR,SAAS,YAAY,IAAI;AAAA,QAC3B;AAAA,MACF;AACA,UAAI;AACF,cAAM,SAAS,MAAM,YAAY,QAAQ,MAAM,SAAS,MAAM,KAAK;AAAA,UACjE,QAAQ,MAAM;AAAA,QAChB,CAAC;AACD,eAAO,oBAAoB,MAAM;AAAA,MACnC,UAAE;AACA,cAAM,MAAM,UAAU;AAAA,MACxB;AAAA,IACF;AAAA,EACF,EAAE;AACN;AAEO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,yBAAyB,CAAC,aAAa,YAAY,YAAY;AACrE,IAAM,qBAAqB,CAAC,UAAU,SAAS,aAAa;AAEnE,SAAS,mBAAmB,MAAqB;AAC/C,MAAI,KAAK,eAAe,UAAU,KAAK,SAAU,QAAO;AACxD,QAAM,WAAW,GAAG,KAAK,IAAI,IAAI,KAAK,eAAe,EAAE,IAAI,KAAK,aAAa,EAAE,GAAG,YAAY;AAC9F,MAAI,gEAAgE,KAAK,QAAQ,EAAG,QAAO;AAC3F,MAAI,CAAC,oDAAoD,KAAK,QAAQ,EAAG,QAAO;AAChF,QAAM,QAAQ,iBAAiB,IAAI;AACnC,SAAO,kBAAkB,KAAK,CAAC,QAAQ,OAAO,KAAK;AACrD;AAEA,eAAe,iBACb,MACA,OACA,SAAS,sIAC4E;AACrF,QAAM,QAAQ,iBAAiB,IAAI;AACnC,QAAM,UAAmC,CAAC;AAC1C,QAAM,YAAY,MAAM,OAAO,cAAc;AAC7C,QAAM,OAAO,MAAM,OAAO;AAC1B,QAAM,MAAM,MAAM,OAAO;AACzB,MAAI;AASJ,MAAI,MAAM,OAAO,SAAS,SAAS,KAAK;AACtC,QAAI;AACF,YAAM,qBAAqB,IAAI,IAAI,GAAG,EAAE,QAAQ;AAAA,IAClD,SAAS,KAAK;AACZ,YAAM,SACJ,eAAe,SAAS,IAAI,QAAQ,WAAW,QAAQ,IACnD,IAAI,QAAQ,MAAM,SAAS,MAAM,EAAE,KAAK,IACxC;AACN,YAAM,IAAI,sBAAsB,EAAE,KAAK,OAAO,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,UAAU,aAAa,OAAO,CAAC,GAAG,gBAAgB,CAAC;AACzD,MAAI,WAAW,MAAM,OAAO,SAAS,YAAY,MAAM;AACrD,UAAM,IAAI,MAAM,eAAe,MAAM,SAAS;AAC9C,YAAQ,OAAO,IAAI;AACnB,cAAU,YAAY;AACpB,YAAS,UAAO,CAAC,EAAE,MAAM,MAAM,MAAS;AACxC,YAAS,SAAW,aAAQ,CAAC,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IACvD;AAAA,EACF,WAAW,WAAW,OAAO;AAC3B,YAAQ,QACN,MAAM,OAAO,SAAS,WAClB,EAAE,MAAM,UAAU,WAAW,YAAY,WAAW,KAAK,IACzD,EAAE,MAAM,OAAO,IAAI;AAAA,EAC3B,WAAW,MAAM,OAAO,SAAS,YAAY,YAAY,OAAO;AAC9D,YAAQ,SAAS;AAAA,EACnB,WAAW,MAAM,OAAO,SAAS,YAAY,UAAU,OAAO;AAC5D,YAAQ,OAAO;AAAA,EACjB,WAAW,MAAM,OAAO,SAAS,SAAS,SAAS,OAAO;AACxD,YAAQ,MAAM;AAAA,EAChB,WAAW,MAAM,OAAO,SAAS,SAAS,eAAe,OAAO;AAC9D,YAAQ,YAAY;AAAA,EACtB,WAAW,MAAM,OAAO,SAAS,SAAS,cAAc,OAAO;AAC7D,YAAQ,WAAW;AAAA,EACrB,OAAO;AACL,WAAO;AAAA,EACT;AAEA,aAAW,OAAO,wBAAwB;AACxC,QAAI,OAAO,MAAO,SAAQ,GAAG,IAAI;AAAA,EACnC;AACA,aAAW,OAAO,oBAAoB;AACpC,QAAI,OAAO,MAAO,SAAQ,GAAG,IAAI;AAAA,EACnC;AACA,QAAM,QAA6E,EAAE,QAAQ;AAC7F,MAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,SAAO;AACT;AAEA,SAAS,aAAa,OAAgC,MAAoC;AACxF,SAAO,KAAK,KAAK,CAAC,QAAQ,OAAO,KAAK;AACxC;AAEA,eAAe,eAAe,MAAc,WAAoC;AAC9E,QAAM,MAAM,UAAU,SAAS,MAAM,KAAK,UAAU,SAAS,KAAK,IAAI,QAAQ;AAC9E,QAAM,MAAM,MAAS,WAAa,UAAQ,UAAO,GAAG,gBAAgB,CAAC;AACrE,QAAM,OAAY,UAAK,KAAK,SAAS,GAAG,EAAE;AAC1C,QAAS,aAAU,MAAM,MAAM,QAAQ;AACvC,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAqC;AAC7D,QAAM,SAAS,KAAK;AACpB,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO,CAAC;AACnD,QAAM,QAAS,OAAgD;AAC/D,SAAO,SAAS,OAAO,UAAU,WAAY,QAAoC,CAAC;AACpF;AAEA,SAAS,oBAAoB,OAAwB;AACnD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MACJ,IAAI,CAAC,SAAS;AACb,UAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,MAAM;AACtD,eAAO,OAAQ,KAAwC,QAAQ,EAAE;AAAA,MACnE;AACA,aAAO,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AAAA,IAC9D,CAAC,EACA,KAAK,IAAI;AAAA,EACd;AACA,MAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,WAAO,OAAQ,MAAyC,QAAQ,EAAE;AAAA,EACpE;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wrongstack/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.285.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "WrongStack default runtime implementations and host-level composition helpers built on @wrongstack/core.",
|
|
6
6
|
"repository": {
|
|
@@ -47,18 +47,18 @@
|
|
|
47
47
|
"README.md"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@wrongstack/core": "0.
|
|
50
|
+
"@wrongstack/core": "0.285.0",
|
|
51
|
+
"@wrongstack/super-memory": "0.285.0"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
54
|
"@types/node": "^26.0.1",
|
|
54
|
-
"
|
|
55
|
-
"typescript": "^6.0.3"
|
|
55
|
+
"typescript": "^7.0.2"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
|
-
"build": "
|
|
61
|
+
"build": "node ../../scripts/build-package.mjs",
|
|
62
62
|
"typecheck": "tsc --noEmit",
|
|
63
63
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""
|
|
64
64
|
}
|