@blotout/qinto-cli 0.1.8 → 0.1.10
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 +3262 -2483
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +547 -48
- package/dist/worker-artifact/main/9026260a7a674b710223f296c5d2e7a01930cfed-q.js.txt +1 -0
- package/dist/worker-artifact/main/index.js +549 -51
- package/dist/worker-artifact/version.json +6 -6
- package/package.json +1 -1
- package/templates/app/full/ui/src/pages/index.astro +0 -2
- package/templates/ui/src/pages/index.astro +1 -2
- package/dist/worker-artifact/main/9dcfd236748459af038da772477100c4bb0223b7-q.js.txt +0 -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) {
|
|
@@ -3036,10 +3040,10 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
3036
3040
|
const shape = def.shape;
|
|
3037
3041
|
const propValues = {};
|
|
3038
3042
|
for (const key in shape) {
|
|
3039
|
-
const
|
|
3040
|
-
if (
|
|
3043
|
+
const field2 = shape[key]._zod;
|
|
3044
|
+
if (field2.values) {
|
|
3041
3045
|
propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
|
|
3042
|
-
for (const v of
|
|
3046
|
+
for (const v of field2.values)
|
|
3043
3047
|
propValues[key].add(v);
|
|
3044
3048
|
}
|
|
3045
3049
|
}
|
|
@@ -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),
|
|
@@ -14701,15 +14710,32 @@ var scheduleSchema = external_exports.object({
|
|
|
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
|
+
}).strict().refine((tool) => {
|
|
14727
|
+
return new TextEncoder().encode(JSON.stringify(tool.arguments)).length <= MAX_TOOL_ARGUMENTS_BYTES;
|
|
14728
|
+
}, "Tool arguments exceed the size cap");
|
|
14704
14729
|
var controlEnvelopeSchema = external_exports.object({
|
|
14705
14730
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
14706
|
-
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule"]),
|
|
14731
|
+
kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule", "tool"]),
|
|
14707
14732
|
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
14708
14733
|
app: external_exports.object({ slug: external_exports.string().min(1).max(30), version: external_exports.string().min(1).max(32) }).strict(),
|
|
14709
14734
|
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
14735
|
lifecycle: lifecycleEventSchema.optional(),
|
|
14711
14736
|
migration: migrationSchema.optional(),
|
|
14712
|
-
schedule: scheduleSchema.optional()
|
|
14737
|
+
schedule: scheduleSchema.optional(),
|
|
14738
|
+
tool: toolSchema.optional()
|
|
14713
14739
|
}).strict().superRefine((envelope, ctx) => {
|
|
14714
14740
|
if (envelope.kind === "lifecycle" !== (envelope.lifecycle !== void 0)) {
|
|
14715
14741
|
ctx.addIssue({ code: "custom", path: ["lifecycle"], message: "Lifecycle payload must match the control kind" });
|
|
@@ -14720,13 +14746,50 @@ var controlEnvelopeSchema = external_exports.object({
|
|
|
14720
14746
|
if (envelope.kind === "schedule" !== (envelope.schedule !== void 0)) {
|
|
14721
14747
|
ctx.addIssue({ code: "custom", path: ["schedule"], message: "Schedule payload must match the control kind" });
|
|
14722
14748
|
}
|
|
14749
|
+
if (envelope.kind === "tool" !== (envelope.tool !== void 0)) {
|
|
14750
|
+
ctx.addIssue({ code: "custom", path: ["tool"], message: "Tool payload must match the control kind" });
|
|
14751
|
+
}
|
|
14723
14752
|
if (envelope.kind === "lifecycle" && envelope.install === void 0) {
|
|
14724
14753
|
ctx.addIssue({ code: "custom", path: ["install"], message: "Lifecycle control needs an install" });
|
|
14725
14754
|
}
|
|
14755
|
+
if (envelope.kind === "tool" && envelope.install === void 0) {
|
|
14756
|
+
ctx.addIssue({ code: "custom", path: ["install"], message: "Tool control needs an install" });
|
|
14757
|
+
}
|
|
14726
14758
|
});
|
|
14759
|
+
var toolDataWithinLimits = (value) => {
|
|
14760
|
+
const stack = [{ value, depth: 0 }];
|
|
14761
|
+
let seen = 0;
|
|
14762
|
+
while (stack.length > 0) {
|
|
14763
|
+
const next = stack.pop();
|
|
14764
|
+
seen += 1;
|
|
14765
|
+
if (next.depth > MAX_TOOL_DATA_DEPTH || seen > MAX_TOOL_DATA_NODES) {
|
|
14766
|
+
return false;
|
|
14767
|
+
}
|
|
14768
|
+
if (next.value !== null && typeof next.value === "object") {
|
|
14769
|
+
for (const child of Object.values(next.value)) {
|
|
14770
|
+
stack.push({ value: child, depth: next.depth + 1 });
|
|
14771
|
+
}
|
|
14772
|
+
}
|
|
14773
|
+
}
|
|
14774
|
+
return true;
|
|
14775
|
+
};
|
|
14776
|
+
var toolResultSchema = external_exports.object({
|
|
14777
|
+
content: external_exports.string().max(MAX_TOOL_RESULT_BYTES),
|
|
14778
|
+
// MCP defines `structuredContent` as an object, so a bare scalar or array is refused here rather
|
|
14779
|
+
// than surfacing as a protocol error at the client.
|
|
14780
|
+
data: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
14781
|
+
// True when the handler chose to fail with `ctx.fail`: `content` is then the app's own message
|
|
14782
|
+
// for the model. A thrown handler is `ok: false` with no `tool` at all.
|
|
14783
|
+
failed: external_exports.boolean()
|
|
14784
|
+
}).strict().refine((result) => {
|
|
14785
|
+
return toolDataWithinLimits(result.data);
|
|
14786
|
+
}, "Tool result nests too deeply or carries too many values").refine((result) => {
|
|
14787
|
+
return new TextEncoder().encode(JSON.stringify({ content: result.content, data: result.data ?? null })).length <= MAX_TOOL_RESULT_BYTES;
|
|
14788
|
+
}, "Tool result exceeds the size cap");
|
|
14727
14789
|
var controlResponseSchema = external_exports.object({
|
|
14728
14790
|
v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
|
|
14729
14791
|
ok: external_exports.boolean(),
|
|
14792
|
+
tool: toolResultSchema.optional(),
|
|
14730
14793
|
migration: external_exports.union([
|
|
14731
14794
|
external_exports.object({ done: external_exports.literal(true) }).strict(),
|
|
14732
14795
|
external_exports.object({ done: external_exports.literal(false), checkpoint: external_exports.unknown() }).strict().refine((result) => {
|
|
@@ -14741,12 +14804,21 @@ var ENDPOINT_CONTEXT_HEADER = "x-qinto-endpoint-context";
|
|
|
14741
14804
|
var ENDPOINT_OUTCOMES_HEADER = "x-qinto-endpoint-outcomes";
|
|
14742
14805
|
var MAX_ENDPOINT_BODY_BYTES = 1024 * 1024;
|
|
14743
14806
|
var MAX_ENDPOINT_OUTCOMES_BYTES = 64 * 1024;
|
|
14807
|
+
var MAX_ENDPOINT_PATH_LENGTH = 16 * 1024;
|
|
14744
14808
|
var installSchema3 = 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();
|
|
14745
14809
|
var endpointContextSchema = external_exports.object({
|
|
14746
|
-
path
|
|
14810
|
+
// The declared template, which keys the bundle's handler map; `path` is what the caller asked
|
|
14811
|
+
// for. Only `route` may key the rate limiter — a concrete path gives every parameter value its
|
|
14812
|
+
// own bucket, which is no limit at all.
|
|
14813
|
+
route: external_exports.string().min(1).max(255),
|
|
14814
|
+
path: external_exports.string().min(1).max(MAX_ENDPOINT_PATH_LENGTH),
|
|
14815
|
+
// A name is cut from `route`, so the route's own cap bounds it; anything tighter would reject a
|
|
14816
|
+
// parameter the manifest grammar accepts and the worker already matched.
|
|
14817
|
+
params: external_exports.record(external_exports.string().min(1).max(255), external_exports.string().max(MAX_ENDPOINT_PATH_LENGTH)).default({}),
|
|
14747
14818
|
method: external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
14748
14819
|
mode: external_exports.enum(["webhook", "api"]),
|
|
14749
14820
|
version: external_exports.string().min(1).max(32),
|
|
14821
|
+
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
14750
14822
|
installs: external_exports.array(installSchema3).min(1).max(15)
|
|
14751
14823
|
}).strict().refine((context) => {
|
|
14752
14824
|
return context.mode === "webhook" || context.installs.length === 1;
|
|
@@ -14761,6 +14833,96 @@ var endpointOutcomesSchema = external_exports.object({
|
|
|
14761
14833
|
).max(15)
|
|
14762
14834
|
}).strict();
|
|
14763
14835
|
|
|
14836
|
+
// ../../../libs/app-envelope/src/oauth.ts
|
|
14837
|
+
var APP_OAUTH_BINDING_PREFIX = "OAUTH_";
|
|
14838
|
+
var appOauthBindingName = (providerId, ordinal) => {
|
|
14839
|
+
return `${APP_OAUTH_BINDING_PREFIX}${providerId.toUpperCase().replaceAll("-", "_")}_${ordinal}`;
|
|
14840
|
+
};
|
|
14841
|
+
var parseAppOauthBinding = (raw) => {
|
|
14842
|
+
if (raw === void 0 || raw === "") {
|
|
14843
|
+
return null;
|
|
14844
|
+
}
|
|
14845
|
+
let parsed;
|
|
14846
|
+
try {
|
|
14847
|
+
parsed = JSON.parse(raw);
|
|
14848
|
+
} catch {
|
|
14849
|
+
return null;
|
|
14850
|
+
}
|
|
14851
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
14852
|
+
return null;
|
|
14853
|
+
}
|
|
14854
|
+
const value = parsed;
|
|
14855
|
+
if (value["st"] !== "connected" && value["st"] !== "reconnect_required") {
|
|
14856
|
+
return null;
|
|
14857
|
+
}
|
|
14858
|
+
const expiresAt = value["e"];
|
|
14859
|
+
const token = value["t"];
|
|
14860
|
+
return {
|
|
14861
|
+
...typeof token === "string" && token !== "" ? { t: token } : {},
|
|
14862
|
+
e: typeof expiresAt === "number" ? expiresAt : null,
|
|
14863
|
+
st: value["st"]
|
|
14864
|
+
};
|
|
14865
|
+
};
|
|
14866
|
+
|
|
14867
|
+
// ../../../libs/app-envelope/src/observability.ts
|
|
14868
|
+
var APP_OBSERVABILITY_HEADER = "x-qinto-app-observability";
|
|
14869
|
+
var APP_OBSERVABILITY_VERSION = 1;
|
|
14870
|
+
var MAX_APP_OBSERVABILITY_EVENTS = 20;
|
|
14871
|
+
var MAX_APP_SAVED_ERRORS = 5;
|
|
14872
|
+
var MAX_APP_EVENT_NAME_BYTES = 128;
|
|
14873
|
+
var MAX_APP_ACTION_NAME_BYTES = 256;
|
|
14874
|
+
var MAX_APP_ERROR_DESCRIPTION_BYTES = 2048;
|
|
14875
|
+
var MAX_APP_ERROR_PAYLOAD_BYTES = 4096;
|
|
14876
|
+
var MAX_APP_DATA_POINT_BLOB_BYTES = 16 * 1024;
|
|
14877
|
+
var MAX_APP_OBSERVABILITY_BYTES = 32 * 1024;
|
|
14878
|
+
var APP_OBSERVABILITY_JSON_BUDGET = MAX_APP_OBSERVABILITY_BYTES / 4 * 3;
|
|
14879
|
+
var APP_EVENT_STATUSES = ["success", "error"];
|
|
14880
|
+
var APP_ERROR_CATEGORIES = ["authorization", "configuration", "validation", "rate_limit", "upstream", "internal"];
|
|
14881
|
+
var encoder = new TextEncoder();
|
|
14882
|
+
var decoder = new TextDecoder();
|
|
14883
|
+
var observabilityEventSchema = external_exports.object({ ord: external_exports.number().int().min(1), name: external_exports.string().min(1).max(MAX_APP_EVENT_NAME_BYTES), status: external_exports.enum(APP_EVENT_STATUSES) }).strict();
|
|
14884
|
+
var savedErrorSchema = external_exports.object({
|
|
14885
|
+
ord: external_exports.number().int().min(1),
|
|
14886
|
+
category: external_exports.enum(APP_ERROR_CATEGORIES),
|
|
14887
|
+
action: external_exports.string().min(1).max(MAX_APP_ACTION_NAME_BYTES),
|
|
14888
|
+
description: external_exports.string().min(1).max(MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
14889
|
+
payload: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional(),
|
|
14890
|
+
error: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional()
|
|
14891
|
+
}).strict();
|
|
14892
|
+
var appObservabilityRecordSchema = external_exports.object({
|
|
14893
|
+
v: external_exports.literal(APP_OBSERVABILITY_VERSION),
|
|
14894
|
+
truncated: external_exports.boolean().optional(),
|
|
14895
|
+
events: external_exports.array(observabilityEventSchema).max(MAX_APP_OBSERVABILITY_EVENTS),
|
|
14896
|
+
errors: external_exports.array(savedErrorSchema).max(MAX_APP_SAVED_ERRORS)
|
|
14897
|
+
}).strict();
|
|
14898
|
+
var utf8Length = (value) => {
|
|
14899
|
+
return encoder.encode(value).length;
|
|
14900
|
+
};
|
|
14901
|
+
var truncateUtf8 = (value, maxBytes) => {
|
|
14902
|
+
if (utf8Length(value) <= maxBytes) {
|
|
14903
|
+
return value;
|
|
14904
|
+
}
|
|
14905
|
+
let kept = "";
|
|
14906
|
+
let used = 0;
|
|
14907
|
+
for (const character of value) {
|
|
14908
|
+
const size = utf8Length(character);
|
|
14909
|
+
if (used + size > maxBytes) {
|
|
14910
|
+
break;
|
|
14911
|
+
}
|
|
14912
|
+
kept += character;
|
|
14913
|
+
used += size;
|
|
14914
|
+
}
|
|
14915
|
+
return kept;
|
|
14916
|
+
};
|
|
14917
|
+
var serializeAppObservability = (record2) => {
|
|
14918
|
+
const bytes = encoder.encode(JSON.stringify(record2));
|
|
14919
|
+
let binary = "";
|
|
14920
|
+
for (const byte of bytes) {
|
|
14921
|
+
binary += String.fromCharCode(byte);
|
|
14922
|
+
}
|
|
14923
|
+
return btoa(binary);
|
|
14924
|
+
};
|
|
14925
|
+
|
|
14764
14926
|
// ../../../libs/app-envelope/src/ui.ts
|
|
14765
14927
|
var UI_CONTEXT_HEADER = "x-qinto-ui-context";
|
|
14766
14928
|
var MAX_UI_BODY_BYTES = 1024 * 1024;
|
|
@@ -14806,10 +14968,10 @@ var formatSpansRecord = (record2) => {
|
|
|
14806
14968
|
};
|
|
14807
14969
|
|
|
14808
14970
|
// ../../../libs/tail-trace/src/app-spans.ts
|
|
14809
|
-
var
|
|
14810
|
-
var
|
|
14971
|
+
var encoder2 = new TextEncoder();
|
|
14972
|
+
var decoder2 = new TextDecoder();
|
|
14811
14973
|
var serializeAppSpans = (record2) => {
|
|
14812
|
-
const bytes =
|
|
14974
|
+
const bytes = encoder2.encode(JSON.stringify(record2));
|
|
14813
14975
|
let binary = "";
|
|
14814
14976
|
for (const byte of bytes) {
|
|
14815
14977
|
binary += String.fromCharCode(byte);
|
|
@@ -14818,12 +14980,12 @@ var serializeAppSpans = (record2) => {
|
|
|
14818
14980
|
};
|
|
14819
14981
|
|
|
14820
14982
|
// ../../../libs/tail-trace/src/budget.ts
|
|
14821
|
-
var
|
|
14983
|
+
var encoder3 = new TextEncoder();
|
|
14822
14984
|
var byteLength = (value) => {
|
|
14823
|
-
return
|
|
14985
|
+
return encoder3.encode(JSON.stringify(value)).length;
|
|
14824
14986
|
};
|
|
14825
14987
|
var fitsBudget = (text, max) => {
|
|
14826
|
-
return text.length * 3 <= max ||
|
|
14988
|
+
return text.length * 3 <= max || encoder3.encode(text).length <= max;
|
|
14827
14989
|
};
|
|
14828
14990
|
var MIN_KEEP = 64;
|
|
14829
14991
|
var halveLongestString = (holders) => {
|
|
@@ -15407,6 +15569,162 @@ var buildAppsClient = (env, envelope) => {
|
|
|
15407
15569
|
};
|
|
15408
15570
|
};
|
|
15409
15571
|
|
|
15572
|
+
// src/oauth.ts
|
|
15573
|
+
var EXPIRY_FLOOR_MS = 1e3;
|
|
15574
|
+
var read = (env, id, ord, now) => {
|
|
15575
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15576
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15577
|
+
if (parsed === null) {
|
|
15578
|
+
return null;
|
|
15579
|
+
}
|
|
15580
|
+
const expired = parsed.e !== null && parsed.e - now < EXPIRY_FLOOR_MS;
|
|
15581
|
+
return {
|
|
15582
|
+
id,
|
|
15583
|
+
status: parsed.st === "connected" && !expired ? "connected" : "reconnect_required",
|
|
15584
|
+
expiresAt: parsed.e
|
|
15585
|
+
};
|
|
15586
|
+
};
|
|
15587
|
+
var buildOauth = (env, ord, now = Date.now) => {
|
|
15588
|
+
return {
|
|
15589
|
+
token: (id) => {
|
|
15590
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15591
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15592
|
+
if (parsed === null) {
|
|
15593
|
+
throw new Error(`not_connected: this install has no ${id} connection`);
|
|
15594
|
+
}
|
|
15595
|
+
const state = read(env, id, ord, now());
|
|
15596
|
+
if (parsed.t === void 0 || state?.status !== "connected") {
|
|
15597
|
+
throw new Error(`reconnect_required: the ${id} connection has ended and a site manager must reconnect it`);
|
|
15598
|
+
}
|
|
15599
|
+
return parsed.t;
|
|
15600
|
+
},
|
|
15601
|
+
connection: (id) => {
|
|
15602
|
+
return read(env, id, ord, now());
|
|
15603
|
+
}
|
|
15604
|
+
};
|
|
15605
|
+
};
|
|
15606
|
+
var oauthTokenValues = (env) => {
|
|
15607
|
+
const values = /* @__PURE__ */ new Set();
|
|
15608
|
+
for (const [name, raw] of Object.entries(env)) {
|
|
15609
|
+
if (!name.startsWith("OAUTH_") || typeof raw !== "string") {
|
|
15610
|
+
continue;
|
|
15611
|
+
}
|
|
15612
|
+
const token = parseAppOauthBinding(raw)?.t;
|
|
15613
|
+
if (token !== void 0 && token !== "") {
|
|
15614
|
+
values.add(token);
|
|
15615
|
+
}
|
|
15616
|
+
}
|
|
15617
|
+
return [...values];
|
|
15618
|
+
};
|
|
15619
|
+
var buildUiOauth = (env, installs, now = Date.now) => {
|
|
15620
|
+
const ordinalOf = (installId) => {
|
|
15621
|
+
return installs.find((install) => install.id === installId)?.ord ?? null;
|
|
15622
|
+
};
|
|
15623
|
+
return {
|
|
15624
|
+
token: (id, options) => {
|
|
15625
|
+
const ord = ordinalOf(options.installId);
|
|
15626
|
+
if (ord === null) {
|
|
15627
|
+
throw new Error(`not_connected: ${options.installId} is not an install of this app`);
|
|
15628
|
+
}
|
|
15629
|
+
return buildOauth(env, ord, now).token(id);
|
|
15630
|
+
},
|
|
15631
|
+
connection: (id, options) => {
|
|
15632
|
+
const ord = ordinalOf(options.installId);
|
|
15633
|
+
return ord === null ? null : buildOauth(env, ord, now).connection(id);
|
|
15634
|
+
}
|
|
15635
|
+
};
|
|
15636
|
+
};
|
|
15637
|
+
|
|
15638
|
+
// src/observability-collector.ts
|
|
15639
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
15640
|
+
var ENVELOPE_OVERHEAD = 64;
|
|
15641
|
+
var collectors = new AsyncLocalStorage2();
|
|
15642
|
+
var serialized = (value) => {
|
|
15643
|
+
if (value instanceof Error) {
|
|
15644
|
+
const stack = value.stack;
|
|
15645
|
+
return JSON.stringify({ name: value.name, message: value.message, ...stack === void 0 ? {} : { stack } });
|
|
15646
|
+
}
|
|
15647
|
+
let text;
|
|
15648
|
+
try {
|
|
15649
|
+
text = JSON.stringify(value);
|
|
15650
|
+
} catch {
|
|
15651
|
+
return String(value);
|
|
15652
|
+
}
|
|
15653
|
+
return typeof text === "string" ? text : String(value);
|
|
15654
|
+
};
|
|
15655
|
+
var field = (value, redact, maxBytes) => {
|
|
15656
|
+
return truncateUtf8(redact(value), maxBytes);
|
|
15657
|
+
};
|
|
15658
|
+
var optionalField = (value, redact) => {
|
|
15659
|
+
if (value === void 0) {
|
|
15660
|
+
return void 0;
|
|
15661
|
+
}
|
|
15662
|
+
return field(serialized(value), redact, MAX_APP_ERROR_PAYLOAD_BYTES);
|
|
15663
|
+
};
|
|
15664
|
+
var createObservabilityCollector = (redact) => {
|
|
15665
|
+
const events = [];
|
|
15666
|
+
const errors = [];
|
|
15667
|
+
let used = ENVELOPE_OVERHEAD;
|
|
15668
|
+
let truncated = false;
|
|
15669
|
+
const size = (entry) => {
|
|
15670
|
+
return utf8Length(JSON.stringify(entry)) + 1;
|
|
15671
|
+
};
|
|
15672
|
+
return {
|
|
15673
|
+
addEvent: (ord, name, status) => {
|
|
15674
|
+
if (name === "" || !APP_EVENT_STATUSES.includes(status)) {
|
|
15675
|
+
truncated = true;
|
|
15676
|
+
return;
|
|
15677
|
+
}
|
|
15678
|
+
if (events.length >= MAX_APP_OBSERVABILITY_EVENTS) {
|
|
15679
|
+
truncated = true;
|
|
15680
|
+
return;
|
|
15681
|
+
}
|
|
15682
|
+
const entry = { ord, name: field(name, redact, MAX_APP_EVENT_NAME_BYTES), status };
|
|
15683
|
+
used += size(entry);
|
|
15684
|
+
events.push(entry);
|
|
15685
|
+
},
|
|
15686
|
+
addError: (ord, input) => {
|
|
15687
|
+
if (!APP_ERROR_CATEGORIES.includes(input.category) || input.action === "" || input.description === "") {
|
|
15688
|
+
truncated = true;
|
|
15689
|
+
return;
|
|
15690
|
+
}
|
|
15691
|
+
if (errors.length >= MAX_APP_SAVED_ERRORS) {
|
|
15692
|
+
truncated = true;
|
|
15693
|
+
return;
|
|
15694
|
+
}
|
|
15695
|
+
const payload = optionalField(input.payload, redact);
|
|
15696
|
+
const error51 = optionalField(input.error, redact);
|
|
15697
|
+
const entry = {
|
|
15698
|
+
ord,
|
|
15699
|
+
category: input.category,
|
|
15700
|
+
action: field(input.action, redact, MAX_APP_ACTION_NAME_BYTES),
|
|
15701
|
+
description: field(input.description, redact, MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
15702
|
+
...payload === void 0 ? {} : { payload },
|
|
15703
|
+
...error51 === void 0 ? {} : { error: error51 }
|
|
15704
|
+
};
|
|
15705
|
+
const entrySize = size(entry);
|
|
15706
|
+
if (used + entrySize > APP_OBSERVABILITY_JSON_BUDGET) {
|
|
15707
|
+
truncated = true;
|
|
15708
|
+
return;
|
|
15709
|
+
}
|
|
15710
|
+
used += entrySize;
|
|
15711
|
+
errors.push(entry);
|
|
15712
|
+
},
|
|
15713
|
+
record: () => {
|
|
15714
|
+
if (events.length === 0 && errors.length === 0) {
|
|
15715
|
+
return null;
|
|
15716
|
+
}
|
|
15717
|
+
return { v: APP_OBSERVABILITY_VERSION, ...truncated ? { truncated } : {}, events, errors };
|
|
15718
|
+
}
|
|
15719
|
+
};
|
|
15720
|
+
};
|
|
15721
|
+
var runWithObservability = (collector, run) => {
|
|
15722
|
+
return collectors.run(collector, run);
|
|
15723
|
+
};
|
|
15724
|
+
var currentObservability = () => {
|
|
15725
|
+
return collectors.getStore();
|
|
15726
|
+
};
|
|
15727
|
+
|
|
15410
15728
|
// src/observability.ts
|
|
15411
15729
|
var exceptionAttrs = (error51) => {
|
|
15412
15730
|
const attrs = {
|
|
@@ -15429,7 +15747,7 @@ var consoleText = (error51) => {
|
|
|
15429
15747
|
}
|
|
15430
15748
|
return redactUrlParams(error51 instanceof Error ? error51.stack ?? error51.message : String(error51));
|
|
15431
15749
|
};
|
|
15432
|
-
var buildObservability = () => {
|
|
15750
|
+
var buildObservability = (ord) => {
|
|
15433
15751
|
return {
|
|
15434
15752
|
log: (message, attrs) => {
|
|
15435
15753
|
addSpanEvent(message, attrs === void 0 ? {} : { attrs });
|
|
@@ -15439,6 +15757,21 @@ var buildObservability = () => {
|
|
|
15439
15757
|
addSpanEvent(message, { level: "error", attrs: { ...attrs, ...error51 === void 0 ? {} : exceptionAttrs(error51) } });
|
|
15440
15758
|
console.error(redactUrlParams(message), consoleText(error51), redactAttrs(attrs ?? {}));
|
|
15441
15759
|
},
|
|
15760
|
+
event: (name, status) => {
|
|
15761
|
+
addSpanEvent(name, { attrs: { "app.event.status": status } });
|
|
15762
|
+
if (ord !== null) {
|
|
15763
|
+
currentObservability()?.addEvent(ord, name, status);
|
|
15764
|
+
}
|
|
15765
|
+
},
|
|
15766
|
+
saveError: (input) => {
|
|
15767
|
+
addSpanEvent(input.description, {
|
|
15768
|
+
level: "error",
|
|
15769
|
+
attrs: { "app.error.category": input.category, "app.error.action": input.action }
|
|
15770
|
+
});
|
|
15771
|
+
if (ord !== null) {
|
|
15772
|
+
currentObservability()?.addError(ord, input);
|
|
15773
|
+
}
|
|
15774
|
+
},
|
|
15442
15775
|
span: ((...args) => {
|
|
15443
15776
|
const [name] = args;
|
|
15444
15777
|
const { attrs, run } = spanParts(args);
|
|
@@ -15515,6 +15848,9 @@ var secretValues = (env) => {
|
|
|
15515
15848
|
values.add(value);
|
|
15516
15849
|
}
|
|
15517
15850
|
}
|
|
15851
|
+
for (const value of oauthTokenValues(env)) {
|
|
15852
|
+
values.add(value);
|
|
15853
|
+
}
|
|
15518
15854
|
return [...values];
|
|
15519
15855
|
};
|
|
15520
15856
|
var projectInstallValues = (maps, kinds, ord) => {
|
|
@@ -15591,13 +15927,13 @@ var readOnce = (env, subject) => {
|
|
|
15591
15927
|
};
|
|
15592
15928
|
};
|
|
15593
15929
|
var fetchedContext = (env, subject, collector) => {
|
|
15594
|
-
const
|
|
15930
|
+
const read2 = readOnce(env, () => {
|
|
15595
15931
|
return subject("context.load");
|
|
15596
15932
|
});
|
|
15597
15933
|
return {
|
|
15598
15934
|
private: {
|
|
15599
15935
|
load: async () => {
|
|
15600
|
-
return (await
|
|
15936
|
+
return (await read2()).private;
|
|
15601
15937
|
},
|
|
15602
15938
|
set: (patch) => {
|
|
15603
15939
|
subject("context.set");
|
|
@@ -15606,7 +15942,7 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15606
15942
|
},
|
|
15607
15943
|
shared: {
|
|
15608
15944
|
load: async () => {
|
|
15609
|
-
return (await
|
|
15945
|
+
return (await read2()).shared;
|
|
15610
15946
|
},
|
|
15611
15947
|
set: (patch) => {
|
|
15612
15948
|
subject("context.set");
|
|
@@ -15616,13 +15952,13 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15616
15952
|
};
|
|
15617
15953
|
};
|
|
15618
15954
|
var asyncContext = (env, subject) => {
|
|
15619
|
-
const
|
|
15955
|
+
const read2 = readOnce(env, () => {
|
|
15620
15956
|
return subject("context.load");
|
|
15621
15957
|
});
|
|
15622
15958
|
return {
|
|
15623
15959
|
private: {
|
|
15624
15960
|
load: async () => {
|
|
15625
|
-
return (await
|
|
15961
|
+
return (await read2()).private;
|
|
15626
15962
|
},
|
|
15627
15963
|
set: async (patch) => {
|
|
15628
15964
|
assertValidPatch(patch);
|
|
@@ -15634,7 +15970,7 @@ var asyncContext = (env, subject) => {
|
|
|
15634
15970
|
},
|
|
15635
15971
|
shared: {
|
|
15636
15972
|
load: async () => {
|
|
15637
|
-
return (await
|
|
15973
|
+
return (await read2()).shared;
|
|
15638
15974
|
},
|
|
15639
15975
|
set: async (patch) => {
|
|
15640
15976
|
assertValidPatch(patch);
|
|
@@ -15694,12 +16030,13 @@ var buildWorkflowContext = (env, stamp) => {
|
|
|
15694
16030
|
env,
|
|
15695
16031
|
install,
|
|
15696
16032
|
startWorkflow: buildStartWorkflow(stamp),
|
|
16033
|
+
oauth: buildOauth(env, stamp.ord),
|
|
15697
16034
|
variables,
|
|
15698
16035
|
secrets,
|
|
15699
16036
|
appVariables,
|
|
15700
16037
|
appSecrets,
|
|
15701
16038
|
userId: stamp.anonId,
|
|
15702
|
-
observability: buildObservability(),
|
|
16039
|
+
observability: buildObservability(stamp.ord),
|
|
15703
16040
|
context: asyncContext(env, (what) => {
|
|
15704
16041
|
return requireSubject(stamp.anonId, what);
|
|
15705
16042
|
}),
|
|
@@ -15776,6 +16113,7 @@ var buildContext = ({
|
|
|
15776
16113
|
secrets,
|
|
15777
16114
|
appVariables: appScope.appVariables,
|
|
15778
16115
|
appSecrets: appScope.appSecrets,
|
|
16116
|
+
oauth: buildOauth(env, install.ord),
|
|
15779
16117
|
user: envelope.user ?? null,
|
|
15780
16118
|
consent: envelope.consent,
|
|
15781
16119
|
geo: envelope.geo,
|
|
@@ -15830,7 +16168,7 @@ var buildContext = ({
|
|
|
15830
16168
|
}
|
|
15831
16169
|
}
|
|
15832
16170
|
},
|
|
15833
|
-
observability: buildObservability(),
|
|
16171
|
+
observability: buildObservability(install.ord),
|
|
15834
16172
|
apps: buildAppsClient(env, envelope)
|
|
15835
16173
|
};
|
|
15836
16174
|
};
|
|
@@ -15902,7 +16240,8 @@ var buildCatalogQuery = ({ env, ticket, installId }) => {
|
|
|
15902
16240
|
// src/schedule.ts
|
|
15903
16241
|
var dispatchSchedule = async (envelope, bundle, env) => {
|
|
15904
16242
|
const schedule = envelope.schedule;
|
|
15905
|
-
const
|
|
16243
|
+
const schedules = bundle.schedules;
|
|
16244
|
+
const handler = schedules !== void 0 && Object.hasOwn(schedules, schedule.id) ? schedules[schedule.id] : void 0;
|
|
15906
16245
|
if (typeof handler !== "function") {
|
|
15907
16246
|
return json2(200, {
|
|
15908
16247
|
v: CONTROL_ENVELOPE_VERSION,
|
|
@@ -15927,11 +16266,12 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
15927
16266
|
installLabel: install.label,
|
|
15928
16267
|
anonId: null
|
|
15929
16268
|
}),
|
|
16269
|
+
oauth: buildOauth(env, install.ord),
|
|
15930
16270
|
variables,
|
|
15931
16271
|
secrets,
|
|
15932
16272
|
appVariables: appScope.appVariables,
|
|
15933
16273
|
appSecrets: appScope.appSecrets,
|
|
15934
|
-
observability: buildObservability(),
|
|
16274
|
+
observability: buildObservability(install.ord),
|
|
15935
16275
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
15936
16276
|
query: buildCatalogQuery({ env, ticket: install.catalogQueryTicket, installId: install.id }),
|
|
15937
16277
|
push: async (userId, message) => {
|
|
@@ -15963,6 +16303,141 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
15963
16303
|
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: true });
|
|
15964
16304
|
};
|
|
15965
16305
|
|
|
16306
|
+
// src/tool.ts
|
|
16307
|
+
var failure = (message) => {
|
|
16308
|
+
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message } });
|
|
16309
|
+
};
|
|
16310
|
+
var isFailure = (value) => {
|
|
16311
|
+
return value !== null && typeof value === "object" && value.kind === "tool_error" && typeof value.message === "string";
|
|
16312
|
+
};
|
|
16313
|
+
var isResult = (value) => {
|
|
16314
|
+
return value !== null && typeof value === "object" && typeof value.content === "string";
|
|
16315
|
+
};
|
|
16316
|
+
var isStructuredData = (data) => {
|
|
16317
|
+
return data === void 0 || data !== null && typeof data === "object" && !Array.isArray(data);
|
|
16318
|
+
};
|
|
16319
|
+
var isPlainContainer = (value) => {
|
|
16320
|
+
const prototype = Object.getPrototypeOf(value);
|
|
16321
|
+
return Array.isArray(value) || prototype === Object.prototype || prototype === null;
|
|
16322
|
+
};
|
|
16323
|
+
var jsonScalarVerdict = (value) => {
|
|
16324
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
16325
|
+
return "ok";
|
|
16326
|
+
}
|
|
16327
|
+
if (typeof value === "number") {
|
|
16328
|
+
return Number.isFinite(value) ? "ok" : "invalid";
|
|
16329
|
+
}
|
|
16330
|
+
if (value === void 0 || typeof value !== "object" || !isPlainContainer(value)) {
|
|
16331
|
+
return "invalid";
|
|
16332
|
+
}
|
|
16333
|
+
return "container";
|
|
16334
|
+
};
|
|
16335
|
+
var isJsonValue = (root) => {
|
|
16336
|
+
const stack = [root];
|
|
16337
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16338
|
+
while (stack.length > 0) {
|
|
16339
|
+
const value = stack.pop();
|
|
16340
|
+
const verdict = jsonScalarVerdict(value);
|
|
16341
|
+
if (verdict === "invalid") {
|
|
16342
|
+
return false;
|
|
16343
|
+
}
|
|
16344
|
+
if (verdict === "ok" || seen.has(value)) {
|
|
16345
|
+
continue;
|
|
16346
|
+
}
|
|
16347
|
+
seen.add(value);
|
|
16348
|
+
if (Array.isArray(value) && Object.keys(value).length !== value.length) {
|
|
16349
|
+
return false;
|
|
16350
|
+
}
|
|
16351
|
+
stack.push(...Object.values(value));
|
|
16352
|
+
}
|
|
16353
|
+
return true;
|
|
16354
|
+
};
|
|
16355
|
+
var truncate = (message) => {
|
|
16356
|
+
return message.length <= MAX_TOOL_ERROR_MESSAGE_LENGTH ? message : message.slice(0, MAX_TOOL_ERROR_MESSAGE_LENGTH);
|
|
16357
|
+
};
|
|
16358
|
+
var checkResult = (result) => {
|
|
16359
|
+
if (!isStructuredData(result.data)) {
|
|
16360
|
+
return "not_structured";
|
|
16361
|
+
}
|
|
16362
|
+
if (result.data !== void 0 && !isJsonValue(result.data)) {
|
|
16363
|
+
return "not_serializable";
|
|
16364
|
+
}
|
|
16365
|
+
let encoded;
|
|
16366
|
+
try {
|
|
16367
|
+
encoded = new TextEncoder().encode(JSON.stringify({ content: result.content, data: result.data ?? null }));
|
|
16368
|
+
} catch {
|
|
16369
|
+
return "not_serializable";
|
|
16370
|
+
}
|
|
16371
|
+
if (encoded.length > MAX_TOOL_RESULT_BYTES || !toolDataWithinLimits(result.data)) {
|
|
16372
|
+
return "too_large";
|
|
16373
|
+
}
|
|
16374
|
+
return "ok";
|
|
16375
|
+
};
|
|
16376
|
+
var buildContext2 = (envelope, env) => {
|
|
16377
|
+
const install = envelope.install;
|
|
16378
|
+
const { variableKinds, appVariableKinds } = contextKindsOf(env);
|
|
16379
|
+
const maps = parseVariableMaps(env);
|
|
16380
|
+
const appScope = projectAppValues(env, appVariableKinds);
|
|
16381
|
+
const { variables, secrets } = projectInstallValues(maps, variableKinds, install.ord);
|
|
16382
|
+
return {
|
|
16383
|
+
env,
|
|
16384
|
+
site: envelope.site,
|
|
16385
|
+
install: { id: install.id, label: install.label },
|
|
16386
|
+
viewer: envelope.tool.viewer,
|
|
16387
|
+
callId: envelope.tool.callId,
|
|
16388
|
+
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
16389
|
+
oauth: buildOauth(env, install.ord),
|
|
16390
|
+
variables,
|
|
16391
|
+
secrets,
|
|
16392
|
+
appVariables: appScope.appVariables,
|
|
16393
|
+
appSecrets: appScope.appSecrets,
|
|
16394
|
+
observability: buildObservability(install.ord),
|
|
16395
|
+
apps: buildAppsClient(env, { depth: 0 }),
|
|
16396
|
+
fail: (message) => {
|
|
16397
|
+
return { kind: "tool_error", message: truncate(message) };
|
|
16398
|
+
}
|
|
16399
|
+
};
|
|
16400
|
+
};
|
|
16401
|
+
var dispatchTool = async (envelope, bundle, env) => {
|
|
16402
|
+
const name = envelope.tool.name;
|
|
16403
|
+
const tools = bundle.tools;
|
|
16404
|
+
const handler = tools !== void 0 && Object.hasOwn(tools, name) ? tools[name] : void 0;
|
|
16405
|
+
if (typeof handler !== "function") {
|
|
16406
|
+
return failure(`missing handler: tools.${name}`);
|
|
16407
|
+
}
|
|
16408
|
+
setSpanAttributes({ "app.tool": name, "app.tool_call_id": envelope.tool.callId });
|
|
16409
|
+
let value;
|
|
16410
|
+
try {
|
|
16411
|
+
value = await installSpan(envelope.install, () => {
|
|
16412
|
+
return handler(envelope.tool.arguments, buildContext2(envelope, env));
|
|
16413
|
+
});
|
|
16414
|
+
} catch (error51) {
|
|
16415
|
+
console.warn(`tool ${name} failed for install ${envelope.install.id}: ${failureMessage(error51)}`);
|
|
16416
|
+
return failure(`tool ${name} failed`);
|
|
16417
|
+
}
|
|
16418
|
+
if (isFailure(value)) {
|
|
16419
|
+
return json2(200, { v: CONTROL_ENVELOPE_VERSION, ok: true, tool: { content: truncate(value.message), failed: true } });
|
|
16420
|
+
}
|
|
16421
|
+
if (!isResult(value)) {
|
|
16422
|
+
return failure(`tool ${name} returned no result`);
|
|
16423
|
+
}
|
|
16424
|
+
const verdict = checkResult(value);
|
|
16425
|
+
if (verdict === "not_structured") {
|
|
16426
|
+
return failure(`tool ${name} returned data that is not a JSON object`);
|
|
16427
|
+
}
|
|
16428
|
+
if (verdict === "not_serializable") {
|
|
16429
|
+
return failure(`tool ${name} returned data that cannot be serialized`);
|
|
16430
|
+
}
|
|
16431
|
+
if (verdict === "too_large") {
|
|
16432
|
+
return failure(`tool ${name} returned a result over the size cap`);
|
|
16433
|
+
}
|
|
16434
|
+
return json2(200, {
|
|
16435
|
+
v: CONTROL_ENVELOPE_VERSION,
|
|
16436
|
+
ok: true,
|
|
16437
|
+
tool: { content: value.content, ...value.data === void 0 ? {} : { data: value.data }, failed: false }
|
|
16438
|
+
});
|
|
16439
|
+
};
|
|
16440
|
+
|
|
15966
16441
|
// src/control.ts
|
|
15967
16442
|
var controlError = (status, message) => {
|
|
15968
16443
|
return json2(status, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message } });
|
|
@@ -15993,7 +16468,7 @@ var lifecycleContext = (env, envelope) => {
|
|
|
15993
16468
|
installLabel: install.label,
|
|
15994
16469
|
anonId: null
|
|
15995
16470
|
}),
|
|
15996
|
-
observability: buildObservability()
|
|
16471
|
+
observability: buildObservability(install.ord)
|
|
15997
16472
|
};
|
|
15998
16473
|
};
|
|
15999
16474
|
var migrationContext = (env, envelope) => {
|
|
@@ -16003,7 +16478,9 @@ var migrationContext = (env, envelope) => {
|
|
|
16003
16478
|
site: envelope.site,
|
|
16004
16479
|
appVariables: appScope.appVariables,
|
|
16005
16480
|
appSecrets: appScope.appSecrets,
|
|
16006
|
-
|
|
16481
|
+
// A migration runs once for the site, not once per install, so it has no install to attribute
|
|
16482
|
+
// an event or a saved error to.
|
|
16483
|
+
observability: buildObservability(null)
|
|
16007
16484
|
};
|
|
16008
16485
|
};
|
|
16009
16486
|
var runStatementMigration = async (env, migration) => {
|
|
@@ -16100,6 +16577,9 @@ var dispatchControl = async ({ request, env, versions }) => {
|
|
|
16100
16577
|
case "schedule": {
|
|
16101
16578
|
return dispatchSchedule(envelope, bundle, env);
|
|
16102
16579
|
}
|
|
16580
|
+
case "tool": {
|
|
16581
|
+
return dispatchTool(envelope, bundle, env);
|
|
16582
|
+
}
|
|
16103
16583
|
}
|
|
16104
16584
|
};
|
|
16105
16585
|
|
|
@@ -16132,19 +16612,22 @@ var handlerRequest = (request, context, body) => {
|
|
|
16132
16612
|
body: body.byteLength === 0 ? void 0 : body
|
|
16133
16613
|
});
|
|
16134
16614
|
};
|
|
16135
|
-
var
|
|
16615
|
+
var buildContext3 = ({ env, maps, kinds, appScope, install, site, params }) => {
|
|
16136
16616
|
const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
|
|
16137
16617
|
return {
|
|
16138
16618
|
env,
|
|
16619
|
+
site,
|
|
16620
|
+
params,
|
|
16139
16621
|
install: { id: install.id, label: install.label },
|
|
16140
16622
|
// An endpoint has no visitor, so a workflow it starts cannot push. `push` below is the
|
|
16141
16623
|
// exception: it names its subject rather than inheriting one.
|
|
16142
16624
|
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
16625
|
+
oauth: buildOauth(env, install.ord),
|
|
16143
16626
|
variables,
|
|
16144
16627
|
secrets,
|
|
16145
16628
|
appVariables: appScope.appVariables,
|
|
16146
16629
|
appSecrets: appScope.appSecrets,
|
|
16147
|
-
observability: buildObservability(),
|
|
16630
|
+
observability: buildObservability(install.ord),
|
|
16148
16631
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
16149
16632
|
push: async (userId, message) => {
|
|
16150
16633
|
await brokerPush(env, {
|
|
@@ -16207,7 +16690,8 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16207
16690
|
return Response.json({ error: "unknown version" }, { status: 404 });
|
|
16208
16691
|
}
|
|
16209
16692
|
const bundle = versions[context.version];
|
|
16210
|
-
const
|
|
16693
|
+
const endpoints = bundle?.endpoints;
|
|
16694
|
+
const candidate = endpoints !== void 0 && Object.hasOwn(endpoints, context.route) ? endpoints[context.route] : void 0;
|
|
16211
16695
|
if (typeof candidate !== "function") {
|
|
16212
16696
|
return Response.json({ error: "not_found" }, { status: 404 });
|
|
16213
16697
|
}
|
|
@@ -16218,7 +16702,10 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16218
16702
|
const appScope = projectAppValues(env, appVariableKinds);
|
|
16219
16703
|
const invoke = async (install) => {
|
|
16220
16704
|
return installSpan(install, () => {
|
|
16221
|
-
return handler(
|
|
16705
|
+
return handler(
|
|
16706
|
+
handlerRequest(request, context, body),
|
|
16707
|
+
buildContext3({ env, maps, kinds: variableKinds, appScope, install, site: context.site, params: context.params })
|
|
16708
|
+
);
|
|
16222
16709
|
});
|
|
16223
16710
|
};
|
|
16224
16711
|
const installs = [...context.installs].sort((left, right) => {
|
|
@@ -16241,29 +16728,38 @@ var appSlug = (context) => {
|
|
|
16241
16728
|
return "app";
|
|
16242
16729
|
}
|
|
16243
16730
|
};
|
|
16244
|
-
var withSpans = (response, record2) => {
|
|
16731
|
+
var withSpans = (response, record2, collector) => {
|
|
16245
16732
|
const headers = new Headers(response.headers);
|
|
16246
16733
|
headers.set(APP_SPANS_HEADER, serializeAppSpans(record2));
|
|
16734
|
+
headers.delete(APP_OBSERVABILITY_HEADER);
|
|
16735
|
+
const observability = collector.record();
|
|
16736
|
+
if (observability !== null) {
|
|
16737
|
+
headers.set(APP_OBSERVABILITY_HEADER, serializeAppObservability(observability));
|
|
16738
|
+
}
|
|
16247
16739
|
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
16248
16740
|
};
|
|
16249
16741
|
var runAppInvocation = async (input, handle) => {
|
|
16250
16742
|
let record2 = { spans: [] };
|
|
16743
|
+
const redact = spanRedactor(input.secrets);
|
|
16744
|
+
const collector = createObservabilityCollector(redact);
|
|
16251
16745
|
try {
|
|
16252
16746
|
const response = await runInvocation(
|
|
16253
16747
|
{
|
|
16254
16748
|
name: appSlug(input.context),
|
|
16255
16749
|
trace: parseTraceContext(input.request.headers.get(TRACE_HEADER)),
|
|
16256
16750
|
budget: APP_SPANS_JSON_BUDGET,
|
|
16257
|
-
redact
|
|
16751
|
+
redact,
|
|
16258
16752
|
emit: (emitted) => {
|
|
16259
16753
|
record2 = emitted;
|
|
16260
16754
|
}
|
|
16261
16755
|
},
|
|
16262
|
-
|
|
16756
|
+
() => {
|
|
16757
|
+
return runWithObservability(collector, handle);
|
|
16758
|
+
}
|
|
16263
16759
|
);
|
|
16264
|
-
return withSpans(response, record2);
|
|
16760
|
+
return withSpans(response, record2, collector);
|
|
16265
16761
|
} catch {
|
|
16266
|
-
return withSpans(input.failure(), record2);
|
|
16762
|
+
return withSpans(input.failure(), record2, collector);
|
|
16267
16763
|
}
|
|
16268
16764
|
};
|
|
16269
16765
|
|
|
@@ -16289,21 +16785,21 @@ var capturedBody = async (open) => {
|
|
|
16289
16785
|
return void 0;
|
|
16290
16786
|
}
|
|
16291
16787
|
const reader = body.getReader();
|
|
16292
|
-
const
|
|
16788
|
+
const decoder3 = new TextDecoder();
|
|
16293
16789
|
const expired = new Promise((resolve) => {
|
|
16294
16790
|
timer = setTimeout(() => resolve(null), READ_BUDGET_MS);
|
|
16295
16791
|
});
|
|
16296
16792
|
let text = "";
|
|
16297
16793
|
for (; ; ) {
|
|
16298
|
-
const
|
|
16299
|
-
if (
|
|
16794
|
+
const read2 = await Promise.race([reader.read(), expired]);
|
|
16795
|
+
if (read2 === null) {
|
|
16300
16796
|
abandon(reader);
|
|
16301
16797
|
return INCOMPLETE;
|
|
16302
16798
|
}
|
|
16303
|
-
if (
|
|
16799
|
+
if (read2.done) {
|
|
16304
16800
|
break;
|
|
16305
16801
|
}
|
|
16306
|
-
text +=
|
|
16802
|
+
text += decoder3.decode(read2.value, { stream: true });
|
|
16307
16803
|
if (text.length > MAX_BODY_CHARS) {
|
|
16308
16804
|
abandon(reader);
|
|
16309
16805
|
return TOO_LARGE;
|
|
@@ -16415,6 +16911,9 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16415
16911
|
env,
|
|
16416
16912
|
install: { id: context.install.id, label: context.install.label },
|
|
16417
16913
|
installs: projectAllInstallValues(maps, variableKinds, context.installs),
|
|
16914
|
+
// The install is named rather than inherited: one panel serves every install, and reading the
|
|
16915
|
+
// subject install's token while showing another account's UI would be silently wrong.
|
|
16916
|
+
oauth: buildUiOauth(env, context.installs),
|
|
16418
16917
|
settings: buildSettings({ env, ticket: context.writeTicket }),
|
|
16419
16918
|
// The panel's viewer is a portal user, not a visitor, so a workflow it starts carries no subject.
|
|
16420
16919
|
startWorkflow: buildUiStartWorkflow(
|
|
@@ -16426,7 +16925,7 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16426
16925
|
appVariables,
|
|
16427
16926
|
appSecrets,
|
|
16428
16927
|
viewer: context.viewer,
|
|
16429
|
-
observability: buildObservability(),
|
|
16928
|
+
observability: buildObservability(context.install.ord),
|
|
16430
16929
|
apps: buildAppsClient(env, { depth: 0 })
|
|
16431
16930
|
};
|
|
16432
16931
|
let response;
|
|
@@ -16491,7 +16990,7 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16491
16990
|
const { variableKinds: kinds, appVariableKinds } = contextKindsOf(env);
|
|
16492
16991
|
const appScope = projectAppValues(env, appVariableKinds);
|
|
16493
16992
|
const groups = [];
|
|
16494
|
-
let
|
|
16993
|
+
let failure2;
|
|
16495
16994
|
for (const install of envelope.installs) {
|
|
16496
16995
|
const emits = [];
|
|
16497
16996
|
const pushes = [];
|
|
@@ -16505,7 +17004,7 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16505
17004
|
} catch (error51) {
|
|
16506
17005
|
const message = failureMessage(error51);
|
|
16507
17006
|
console.warn(`app hook failed for install ${install.id}: ${message}`);
|
|
16508
|
-
|
|
17007
|
+
failure2 ??= message;
|
|
16509
17008
|
continue;
|
|
16510
17009
|
}
|
|
16511
17010
|
const contextWrites = context.writes();
|
|
@@ -16517,8 +17016,8 @@ var runInstalls = async (envelope, env, invoke) => {
|
|
|
16517
17016
|
if (groups.length > 0) {
|
|
16518
17017
|
body.effects = groups;
|
|
16519
17018
|
}
|
|
16520
|
-
if (
|
|
16521
|
-
body.error = { message:
|
|
17019
|
+
if (failure2 !== void 0) {
|
|
17020
|
+
body.error = { message: failure2 };
|
|
16522
17021
|
}
|
|
16523
17022
|
return json2(200, body);
|
|
16524
17023
|
};
|