@blotout/qinto-cli 0.1.9 → 0.1.11
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/index.js +2412 -2175
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +261 -37
- package/dist/worker-artifact/main/index.js +134 -29
- package/dist/worker-artifact/version.json +4 -4
- package/package.json +1 -1
|
@@ -739,6 +739,10 @@ var MAX_APPS_Q_BYTES = 4 * 1024 * 1024;
|
|
|
739
739
|
// ../../libs/app-manifest/src/cron.ts
|
|
740
740
|
var MAX_CRON_LENGTH = 128;
|
|
741
741
|
|
|
742
|
+
// ../../libs/app-manifest/src/tool-names.ts
|
|
743
|
+
var MAX_APP_TOOL_NAME_LENGTH = 32;
|
|
744
|
+
var APP_TOOL_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
745
|
+
|
|
742
746
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
743
747
|
var external_exports = {};
|
|
744
748
|
__export(external_exports, {
|
|
@@ -15853,6 +15857,12 @@ var validateEnvelopeResponse = /* @__PURE__ */ __name((raw2, installCount) => {
|
|
|
15853
15857
|
var CONTROL_ENVELOPE_VERSION = 1;
|
|
15854
15858
|
var MAX_CONTROL_BYTES = 256 * 1024;
|
|
15855
15859
|
var MAX_MIGRATION_CHECKPOINT_BYTES = 16 * 1024;
|
|
15860
|
+
var MAX_TOOL_ARGUMENTS_BYTES = 32 * 1024;
|
|
15861
|
+
var MAX_TOOL_RESULT_BYTES = 64 * 1024;
|
|
15862
|
+
var MAX_TOOL_DATA_DEPTH = 8;
|
|
15863
|
+
var MAX_TOOL_DATA_NODES = 5e3;
|
|
15864
|
+
var CONTROL_FORWARD_TIMEOUT_MS = 1e4;
|
|
15865
|
+
var CONTROL_TOOL_FORWARD_TIMEOUT_MS = 5e4;
|
|
15856
15866
|
var installSchema2 = external_exports.object({
|
|
15857
15867
|
id: external_exports.string().min(1).max(64),
|
|
15858
15868
|
ord: external_exports.number().int().min(1),
|
|
@@ -15922,19 +15932,39 @@ var scheduleSchema = external_exports.object({
|
|
|
15922
15932
|
id: external_exports.string().min(1).max(64),
|
|
15923
15933
|
ord: external_exports.number().int().min(1),
|
|
15924
15934
|
label: external_exports.string().max(100),
|
|
15925
|
-
|
|
15935
|
+
queryTicket: external_exports.string().min(1).max(2048)
|
|
15926
15936
|
}).strict()
|
|
15927
15937
|
).min(1).max(MAX_INSTALLS_PER_APP)
|
|
15928
15938
|
}).strict();
|
|
15939
|
+
var toolSchema = external_exports.object({
|
|
15940
|
+
// The manifest's tools[].name, never the `<slug>_` composed MCP name: the slug is already in
|
|
15941
|
+
// `app.slug`, and carrying it twice would give the app worker two sources for one fact.
|
|
15942
|
+
name: external_exports.string().min(1).max(MAX_APP_TOOL_NAME_LENGTH).regex(APP_TOOL_NAME_PATTERN),
|
|
15943
|
+
// Who asked, and what they may do on this site. Derived from the bearer by the portal, never
|
|
15944
|
+
// from the model's arguments.
|
|
15945
|
+
viewer: external_exports.object({ userId: external_exports.string().min(1).max(64), access: external_exports.enum(["read", "write"]) }).strict(),
|
|
15946
|
+
// Already validated against the tool's declared inputSchema, with the reserved routing names
|
|
15947
|
+
// stripped. Every declared input schema has an object root, so this is an object too — and a
|
|
15948
|
+
// call that names no arguments normalizes to `{}` rather than reaching the handler as undefined.
|
|
15949
|
+
arguments: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
15950
|
+
// Stable across a collapsed retry, so an app can deduplicate its external effects on it.
|
|
15951
|
+
callId: external_exports.string().min(1).max(64),
|
|
15952
|
+
// The short-lived install/version-scoped credential used only by the app runtime's query
|
|
15953
|
+
// broker. It never enters handler arguments or app-authored result data.
|
|
15954
|
+
queryTicket: external_exports.string().min(1).max(2048)
|
|
15955
|
+
}).strict().refine((tool) => {
|
|
15956
|
+
return new TextEncoder().encode(JSON.stringify(tool.arguments)).length <= MAX_TOOL_ARGUMENTS_BYTES;
|
|
15957
|
+
}, "Tool arguments exceed the size cap");
|
|
15929
15958
|
var controlEnvelopeSchema = external_exports.object({
|
|
15930
15959
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
15931
|
-
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule"]),
|
|
15960
|
+
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule", "tool"]),
|
|
15932
15961
|
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
15933
15962
|
app: external_exports.object({ slug: external_exports.string().min(1).max(30), version: external_exports.string().min(1).max(32) }).strict(),
|
|
15934
15963
|
install: external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100) }).strict().optional(),
|
|
15935
15964
|
lifecycle: lifecycleEventSchema.optional(),
|
|
15936
15965
|
migration: migrationSchema.optional(),
|
|
15937
|
-
schedule: scheduleSchema.optional()
|
|
15966
|
+
schedule: scheduleSchema.optional(),
|
|
15967
|
+
tool: toolSchema.optional()
|
|
15938
15968
|
}).strict().superRefine((envelope, ctx) => {
|
|
15939
15969
|
if (envelope.kind === "lifecycle" !== (envelope.lifecycle !== void 0)) {
|
|
15940
15970
|
ctx.addIssue({ code: "custom", path: ["lifecycle"], message: "Lifecycle payload must match the control kind" });
|
|
@@ -15945,13 +15975,50 @@ var controlEnvelopeSchema = external_exports.object({
|
|
|
15945
15975
|
if (envelope.kind === "schedule" !== (envelope.schedule !== void 0)) {
|
|
15946
15976
|
ctx.addIssue({ code: "custom", path: ["schedule"], message: "Schedule payload must match the control kind" });
|
|
15947
15977
|
}
|
|
15978
|
+
if (envelope.kind === "tool" !== (envelope.tool !== void 0)) {
|
|
15979
|
+
ctx.addIssue({ code: "custom", path: ["tool"], message: "Tool payload must match the control kind" });
|
|
15980
|
+
}
|
|
15948
15981
|
if (envelope.kind === "lifecycle" && envelope.install === void 0) {
|
|
15949
15982
|
ctx.addIssue({ code: "custom", path: ["install"], message: "Lifecycle control needs an install" });
|
|
15950
15983
|
}
|
|
15984
|
+
if (envelope.kind === "tool" && envelope.install === void 0) {
|
|
15985
|
+
ctx.addIssue({ code: "custom", path: ["install"], message: "Tool control needs an install" });
|
|
15986
|
+
}
|
|
15951
15987
|
});
|
|
15988
|
+
var toolDataWithinLimits = /* @__PURE__ */ __name((value) => {
|
|
15989
|
+
const stack = [{ value, depth: 0 }];
|
|
15990
|
+
let seen = 0;
|
|
15991
|
+
while (stack.length > 0) {
|
|
15992
|
+
const next = stack.pop();
|
|
15993
|
+
seen += 1;
|
|
15994
|
+
if (next.depth > MAX_TOOL_DATA_DEPTH || seen > MAX_TOOL_DATA_NODES) {
|
|
15995
|
+
return false;
|
|
15996
|
+
}
|
|
15997
|
+
if (next.value !== null && typeof next.value === "object") {
|
|
15998
|
+
for (const child of Object.values(next.value)) {
|
|
15999
|
+
stack.push({ value: child, depth: next.depth + 1 });
|
|
16000
|
+
}
|
|
16001
|
+
}
|
|
16002
|
+
}
|
|
16003
|
+
return true;
|
|
16004
|
+
}, "toolDataWithinLimits");
|
|
16005
|
+
var toolResultSchema = external_exports.object({
|
|
16006
|
+
content: external_exports.string().max(MAX_TOOL_RESULT_BYTES),
|
|
16007
|
+
// MCP defines `structuredContent` as an object, so a bare scalar or array is refused here rather
|
|
16008
|
+
// than surfacing as a protocol error at the client.
|
|
16009
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
16010
|
+
// True when the handler chose to fail with `ctx.fail`: `content` is then the app's own message
|
|
16011
|
+
// for the model. A thrown handler is `ok: false` with no `tool` at all.
|
|
16012
|
+
failed: external_exports.boolean()
|
|
16013
|
+
}).strict().refine((result) => {
|
|
16014
|
+
return toolDataWithinLimits(result.data);
|
|
16015
|
+
}, "Tool result nests too deeply or carries too many values").refine((result) => {
|
|
16016
|
+
return new TextEncoder().encode(JSON.stringify({ content: result.content, data: result.data ?? null })).length <= MAX_TOOL_RESULT_BYTES;
|
|
16017
|
+
}, "Tool result exceeds the size cap");
|
|
15952
16018
|
var controlResponseSchema = external_exports.object({
|
|
15953
16019
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
15954
16020
|
ok: external_exports.boolean(),
|
|
16021
|
+
tool: toolResultSchema.optional(),
|
|
15955
16022
|
migration: external_exports.union([
|
|
15956
16023
|
external_exports.object({ done: external_exports.literal(true) }).strict(),
|
|
15957
16024
|
external_exports.object({ done: external_exports.literal(false), checkpoint: external_exports.unknown() }).strict().refine((result) => {
|
|
@@ -19052,17 +19119,25 @@ var readableContext = /* @__PURE__ */ __name((own, shared) => {
|
|
|
19052
19119
|
}, "readableContext");
|
|
19053
19120
|
|
|
19054
19121
|
// src/apps/observability.ts
|
|
19122
|
+
var APP_ERROR_DATA_POINT_RESERVE = 50;
|
|
19055
19123
|
var observabilityApp = /* @__PURE__ */ __name((slug, app2) => {
|
|
19056
19124
|
return { slug, name: app2.name, version: app2.version };
|
|
19057
19125
|
}, "observabilityApp");
|
|
19058
19126
|
var createDataPointBudget = /* @__PURE__ */ __name(() => {
|
|
19059
|
-
let
|
|
19127
|
+
let events = 0;
|
|
19128
|
+
let total = 0;
|
|
19060
19129
|
return {
|
|
19061
|
-
take: /* @__PURE__ */ __name(() => {
|
|
19062
|
-
if (
|
|
19130
|
+
take: /* @__PURE__ */ __name((kind2) => {
|
|
19131
|
+
if (total >= MAX_APP_DATA_POINTS_PER_INVOCATION) {
|
|
19063
19132
|
return false;
|
|
19064
19133
|
}
|
|
19065
|
-
|
|
19134
|
+
if (kind2 === "event") {
|
|
19135
|
+
if (events >= MAX_APP_DATA_POINTS_PER_INVOCATION - APP_ERROR_DATA_POINT_RESERVE) {
|
|
19136
|
+
return false;
|
|
19137
|
+
}
|
|
19138
|
+
events += 1;
|
|
19139
|
+
}
|
|
19140
|
+
total += 1;
|
|
19066
19141
|
return true;
|
|
19067
19142
|
}, "take")
|
|
19068
19143
|
};
|
|
@@ -19085,43 +19160,71 @@ var errorBlobs = /* @__PURE__ */ __name((app2, install, record2, rowId) => {
|
|
|
19085
19160
|
var eventBlobs = /* @__PURE__ */ __name((app2, install, record2) => {
|
|
19086
19161
|
return [app2.slug, app2.name, install.id, install.label, app2.version, record2.name, record2.status];
|
|
19087
19162
|
}, "eventBlobs");
|
|
19088
|
-
var
|
|
19089
|
-
const
|
|
19090
|
-
if (record2 === null) {
|
|
19091
|
-
return;
|
|
19092
|
-
}
|
|
19093
|
-
const byOrd = new Map(
|
|
19094
|
-
target.installs.map((install) => {
|
|
19095
|
-
return [install.ord, install];
|
|
19096
|
-
})
|
|
19097
|
-
);
|
|
19098
|
-
for (const event of record2.events) {
|
|
19163
|
+
var writeEvents = /* @__PURE__ */ __name((env, target, byOrd, events) => {
|
|
19164
|
+
for (const [index, event] of events.entries()) {
|
|
19099
19165
|
const install = byOrd.get(event.ord);
|
|
19100
19166
|
if (install === void 0) {
|
|
19101
19167
|
addSpanEvent("app observability names an install the site did not send", { level: "warn", attrs: { app: target.app.slug } });
|
|
19102
19168
|
continue;
|
|
19103
19169
|
}
|
|
19104
|
-
if (!target.budget.take()) {
|
|
19105
|
-
addSpanEvent("app observability dropped at the data-point cap", {
|
|
19106
|
-
|
|
19170
|
+
if (!target.budget.take("event")) {
|
|
19171
|
+
addSpanEvent("app observability dropped events at the data-point cap", {
|
|
19172
|
+
level: "warn",
|
|
19173
|
+
attrs: { app: target.app.slug, skipped: events.length - index }
|
|
19174
|
+
});
|
|
19175
|
+
break;
|
|
19107
19176
|
}
|
|
19108
19177
|
env.APP_EVENTS.writeDataPoint({ indexes: [`${install.id}:${event.status}`], blobs: eventBlobs(target.app, install, event) });
|
|
19109
19178
|
}
|
|
19110
|
-
|
|
19179
|
+
}, "writeEvents");
|
|
19180
|
+
var writeErrors = /* @__PURE__ */ __name((env, target, byOrd, errors) => {
|
|
19181
|
+
for (const [index, saved] of errors.entries()) {
|
|
19111
19182
|
const install = byOrd.get(saved.ord);
|
|
19112
19183
|
if (install === void 0) {
|
|
19113
19184
|
addSpanEvent("app observability names an install the site did not send", { level: "warn", attrs: { app: target.app.slug } });
|
|
19114
19185
|
continue;
|
|
19115
19186
|
}
|
|
19116
|
-
if (!target.budget.take()) {
|
|
19117
|
-
addSpanEvent("app observability dropped at the data-point cap", {
|
|
19118
|
-
|
|
19187
|
+
if (!target.budget.take("error")) {
|
|
19188
|
+
addSpanEvent("app observability dropped saved errors at the data-point cap", {
|
|
19189
|
+
level: "warn",
|
|
19190
|
+
attrs: { app: target.app.slug, skipped: errors.length - index }
|
|
19191
|
+
});
|
|
19192
|
+
break;
|
|
19119
19193
|
}
|
|
19120
19194
|
env.APP_ERRORS.writeDataPoint({
|
|
19121
19195
|
indexes: [`${install.id}:${saved.category}`],
|
|
19122
19196
|
blobs: errorBlobs(target.app, install, saved, ulid3())
|
|
19123
19197
|
});
|
|
19124
19198
|
}
|
|
19199
|
+
}, "writeErrors");
|
|
19200
|
+
var guarded = /* @__PURE__ */ __name((target, write) => {
|
|
19201
|
+
try {
|
|
19202
|
+
write();
|
|
19203
|
+
return true;
|
|
19204
|
+
} catch (error51) {
|
|
19205
|
+
addSpanEvent("app observability write failed", { level: "warn", attrs: { app: target.app.slug, error: String(error51) } });
|
|
19206
|
+
return false;
|
|
19207
|
+
}
|
|
19208
|
+
}, "guarded");
|
|
19209
|
+
var writeAppObservability = /* @__PURE__ */ __name((env, response, target) => {
|
|
19210
|
+
const record2 = parseAppObservability(response.headers.get(APP_OBSERVABILITY_HEADER));
|
|
19211
|
+
if (record2 === null) {
|
|
19212
|
+
return;
|
|
19213
|
+
}
|
|
19214
|
+
const byOrd = new Map(
|
|
19215
|
+
target.installs.map((install) => {
|
|
19216
|
+
return [install.ord, install];
|
|
19217
|
+
})
|
|
19218
|
+
);
|
|
19219
|
+
const eventsWritten = guarded(target, () => {
|
|
19220
|
+
writeEvents(env, target, byOrd, record2.events);
|
|
19221
|
+
});
|
|
19222
|
+
const errorsWritten = guarded(target, () => {
|
|
19223
|
+
writeErrors(env, target, byOrd, record2.errors);
|
|
19224
|
+
});
|
|
19225
|
+
if (!eventsWritten || !errorsWritten) {
|
|
19226
|
+
return;
|
|
19227
|
+
}
|
|
19125
19228
|
if (record2.truncated === true) {
|
|
19126
19229
|
addSpanEvent("the app recorded more observability than one invocation carries", { level: "warn", attrs: { app: target.app.slug } });
|
|
19127
19230
|
}
|
|
@@ -20128,7 +20231,9 @@ var handleControl = /* @__PURE__ */ __name(async (request, env) => {
|
|
|
20128
20231
|
method: "POST",
|
|
20129
20232
|
headers,
|
|
20130
20233
|
body,
|
|
20131
|
-
|
|
20234
|
+
// Strictly inside the portal's own deadline for the same kind, so a slow tool times out here
|
|
20235
|
+
// first and the failure is attributable to the app worker rather than to the hop above it.
|
|
20236
|
+
signal: AbortSignal.timeout(envelope.kind === "tool" ? CONTROL_TOOL_FORWARD_TIMEOUT_MS : CONTROL_FORWARD_TIMEOUT_MS)
|
|
20132
20237
|
});
|
|
20133
20238
|
adoptAppSpans(upstream);
|
|
20134
20239
|
writeControlObservability(env, upstream, envelope);
|
|
@@ -20891,10 +20996,10 @@ var verifyAppUiToken = /* @__PURE__ */ __name(async (input) => {
|
|
|
20891
20996
|
return { ok: true, claims: claims.data, kid: signature.kid, key: signature.key };
|
|
20892
20997
|
}, "verifyAppUiToken");
|
|
20893
20998
|
|
|
20894
|
-
// ../../libs/app-ui-token/src/
|
|
20895
|
-
var
|
|
20999
|
+
// ../../libs/app-ui-token/src/runtime-query-ticket.ts
|
|
21000
|
+
var APP_RUNTIME_QUERY_TICKET_ISSUER = "qinto-portal";
|
|
20896
21001
|
var claimsSchema2 = external_exports.object({
|
|
20897
|
-
iss: external_exports.literal(
|
|
21002
|
+
iss: external_exports.literal(APP_RUNTIME_QUERY_TICKET_ISSUER),
|
|
20898
21003
|
aud: external_exports.string().min(1),
|
|
20899
21004
|
sub: external_exports.string().min(1),
|
|
20900
21005
|
iat: external_exports.number().int(),
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"main": {
|
|
3
3
|
"version": "0.1.0",
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-08-
|
|
4
|
+
"gitSha": "83bcac7072f2feb866505c4a7b99f7281b08d972",
|
|
5
|
+
"builtAt": "2026-08-29T21:13:15.188Z",
|
|
6
6
|
"compatibilityDate": "2026-06-23",
|
|
7
7
|
"compatibilityFlags": [
|
|
8
8
|
"nodejs_compat"
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"app-runtime": {
|
|
42
42
|
"version": "0.1.0",
|
|
43
|
-
"gitSha": "
|
|
44
|
-
"builtAt": "2026-08-
|
|
43
|
+
"gitSha": "83bcac7072f2feb866505c4a7b99f7281b08d972",
|
|
44
|
+
"builtAt": "2026-08-29T21:13:19.154Z",
|
|
45
45
|
"compatibilityDate": "2026-06-23",
|
|
46
46
|
"compatibilityFlags": [
|
|
47
47
|
"nodejs_compat"
|