@deslop/scope 0.1.1102 → 0.1.1109
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/server.js +55 -53
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -67036,7 +67036,6 @@ const Resource$1 = Literals([
|
|
|
67036
67036
|
"https://stash.mp281x.xyz",
|
|
67037
67037
|
"https://stash.mp281x.xyz/mcp",
|
|
67038
67038
|
"https://scope.mp281x.xyz/mcp",
|
|
67039
|
-
"https://portfolio.mp281x.xyz/mcp",
|
|
67040
67039
|
"https://otel.mp281x.xyz"
|
|
67041
67040
|
]);
|
|
67042
67041
|
const authorizationFields = {
|
|
@@ -67211,6 +67210,18 @@ function oauth(handler) {
|
|
|
67211
67210
|
error_description: failure.message
|
|
67212
67211
|
}, { status: 400 }))), map$2(setHeader("cache-control", "no-store")));
|
|
67213
67212
|
}
|
|
67213
|
+
function publicRequest(request, expiresAt) {
|
|
67214
|
+
return {
|
|
67215
|
+
...pipe(request, pick([
|
|
67216
|
+
"clientName",
|
|
67217
|
+
"createdAt",
|
|
67218
|
+
"id",
|
|
67219
|
+
"redirectUri",
|
|
67220
|
+
"resources"
|
|
67221
|
+
])),
|
|
67222
|
+
expiresAt
|
|
67223
|
+
};
|
|
67224
|
+
}
|
|
67214
67225
|
function allowedRedirect(redirect) {
|
|
67215
67226
|
if (redirect === "stash://auth/callback" || redirect === "stash-dev://auth/callback") return true;
|
|
67216
67227
|
return match$2(fromString(redirect), {
|
|
@@ -67223,7 +67234,11 @@ var Auth = class Auth extends Service$2()("@deslop/auth/service/Auth") {
|
|
|
67223
67234
|
static layer = (resource) => effectContext(gen(function* () {
|
|
67224
67235
|
const url = yield* pipe(String$1("AUTH_URL"), withDefault(AUTH_URL));
|
|
67225
67236
|
const client = filterStatusOk(yield* HttpClient);
|
|
67226
|
-
const origins = [
|
|
67237
|
+
const origins = [
|
|
67238
|
+
new URL(url).origin,
|
|
67239
|
+
"https://portfolio.mp281x.xyz",
|
|
67240
|
+
...map$5(Resource$1.literals, (identifier) => new URL(identifier).origin)
|
|
67241
|
+
];
|
|
67227
67242
|
const access = fn("Auth.access")(function* (headers, audience) {
|
|
67228
67243
|
return yield* pipe(client.get(`${url}/auth/verify`, {
|
|
67229
67244
|
headers: { authorization: headers["authorization"] ?? "" },
|
|
@@ -67253,7 +67268,6 @@ var Auth = class Auth extends Service$2()("@deslop/auth/service/Auth") {
|
|
|
67253
67268
|
users: Array$1(String$2, "GITHUB_USERS")
|
|
67254
67269
|
});
|
|
67255
67270
|
yield* sql`CREATE TABLE IF NOT EXISTS auth_state (hash TEXT PRIMARY KEY, payload TEXT NOT NULL, expires_at INTEGER NOT NULL)`;
|
|
67256
|
-
yield* sql`DELETE FROM auth_state WHERE json_extract(payload, '$._tag') = 'Request' AND json_extract(payload, '$.id') IS NULL`;
|
|
67257
67271
|
const hash = fnUntraced(function* (value) {
|
|
67258
67272
|
return encode(yield* random.digest("SHA-256", new TextEncoder().encode(value)));
|
|
67259
67273
|
});
|
|
@@ -67337,18 +67351,6 @@ var Auth = class Auth extends Service$2()("@deslop/auth/service/Auth") {
|
|
|
67337
67351
|
}));
|
|
67338
67352
|
}));
|
|
67339
67353
|
}
|
|
67340
|
-
function publicRequest(request, expiresAt) {
|
|
67341
|
-
return {
|
|
67342
|
-
...pipe(request, pick([
|
|
67343
|
-
"clientName",
|
|
67344
|
-
"createdAt",
|
|
67345
|
-
"id",
|
|
67346
|
-
"redirectUri",
|
|
67347
|
-
"resources"
|
|
67348
|
-
])),
|
|
67349
|
-
expiresAt
|
|
67350
|
-
};
|
|
67351
|
-
}
|
|
67352
67354
|
const pending = fnUntraced(function* (headers) {
|
|
67353
67355
|
yield* session(headers);
|
|
67354
67356
|
const rows = yield* pipe(sql`SELECT payload, hash, expires_at AS "expiresAt" FROM auth_state WHERE json_extract(payload, '$._tag') = 'Request' AND json_extract(payload, '$.decision._tag') = 'Pending' AND expires_at > ${yield* currentTimeMillis} ORDER BY json_extract(payload, '$.createdAt') DESC, hash`, flatMap$1(decodeUnknownEffect(ArraySchema(AuthorizationRow))));
|
|
@@ -67711,7 +67713,7 @@ const layerNodeHttpServer = layerConfig(createServer, {
|
|
|
67711
67713
|
});
|
|
67712
67714
|
//#endregion
|
|
67713
67715
|
//#region package.json
|
|
67714
|
-
var version = "0.1.
|
|
67716
|
+
var version = "0.1.1109";
|
|
67715
67717
|
//#endregion
|
|
67716
67718
|
//#region src/services/telemetry/schema.ts
|
|
67717
67719
|
var TelemetryError = class extends TaggedError()("TelemetryError", {
|
|
@@ -67863,19 +67865,19 @@ const StoredEntry = Struct({ json: fromJsonString(Entry) });
|
|
|
67863
67865
|
const Filters = Struct({
|
|
67864
67866
|
errors: pipe(Query.fields.errors, withDecodingDefaultTypeKey(succeed$4(false)), annotateEncoded({ description: "Only failed spans and error logs." })),
|
|
67865
67867
|
operation: pipe(Query.fields.operation, withDecodingDefaultTypeKey(succeed$4("")), annotateEncoded({ description: "Exact span name." })),
|
|
67866
|
-
service: pipe(Query.fields.service, withDecodingDefaultTypeKey(succeed$4("")), annotateEncoded({ description: "Exact service name, from
|
|
67868
|
+
service: pipe(Query.fields.service, withDecodingDefaultTypeKey(succeed$4("")), annotateEncoded({ description: "Exact service name, from list_services." })),
|
|
67867
67869
|
since: pipe(DurationFromString, check(makeFilter(isFinite$1, { expected: "a finite duration" })), withDecodingDefaultTypeKey(succeed$4(minutes(10))), annotateEncoded({ description: "Lookback, such as \"10 minutes\" or \"1 hour\"." })),
|
|
67868
67870
|
text: pipe(Query.fields.text, withDecodingDefaultTypeKey(succeed$4("")), annotateEncoded({ description: "Case-insensitive text in the span name, log message or attributes." })),
|
|
67869
|
-
traceId: pipe(Query.fields.traceId, withDecodingDefaultTypeKey(succeed$4("")))
|
|
67871
|
+
traceId: pipe(Query.fields.traceId, withDecodingDefaultTypeKey(succeed$4("")), annotateEncoded({ description: "Only entries of this trace." }))
|
|
67870
67872
|
});
|
|
67871
67873
|
const PageFilters = Struct({
|
|
67872
67874
|
...Filters.fields,
|
|
67873
67875
|
limit: pipe(Query.fields.limit, withDecodingDefaultTypeKey(succeed$4(100)), annotateEncoded({ description: "Page size, 1 to 1000." })),
|
|
67874
|
-
offset: pipe(Query.fields.offset, withDecodingDefaultTypeKey(succeed$4(0)))
|
|
67876
|
+
offset: pipe(Query.fields.offset, withDecodingDefaultTypeKey(succeed$4(0)), annotateEncoded({ description: "Entries to skip, for the next page." }))
|
|
67875
67877
|
});
|
|
67876
67878
|
const SortFilters = Struct({
|
|
67877
67879
|
...PageFilters.fields,
|
|
67878
|
-
sort: pipe(Query.fields.sort, withDecodingDefaultTypeKey(succeed$4("recent")))
|
|
67880
|
+
sort: pipe(Query.fields.sort, withDecodingDefaultTypeKey(succeed$4("recent")), annotateEncoded({ description: "\"recent\" puts the newest first, \"slowest\" the longest first." }))
|
|
67879
67881
|
});
|
|
67880
67882
|
//#endregion
|
|
67881
67883
|
//#region src/services/telemetry/lib/utils.ts
|
|
@@ -67935,6 +67937,12 @@ function summary(entries, query) {
|
|
|
67935
67937
|
to: query.to
|
|
67936
67938
|
};
|
|
67937
67939
|
}
|
|
67940
|
+
function filterEntries(entries, query, signal) {
|
|
67941
|
+
return filter$1(entries, (entry) => {
|
|
67942
|
+
const milliseconds = pipe(parse$2(`${BigInt(entry.time) / 1000000n}`), getOrThrow$1);
|
|
67943
|
+
return (signal === "all" || entry.signal === signal) && milliseconds >= query.from && milliseconds <= query.to && (query.service === "" || entry.service === query.service) && (query.operation === "" || entry.name === query.operation) && (query.traceId === "" || entry.traceId === toLowerCase(query.traceId)) && (!query.errors || entry.status === 2) && includes(toLowerCase(query.text))(toLowerCase(displayValue(entry)));
|
|
67944
|
+
});
|
|
67945
|
+
}
|
|
67938
67946
|
function orderEntries(entries, sort$1) {
|
|
67939
67947
|
return sort(entries, match(sort$1 === "slowest", {
|
|
67940
67948
|
onFalse: () => flip$2(mapInput(BigInt$5, (entry) => BigInt(entry.time))),
|
|
@@ -68017,14 +68025,8 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
|
|
|
68017
68025
|
discard: true
|
|
68018
68026
|
}));
|
|
68019
68027
|
}, failed);
|
|
68020
|
-
function find(entries, query, signal) {
|
|
68021
|
-
return filter$1(entries, (entry) => {
|
|
68022
|
-
const milliseconds = pipe(parse$2(`${BigInt(entry.time) / 1000000n}`), getOrThrow$1);
|
|
68023
|
-
return (signal === "all" || entry.signal === signal) && milliseconds >= query.from && milliseconds <= query.to && (query.service === "" || entry.service === query.service) && (query.operation === "" || entry.name === query.operation) && (query.traceId === "" || entry.traceId === toLowerCase(query.traceId)) && (!query.errors || entry.status === 2) && includes(toLowerCase(query.text))(toLowerCase(displayValue(entry)));
|
|
68024
|
-
});
|
|
68025
|
-
}
|
|
68026
68028
|
const page = fnUntraced(function* (query, signal) {
|
|
68027
|
-
const entries = orderEntries(
|
|
68029
|
+
const entries = orderEntries(filterEntries(currentEntries(yield* read()), query, signal), query.sort);
|
|
68028
68030
|
return {
|
|
68029
68031
|
entries: take$3(drop$1(entries, query.offset), query.limit),
|
|
68030
68032
|
total: entries.length
|
|
@@ -68085,7 +68087,7 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
|
|
|
68085
68087
|
return yield* page(query, "trace");
|
|
68086
68088
|
}),
|
|
68087
68089
|
stats: fn("Telemetry.stats")(function* (query) {
|
|
68088
|
-
return summary(
|
|
68090
|
+
return summary(filterEntries(currentEntries(yield* read()), query, "trace"), query);
|
|
68089
68091
|
}),
|
|
68090
68092
|
trace: fn("Telemetry.trace")(function* (id) {
|
|
68091
68093
|
const entries = yield* read();
|
|
@@ -68094,7 +68096,7 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
|
|
|
68094
68096
|
}),
|
|
68095
68097
|
traces: fn("Telemetry.traces")(function* (query) {
|
|
68096
68098
|
const active = currentEntries(yield* read());
|
|
68097
|
-
const entries = map$5(dedupe(map$5(filter$1(
|
|
68099
|
+
const entries = map$5(dedupe(map$5(filter$1(filterEntries(active, query, "all"), (entry) => entry.traceId !== ""), (entry) => entry.traceId)), (id) => {
|
|
68098
68100
|
const records = filter$1(active, (entry) => entry.traceId === id);
|
|
68099
68101
|
const view = traceView(records, id);
|
|
68100
68102
|
const root = getOrElse(head(view.spans), () => getOrThrow$1(head(records)));
|
|
@@ -68125,35 +68127,35 @@ var Telemetry = class extends Service$2()("@deslop/scope/services/telemetry/serv
|
|
|
68125
68127
|
};
|
|
68126
68128
|
//#endregion
|
|
68127
68129
|
//#region src/tools/contracts.ts
|
|
68128
|
-
const Tools = make$6(make$7("
|
|
68129
|
-
description: "List the
|
|
68130
|
+
const Tools = make$6(make$7("list_services", {
|
|
68131
|
+
description: "List the apps sending telemetry in their current run, with their runtime: web, mobile or server. Call it first: the other tools filter by these exact names.",
|
|
68130
68132
|
failure: TelemetryError,
|
|
68131
68133
|
success: Struct({ services: ArraySchema(Service) })
|
|
68132
|
-
}).annotate(Readonly, true), make$7("
|
|
68133
|
-
description: "
|
|
68134
|
+
}).annotate(Readonly, true), make$7("find_traces", {
|
|
68135
|
+
description: "Find traces, each one request or user action across client and server, newest or slowest first. Call it after reproducing a bug, or with sort \"slowest\" before claiming an action is fast; then open one with read_trace.",
|
|
68134
68136
|
failure: TelemetryError,
|
|
68135
68137
|
parameters: SortFilters,
|
|
68136
68138
|
success: TracesPage
|
|
68137
|
-
}).annotate(Readonly, true), make$7("
|
|
68138
|
-
description: "
|
|
68139
|
+
}).annotate(Readonly, true), make$7("read_trace", {
|
|
68140
|
+
description: "Read one trace whole: every span in parent order with its depth, start offset, runtime and logs. Shows where an action spent its time and which span failed.",
|
|
68139
68141
|
failure: TelemetryError,
|
|
68140
|
-
parameters:
|
|
68141
|
-
success:
|
|
68142
|
-
}).annotate(Readonly, true), make$7("
|
|
68143
|
-
description: "
|
|
68142
|
+
parameters: Struct({ id: pipe(TraceId, annotateEncoded({ description: "The 32-character id from find_traces or a span." })) }),
|
|
68143
|
+
success: Trace
|
|
68144
|
+
}).annotate(Readonly, true), make$7("find_logs", {
|
|
68145
|
+
description: "Find what the apps logged, newest first, with or without a span; errors: true keeps only failures. Call it to see what happened during a reproduced bug.",
|
|
68144
68146
|
failure: TelemetryError,
|
|
68145
68147
|
parameters: PageFilters,
|
|
68146
68148
|
success: Page
|
|
68147
|
-
}).annotate(Readonly, true), make$7("
|
|
68148
|
-
description: "
|
|
68149
|
+
}).annotate(Readonly, true), make$7("find_spans", {
|
|
68150
|
+
description: "Find single spans with their original OTLP attributes and events, when one operation matters more than its trace, such as every failed call to one endpoint.",
|
|
68151
|
+
failure: TelemetryError,
|
|
68152
|
+
parameters: SortFilters,
|
|
68153
|
+
success: Page
|
|
68154
|
+
}).annotate(Readonly, true), make$7("measure_latency", {
|
|
68155
|
+
description: "Count, errors and p50, p95 and max latency of the matching spans over the lookback. Run it on the same operation before and after a change to prove it got faster.",
|
|
68149
68156
|
failure: TelemetryError,
|
|
68150
68157
|
parameters: Filters,
|
|
68151
68158
|
success: Stats
|
|
68152
|
-
}).annotate(Readonly, true), make$7("trace", {
|
|
68153
|
-
description: "Read one trace whole: spans in parent order with depth, offset, runtime and their logs. No window or cap.",
|
|
68154
|
-
failure: TelemetryError,
|
|
68155
|
-
parameters: Struct({ id: TraceId }),
|
|
68156
|
-
success: Trace
|
|
68157
68159
|
}).annotate(Readonly, true));
|
|
68158
68160
|
//#endregion
|
|
68159
68161
|
//#region src/tools/handlers.ts
|
|
@@ -68171,12 +68173,12 @@ const query = fnUntraced(function* (filters) {
|
|
|
68171
68173
|
const ToolHandlers = Tools.toLayer(gen(function* () {
|
|
68172
68174
|
const telemetry = yield* Telemetry;
|
|
68173
68175
|
return Tools.of({
|
|
68174
|
-
|
|
68175
|
-
|
|
68176
|
-
|
|
68177
|
-
|
|
68178
|
-
|
|
68179
|
-
|
|
68176
|
+
find_logs: (filters) => flatMap$1(query(filters), telemetry.logs),
|
|
68177
|
+
find_spans: (filters) => flatMap$1(query(filters), telemetry.spans),
|
|
68178
|
+
find_traces: (filters) => flatMap$1(query(filters), telemetry.traces),
|
|
68179
|
+
list_services: () => map$2(telemetry.services(), (services) => ({ services })),
|
|
68180
|
+
measure_latency: (filters) => flatMap$1(query(filters), telemetry.stats),
|
|
68181
|
+
read_trace: (input) => telemetry.trace(input.id)
|
|
68180
68182
|
});
|
|
68181
68183
|
}));
|
|
68182
68184
|
//#endregion
|
|
@@ -68221,7 +68223,7 @@ const receiver = use((router) => gen(function* () {
|
|
|
68221
68223
|
yield* router.add("GET", "/health", text("ready"));
|
|
68222
68224
|
}));
|
|
68223
68225
|
const mcp = pipe(toolkit(Tools), provide$3(ToolHandlers), provide$3(layerMcp({
|
|
68224
|
-
instructions: "Scope
|
|
68226
|
+
instructions: "Scope is the debugger for the user's Effect apps: each app's web, mobile and server code exports its traces and logs here, and Scope keeps only the current run of each app. Use it to see what the code actually did instead of guessing: reproduce the action, then list_services, find_traces and read_trace; find_logs for what the app said; measure_latency before and after a change to prove it got faster.",
|
|
68225
68227
|
name: "scope",
|
|
68226
68228
|
version
|
|
68227
68229
|
})));
|