@stardeck-customer-apps/testing 0.20.0 → 0.21.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/SKILL.md +7 -2
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +51 -7
- package/dist/index.mjs +51 -7
- package/dist/setup.js +51 -7
- package/dist/setup.mjs +51 -7
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -530,8 +530,13 @@ cursor, limit })`; `list()` intentionally keeps its previous array shape.
|
|
|
530
530
|
production) or `app.starlens.reject("not a receipt")` (the 422 the SDK maps to
|
|
531
531
|
`UnsupportedDocumentError`). An unregistered call fails with a descriptive 502 so a
|
|
532
532
|
test never passes on an invented extraction. `app.starlens.calls` records each
|
|
533
|
-
request's version, input names/media types (never bytes), schema and
|
|
534
|
-
instructions — assert your `.describe()` aliases
|
|
533
|
+
request's version, effort, input names/media types (never bytes), schema and
|
|
534
|
+
instructions — assert your `.describe()` aliases and `effort: "high"` retries
|
|
535
|
+
reached the wire there. `version: "v1"` with `effort: "high"` is refused with the
|
|
536
|
+
same 400 `unsupported_effort` as production (the SDK throws `ValidationError`). A
|
|
537
|
+
high request with no image input answers `effort: "low"` as production does;
|
|
538
|
+
pass `effort: "low"` in `app.starlens.mock(...)` to simulate an image production
|
|
539
|
+
could not decode.
|
|
535
540
|
|
|
536
541
|
### Receipt layout and printer capabilities
|
|
537
542
|
|
package/dist/index.d.mts
CHANGED
|
@@ -536,7 +536,10 @@ interface TestEdge {
|
|
|
536
536
|
}
|
|
537
537
|
/** One Starlens request the app made, as the simulator saw it (names only, never bytes). */
|
|
538
538
|
interface CapturedStarlensCall {
|
|
539
|
+
/** As sent (`latest` stays `latest`). */
|
|
539
540
|
version: string;
|
|
541
|
+
/** As requested; `"low"` when the app did not set one. The reply says what ran. */
|
|
542
|
+
effort: "low" | "high";
|
|
540
543
|
inputs: {
|
|
541
544
|
name: string;
|
|
542
545
|
mediaType: string | null;
|
|
@@ -557,6 +560,12 @@ type StarlensReply = {
|
|
|
557
560
|
path: string;
|
|
558
561
|
reason: string;
|
|
559
562
|
}[];
|
|
563
|
+
/**
|
|
564
|
+
* The effort the reply says ran. Defaults to the requested effort, or `"low"` for a
|
|
565
|
+
* high request with no image input (production cannot crop a PDF, audio or video).
|
|
566
|
+
* Set `"low"` to simulate a high request on an image production could not decode.
|
|
567
|
+
*/
|
|
568
|
+
effort?: "low" | "high";
|
|
560
569
|
} | {
|
|
561
570
|
reject: string;
|
|
562
571
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -536,7 +536,10 @@ interface TestEdge {
|
|
|
536
536
|
}
|
|
537
537
|
/** One Starlens request the app made, as the simulator saw it (names only, never bytes). */
|
|
538
538
|
interface CapturedStarlensCall {
|
|
539
|
+
/** As sent (`latest` stays `latest`). */
|
|
539
540
|
version: string;
|
|
541
|
+
/** As requested; `"low"` when the app did not set one. The reply says what ran. */
|
|
542
|
+
effort: "low" | "high";
|
|
540
543
|
inputs: {
|
|
541
544
|
name: string;
|
|
542
545
|
mediaType: string | null;
|
|
@@ -557,6 +560,12 @@ type StarlensReply = {
|
|
|
557
560
|
path: string;
|
|
558
561
|
reason: string;
|
|
559
562
|
}[];
|
|
563
|
+
/**
|
|
564
|
+
* The effort the reply says ran. Defaults to the requested effort, or `"low"` for a
|
|
565
|
+
* high request with no image input (production cannot crop a PDF, audio or video).
|
|
566
|
+
* Set `"low"` to simulate a high request on an image production could not decode.
|
|
567
|
+
*/
|
|
568
|
+
effort?: "low" | "high";
|
|
560
569
|
} | {
|
|
561
570
|
reject: string;
|
|
562
571
|
};
|
package/dist/index.js
CHANGED
|
@@ -3102,6 +3102,7 @@ function createEdge() {
|
|
|
3102
3102
|
}
|
|
3103
3103
|
|
|
3104
3104
|
// src/simulator/starlens.ts
|
|
3105
|
+
var LATEST_VERSION = "v2";
|
|
3105
3106
|
function starlensFailure(error, status, code) {
|
|
3106
3107
|
return json({ success: false, error, code }, status);
|
|
3107
3108
|
}
|
|
@@ -3120,11 +3121,18 @@ function nullFlagged(output, issues) {
|
|
|
3120
3121
|
}
|
|
3121
3122
|
return copy;
|
|
3122
3123
|
}
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3124
|
+
function isInputShape(input) {
|
|
3125
|
+
if (!input || typeof input !== "object") return false;
|
|
3126
|
+
const i = input;
|
|
3127
|
+
return typeof i.url === "string" || typeof i.data === "string" && i.data.length > 0 && typeof i.mediaType === "string";
|
|
3128
|
+
}
|
|
3129
|
+
var NON_IMAGE_EXTENSION = /\.(pdf|mp3|m4a|wav|ogg|aac|flac|mp4|mov|webm|mkv)(\?|#|$)/i;
|
|
3130
|
+
function isCroppable(input) {
|
|
3131
|
+
if (typeof input.mediaType === "string") return input.mediaType.startsWith("image/");
|
|
3132
|
+
const name = typeof input.filename === "string" ? input.filename : input.url;
|
|
3133
|
+
return !(typeof name === "string" && NON_IMAGE_EXTENSION.test(name));
|
|
3134
|
+
}
|
|
3135
|
+
function validateStarlensBody(body) {
|
|
3128
3136
|
const inputs = Array.isArray(body.inputs) ? body.inputs : [];
|
|
3129
3137
|
if (inputs.length === 0) {
|
|
3130
3138
|
return starlensFailure(
|
|
@@ -3133,6 +3141,13 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3133
3141
|
"VALIDATION_ERROR"
|
|
3134
3142
|
);
|
|
3135
3143
|
}
|
|
3144
|
+
if (!inputs.every(isInputShape)) {
|
|
3145
|
+
return starlensFailure(
|
|
3146
|
+
"Validation failed \u2014 inputs: each input needs a url, or data with a mediaType",
|
|
3147
|
+
400,
|
|
3148
|
+
"VALIDATION_ERROR"
|
|
3149
|
+
);
|
|
3150
|
+
}
|
|
3136
3151
|
const schema = body.schema;
|
|
3137
3152
|
if (!schema || schema.type !== "object" || typeof schema.properties !== "object") {
|
|
3138
3153
|
return starlensFailure(
|
|
@@ -3141,8 +3156,35 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3141
3156
|
"VALIDATION_ERROR"
|
|
3142
3157
|
);
|
|
3143
3158
|
}
|
|
3159
|
+
const version = body.version ?? "latest";
|
|
3160
|
+
if (version !== "v1" && version !== "v2" && version !== "latest") {
|
|
3161
|
+
return starlensFailure("Validation failed \u2014 version: unknown version", 400, "VALIDATION_ERROR");
|
|
3162
|
+
}
|
|
3163
|
+
const effort = body.effort ?? "low";
|
|
3164
|
+
if (effort !== "low" && effort !== "high") {
|
|
3165
|
+
return starlensFailure("Validation failed \u2014 effort: low or high", 400, "VALIDATION_ERROR");
|
|
3166
|
+
}
|
|
3167
|
+
const resolved = version === "latest" ? LATEST_VERSION : version;
|
|
3168
|
+
if (effort === "high" && resolved === "v1") {
|
|
3169
|
+
return starlensFailure(
|
|
3170
|
+
`Starlens v1 does not support effort "high"; use version "v2"`,
|
|
3171
|
+
400,
|
|
3172
|
+
"unsupported_effort"
|
|
3173
|
+
);
|
|
3174
|
+
}
|
|
3175
|
+
return { version, resolved, effort, inputs, schema };
|
|
3176
|
+
}
|
|
3177
|
+
async function handleStarlensExtract(request, signedDeploymentId) {
|
|
3178
|
+
const body = await readJsonBody(request);
|
|
3179
|
+
const valid = validateStarlensBody(body);
|
|
3180
|
+
if (valid instanceof Response) return valid;
|
|
3181
|
+
const { version, resolved, effort, inputs, schema } = valid;
|
|
3182
|
+
if (signedDeploymentId !== null && body.deploymentId !== signedDeploymentId) {
|
|
3183
|
+
return starlensFailure("Deployment ID mismatch", 401, "AUTHENTICATION_ERROR");
|
|
3184
|
+
}
|
|
3144
3185
|
const call = {
|
|
3145
|
-
version
|
|
3186
|
+
version,
|
|
3187
|
+
effort,
|
|
3146
3188
|
inputs: inputs.map((i) => ({
|
|
3147
3189
|
name: typeof i.filename === "string" ? i.filename : typeof i.url === "string" ? i.url : "upload",
|
|
3148
3190
|
mediaType: typeof i.mediaType === "string" ? i.mediaType : null,
|
|
@@ -3164,8 +3206,10 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3164
3206
|
return starlensFailure(reply.reject, 422, "unsupported_document");
|
|
3165
3207
|
}
|
|
3166
3208
|
const issues = reply.issues ?? [];
|
|
3209
|
+
const ran = reply.effort ?? (effort === "high" && !inputs.some(isCroppable) ? "low" : effort);
|
|
3167
3210
|
return success({
|
|
3168
|
-
version:
|
|
3211
|
+
version: resolved,
|
|
3212
|
+
effort: ran,
|
|
3169
3213
|
output: nullFlagged(reply.output, issues),
|
|
3170
3214
|
issues,
|
|
3171
3215
|
usage: { inputTokens: 0, outputTokens: 0, cost: 0 }
|
package/dist/index.mjs
CHANGED
|
@@ -3063,6 +3063,7 @@ function createEdge() {
|
|
|
3063
3063
|
}
|
|
3064
3064
|
|
|
3065
3065
|
// src/simulator/starlens.ts
|
|
3066
|
+
var LATEST_VERSION = "v2";
|
|
3066
3067
|
function starlensFailure(error, status, code) {
|
|
3067
3068
|
return json({ success: false, error, code }, status);
|
|
3068
3069
|
}
|
|
@@ -3081,11 +3082,18 @@ function nullFlagged(output, issues) {
|
|
|
3081
3082
|
}
|
|
3082
3083
|
return copy;
|
|
3083
3084
|
}
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3085
|
+
function isInputShape(input) {
|
|
3086
|
+
if (!input || typeof input !== "object") return false;
|
|
3087
|
+
const i = input;
|
|
3088
|
+
return typeof i.url === "string" || typeof i.data === "string" && i.data.length > 0 && typeof i.mediaType === "string";
|
|
3089
|
+
}
|
|
3090
|
+
var NON_IMAGE_EXTENSION = /\.(pdf|mp3|m4a|wav|ogg|aac|flac|mp4|mov|webm|mkv)(\?|#|$)/i;
|
|
3091
|
+
function isCroppable(input) {
|
|
3092
|
+
if (typeof input.mediaType === "string") return input.mediaType.startsWith("image/");
|
|
3093
|
+
const name = typeof input.filename === "string" ? input.filename : input.url;
|
|
3094
|
+
return !(typeof name === "string" && NON_IMAGE_EXTENSION.test(name));
|
|
3095
|
+
}
|
|
3096
|
+
function validateStarlensBody(body) {
|
|
3089
3097
|
const inputs = Array.isArray(body.inputs) ? body.inputs : [];
|
|
3090
3098
|
if (inputs.length === 0) {
|
|
3091
3099
|
return starlensFailure(
|
|
@@ -3094,6 +3102,13 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3094
3102
|
"VALIDATION_ERROR"
|
|
3095
3103
|
);
|
|
3096
3104
|
}
|
|
3105
|
+
if (!inputs.every(isInputShape)) {
|
|
3106
|
+
return starlensFailure(
|
|
3107
|
+
"Validation failed \u2014 inputs: each input needs a url, or data with a mediaType",
|
|
3108
|
+
400,
|
|
3109
|
+
"VALIDATION_ERROR"
|
|
3110
|
+
);
|
|
3111
|
+
}
|
|
3097
3112
|
const schema = body.schema;
|
|
3098
3113
|
if (!schema || schema.type !== "object" || typeof schema.properties !== "object") {
|
|
3099
3114
|
return starlensFailure(
|
|
@@ -3102,8 +3117,35 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3102
3117
|
"VALIDATION_ERROR"
|
|
3103
3118
|
);
|
|
3104
3119
|
}
|
|
3120
|
+
const version = body.version ?? "latest";
|
|
3121
|
+
if (version !== "v1" && version !== "v2" && version !== "latest") {
|
|
3122
|
+
return starlensFailure("Validation failed \u2014 version: unknown version", 400, "VALIDATION_ERROR");
|
|
3123
|
+
}
|
|
3124
|
+
const effort = body.effort ?? "low";
|
|
3125
|
+
if (effort !== "low" && effort !== "high") {
|
|
3126
|
+
return starlensFailure("Validation failed \u2014 effort: low or high", 400, "VALIDATION_ERROR");
|
|
3127
|
+
}
|
|
3128
|
+
const resolved = version === "latest" ? LATEST_VERSION : version;
|
|
3129
|
+
if (effort === "high" && resolved === "v1") {
|
|
3130
|
+
return starlensFailure(
|
|
3131
|
+
`Starlens v1 does not support effort "high"; use version "v2"`,
|
|
3132
|
+
400,
|
|
3133
|
+
"unsupported_effort"
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
3136
|
+
return { version, resolved, effort, inputs, schema };
|
|
3137
|
+
}
|
|
3138
|
+
async function handleStarlensExtract(request, signedDeploymentId) {
|
|
3139
|
+
const body = await readJsonBody(request);
|
|
3140
|
+
const valid = validateStarlensBody(body);
|
|
3141
|
+
if (valid instanceof Response) return valid;
|
|
3142
|
+
const { version, resolved, effort, inputs, schema } = valid;
|
|
3143
|
+
if (signedDeploymentId !== null && body.deploymentId !== signedDeploymentId) {
|
|
3144
|
+
return starlensFailure("Deployment ID mismatch", 401, "AUTHENTICATION_ERROR");
|
|
3145
|
+
}
|
|
3105
3146
|
const call = {
|
|
3106
|
-
version
|
|
3147
|
+
version,
|
|
3148
|
+
effort,
|
|
3107
3149
|
inputs: inputs.map((i) => ({
|
|
3108
3150
|
name: typeof i.filename === "string" ? i.filename : typeof i.url === "string" ? i.url : "upload",
|
|
3109
3151
|
mediaType: typeof i.mediaType === "string" ? i.mediaType : null,
|
|
@@ -3125,8 +3167,10 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
3125
3167
|
return starlensFailure(reply.reject, 422, "unsupported_document");
|
|
3126
3168
|
}
|
|
3127
3169
|
const issues = reply.issues ?? [];
|
|
3170
|
+
const ran = reply.effort ?? (effort === "high" && !inputs.some(isCroppable) ? "low" : effort);
|
|
3128
3171
|
return success({
|
|
3129
|
-
version:
|
|
3172
|
+
version: resolved,
|
|
3173
|
+
effort: ran,
|
|
3130
3174
|
output: nullFlagged(reply.output, issues),
|
|
3131
3175
|
issues,
|
|
3132
3176
|
usage: { inputTokens: 0, outputTokens: 0, cost: 0 }
|
package/dist/setup.js
CHANGED
|
@@ -2247,6 +2247,7 @@ async function handleEdgeRequest(request, subPath) {
|
|
|
2247
2247
|
}
|
|
2248
2248
|
|
|
2249
2249
|
// src/simulator/starlens.ts
|
|
2250
|
+
var LATEST_VERSION = "v2";
|
|
2250
2251
|
function starlensFailure(error, status, code) {
|
|
2251
2252
|
return json({ success: false, error, code }, status);
|
|
2252
2253
|
}
|
|
@@ -2265,11 +2266,18 @@ function nullFlagged(output, issues) {
|
|
|
2265
2266
|
}
|
|
2266
2267
|
return copy;
|
|
2267
2268
|
}
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2269
|
+
function isInputShape(input) {
|
|
2270
|
+
if (!input || typeof input !== "object") return false;
|
|
2271
|
+
const i = input;
|
|
2272
|
+
return typeof i.url === "string" || typeof i.data === "string" && i.data.length > 0 && typeof i.mediaType === "string";
|
|
2273
|
+
}
|
|
2274
|
+
var NON_IMAGE_EXTENSION = /\.(pdf|mp3|m4a|wav|ogg|aac|flac|mp4|mov|webm|mkv)(\?|#|$)/i;
|
|
2275
|
+
function isCroppable(input) {
|
|
2276
|
+
if (typeof input.mediaType === "string") return input.mediaType.startsWith("image/");
|
|
2277
|
+
const name = typeof input.filename === "string" ? input.filename : input.url;
|
|
2278
|
+
return !(typeof name === "string" && NON_IMAGE_EXTENSION.test(name));
|
|
2279
|
+
}
|
|
2280
|
+
function validateStarlensBody(body) {
|
|
2273
2281
|
const inputs = Array.isArray(body.inputs) ? body.inputs : [];
|
|
2274
2282
|
if (inputs.length === 0) {
|
|
2275
2283
|
return starlensFailure(
|
|
@@ -2278,6 +2286,13 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2278
2286
|
"VALIDATION_ERROR"
|
|
2279
2287
|
);
|
|
2280
2288
|
}
|
|
2289
|
+
if (!inputs.every(isInputShape)) {
|
|
2290
|
+
return starlensFailure(
|
|
2291
|
+
"Validation failed \u2014 inputs: each input needs a url, or data with a mediaType",
|
|
2292
|
+
400,
|
|
2293
|
+
"VALIDATION_ERROR"
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2281
2296
|
const schema = body.schema;
|
|
2282
2297
|
if (!schema || schema.type !== "object" || typeof schema.properties !== "object") {
|
|
2283
2298
|
return starlensFailure(
|
|
@@ -2286,8 +2301,35 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2286
2301
|
"VALIDATION_ERROR"
|
|
2287
2302
|
);
|
|
2288
2303
|
}
|
|
2304
|
+
const version = body.version ?? "latest";
|
|
2305
|
+
if (version !== "v1" && version !== "v2" && version !== "latest") {
|
|
2306
|
+
return starlensFailure("Validation failed \u2014 version: unknown version", 400, "VALIDATION_ERROR");
|
|
2307
|
+
}
|
|
2308
|
+
const effort = body.effort ?? "low";
|
|
2309
|
+
if (effort !== "low" && effort !== "high") {
|
|
2310
|
+
return starlensFailure("Validation failed \u2014 effort: low or high", 400, "VALIDATION_ERROR");
|
|
2311
|
+
}
|
|
2312
|
+
const resolved = version === "latest" ? LATEST_VERSION : version;
|
|
2313
|
+
if (effort === "high" && resolved === "v1") {
|
|
2314
|
+
return starlensFailure(
|
|
2315
|
+
`Starlens v1 does not support effort "high"; use version "v2"`,
|
|
2316
|
+
400,
|
|
2317
|
+
"unsupported_effort"
|
|
2318
|
+
);
|
|
2319
|
+
}
|
|
2320
|
+
return { version, resolved, effort, inputs, schema };
|
|
2321
|
+
}
|
|
2322
|
+
async function handleStarlensExtract(request, signedDeploymentId) {
|
|
2323
|
+
const body = await readJsonBody(request);
|
|
2324
|
+
const valid = validateStarlensBody(body);
|
|
2325
|
+
if (valid instanceof Response) return valid;
|
|
2326
|
+
const { version, resolved, effort, inputs, schema } = valid;
|
|
2327
|
+
if (signedDeploymentId !== null && body.deploymentId !== signedDeploymentId) {
|
|
2328
|
+
return starlensFailure("Deployment ID mismatch", 401, "AUTHENTICATION_ERROR");
|
|
2329
|
+
}
|
|
2289
2330
|
const call = {
|
|
2290
|
-
version
|
|
2331
|
+
version,
|
|
2332
|
+
effort,
|
|
2291
2333
|
inputs: inputs.map((i) => ({
|
|
2292
2334
|
name: typeof i.filename === "string" ? i.filename : typeof i.url === "string" ? i.url : "upload",
|
|
2293
2335
|
mediaType: typeof i.mediaType === "string" ? i.mediaType : null,
|
|
@@ -2309,8 +2351,10 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2309
2351
|
return starlensFailure(reply.reject, 422, "unsupported_document");
|
|
2310
2352
|
}
|
|
2311
2353
|
const issues = reply.issues ?? [];
|
|
2354
|
+
const ran = reply.effort ?? (effort === "high" && !inputs.some(isCroppable) ? "low" : effort);
|
|
2312
2355
|
return success({
|
|
2313
|
-
version:
|
|
2356
|
+
version: resolved,
|
|
2357
|
+
effort: ran,
|
|
2314
2358
|
output: nullFlagged(reply.output, issues),
|
|
2315
2359
|
issues,
|
|
2316
2360
|
usage: { inputTokens: 0, outputTokens: 0, cost: 0 }
|
package/dist/setup.mjs
CHANGED
|
@@ -2223,6 +2223,7 @@ async function handleEdgeRequest(request, subPath) {
|
|
|
2223
2223
|
}
|
|
2224
2224
|
|
|
2225
2225
|
// src/simulator/starlens.ts
|
|
2226
|
+
var LATEST_VERSION = "v2";
|
|
2226
2227
|
function starlensFailure(error, status, code) {
|
|
2227
2228
|
return json({ success: false, error, code }, status);
|
|
2228
2229
|
}
|
|
@@ -2241,11 +2242,18 @@ function nullFlagged(output, issues) {
|
|
|
2241
2242
|
}
|
|
2242
2243
|
return copy;
|
|
2243
2244
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2245
|
+
function isInputShape(input) {
|
|
2246
|
+
if (!input || typeof input !== "object") return false;
|
|
2247
|
+
const i = input;
|
|
2248
|
+
return typeof i.url === "string" || typeof i.data === "string" && i.data.length > 0 && typeof i.mediaType === "string";
|
|
2249
|
+
}
|
|
2250
|
+
var NON_IMAGE_EXTENSION = /\.(pdf|mp3|m4a|wav|ogg|aac|flac|mp4|mov|webm|mkv)(\?|#|$)/i;
|
|
2251
|
+
function isCroppable(input) {
|
|
2252
|
+
if (typeof input.mediaType === "string") return input.mediaType.startsWith("image/");
|
|
2253
|
+
const name = typeof input.filename === "string" ? input.filename : input.url;
|
|
2254
|
+
return !(typeof name === "string" && NON_IMAGE_EXTENSION.test(name));
|
|
2255
|
+
}
|
|
2256
|
+
function validateStarlensBody(body) {
|
|
2249
2257
|
const inputs = Array.isArray(body.inputs) ? body.inputs : [];
|
|
2250
2258
|
if (inputs.length === 0) {
|
|
2251
2259
|
return starlensFailure(
|
|
@@ -2254,6 +2262,13 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2254
2262
|
"VALIDATION_ERROR"
|
|
2255
2263
|
);
|
|
2256
2264
|
}
|
|
2265
|
+
if (!inputs.every(isInputShape)) {
|
|
2266
|
+
return starlensFailure(
|
|
2267
|
+
"Validation failed \u2014 inputs: each input needs a url, or data with a mediaType",
|
|
2268
|
+
400,
|
|
2269
|
+
"VALIDATION_ERROR"
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2257
2272
|
const schema = body.schema;
|
|
2258
2273
|
if (!schema || schema.type !== "object" || typeof schema.properties !== "object") {
|
|
2259
2274
|
return starlensFailure(
|
|
@@ -2262,8 +2277,35 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2262
2277
|
"VALIDATION_ERROR"
|
|
2263
2278
|
);
|
|
2264
2279
|
}
|
|
2280
|
+
const version = body.version ?? "latest";
|
|
2281
|
+
if (version !== "v1" && version !== "v2" && version !== "latest") {
|
|
2282
|
+
return starlensFailure("Validation failed \u2014 version: unknown version", 400, "VALIDATION_ERROR");
|
|
2283
|
+
}
|
|
2284
|
+
const effort = body.effort ?? "low";
|
|
2285
|
+
if (effort !== "low" && effort !== "high") {
|
|
2286
|
+
return starlensFailure("Validation failed \u2014 effort: low or high", 400, "VALIDATION_ERROR");
|
|
2287
|
+
}
|
|
2288
|
+
const resolved = version === "latest" ? LATEST_VERSION : version;
|
|
2289
|
+
if (effort === "high" && resolved === "v1") {
|
|
2290
|
+
return starlensFailure(
|
|
2291
|
+
`Starlens v1 does not support effort "high"; use version "v2"`,
|
|
2292
|
+
400,
|
|
2293
|
+
"unsupported_effort"
|
|
2294
|
+
);
|
|
2295
|
+
}
|
|
2296
|
+
return { version, resolved, effort, inputs, schema };
|
|
2297
|
+
}
|
|
2298
|
+
async function handleStarlensExtract(request, signedDeploymentId) {
|
|
2299
|
+
const body = await readJsonBody(request);
|
|
2300
|
+
const valid = validateStarlensBody(body);
|
|
2301
|
+
if (valid instanceof Response) return valid;
|
|
2302
|
+
const { version, resolved, effort, inputs, schema } = valid;
|
|
2303
|
+
if (signedDeploymentId !== null && body.deploymentId !== signedDeploymentId) {
|
|
2304
|
+
return starlensFailure("Deployment ID mismatch", 401, "AUTHENTICATION_ERROR");
|
|
2305
|
+
}
|
|
2265
2306
|
const call = {
|
|
2266
|
-
version
|
|
2307
|
+
version,
|
|
2308
|
+
effort,
|
|
2267
2309
|
inputs: inputs.map((i) => ({
|
|
2268
2310
|
name: typeof i.filename === "string" ? i.filename : typeof i.url === "string" ? i.url : "upload",
|
|
2269
2311
|
mediaType: typeof i.mediaType === "string" ? i.mediaType : null,
|
|
@@ -2285,8 +2327,10 @@ async function handleStarlensExtract(request, signedDeploymentId) {
|
|
|
2285
2327
|
return starlensFailure(reply.reject, 422, "unsupported_document");
|
|
2286
2328
|
}
|
|
2287
2329
|
const issues = reply.issues ?? [];
|
|
2330
|
+
const ran = reply.effort ?? (effort === "high" && !inputs.some(isCroppable) ? "low" : effort);
|
|
2288
2331
|
return success({
|
|
2289
|
-
version:
|
|
2332
|
+
version: resolved,
|
|
2333
|
+
effort: ran,
|
|
2290
2334
|
output: nullFlagged(reply.output, issues),
|
|
2291
2335
|
issues,
|
|
2292
2336
|
usage: { inputTokens: 0, outputTokens: 0, cost: 0 }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stardeck-customer-apps/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Vitest test harness for Stardeck customer apps — in-process Postgres (PGlite) plus a control-plane simulator so the real Stardeck SDKs run unmodified in tests",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|