@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
|
@@ -7,6 +7,10 @@ var __export = (target, all) => {
|
|
|
7
7
|
// ../../../libs/app-manifest/src/cron.ts
|
|
8
8
|
var MAX_CRON_LENGTH = 128;
|
|
9
9
|
|
|
10
|
+
// ../../../libs/app-manifest/src/tool-names.ts
|
|
11
|
+
var MAX_APP_TOOL_NAME_LENGTH = 32;
|
|
12
|
+
var APP_TOOL_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
13
|
+
|
|
10
14
|
// ../../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
11
15
|
var external_exports = {};
|
|
12
16
|
__export(external_exports, {
|
|
@@ -2348,13 +2352,13 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
2348
2352
|
canary.aborted = true;
|
|
2349
2353
|
return canary;
|
|
2350
2354
|
}
|
|
2351
|
-
const
|
|
2352
|
-
if (
|
|
2355
|
+
const checkResult2 = runChecks(payload, checks, ctx);
|
|
2356
|
+
if (checkResult2 instanceof Promise) {
|
|
2353
2357
|
if (ctx.async === false)
|
|
2354
2358
|
throw new $ZodAsyncError();
|
|
2355
|
-
return
|
|
2359
|
+
return checkResult2.then((checkResult3) => inst._zod.parse(checkResult3, ctx));
|
|
2356
2360
|
}
|
|
2357
|
-
return inst._zod.parse(
|
|
2361
|
+
return inst._zod.parse(checkResult2, ctx);
|
|
2358
2362
|
};
|
|
2359
2363
|
inst._zod.run = (payload, ctx) => {
|
|
2360
2364
|
if (ctx.skipChecks) {
|
|
@@ -14628,6 +14632,11 @@ var envelopeResponseSchema = external_exports.object({
|
|
|
14628
14632
|
var CONTROL_ENVELOPE_VERSION = 1;
|
|
14629
14633
|
var MAX_CONTROL_BYTES = 256 * 1024;
|
|
14630
14634
|
var MAX_MIGRATION_CHECKPOINT_BYTES = 16 * 1024;
|
|
14635
|
+
var MAX_TOOL_ARGUMENTS_BYTES = 32 * 1024;
|
|
14636
|
+
var MAX_TOOL_RESULT_BYTES = 64 * 1024;
|
|
14637
|
+
var MAX_TOOL_DATA_DEPTH = 8;
|
|
14638
|
+
var MAX_TOOL_DATA_NODES = 5e3;
|
|
14639
|
+
var MAX_TOOL_ERROR_MESSAGE_LENGTH = 512;
|
|
14631
14640
|
var installSchema2 = external_exports.object({
|
|
14632
14641
|
id: external_exports.string().min(1).max(64),
|
|
14633
14642
|
ord: external_exports.number().int().min(1),
|
|
@@ -14697,19 +14706,39 @@ var scheduleSchema = external_exports.object({
|
|
|
14697
14706
|
id: external_exports.string().min(1).max(64),
|
|
14698
14707
|
ord: external_exports.number().int().min(1),
|
|
14699
14708
|
label: external_exports.string().max(100),
|
|
14700
|
-
|
|
14709
|
+
queryTicket: external_exports.string().min(1).max(2048)
|
|
14701
14710
|
}).strict()
|
|
14702
14711
|
).min(1).max(MAX_INSTALLS_PER_APP)
|
|
14703
14712
|
}).strict();
|
|
14713
|
+
var toolSchema = external_exports.object({
|
|
14714
|
+
// The manifest's tools[].name, never the `<slug>_` composed MCP name: the slug is already in
|
|
14715
|
+
// `app.slug`, and carrying it twice would give the app worker two sources for one fact.
|
|
14716
|
+
name: external_exports.string().min(1).max(MAX_APP_TOOL_NAME_LENGTH).regex(APP_TOOL_NAME_PATTERN),
|
|
14717
|
+
// Who asked, and what they may do on this site. Derived from the bearer by the portal, never
|
|
14718
|
+
// from the model's arguments.
|
|
14719
|
+
viewer: external_exports.object({ userId: external_exports.string().min(1).max(64), access: external_exports.enum(["read", "write"]) }).strict(),
|
|
14720
|
+
// Already validated against the tool's declared inputSchema, with the reserved routing names
|
|
14721
|
+
// stripped. Every declared input schema has an object root, so this is an object too — and a
|
|
14722
|
+
// call that names no arguments normalizes to `{}` rather than reaching the handler as undefined.
|
|
14723
|
+
arguments: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
14724
|
+
// Stable across a collapsed retry, so an app can deduplicate its external effects on it.
|
|
14725
|
+
callId: external_exports.string().min(1).max(64),
|
|
14726
|
+
// The short-lived install/version-scoped credential used only by the app runtime's query
|
|
14727
|
+
// broker. It never enters handler arguments or app-authored result data.
|
|
14728
|
+
queryTicket: external_exports.string().min(1).max(2048)
|
|
14729
|
+
}).strict().refine((tool) => {
|
|
14730
|
+
return new TextEncoder().encode(JSON.stringify(tool.arguments)).length <= MAX_TOOL_ARGUMENTS_BYTES;
|
|
14731
|
+
}, "Tool arguments exceed the size cap");
|
|
14704
14732
|
var controlEnvelopeSchema = external_exports.object({
|
|
14705
14733
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
14706
|
-
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule"]),
|
|
14734
|
+
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule", "tool"]),
|
|
14707
14735
|
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
14708
14736
|
app: external_exports.object({ slug: external_exports.string().min(1).max(30), version: external_exports.string().min(1).max(32) }).strict(),
|
|
14709
14737
|
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(),
|
|
14710
14738
|
lifecycle: lifecycleEventSchema.optional(),
|
|
14711
14739
|
migration: migrationSchema.optional(),
|
|
14712
|
-
schedule: scheduleSchema.optional()
|
|
14740
|
+
schedule: scheduleSchema.optional(),
|
|
14741
|
+
tool: toolSchema.optional()
|
|
14713
14742
|
}).strict().superRefine((envelope, ctx) => {
|
|
14714
14743
|
if (envelope.kind === "lifecycle" !== (envelope.lifecycle !== void 0)) {
|
|
14715
14744
|
ctx.addIssue({ code: "custom", path: ["lifecycle"], message: "Lifecycle payload must match the control kind" });
|
|
@@ -14720,13 +14749,50 @@ var controlEnvelopeSchema = external_exports.object({
|
|
|
14720
14749
|
if (envelope.kind === "schedule" !== (envelope.schedule !== void 0)) {
|
|
14721
14750
|
ctx.addIssue({ code: "custom", path: ["schedule"], message: "Schedule payload must match the control kind" });
|
|
14722
14751
|
}
|
|
14752
|
+
if (envelope.kind === "tool" !== (envelope.tool !== void 0)) {
|
|
14753
|
+
ctx.addIssue({ code: "custom", path: ["tool"], message: "Tool payload must match the control kind" });
|
|
14754
|
+
}
|
|
14723
14755
|
if (envelope.kind === "lifecycle" && envelope.install === void 0) {
|
|
14724
14756
|
ctx.addIssue({ code: "custom", path: ["install"], message: "Lifecycle control needs an install" });
|
|
14725
14757
|
}
|
|
14758
|
+
if (envelope.kind === "tool" && envelope.install === void 0) {
|
|
14759
|
+
ctx.addIssue({ code: "custom", path: ["install"], message: "Tool control needs an install" });
|
|
14760
|
+
}
|
|
14726
14761
|
});
|
|
14762
|
+
var toolDataWithinLimits = (value) => {
|
|
14763
|
+
const stack = [{ value, depth: 0 }];
|
|
14764
|
+
let seen = 0;
|
|
14765
|
+
while (stack.length > 0) {
|
|
14766
|
+
const next = stack.pop();
|
|
14767
|
+
seen += 1;
|
|
14768
|
+
if (next.depth > MAX_TOOL_DATA_DEPTH || seen > MAX_TOOL_DATA_NODES) {
|
|
14769
|
+
return false;
|
|
14770
|
+
}
|
|
14771
|
+
if (next.value !== null && typeof next.value === "object") {
|
|
14772
|
+
for (const child of Object.values(next.value)) {
|
|
14773
|
+
stack.push({ value: child, depth: next.depth + 1 });
|
|
14774
|
+
}
|
|
14775
|
+
}
|
|
14776
|
+
}
|
|
14777
|
+
return true;
|
|
14778
|
+
};
|
|
14779
|
+
var toolResultSchema = external_exports.object({
|
|
14780
|
+
content: external_exports.string().max(MAX_TOOL_RESULT_BYTES),
|
|
14781
|
+
// MCP defines `structuredContent` as an object, so a bare scalar or array is refused here rather
|
|
14782
|
+
// than surfacing as a protocol error at the client.
|
|
14783
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
14784
|
+
// True when the handler chose to fail with `ctx.fail`: `content` is then the app's own message
|
|
14785
|
+
// for the model. A thrown handler is `ok: false` with no `tool` at all.
|
|
14786
|
+
failed: external_exports.boolean()
|
|
14787
|
+
}).strict().refine((result) => {
|
|
14788
|
+
return toolDataWithinLimits(result.data);
|
|
14789
|
+
}, "Tool result nests too deeply or carries too many values").refine((result) => {
|
|
14790
|
+
return new TextEncoder().encode(JSON.stringify({ content: result.content, data: result.data ?? null })).length <= MAX_TOOL_RESULT_BYTES;
|
|
14791
|
+
}, "Tool result exceeds the size cap");
|
|
14727
14792
|
var controlResponseSchema = external_exports.object({
|
|
14728
14793
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
14729
14794
|
ok: external_exports.boolean(),
|
|
14795
|
+
tool: toolResultSchema.optional(),
|
|
14730
14796
|
migration: external_exports.union([
|
|
14731
14797
|
external_exports.object({ done: external_exports.literal(true) }).strict(),
|
|
14732
14798
|
external_exports.object({ done: external_exports.literal(false), checkpoint: external_exports.unknown() }).strict().refine((result) => {
|
|
@@ -14869,6 +14935,9 @@ var appUiWritePath = (domainId, appSlug2) => {
|
|
|
14869
14935
|
var appUiCatalogQueryPath = (domainId, appSlug2, resourceIdentifier) => {
|
|
14870
14936
|
return `/app-ui/sites/${domainId}/apps/${appSlug2}/catalogs/${resourceIdentifier}/query`;
|
|
14871
14937
|
};
|
|
14938
|
+
var appUiAnalyticsQueryPath = (domainId, appSlug2, resourceIdentifier) => {
|
|
14939
|
+
return `/app-ui/sites/${domainId}/apps/${appSlug2}/analytics/${resourceIdentifier}/query`;
|
|
14940
|
+
};
|
|
14872
14941
|
var uiInstallSchema = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100), enabled: external_exports.boolean() }).strict();
|
|
14873
14942
|
var uiContextSchema = external_exports.object({
|
|
14874
14943
|
version: external_exports.string().min(1).max(32),
|
|
@@ -16132,43 +16201,58 @@ var failureMessage = (error51) => {
|
|
|
16132
16201
|
return message.slice(0, MAX_ERROR_MESSAGE_LENGTH);
|
|
16133
16202
|
};
|
|
16134
16203
|
|
|
16135
|
-
// src/
|
|
16136
|
-
var
|
|
16137
|
-
var
|
|
16138
|
-
const raw = await readBody(response,
|
|
16204
|
+
// src/query.ts
|
|
16205
|
+
var MAX_QUERY_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
16206
|
+
var parseQueryResponse = async (kind, response) => {
|
|
16207
|
+
const raw = await readBody(response, MAX_QUERY_RESPONSE_BYTES);
|
|
16139
16208
|
if (raw === null) {
|
|
16140
|
-
throw new Error(
|
|
16209
|
+
throw new Error(`The ${kind} query response exceeded the app runtime limit.`);
|
|
16141
16210
|
}
|
|
16142
16211
|
let body;
|
|
16143
16212
|
try {
|
|
16144
16213
|
body = JSON.parse(raw);
|
|
16145
16214
|
} catch {
|
|
16146
|
-
throw new Error(`The
|
|
16215
|
+
throw new Error(`The ${kind} query returned an invalid response (${response.status}).`);
|
|
16147
16216
|
}
|
|
16148
16217
|
if (!response.ok) {
|
|
16149
16218
|
const error51 = body;
|
|
16150
16219
|
const reason = typeof error51.message === "string" ? error51.message : typeof error51.error === "string" ? error51.error : `request failed with status ${response.status}`;
|
|
16151
|
-
throw new Error(
|
|
16220
|
+
throw new Error(`${kind === "catalog" ? "Catalog" : "Analytics"} query failed: ${reason}`);
|
|
16152
16221
|
}
|
|
16153
16222
|
return body;
|
|
16154
16223
|
};
|
|
16155
|
-
var
|
|
16224
|
+
var buildQuery = ({ env, ticket, installId }) => {
|
|
16225
|
+
const platform = env;
|
|
16226
|
+
const context = JSON.parse(platform.APP_CONTEXT);
|
|
16227
|
+
const post = async (kind, path, resourceIdentifier, sql) => {
|
|
16228
|
+
return traced(
|
|
16229
|
+
`qinto.${kind}.query`,
|
|
16230
|
+
{ attrs: { "app.install_id": installId, [`app.${kind}.resource`]: resourceIdentifier } },
|
|
16231
|
+
async () => {
|
|
16232
|
+
const response = await fetch(new URL(path, platform.QINTO_PLATFORM_API), {
|
|
16233
|
+
method: "POST",
|
|
16234
|
+
headers: { authorization: `Bearer ${ticket}`, "content-type": "application/json" },
|
|
16235
|
+
body: JSON.stringify({ sql })
|
|
16236
|
+
});
|
|
16237
|
+
return parseQueryResponse(kind, response);
|
|
16238
|
+
}
|
|
16239
|
+
);
|
|
16240
|
+
};
|
|
16156
16241
|
return {
|
|
16157
16242
|
catalog: async (resourceIdentifier, sql) => {
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
}
|
|
16243
|
+
return post(
|
|
16244
|
+
"catalog",
|
|
16245
|
+
appUiCatalogQueryPath(context.domainId, context.slug, resourceIdentifier),
|
|
16246
|
+
resourceIdentifier,
|
|
16247
|
+
sql
|
|
16248
|
+
);
|
|
16249
|
+
},
|
|
16250
|
+
analytics: async (resourceIdentifier, sql) => {
|
|
16251
|
+
return post(
|
|
16252
|
+
"analytics",
|
|
16253
|
+
appUiAnalyticsQueryPath(context.domainId, context.slug, resourceIdentifier),
|
|
16254
|
+
resourceIdentifier,
|
|
16255
|
+
sql
|
|
16172
16256
|
);
|
|
16173
16257
|
}
|
|
16174
16258
|
};
|
|
@@ -16177,7 +16261,8 @@ var buildCatalogQuery = ({ env, ticket, installId }) => {
|
|
|
16177
16261
|
// src/schedule.ts
|
|
16178
16262
|
var dispatchSchedule = async (envelope, bundle, env) => {
|
|
16179
16263
|
const schedule = envelope.schedule;
|
|
16180
|
-
const
|
|
16264
|
+
const schedules = bundle.schedules;
|
|
16265
|
+
const handler = schedules !== void 0 && Object.hasOwn(schedules, schedule.id) ? schedules[schedule.id] : void 0;
|
|
16181
16266
|
if (typeof handler !== "function") {
|
|
16182
16267
|
return json2(200, {
|
|
16183
16268
|
v: CONTROL_ENVELOPE_VERSION,
|
|
@@ -16209,7 +16294,7 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
16209
16294
|
appSecrets: appScope.appSecrets,
|
|
16210
16295
|
observability: buildObservability(install.ord),
|
|
16211
16296
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
16212
|
-
query:
|
|
16297
|
+
query: buildQuery({ env, ticket: install.queryTicket, installId: install.id }),
|
|
16213
16298
|
push: async (userId, message) => {
|
|
16214
16299
|
await brokerPush(env, {
|
|
16215
16300
|
userId,
|
|
@@ -16239,6 +16324,142 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
16239
16324
|
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: true });
|
|
16240
16325
|
};
|
|
16241
16326
|
|
|
16327
|
+
// src/tool.ts
|
|
16328
|
+
var failure = (message) => {
|
|
16329
|
+
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message } });
|
|
16330
|
+
};
|
|
16331
|
+
var isFailure = (value) => {
|
|
16332
|
+
return value !== null && typeof value === "object" && value.kind === "tool_error" && typeof value.message === "string";
|
|
16333
|
+
};
|
|
16334
|
+
var isResult = (value) => {
|
|
16335
|
+
return value !== null && typeof value === "object" && typeof value.content === "string";
|
|
16336
|
+
};
|
|
16337
|
+
var isStructuredData = (data) => {
|
|
16338
|
+
return data === void 0 || data !== null && typeof data === "object" && !Array.isArray(data);
|
|
16339
|
+
};
|
|
16340
|
+
var isPlainContainer = (value) => {
|
|
16341
|
+
const prototype = Object.getPrototypeOf(value);
|
|
16342
|
+
return Array.isArray(value) || prototype === Object.prototype || prototype === null;
|
|
16343
|
+
};
|
|
16344
|
+
var jsonScalarVerdict = (value) => {
|
|
16345
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
16346
|
+
return "ok";
|
|
16347
|
+
}
|
|
16348
|
+
if (typeof value === "number") {
|
|
16349
|
+
return Number.isFinite(value) ? "ok" : "invalid";
|
|
16350
|
+
}
|
|
16351
|
+
if (value === void 0 || typeof value !== "object" || !isPlainContainer(value)) {
|
|
16352
|
+
return "invalid";
|
|
16353
|
+
}
|
|
16354
|
+
return "container";
|
|
16355
|
+
};
|
|
16356
|
+
var isJsonValue = (root) => {
|
|
16357
|
+
const stack = [root];
|
|
16358
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16359
|
+
while (stack.length > 0) {
|
|
16360
|
+
const value = stack.pop();
|
|
16361
|
+
const verdict = jsonScalarVerdict(value);
|
|
16362
|
+
if (verdict === "invalid") {
|
|
16363
|
+
return false;
|
|
16364
|
+
}
|
|
16365
|
+
if (verdict === "ok" || seen.has(value)) {
|
|
16366
|
+
continue;
|
|
16367
|
+
}
|
|
16368
|
+
seen.add(value);
|
|
16369
|
+
if (Array.isArray(value) && Object.keys(value).length !== value.length) {
|
|
16370
|
+
return false;
|
|
16371
|
+
}
|
|
16372
|
+
stack.push(...Object.values(value));
|
|
16373
|
+
}
|
|
16374
|
+
return true;
|
|
16375
|
+
};
|
|
16376
|
+
var truncate = (message) => {
|
|
16377
|
+
return message.length <= MAX_TOOL_ERROR_MESSAGE_LENGTH ? message : message.slice(0, MAX_TOOL_ERROR_MESSAGE_LENGTH);
|
|
16378
|
+
};
|
|
16379
|
+
var checkResult = (result) => {
|
|
16380
|
+
if (!isStructuredData(result.data)) {
|
|
16381
|
+
return "not_structured";
|
|
16382
|
+
}
|
|
16383
|
+
if (result.data !== void 0 && !isJsonValue(result.data)) {
|
|
16384
|
+
return "not_serializable";
|
|
16385
|
+
}
|
|
16386
|
+
let encoded;
|
|
16387
|
+
try {
|
|
16388
|
+
encoded = new TextEncoder().encode(JSON.stringify({ content: result.content, data: result.data ?? null }));
|
|
16389
|
+
} catch {
|
|
16390
|
+
return "not_serializable";
|
|
16391
|
+
}
|
|
16392
|
+
if (encoded.length > MAX_TOOL_RESULT_BYTES || !toolDataWithinLimits(result.data)) {
|
|
16393
|
+
return "too_large";
|
|
16394
|
+
}
|
|
16395
|
+
return "ok";
|
|
16396
|
+
};
|
|
16397
|
+
var buildContext2 = (envelope, env) => {
|
|
16398
|
+
const install = envelope.install;
|
|
16399
|
+
const { variableKinds, appVariableKinds } = contextKindsOf(env);
|
|
16400
|
+
const maps = parseVariableMaps(env);
|
|
16401
|
+
const appScope = projectAppValues(env, appVariableKinds);
|
|
16402
|
+
const { variables, secrets } = projectInstallValues(maps, variableKinds, install.ord);
|
|
16403
|
+
return {
|
|
16404
|
+
env,
|
|
16405
|
+
site: envelope.site,
|
|
16406
|
+
install: { id: install.id, label: install.label },
|
|
16407
|
+
viewer: envelope.tool.viewer,
|
|
16408
|
+
callId: envelope.tool.callId,
|
|
16409
|
+
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
16410
|
+
oauth: buildOauth(env, install.ord),
|
|
16411
|
+
variables,
|
|
16412
|
+
secrets,
|
|
16413
|
+
appVariables: appScope.appVariables,
|
|
16414
|
+
appSecrets: appScope.appSecrets,
|
|
16415
|
+
observability: buildObservability(install.ord),
|
|
16416
|
+
apps: buildAppsClient(env, { depth: 0 }),
|
|
16417
|
+
query: buildQuery({ env, ticket: envelope.tool.queryTicket, installId: install.id }),
|
|
16418
|
+
fail: (message) => {
|
|
16419
|
+
return { kind: "tool_error", message: truncate(message) };
|
|
16420
|
+
}
|
|
16421
|
+
};
|
|
16422
|
+
};
|
|
16423
|
+
var dispatchTool = async (envelope, bundle, env) => {
|
|
16424
|
+
const name = envelope.tool.name;
|
|
16425
|
+
const tools = bundle.tools;
|
|
16426
|
+
const handler = tools !== void 0 && Object.hasOwn(tools, name) ? tools[name] : void 0;
|
|
16427
|
+
if (typeof handler !== "function") {
|
|
16428
|
+
return failure(`missing handler: tools.${name}`);
|
|
16429
|
+
}
|
|
16430
|
+
setSpanAttributes({ "app.tool": name, "app.tool_call_id": envelope.tool.callId });
|
|
16431
|
+
let value;
|
|
16432
|
+
try {
|
|
16433
|
+
value = await installSpan(envelope.install, () => {
|
|
16434
|
+
return handler(envelope.tool.arguments, buildContext2(envelope, env));
|
|
16435
|
+
});
|
|
16436
|
+
} catch (error51) {
|
|
16437
|
+
console.warn(`tool ${name} failed for install ${envelope.install.id}: ${failureMessage(error51)}`);
|
|
16438
|
+
return failure(`tool ${name} failed`);
|
|
16439
|
+
}
|
|
16440
|
+
if (isFailure(value)) {
|
|
16441
|
+
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: true, tool: { content: truncate(value.message), failed: true } });
|
|
16442
|
+
}
|
|
16443
|
+
if (!isResult(value)) {
|
|
16444
|
+
return failure(`tool ${name} returned no result`);
|
|
16445
|
+
}
|
|
16446
|
+
const verdict = checkResult(value);
|
|
16447
|
+
if (verdict === "not_structured") {
|
|
16448
|
+
return failure(`tool ${name} returned data that is not a JSON object`);
|
|
16449
|
+
}
|
|
16450
|
+
if (verdict === "not_serializable") {
|
|
16451
|
+
return failure(`tool ${name} returned data that cannot be serialized`);
|
|
16452
|
+
}
|
|
16453
|
+
if (verdict === "too_large") {
|
|
16454
|
+
return failure(`tool ${name} returned a result over the size cap`);
|
|
16455
|
+
}
|
|
16456
|
+
return json2(200, {
|
|
16457
|
+
v: CONTROL_ENVELOPE_VERSION,
|
|
16458
|
+
ok: true,
|
|
16459
|
+
tool: { content: value.content, ...value.data === void 0 ? {} : { data: value.data }, failed: false }
|
|
16460
|
+
});
|
|
16461
|
+
};
|
|
16462
|
+
|
|
16242
16463
|
// src/control.ts
|
|
16243
16464
|
var controlError = (status, message) => {
|
|
16244
16465
|
return json2(status, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message } });
|
|
@@ -16378,6 +16599,9 @@ var dispatchControl = async ({ request, env, versions }) => {
|
|
|
16378
16599
|
case "schedule": {
|
|
16379
16600
|
return dispatchSchedule(envelope, bundle, env);
|
|
16380
16601
|
}
|
|
16602
|
+
case "tool": {
|
|
16603
|
+
return dispatchTool(envelope, bundle, env);
|
|
16604
|
+
}
|
|
16381
16605
|
}
|
|
16382
16606
|
};
|
|
16383
16607
|
|
|
@@ -16410,7 +16634,7 @@ var handlerRequest = (request, context, body) => {
|
|
|
16410
16634
|
body: body.byteLength === 0 ? void 0 : body
|
|
16411
16635
|
});
|
|
16412
16636
|
};
|
|
16413
|
-
var
|
|
16637
|
+
var buildContext3 = ({ env, maps, kinds, appScope, install, site, params }) => {
|
|
16414
16638
|
const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
|
|
16415
16639
|
return {
|
|
16416
16640
|
env,
|
|
@@ -16502,7 +16726,7 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16502
16726
|
return installSpan(install, () => {
|
|
16503
16727
|
return handler(
|
|
16504
16728
|
handlerRequest(request, context, body),
|
|
16505
|
-
|
|
16729
|
+
buildContext3({ env, maps, kinds: variableKinds, appScope, install, site: context.site, params: context.params })
|
|
16506
16730
|
);
|
|
16507
16731
|
});
|
|
16508
16732
|
};
|
|
@@ -16788,7 +17012,7 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16788
17012
|
const { variableKinds: kinds, appVariableKinds } = contextKindsOf(env);
|
|
16789
17013
|
const appScope = projectAppValues(env, appVariableKinds);
|
|
16790
17014
|
const groups = [];
|
|
16791
|
-
let
|
|
17015
|
+
let failure2;
|
|
16792
17016
|
for (const install of envelope.installs) {
|
|
16793
17017
|
const emits = [];
|
|
16794
17018
|
const pushes = [];
|
|
@@ -16802,7 +17026,7 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16802
17026
|
} catch (error51) {
|
|
16803
17027
|
const message = failureMessage(error51);
|
|
16804
17028
|
console.warn(`app hook failed for install ${install.id}: ${message}`);
|
|
16805
|
-
|
|
17029
|
+
failure2 ??= message;
|
|
16806
17030
|
continue;
|
|
16807
17031
|
}
|
|
16808
17032
|
const contextWrites = context.writes();
|
|
@@ -16814,8 +17038,8 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16814
17038
|
if (groups.length > 0) {
|
|
16815
17039
|
body.effects = groups;
|
|
16816
17040
|
}
|
|
16817
|
-
if (
|
|
16818
|
-
body.error = { message:
|
|
17041
|
+
if (failure2 !== void 0) {
|
|
17042
|
+
body.error = { message: failure2 };
|
|
16819
17043
|
}
|
|
16820
17044
|
return json2(200, body);
|
|
16821
17045
|
};
|