@usecontextlayer/ctxs 0.5.23 → 0.5.25
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/cli.mjs +695 -147
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -4
package/dist/cli.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3205b84e-0fd0-5843-a715-326779c52b1a")}catch(e){}}();
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import * as Sentry from "@sentry/node";
|
|
6
6
|
import * as fs$2 from "node:fs/promises";
|
|
7
7
|
import { access, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
8
8
|
import path, { sep } from "node:path";
|
|
9
|
-
import childProcess, { execFile } from "node:child_process";
|
|
9
|
+
import childProcess, { execFile, spawn } from "node:child_process";
|
|
10
10
|
import { formatWithOptions, promisify, stripVTControlCharacters } from "node:util";
|
|
11
|
-
import { randomUUID } from "node:crypto";
|
|
11
|
+
import { randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
12
12
|
import { serve, upgradeWebSocket } from "@hono/node-server";
|
|
13
13
|
import { Hono } from "hono";
|
|
14
14
|
import { cors } from "hono/cors";
|
|
@@ -642,7 +642,7 @@ const _safeParseAsync$1 = (_Err) => async (schema, value, _ctx) => {
|
|
|
642
642
|
};
|
|
643
643
|
};
|
|
644
644
|
const safeParseAsync$4 = /* @__PURE__*/ _safeParseAsync$1($ZodRealError$1);
|
|
645
|
-
const _encode$
|
|
645
|
+
const _encode$2 = (_Err) => (schema, value, _ctx) => {
|
|
646
646
|
const ctx = _ctx ? {
|
|
647
647
|
..._ctx,
|
|
648
648
|
direction: "backward"
|
|
@@ -3851,7 +3851,7 @@ const parse$3 = /* @__PURE__ */ _parse$1(ZodRealError$1);
|
|
|
3851
3851
|
const parseAsync$1 = /* @__PURE__ */ _parseAsync$1(ZodRealError$1);
|
|
3852
3852
|
const safeParse$3 = /* @__PURE__ */ _safeParse$1(ZodRealError$1);
|
|
3853
3853
|
const safeParseAsync$3 = /* @__PURE__ */ _safeParseAsync$1(ZodRealError$1);
|
|
3854
|
-
const encode$
|
|
3854
|
+
const encode$3 = /* @__PURE__ */ _encode$2(ZodRealError$1);
|
|
3855
3855
|
const decode$3 = /* @__PURE__ */ _decode$1(ZodRealError$1);
|
|
3856
3856
|
const encodeAsync$1 = /* @__PURE__ */ _encodeAsync$1(ZodRealError$1);
|
|
3857
3857
|
const decodeAsync$1 = /* @__PURE__ */ _decodeAsync$1(ZodRealError$1);
|
|
@@ -3913,7 +3913,7 @@ const ZodType$2 = /*@__PURE__*/ $constructor$1("ZodType", (inst, def) => {
|
|
|
3913
3913
|
inst.parseAsync = async (data, params) => parseAsync$1(inst, data, params, { callee: inst.parseAsync });
|
|
3914
3914
|
inst.safeParseAsync = async (data, params) => safeParseAsync$3(inst, data, params);
|
|
3915
3915
|
inst.spa = inst.safeParseAsync;
|
|
3916
|
-
inst.encode = (data, params) => encode$
|
|
3916
|
+
inst.encode = (data, params) => encode$3(inst, data, params);
|
|
3917
3917
|
inst.decode = (data, params) => decode$3(inst, data, params);
|
|
3918
3918
|
inst.encodeAsync = async (data, params) => encodeAsync$1(inst, data, params);
|
|
3919
3919
|
inst.decodeAsync = async (data, params) => decodeAsync$1(inst, data, params);
|
|
@@ -4418,7 +4418,7 @@ function strictObject$1(shape, params) {
|
|
|
4418
4418
|
...normalizeParams$1(params)
|
|
4419
4419
|
});
|
|
4420
4420
|
}
|
|
4421
|
-
function looseObject(shape, params) {
|
|
4421
|
+
function looseObject$1(shape, params) {
|
|
4422
4422
|
return new ZodObject$2({
|
|
4423
4423
|
type: "object",
|
|
4424
4424
|
shape,
|
|
@@ -4788,7 +4788,7 @@ function normalizedKey(event) {
|
|
|
4788
4788
|
|
|
4789
4789
|
//#endregion
|
|
4790
4790
|
//#region package.json
|
|
4791
|
-
var version$1 = "0.5.
|
|
4791
|
+
var version$1 = "0.5.25";
|
|
4792
4792
|
|
|
4793
4793
|
//#endregion
|
|
4794
4794
|
//#region sentry.ts
|
|
@@ -4969,6 +4969,16 @@ function createGuestMemoryProbe(readMetrics) {
|
|
|
4969
4969
|
function isNodeError(error) {
|
|
4970
4970
|
return error instanceof Error && "code" in error;
|
|
4971
4971
|
}
|
|
4972
|
+
function createSandboxDisposer(input) {
|
|
4973
|
+
let disposePromise = null;
|
|
4974
|
+
return () => {
|
|
4975
|
+
if (disposePromise === null) {
|
|
4976
|
+
input.stopMemoryProbe();
|
|
4977
|
+
disposePromise = input.stopSandbox();
|
|
4978
|
+
}
|
|
4979
|
+
return disposePromise;
|
|
4980
|
+
};
|
|
4981
|
+
}
|
|
4972
4982
|
async function ensureHostFilesystemReady(bindMounts) {
|
|
4973
4983
|
for (const mount of bindMounts) {
|
|
4974
4984
|
if (mount.hostPathBehavior === "createDir") {
|
|
@@ -5008,8 +5018,13 @@ async function bootSandbox(microsandboxLib, config) {
|
|
|
5008
5018
|
});
|
|
5009
5019
|
builder = builder.network((nb) => nb.policy(microsandboxLib.NetworkPolicy.allowAll()));
|
|
5010
5020
|
const sandbox = await builder.create();
|
|
5021
|
+
const guestMemory = createGuestMemoryProbe(() => sandbox.metrics());
|
|
5011
5022
|
return {
|
|
5012
|
-
|
|
5023
|
+
dispose: createSandboxDisposer({
|
|
5024
|
+
stopMemoryProbe: guestMemory.stop,
|
|
5025
|
+
stopSandbox: () => sandbox.stopWithTimeout(SANDBOX_STOP_TIMEOUT_MS)
|
|
5026
|
+
}),
|
|
5027
|
+
guestMemory,
|
|
5013
5028
|
sandbox
|
|
5014
5029
|
};
|
|
5015
5030
|
}
|
|
@@ -5118,7 +5133,7 @@ function guestGitEnv(input) {
|
|
|
5118
5133
|
name: input.sub
|
|
5119
5134
|
}), entries);
|
|
5120
5135
|
}
|
|
5121
|
-
const execFileAsync = promisify(execFile);
|
|
5136
|
+
const execFileAsync$1 = promisify(execFile);
|
|
5122
5137
|
const CAPTURE_AUTHOR_NAME = "contextlayer";
|
|
5123
5138
|
const CAPTURE_AUTHOR_EMAIL = "noreply@usecontextlayer.com";
|
|
5124
5139
|
const BRANCH = "main";
|
|
@@ -5281,7 +5296,7 @@ async function runGit(args, options = {}) {
|
|
|
5281
5296
|
})
|
|
5282
5297
|
};
|
|
5283
5298
|
try {
|
|
5284
|
-
const { stdout, stderr } = await execFileAsync("git", args, {
|
|
5299
|
+
const { stdout, stderr } = await execFileAsync$1("git", args, {
|
|
5285
5300
|
cwd: options.cwd,
|
|
5286
5301
|
env
|
|
5287
5302
|
});
|
|
@@ -6439,7 +6454,7 @@ const _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
6439
6454
|
};
|
|
6440
6455
|
};
|
|
6441
6456
|
const safeParseAsync$1 = /* @__PURE__*/ _safeParseAsync($ZodRealError);
|
|
6442
|
-
const _encode = (_Err) => (schema, value, _ctx) => {
|
|
6457
|
+
const _encode$1 = (_Err) => (schema, value, _ctx) => {
|
|
6443
6458
|
const ctx = _ctx ? {
|
|
6444
6459
|
..._ctx,
|
|
6445
6460
|
direction: "backward"
|
|
@@ -9025,7 +9040,7 @@ const parse$2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
|
9025
9040
|
const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
9026
9041
|
const safeParse$2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
9027
9042
|
const safeParseAsync$2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
9028
|
-
const encode$
|
|
9043
|
+
const encode$2 = /* @__PURE__ */ _encode$1(ZodRealError);
|
|
9029
9044
|
const decode$2 = /* @__PURE__ */ _decode(ZodRealError);
|
|
9030
9045
|
const encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
9031
9046
|
const decodeAsync = /* @__PURE__ */ _decodeAsync(ZodRealError);
|
|
@@ -9084,7 +9099,7 @@ const ZodType$1 = /*@__PURE__*/ $constructor("ZodType", (inst, def) => {
|
|
|
9084
9099
|
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
9085
9100
|
inst.safeParseAsync = async (data, params) => safeParseAsync$2(inst, data, params);
|
|
9086
9101
|
inst.spa = inst.safeParseAsync;
|
|
9087
|
-
inst.encode = (data, params) => encode$
|
|
9102
|
+
inst.encode = (data, params) => encode$2(inst, data, params);
|
|
9088
9103
|
inst.decode = (data, params) => decode$2(inst, data, params);
|
|
9089
9104
|
inst.encodeAsync = async (data, params) => encodeAsync(inst, data, params);
|
|
9090
9105
|
inst.decodeAsync = async (data, params) => decodeAsync(inst, data, params);
|
|
@@ -9499,6 +9514,14 @@ function strictObject(shape, params) {
|
|
|
9499
9514
|
...normalizeParams(params)
|
|
9500
9515
|
});
|
|
9501
9516
|
}
|
|
9517
|
+
function looseObject(shape, params) {
|
|
9518
|
+
return new ZodObject$1({
|
|
9519
|
+
type: "object",
|
|
9520
|
+
shape,
|
|
9521
|
+
catchall: unknown$2(),
|
|
9522
|
+
...normalizeParams(params)
|
|
9523
|
+
});
|
|
9524
|
+
}
|
|
9502
9525
|
const ZodUnion$1 = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
|
|
9503
9526
|
$ZodUnion.init(inst, def);
|
|
9504
9527
|
ZodType$1.init(inst, def);
|
|
@@ -9831,7 +9854,7 @@ function superRefine(fn, params) {
|
|
|
9831
9854
|
freshness: {
|
|
9832
9855
|
props: {
|
|
9833
9856
|
text: { $concat: ["Updated ", { $relativeDay: {
|
|
9834
|
-
|
|
9857
|
+
today: { $state: "/today" },
|
|
9835
9858
|
value: { $maxBy: {
|
|
9836
9859
|
field: "last_updated",
|
|
9837
9860
|
items: { $state: "/items" }
|
|
@@ -9938,6 +9961,11 @@ const sessionMetaSchema$1 = object$3({
|
|
|
9938
9961
|
sessionId: string$4()
|
|
9939
9962
|
});
|
|
9940
9963
|
record$1(string$4(), sessionMetaSchema$1);
|
|
9964
|
+
looseObject({
|
|
9965
|
+
timestamp: string$4().optional(),
|
|
9966
|
+
type: string$4(),
|
|
9967
|
+
uuid: string$4().optional()
|
|
9968
|
+
});
|
|
9941
9969
|
async function ensureWorkspaceCheckout(workspaceId, ctx) {
|
|
9942
9970
|
const repo = await resolveRepo({
|
|
9943
9971
|
platformUrl: ctx.platformUrl,
|
|
@@ -13300,7 +13328,7 @@ function concat(...buffers) {
|
|
|
13300
13328
|
}
|
|
13301
13329
|
return buf;
|
|
13302
13330
|
}
|
|
13303
|
-
function encode(string) {
|
|
13331
|
+
function encode$1(string) {
|
|
13304
13332
|
const bytes = new Uint8Array(string.length);
|
|
13305
13333
|
for (let i = 0; i < string.length; i++) {
|
|
13306
13334
|
const code = string.charCodeAt(i);
|
|
@@ -14021,7 +14049,7 @@ async function flattenedVerify(jws, key, options) {
|
|
|
14021
14049
|
resolvedKey = true;
|
|
14022
14050
|
}
|
|
14023
14051
|
checkKeyType(alg, key, "verify");
|
|
14024
|
-
const data = concat(jws.protected !== void 0 ? encode(jws.protected) : new Uint8Array(), encode("."), typeof jws.payload === "string" ? b64 ? encode(jws.payload) : encoder.encode(jws.payload) : jws.payload);
|
|
14052
|
+
const data = concat(jws.protected !== void 0 ? encode$1(jws.protected) : new Uint8Array(), encode$1("."), typeof jws.payload === "string" ? b64 ? encode$1(jws.payload) : encoder.encode(jws.payload) : jws.payload);
|
|
14025
14053
|
const signature = decodeBase64url(jws.signature, "signature", JWSInvalid);
|
|
14026
14054
|
const k = await normalizeKey$1(key, alg);
|
|
14027
14055
|
if (!await verify(alg, k, signature, data)) throw new JWSSignatureVerificationFailed();
|
|
@@ -14636,6 +14664,99 @@ function createDevJwtVerifier() {
|
|
|
14636
14664
|
};
|
|
14637
14665
|
}
|
|
14638
14666
|
|
|
14667
|
+
//#endregion
|
|
14668
|
+
//#region ../../node_modules/.pnpm/js-base64@3.9.1/node_modules/js-base64/base64.mjs
|
|
14669
|
+
const _TD = typeof TextDecoder === "function" ? new TextDecoder("utf-8", { ignoreBOM: true }) : void 0;
|
|
14670
|
+
const _TE = typeof TextEncoder === "function" ? new TextEncoder() : void 0;
|
|
14671
|
+
const b64chs = Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=");
|
|
14672
|
+
const b64tab = ((a) => {
|
|
14673
|
+
let tab = {};
|
|
14674
|
+
a.forEach((c, i) => tab[c] = i);
|
|
14675
|
+
return tab;
|
|
14676
|
+
})(b64chs);
|
|
14677
|
+
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
14678
|
+
const _fromCC = String.fromCharCode.bind(String);
|
|
14679
|
+
const _U8Afrom = typeof Uint8Array.from === "function" ? Uint8Array.from.bind(Uint8Array) : (it) => new Uint8Array(Array.prototype.slice.call(it, 0));
|
|
14680
|
+
const _mkUriSafe = (src) => src.replace(/=/g, "").replace(/[+\/]/g, (m0) => m0 == "+" ? "-" : "_");
|
|
14681
|
+
const _tidyB64 = (s) => s.replace(/[^A-Za-z0-9\+\/]/g, "");
|
|
14682
|
+
/**
|
|
14683
|
+
* polyfill version of `btoa`
|
|
14684
|
+
*/
|
|
14685
|
+
const btoaPolyfill = (bin) => {
|
|
14686
|
+
let u32, c0, c1, c2, asc = "";
|
|
14687
|
+
const pad = bin.length % 3;
|
|
14688
|
+
for (let i = 0; i < bin.length;) {
|
|
14689
|
+
if ((c0 = bin.charCodeAt(i++)) > 255 || (c1 = bin.charCodeAt(i++)) > 255 || (c2 = bin.charCodeAt(i++)) > 255) throw new TypeError("invalid character found");
|
|
14690
|
+
u32 = c0 << 16 | c1 << 8 | c2;
|
|
14691
|
+
asc += b64chs[u32 >> 18 & 63] + b64chs[u32 >> 12 & 63] + b64chs[u32 >> 6 & 63] + b64chs[u32 & 63];
|
|
14692
|
+
}
|
|
14693
|
+
return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
|
|
14694
|
+
};
|
|
14695
|
+
/**
|
|
14696
|
+
* does what `window.btoa` of web browsers do.
|
|
14697
|
+
* @param {String} bin binary string
|
|
14698
|
+
* @returns {string} Base64-encoded string
|
|
14699
|
+
*/
|
|
14700
|
+
const _btoa = typeof btoa === "function" ? (bin) => btoa(bin) : btoaPolyfill;
|
|
14701
|
+
const _fromUint8Array = typeof Uint8Array.prototype.toBase64 === "function" ? (u8a) => u8a.toBase64() : (u8a) => {
|
|
14702
|
+
const maxargs = 4096;
|
|
14703
|
+
let strs = [];
|
|
14704
|
+
for (let i = 0, l = u8a.length; i < l; i += maxargs) strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));
|
|
14705
|
+
return _btoa(strs.join(""));
|
|
14706
|
+
};
|
|
14707
|
+
const cb_utob = (c) => {
|
|
14708
|
+
if (c.length < 2) {
|
|
14709
|
+
var cc = c.charCodeAt(0);
|
|
14710
|
+
return cc < 128 ? c : cc < 2048 ? _fromCC(192 | cc >>> 6) + _fromCC(128 | cc & 63) : _fromCC(224 | cc >>> 12 & 15) + _fromCC(128 | cc >>> 6 & 63) + _fromCC(128 | cc & 63);
|
|
14711
|
+
} else {
|
|
14712
|
+
var cc = 65536 + (c.charCodeAt(0) - 55296) * 1024 + (c.charCodeAt(1) - 56320);
|
|
14713
|
+
return _fromCC(240 | cc >>> 18 & 7) + _fromCC(128 | cc >>> 12 & 63) + _fromCC(128 | cc >>> 6 & 63) + _fromCC(128 | cc & 63);
|
|
14714
|
+
}
|
|
14715
|
+
};
|
|
14716
|
+
const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
|
|
14717
|
+
/**
|
|
14718
|
+
* @deprecated should have been internal use only.
|
|
14719
|
+
* @param {string} src UTF-8 string
|
|
14720
|
+
* @returns {string} UTF-16 string
|
|
14721
|
+
*/
|
|
14722
|
+
const utob = (u) => u.replace(re_utob, cb_utob);
|
|
14723
|
+
const _encode = _TE ? (s) => _fromUint8Array(_TE.encode(s)) : (s) => _btoa(utob(s));
|
|
14724
|
+
/**
|
|
14725
|
+
* converts a UTF-8-encoded string to a Base64 string.
|
|
14726
|
+
* @param {boolean} [urlsafe] if `true` make the result URL-safe
|
|
14727
|
+
* @returns {string} Base64 string
|
|
14728
|
+
*/
|
|
14729
|
+
const encode = (src, urlsafe = false) => urlsafe ? _mkUriSafe(_encode(src)) : _encode(src);
|
|
14730
|
+
/**
|
|
14731
|
+
* converts a UTF-8-encoded string to URL-safe Base64 RFC4648 §5.
|
|
14732
|
+
* @returns {string} Base64 string
|
|
14733
|
+
*/
|
|
14734
|
+
const encodeURI$1 = (src) => encode(src, true);
|
|
14735
|
+
/**
|
|
14736
|
+
* polyfill version of `atob`
|
|
14737
|
+
*/
|
|
14738
|
+
const atobPolyfill = (asc) => {
|
|
14739
|
+
asc = asc.replace(/\s+/g, "");
|
|
14740
|
+
if (!b64re.test(asc)) throw new TypeError("malformed base64.");
|
|
14741
|
+
asc += "==".slice(2 - (asc.length & 3));
|
|
14742
|
+
let u24, r1, r2;
|
|
14743
|
+
let binArray = [];
|
|
14744
|
+
for (let i = 0; i < asc.length;) {
|
|
14745
|
+
u24 = b64tab[asc.charAt(i++)] << 18 | b64tab[asc.charAt(i++)] << 12 | (r1 = b64tab[asc.charAt(i++)]) << 6 | (r2 = b64tab[asc.charAt(i++)]);
|
|
14746
|
+
if (r1 === 64) binArray.push(_fromCC(u24 >> 16 & 255));
|
|
14747
|
+
else if (r2 === 64) binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255));
|
|
14748
|
+
else binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255));
|
|
14749
|
+
}
|
|
14750
|
+
return binArray.join("");
|
|
14751
|
+
};
|
|
14752
|
+
/**
|
|
14753
|
+
* does what `window.atob` of web browsers do.
|
|
14754
|
+
* @param {String} asc Base64-encoded string
|
|
14755
|
+
* @returns {string} binary string
|
|
14756
|
+
*/
|
|
14757
|
+
const _atob = typeof atob === "function" ? (asc) => atob(_tidyB64(asc)) : atobPolyfill;
|
|
14758
|
+
const _toUint8Array = typeof Uint8Array.fromBase64 === "function" ? (a) => Uint8Array.fromBase64(a) : (a) => _U8Afrom(_atob(a).split("").map((c) => c.charCodeAt(0)));
|
|
14759
|
+
|
|
14639
14760
|
//#endregion
|
|
14640
14761
|
//#region ../slate-shared/dist/index.mjs
|
|
14641
14762
|
const INBOX_DOCS_TREE = {
|
|
@@ -14781,6 +14902,8 @@ export default async ({ docs }) => {
|
|
|
14781
14902
|
},
|
|
14782
14903
|
{ sort },
|
|
14783
14904
|
)
|
|
14905
|
+
// This neutral dev fixture has no customer timezone, so its calendar day is UTC.
|
|
14906
|
+
const today = new Date().toISOString().slice(0, 10)
|
|
14784
14907
|
const items = rows.map((u) => {
|
|
14785
14908
|
const proposedTitle = u.proposed_title ?? ""
|
|
14786
14909
|
const separatorIndex = proposedTitle.indexOf(" - ")
|
|
@@ -14798,7 +14921,7 @@ export default async ({ docs }) => {
|
|
|
14798
14921
|
: proposedTitle || u.path,
|
|
14799
14922
|
}
|
|
14800
14923
|
})
|
|
14801
|
-
return { items }
|
|
14924
|
+
return { items, today }
|
|
14802
14925
|
}
|
|
14803
14926
|
`,
|
|
14804
14927
|
"docs/views/inbox.render-spec.json": `${JSON.stringify({
|
|
@@ -14808,7 +14931,7 @@ export default async ({ docs }) => {
|
|
|
14808
14931
|
freshness: {
|
|
14809
14932
|
props: {
|
|
14810
14933
|
text: { $concat: ["Updated ", { $relativeDay: {
|
|
14811
|
-
|
|
14934
|
+
today: { $state: "/today" },
|
|
14812
14935
|
value: { $maxBy: {
|
|
14813
14936
|
field: "last_updated",
|
|
14814
14937
|
items: { $state: "/items" }
|
|
@@ -14892,7 +15015,24 @@ export default async ({ docs }) => {
|
|
|
14892
15015
|
}
|
|
14893
15016
|
}, null, " ")}\n`
|
|
14894
15017
|
};
|
|
15018
|
+
const DEV_IDENTITY = {
|
|
15019
|
+
email: "joeblack@gmail.com",
|
|
15020
|
+
name: "Joe Black",
|
|
15021
|
+
sub: "user-dev"
|
|
15022
|
+
};
|
|
14895
15023
|
const docPathSchema = string$5().min(1, "a doc path must be non-empty").refine((docPath) => !docPath.startsWith("/"), { message: "a doc path must be root-relative, not absolute" }).refine((docPath) => !docPath.split("/").includes(".."), { message: "a doc path must not contain a '..' segment" });
|
|
15024
|
+
function encodeBase64UrlJson(value) {
|
|
15025
|
+
return encodeURI$1(JSON.stringify(value));
|
|
15026
|
+
}
|
|
15027
|
+
function mintUnsignedCtxToken(sub) {
|
|
15028
|
+
return `${encodeBase64UrlJson({
|
|
15029
|
+
alg: "none",
|
|
15030
|
+
typ: "JWT"
|
|
15031
|
+
})}.${encodeBase64UrlJson({
|
|
15032
|
+
aud: "ctx",
|
|
15033
|
+
sub
|
|
15034
|
+
})}.`;
|
|
15035
|
+
}
|
|
14896
15036
|
const renderSpecSchema = strictObject$1({
|
|
14897
15037
|
params: record$2(string$5().min(1), strictObject$1({ default: string$5().min(1) })).optional().describe("URL search params this surface accepts, each with its default. Resolution is `URL value ?? default`; the default is stripped back out of the URL, and an undeclared URL key is ignored. What a value MEANS — which are legal, what each expands to — is the loader's job, in JS."),
|
|
14898
15038
|
render: unknown$3().describe("The render tree — a @json-render Spec. Its elements name the components and directives published under `components` and `directives` in this artifact, and those contracts govern what each element may carry. This envelope does not constrain the tree's contents.")
|
|
@@ -14917,6 +15057,40 @@ const sessionMetaSchema = object$4({
|
|
|
14917
15057
|
sessionId: string$5()
|
|
14918
15058
|
});
|
|
14919
15059
|
const claudeIndexSchema = record$2(string$5(), sessionMetaSchema);
|
|
15060
|
+
const sessionStoreEntrySchema = looseObject$1({
|
|
15061
|
+
timestamp: string$5().optional(),
|
|
15062
|
+
type: string$5(),
|
|
15063
|
+
uuid: string$5().optional()
|
|
15064
|
+
});
|
|
15065
|
+
function parseSessionStoreJsonl(jsonl, malformedEntryPolicy) {
|
|
15066
|
+
const entries = [];
|
|
15067
|
+
for (const [index, line] of jsonl.split("\n").entries()) {
|
|
15068
|
+
if (line.trim() === "") continue;
|
|
15069
|
+
try {
|
|
15070
|
+
const parsed = JSON.parse(line);
|
|
15071
|
+
entries.push(malformedEntryPolicy === "throw" ? sessionStoreEntrySchema.parse(parsed) : parsed);
|
|
15072
|
+
} catch (cause) {
|
|
15073
|
+
if (malformedEntryPolicy === "skip") continue;
|
|
15074
|
+
throw new Error(`invalid session transcript entry at line ${index + 1}`, { cause });
|
|
15075
|
+
}
|
|
15076
|
+
}
|
|
15077
|
+
return entries;
|
|
15078
|
+
}
|
|
15079
|
+
function singleSessionStore(sessionId, entries) {
|
|
15080
|
+
return {
|
|
15081
|
+
append: () => {
|
|
15082
|
+
throw new Error("singleSessionStore is read-only; append() is not supported");
|
|
15083
|
+
},
|
|
15084
|
+
listSessions: async () => [{
|
|
15085
|
+
mtime: 0,
|
|
15086
|
+
sessionId
|
|
15087
|
+
}],
|
|
15088
|
+
load: async (key) => {
|
|
15089
|
+
if (key.sessionId !== sessionId || key.subpath) return null;
|
|
15090
|
+
return entries;
|
|
15091
|
+
}
|
|
15092
|
+
};
|
|
15093
|
+
}
|
|
14920
15094
|
|
|
14921
15095
|
//#endregion
|
|
14922
15096
|
//#region ../../node_modules/.pnpm/undici@8.8.0/node_modules/undici/lib/core/symbols.js
|
|
@@ -40450,7 +40624,7 @@ const SafeUrlSchema = url().superRefine((val, ctx) => {
|
|
|
40450
40624
|
/**
|
|
40451
40625
|
* RFC 9728 OAuth Protected Resource Metadata
|
|
40452
40626
|
*/
|
|
40453
|
-
const OAuthProtectedResourceMetadataSchema = looseObject({
|
|
40627
|
+
const OAuthProtectedResourceMetadataSchema = looseObject$1({
|
|
40454
40628
|
resource: string$5().url(),
|
|
40455
40629
|
authorization_servers: array$1(SafeUrlSchema).optional(),
|
|
40456
40630
|
jwks_uri: string$5().url().optional(),
|
|
@@ -40469,7 +40643,7 @@ const OAuthProtectedResourceMetadataSchema = looseObject({
|
|
|
40469
40643
|
/**
|
|
40470
40644
|
* RFC 8414 OAuth 2.0 Authorization Server Metadata
|
|
40471
40645
|
*/
|
|
40472
|
-
const OAuthMetadataSchema = looseObject({
|
|
40646
|
+
const OAuthMetadataSchema = looseObject$1({
|
|
40473
40647
|
issuer: string$5(),
|
|
40474
40648
|
authorization_endpoint: SafeUrlSchema,
|
|
40475
40649
|
token_endpoint: SafeUrlSchema,
|
|
@@ -40494,7 +40668,7 @@ const OAuthMetadataSchema = looseObject({
|
|
|
40494
40668
|
* OpenID Connect Discovery 1.0 Provider Metadata
|
|
40495
40669
|
* see: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
|
40496
40670
|
*/
|
|
40497
|
-
const OpenIdProviderMetadataSchema = looseObject({
|
|
40671
|
+
const OpenIdProviderMetadataSchema = looseObject$1({
|
|
40498
40672
|
issuer: string$5(),
|
|
40499
40673
|
authorization_endpoint: SafeUrlSchema,
|
|
40500
40674
|
token_endpoint: SafeUrlSchema,
|
|
@@ -40729,7 +40903,7 @@ const CursorSchema = string$5();
|
|
|
40729
40903
|
/**
|
|
40730
40904
|
* Task creation parameters, used to ask that the server create a task to represent a request.
|
|
40731
40905
|
*/
|
|
40732
|
-
const TaskCreationParamsSchema = looseObject({
|
|
40906
|
+
const TaskCreationParamsSchema = looseObject$1({
|
|
40733
40907
|
/**
|
|
40734
40908
|
* Requested duration in milliseconds to retain task from creation.
|
|
40735
40909
|
*/
|
|
@@ -40745,7 +40919,7 @@ const TaskMetadataSchema = object$4({ ttl: number$4().optional() });
|
|
|
40745
40919
|
* Include this in the `_meta` field under the key `io.modelcontextprotocol/related-task`.
|
|
40746
40920
|
*/
|
|
40747
40921
|
const RelatedTaskMetadataSchema = object$4({ taskId: string$5() });
|
|
40748
|
-
const RequestMetaSchema = looseObject({
|
|
40922
|
+
const RequestMetaSchema = looseObject$1({
|
|
40749
40923
|
/**
|
|
40750
40924
|
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
|
|
40751
40925
|
*/
|
|
@@ -40797,7 +40971,7 @@ const NotificationSchema = object$4({
|
|
|
40797
40971
|
method: string$5(),
|
|
40798
40972
|
params: NotificationsParamsSchema.loose().optional()
|
|
40799
40973
|
});
|
|
40800
|
-
const ResultSchema = looseObject({
|
|
40974
|
+
const ResultSchema = looseObject$1({
|
|
40801
40975
|
/**
|
|
40802
40976
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
40803
40977
|
* for notes on _meta usage.
|
|
@@ -41011,7 +41185,7 @@ const ElicitationCapabilitySchema = preprocess$1((value) => {
|
|
|
41011
41185
|
/**
|
|
41012
41186
|
* Task capabilities for clients, indicating which request types support task creation.
|
|
41013
41187
|
*/
|
|
41014
|
-
const ClientTasksCapabilitySchema = looseObject({
|
|
41188
|
+
const ClientTasksCapabilitySchema = looseObject$1({
|
|
41015
41189
|
/**
|
|
41016
41190
|
* Present if the client supports listing tasks.
|
|
41017
41191
|
*/
|
|
@@ -41023,21 +41197,21 @@ const ClientTasksCapabilitySchema = looseObject({
|
|
|
41023
41197
|
/**
|
|
41024
41198
|
* Capabilities for task creation on specific request types.
|
|
41025
41199
|
*/
|
|
41026
|
-
requests: looseObject({
|
|
41200
|
+
requests: looseObject$1({
|
|
41027
41201
|
/**
|
|
41028
41202
|
* Task support for sampling requests.
|
|
41029
41203
|
*/
|
|
41030
|
-
sampling: looseObject({ createMessage: AssertObjectSchema.optional() }).optional(),
|
|
41204
|
+
sampling: looseObject$1({ createMessage: AssertObjectSchema.optional() }).optional(),
|
|
41031
41205
|
/**
|
|
41032
41206
|
* Task support for elicitation requests.
|
|
41033
41207
|
*/
|
|
41034
|
-
elicitation: looseObject({ create: AssertObjectSchema.optional() }).optional()
|
|
41208
|
+
elicitation: looseObject$1({ create: AssertObjectSchema.optional() }).optional()
|
|
41035
41209
|
}).optional()
|
|
41036
41210
|
});
|
|
41037
41211
|
/**
|
|
41038
41212
|
* Task capabilities for servers, indicating which request types support task creation.
|
|
41039
41213
|
*/
|
|
41040
|
-
const ServerTasksCapabilitySchema = looseObject({
|
|
41214
|
+
const ServerTasksCapabilitySchema = looseObject$1({
|
|
41041
41215
|
/**
|
|
41042
41216
|
* Present if the server supports listing tasks.
|
|
41043
41217
|
*/
|
|
@@ -41049,11 +41223,11 @@ const ServerTasksCapabilitySchema = looseObject({
|
|
|
41049
41223
|
/**
|
|
41050
41224
|
* Capabilities for task creation on specific request types.
|
|
41051
41225
|
*/
|
|
41052
|
-
requests: looseObject({
|
|
41226
|
+
requests: looseObject$1({
|
|
41053
41227
|
/**
|
|
41054
41228
|
* Task support for tool requests.
|
|
41055
41229
|
*/
|
|
41056
|
-
tools: looseObject({ call: AssertObjectSchema.optional() }).optional() }).optional()
|
|
41230
|
+
tools: looseObject$1({ call: AssertObjectSchema.optional() }).optional() }).optional()
|
|
41057
41231
|
});
|
|
41058
41232
|
/**
|
|
41059
41233
|
* Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
|
|
@@ -41434,7 +41608,7 @@ const ResourceSchema = object$4({
|
|
|
41434
41608
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
41435
41609
|
* for notes on _meta usage.
|
|
41436
41610
|
*/
|
|
41437
|
-
_meta: optional$3(looseObject({}))
|
|
41611
|
+
_meta: optional$3(looseObject$1({}))
|
|
41438
41612
|
});
|
|
41439
41613
|
/**
|
|
41440
41614
|
* A template description for resources available on the server.
|
|
@@ -41464,7 +41638,7 @@ const ResourceTemplateSchema = object$4({
|
|
|
41464
41638
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
41465
41639
|
* for notes on _meta usage.
|
|
41466
41640
|
*/
|
|
41467
|
-
_meta: optional$3(looseObject({}))
|
|
41641
|
+
_meta: optional$3(looseObject$1({}))
|
|
41468
41642
|
});
|
|
41469
41643
|
/**
|
|
41470
41644
|
* Sent from the client to request a list of resources the server has.
|
|
@@ -41577,7 +41751,7 @@ const PromptSchema = object$4({
|
|
|
41577
41751
|
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
|
|
41578
41752
|
* for notes on _meta usage.
|
|
41579
41753
|
*/
|
|
41580
|
-
_meta: optional$3(looseObject({}))
|
|
41754
|
+
_meta: optional$3(looseObject$1({}))
|
|
41581
41755
|
});
|
|
41582
41756
|
/**
|
|
41583
41757
|
* Sent from the client to request a list of prompts and prompt templates the server has.
|
|
@@ -42513,7 +42687,7 @@ function assertCompleteRequestResourceTemplate(request) {
|
|
|
42513
42687
|
/**
|
|
42514
42688
|
* The server's response to a completion/complete request
|
|
42515
42689
|
*/
|
|
42516
|
-
const CompleteResultSchema = ResultSchema.extend({ completion: looseObject({
|
|
42690
|
+
const CompleteResultSchema = ResultSchema.extend({ completion: looseObject$1({
|
|
42517
42691
|
/**
|
|
42518
42692
|
* An array of completion values. Must not exceed 100 items.
|
|
42519
42693
|
*/
|
|
@@ -58964,7 +59138,7 @@ function createScheduleApiClient(config) {
|
|
|
58964
59138
|
})
|
|
58965
59139
|
};
|
|
58966
59140
|
}
|
|
58967
|
-
const SERVER_VERSION = "0.5.
|
|
59141
|
+
const SERVER_VERSION = "0.5.25";
|
|
58968
59142
|
/** The most operations one OperationSet will carry. The service's own ceiling. */
|
|
58969
59143
|
const MAX_OPERATIONS = 200;
|
|
58970
59144
|
/**
|
|
@@ -95483,6 +95657,9 @@ function stemOf(relPath) {
|
|
|
95483
95657
|
function isMarkdownPath(relPath) {
|
|
95484
95658
|
return normalizeRelativePath(relPath).endsWith(".md");
|
|
95485
95659
|
}
|
|
95660
|
+
function isVisibleIndexPath(relPath) {
|
|
95661
|
+
return normalizeRelativePath(relPath).split("/").every((segment) => !segment.startsWith("."));
|
|
95662
|
+
}
|
|
95486
95663
|
function escapesIndexRoot(target) {
|
|
95487
95664
|
return normalizedPathEscapesRoot(normalizeAuthoredPath(target));
|
|
95488
95665
|
}
|
|
@@ -95559,26 +95736,6 @@ function unique(values) {
|
|
|
95559
95736
|
function uniqueSorted(values) {
|
|
95560
95737
|
return unique(values).sort(comparePath);
|
|
95561
95738
|
}
|
|
95562
|
-
function computeBacklinks(docs) {
|
|
95563
|
-
const backlinks = /* @__PURE__ */ new Map();
|
|
95564
|
-
for (const doc of docs) backlinks.set(normalizeLinkTarget(doc.path), backlinks.get(normalizeLinkTarget(doc.path)) ?? []);
|
|
95565
|
-
for (const doc of docs) {
|
|
95566
|
-
const targets = new Set([...doc.outgoingLinks, ...Object.values(doc.relationships).flat()]);
|
|
95567
|
-
for (const target of targets) {
|
|
95568
|
-
const normalized = normalizeLinkTarget(target);
|
|
95569
|
-
addBacklink(backlinks, normalized, doc.path);
|
|
95570
|
-
const resolved = resolveWikilink(normalized, docs);
|
|
95571
|
-
if (resolved) addBacklink(backlinks, normalizeLinkTarget(resolved.path), doc.path);
|
|
95572
|
-
}
|
|
95573
|
-
}
|
|
95574
|
-
for (const [target, sources] of backlinks) backlinks.set(target, sources.sort(comparePath));
|
|
95575
|
-
return backlinks;
|
|
95576
|
-
}
|
|
95577
|
-
function addBacklink(backlinks, target, source) {
|
|
95578
|
-
const sources = backlinks.get(target) ?? [];
|
|
95579
|
-
if (!sources.includes(source)) sources.push(source);
|
|
95580
|
-
backlinks.set(target, sources);
|
|
95581
|
-
}
|
|
95582
95739
|
const MDAST_OPTIONS = {
|
|
95583
95740
|
extensions: [frontmatter()],
|
|
95584
95741
|
mdastExtensions: [frontmatterFromMarkdown()]
|
|
@@ -95662,6 +95819,26 @@ function extractRelationships(frontmatter) {
|
|
|
95662
95819
|
}
|
|
95663
95820
|
return relationships;
|
|
95664
95821
|
}
|
|
95822
|
+
function computeBacklinks(docs) {
|
|
95823
|
+
const backlinks = /* @__PURE__ */ new Map();
|
|
95824
|
+
for (const doc of docs) backlinks.set(normalizeLinkTarget(doc.path), backlinks.get(normalizeLinkTarget(doc.path)) ?? []);
|
|
95825
|
+
for (const doc of docs) {
|
|
95826
|
+
const targets = new Set([...doc.outgoingLinks, ...Object.values(doc.relationships).flat()]);
|
|
95827
|
+
for (const target of targets) {
|
|
95828
|
+
const normalized = normalizeLinkTarget(target);
|
|
95829
|
+
addBacklink(backlinks, normalized, doc.path);
|
|
95830
|
+
const resolved = resolveWikilink(normalized, docs);
|
|
95831
|
+
if (resolved) addBacklink(backlinks, normalizeLinkTarget(resolved.path), doc.path);
|
|
95832
|
+
}
|
|
95833
|
+
}
|
|
95834
|
+
for (const [target, sources] of backlinks) backlinks.set(target, sources.sort(comparePath));
|
|
95835
|
+
return backlinks;
|
|
95836
|
+
}
|
|
95837
|
+
function addBacklink(backlinks, target, source) {
|
|
95838
|
+
const sources = backlinks.get(target) ?? [];
|
|
95839
|
+
if (!sources.includes(source)) sources.push(source);
|
|
95840
|
+
backlinks.set(target, sources);
|
|
95841
|
+
}
|
|
95665
95842
|
const RESERVED = new Set([
|
|
95666
95843
|
"type",
|
|
95667
95844
|
"title",
|
|
@@ -95964,7 +96141,7 @@ var Docs = class {
|
|
|
95964
96141
|
const dirents = await this.fs.readdir(absDir, { withFileTypes: true });
|
|
95965
96142
|
for (const dirent of dirents) {
|
|
95966
96143
|
const relPath = normalizeRelativePath(posixJoin(relDir, dirent.name));
|
|
95967
|
-
if (
|
|
96144
|
+
if (!isVisibleIndexPath(relPath)) continue;
|
|
95968
96145
|
if (dirent.isDirectory()) {
|
|
95969
96146
|
const child = await this.walk(this.abs(relPath), relPath);
|
|
95970
96147
|
markdownFiles.push(...child.markdownFiles);
|
|
@@ -97934,7 +98111,82 @@ function osUsername() {
|
|
|
97934
98111
|
}
|
|
97935
98112
|
|
|
97936
98113
|
//#endregion
|
|
97937
|
-
//#region ../
|
|
98114
|
+
//#region ../db-infra/dist/postgres-DrlDW_Ri.mjs
|
|
98115
|
+
const env$2 = { NODE_ENV: process.env.NODE_ENV };
|
|
98116
|
+
|
|
98117
|
+
//#endregion
|
|
98118
|
+
//#region ../db-infra/dist/ephemeral.mjs
|
|
98119
|
+
const PG_HOST = "postgres://postgres:postgres@127.0.0.1:6489";
|
|
98120
|
+
const ADMIN_URL = `${PG_HOST}/postgres`;
|
|
98121
|
+
async function createEphemeralDatabase(baseName) {
|
|
98122
|
+
const name = `${baseName}_${randomBytes(4).toString("hex")}`;
|
|
98123
|
+
const admin = src_default(ADMIN_URL, { max: 1 });
|
|
98124
|
+
try {
|
|
98125
|
+
await admin.unsafe(`CREATE DATABASE ${name}`);
|
|
98126
|
+
} finally {
|
|
98127
|
+
await admin.end();
|
|
98128
|
+
}
|
|
98129
|
+
return {
|
|
98130
|
+
async drop() {
|
|
98131
|
+
const admin2 = src_default(ADMIN_URL, { max: 1 });
|
|
98132
|
+
try {
|
|
98133
|
+
await admin2`SELECT pg_terminate_backend(pid) FROM pg_stat_activity
|
|
98134
|
+
WHERE datname = ${name} AND pid <> pg_backend_pid()`;
|
|
98135
|
+
await admin2.unsafe(`DROP DATABASE IF EXISTS ${name}`);
|
|
98136
|
+
} finally {
|
|
98137
|
+
await admin2.end();
|
|
98138
|
+
}
|
|
98139
|
+
},
|
|
98140
|
+
url: `${PG_HOST}/${name}`
|
|
98141
|
+
};
|
|
98142
|
+
}
|
|
98143
|
+
function isPerKeyMode(opts) {
|
|
98144
|
+
return opts.migrators !== void 0;
|
|
98145
|
+
}
|
|
98146
|
+
/**
|
|
98147
|
+
* A composition's whole database dance in one call: CREATE a fresh database per
|
|
98148
|
+
* base name, run the migrate step, and hand back the urls + one `dropAll`. If
|
|
98149
|
+
* ANY create or migrate fails, every database already created is dropped before
|
|
98150
|
+
* the error rethrows — a failed boot must not leak `ctx_*_<hex8>` litter.
|
|
98151
|
+
*/
|
|
98152
|
+
async function provisionEphemeralDatabases(opts) {
|
|
98153
|
+
let baseNames;
|
|
98154
|
+
let migrate;
|
|
98155
|
+
if (isPerKeyMode(opts)) {
|
|
98156
|
+
const { migrators } = opts;
|
|
98157
|
+
baseNames = Object.keys(migrators);
|
|
98158
|
+
migrate = async (urls) => {
|
|
98159
|
+
await Promise.all(Object.keys(migrators).map((baseName) => migrators[baseName](urls[baseName])));
|
|
98160
|
+
};
|
|
98161
|
+
} else ({migrate, baseNames} = opts);
|
|
98162
|
+
const settled = await Promise.allSettled(baseNames.map(async (baseName) => ({
|
|
98163
|
+
baseName,
|
|
98164
|
+
db: await createEphemeralDatabase(baseName)
|
|
98165
|
+
})));
|
|
98166
|
+
const created = settled.filter((r) => r.status === "fulfilled").map((r) => r.value);
|
|
98167
|
+
const dropAll = async () => {
|
|
98168
|
+
await Promise.all(created.map(({ db }) => db.drop()));
|
|
98169
|
+
};
|
|
98170
|
+
const failed = settled.find((r) => r.status === "rejected");
|
|
98171
|
+
if (failed) {
|
|
98172
|
+
await dropAll();
|
|
98173
|
+
throw failed.reason;
|
|
98174
|
+
}
|
|
98175
|
+
const urls = Object.fromEntries(created.map(({ baseName, db }) => [baseName, db.url]));
|
|
98176
|
+
try {
|
|
98177
|
+
await migrate(urls);
|
|
98178
|
+
} catch (err) {
|
|
98179
|
+
await dropAll();
|
|
98180
|
+
throw err;
|
|
98181
|
+
}
|
|
98182
|
+
return {
|
|
98183
|
+
dropAll,
|
|
98184
|
+
urls
|
|
98185
|
+
};
|
|
98186
|
+
}
|
|
98187
|
+
|
|
98188
|
+
//#endregion
|
|
98189
|
+
//#region ../slate-bridge/dist/platform-harness-CL-GGo8J.mjs
|
|
97938
98190
|
const nonEmptyStringSchema = string$5().trim().min(1);
|
|
97939
98191
|
const portSchema = number$3().int().min(0).max(65535).default(7777);
|
|
97940
98192
|
const envSchema = object$4({
|
|
@@ -97943,7 +98195,7 @@ const envSchema = object$4({
|
|
|
97943
98195
|
CTX_PLATFORM_URL: url().default("http://127.0.0.1:3010").transform((url) => url.replace(/\/+$/, "")),
|
|
97944
98196
|
CTX_WEB_URL: url().default("http://localhost:3000").transform((url) => url.replace(/\/+$/, "")),
|
|
97945
98197
|
CTXS_BRIDGE_PORT: portSchema,
|
|
97946
|
-
CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.
|
|
98198
|
+
CTXS_CLAUDE_IMAGE: nonEmptyStringSchema.default("ghcr.io/usecontextlayer/ctx-sandbox:0.5.25"),
|
|
97947
98199
|
CTXS_CLAUDE_MODEL: nonEmptyStringSchema.default("opus"),
|
|
97948
98200
|
CTXS_HOST_CLAUDE_JSON_PATH: nonEmptyStringSchema.default(() => path.join(os.homedir(), ".claude.json")),
|
|
97949
98201
|
NODE_ENV: _enum$1([
|
|
@@ -97982,7 +98234,6 @@ Do this bookkeeping quietly. Don't narrate routine git operations — mention gi
|
|
|
97982
98234
|
The workspace's synced source data — email, meetings, tasks, whatever the user connected — lives in a Postgres database called the base. Query it with the \`ctxb\` CLI, following the contextbase skill. \`CTXB_DATABASE_URL\` is already set when this workspace has a base; if it is unset, no base is connected. Answer data questions from the base, not from memory.`;
|
|
97983
98235
|
const BUILTIN_ALLOWED_TOOLS = [
|
|
97984
98236
|
"Agent",
|
|
97985
|
-
"AskUserQuestion",
|
|
97986
98237
|
"Bash",
|
|
97987
98238
|
"BashOutput",
|
|
97988
98239
|
"Edit",
|
|
@@ -98004,6 +98255,7 @@ const BUILTIN_ALLOWED_TOOLS = [
|
|
|
98004
98255
|
"WebSearch",
|
|
98005
98256
|
"Write"
|
|
98006
98257
|
];
|
|
98258
|
+
const BUILTIN_DISALLOWED_TOOLS = ["AskUserQuestion"];
|
|
98007
98259
|
const CLAUDE_ARGS = [
|
|
98008
98260
|
"--input-format",
|
|
98009
98261
|
"stream-json",
|
|
@@ -98029,12 +98281,13 @@ function resolveChatBaseId(baseIds, workspaceId) {
|
|
|
98029
98281
|
}
|
|
98030
98282
|
function buildChatSpawnPlan(input) {
|
|
98031
98283
|
const { allowedTools, disallowedTools } = input.mcpToolRules;
|
|
98284
|
+
const deniedTools = [...BUILTIN_DISALLOWED_TOOLS, ...disallowedTools];
|
|
98032
98285
|
return {
|
|
98033
98286
|
args: [
|
|
98034
98287
|
...CLAUDE_ARGS,
|
|
98035
98288
|
"--allowedTools",
|
|
98036
98289
|
[...BUILTIN_ALLOWED_TOOLS, ...allowedTools].join(","),
|
|
98037
|
-
...
|
|
98290
|
+
...deniedTools.length > 0 ? ["--disallowedTools", deniedTools.join(",")] : [],
|
|
98038
98291
|
...input.mcpConfigArgs ?? [],
|
|
98039
98292
|
"--model",
|
|
98040
98293
|
input.model,
|
|
@@ -98361,16 +98614,9 @@ async function createClaudeMicrosandbox(options) {
|
|
|
98361
98614
|
workdir: options.hostProjectDir
|
|
98362
98615
|
});
|
|
98363
98616
|
await ensureHostFilesystemReady(bootConfig.bindMounts);
|
|
98364
|
-
const { guestMemory, sandbox } = await bootSandbox(await import("microsandbox"), bootConfig);
|
|
98365
|
-
let disposePromise = null;
|
|
98617
|
+
const { dispose, guestMemory, sandbox } = await bootSandbox(await import("microsandbox"), bootConfig);
|
|
98366
98618
|
return {
|
|
98367
|
-
dispose
|
|
98368
|
-
if (disposePromise === null) {
|
|
98369
|
-
guestMemory.stop();
|
|
98370
|
-
disposePromise = sandbox.stopWithTimeout(SANDBOX_STOP_TIMEOUT_MS);
|
|
98371
|
-
}
|
|
98372
|
-
return disposePromise;
|
|
98373
|
-
},
|
|
98619
|
+
dispose,
|
|
98374
98620
|
guestMemory: () => guestMemory.read(),
|
|
98375
98621
|
spawn: (spawnOptions) => spawnClaudeProcess(sandbox, spawnOptions)
|
|
98376
98622
|
};
|
|
@@ -98487,11 +98733,7 @@ function generateSandboxName() {
|
|
|
98487
98733
|
}
|
|
98488
98734
|
const VIEW_NAME = /^[\w-]+$/;
|
|
98489
98735
|
const EVAL_TIMEOUT_MS = 1e4;
|
|
98490
|
-
const RESERVED_STATE_KEYS = [
|
|
98491
|
-
"now",
|
|
98492
|
-
"params",
|
|
98493
|
-
"workspaceId"
|
|
98494
|
-
];
|
|
98736
|
+
const RESERVED_STATE_KEYS = ["params", "workspaceId"];
|
|
98495
98737
|
async function runWorkspaceView(opts) {
|
|
98496
98738
|
if (!VIEW_NAME.test(opts.view)) throw new Error(`views/run: invalid view name "${opts.view}"`);
|
|
98497
98739
|
return runSurfacePair({
|
|
@@ -99056,6 +99298,190 @@ async function createBridgeServer(opts) {
|
|
|
99056
99298
|
port: boundPort
|
|
99057
99299
|
};
|
|
99058
99300
|
}
|
|
99301
|
+
const REPO_ROOT = path.resolve(fileURLToPath(new URL(".", import.meta.url)), "..", "..", "..");
|
|
99302
|
+
const EPHEMERAL_SECRETS_ENCRYPTION_KEY_HEX = "0".repeat(64);
|
|
99303
|
+
function platformEnv(extra) {
|
|
99304
|
+
const env = {
|
|
99305
|
+
...process.env,
|
|
99306
|
+
...extra
|
|
99307
|
+
};
|
|
99308
|
+
delete env.CTX_AUTH_SUB_ID;
|
|
99309
|
+
return env;
|
|
99310
|
+
}
|
|
99311
|
+
const PLATFORM_DATABASES = [
|
|
99312
|
+
"ctx_base_platform",
|
|
99313
|
+
"ctx_pggit",
|
|
99314
|
+
"ctx_secrets",
|
|
99315
|
+
"ctx_slate_platform"
|
|
99316
|
+
];
|
|
99317
|
+
function toPlatformDatabaseEnv(urls) {
|
|
99318
|
+
return {
|
|
99319
|
+
CTX_BASE_DATABASE_URL: urls.ctx_base_platform,
|
|
99320
|
+
CTX_PGGIT_DATABASE_URL: urls.ctx_pggit,
|
|
99321
|
+
CTX_SECRETS_DATABASE_URL: urls.ctx_secrets,
|
|
99322
|
+
CTX_SECRETS_ENCRYPTION_KEY: EPHEMERAL_SECRETS_ENCRYPTION_KEY_HEX,
|
|
99323
|
+
CTX_SLATE_DATABASE_URL: urls.ctx_slate_platform
|
|
99324
|
+
};
|
|
99325
|
+
}
|
|
99326
|
+
async function provisionPlatformDatabases() {
|
|
99327
|
+
const provisioned = await provisionEphemeralDatabases({
|
|
99328
|
+
baseNames: PLATFORM_DATABASES,
|
|
99329
|
+
migrate: (urls) => migrateAll(toPlatformDatabaseEnv(urls))
|
|
99330
|
+
});
|
|
99331
|
+
return {
|
|
99332
|
+
databaseEnv: toPlatformDatabaseEnv(provisioned.urls),
|
|
99333
|
+
dropAll: provisioned.dropAll
|
|
99334
|
+
};
|
|
99335
|
+
}
|
|
99336
|
+
async function migrateAll(databaseEnv) {
|
|
99337
|
+
await runToCompletion([
|
|
99338
|
+
"--filter",
|
|
99339
|
+
"@usecontextlayer/platform",
|
|
99340
|
+
"run",
|
|
99341
|
+
"db.latest"
|
|
99342
|
+
], platformEnv(databaseEnv));
|
|
99343
|
+
}
|
|
99344
|
+
function runToCompletion(args, env) {
|
|
99345
|
+
return new Promise((resolve, reject) => {
|
|
99346
|
+
const proc = spawn("pnpm", args, {
|
|
99347
|
+
cwd: REPO_ROOT,
|
|
99348
|
+
env,
|
|
99349
|
+
stdio: [
|
|
99350
|
+
"ignore",
|
|
99351
|
+
"pipe",
|
|
99352
|
+
"pipe"
|
|
99353
|
+
]
|
|
99354
|
+
});
|
|
99355
|
+
let err = "";
|
|
99356
|
+
proc.stderr?.on("data", (c) => {
|
|
99357
|
+
err += c.toString("utf-8");
|
|
99358
|
+
});
|
|
99359
|
+
proc.once("error", reject);
|
|
99360
|
+
proc.once("exit", (code) => code === 0 ? resolve() : reject(/* @__PURE__ */ new Error(`pnpm ${args.join(" ")} exited ${code}\n${err}`)));
|
|
99361
|
+
});
|
|
99362
|
+
}
|
|
99363
|
+
async function bootPlatform(databaseEnv) {
|
|
99364
|
+
const port = randomInt(2e4, 6e4);
|
|
99365
|
+
const proc = spawn("pnpm", [
|
|
99366
|
+
"--filter",
|
|
99367
|
+
"@usecontextlayer/platform",
|
|
99368
|
+
"run",
|
|
99369
|
+
"start"
|
|
99370
|
+
], {
|
|
99371
|
+
cwd: REPO_ROOT,
|
|
99372
|
+
detached: true,
|
|
99373
|
+
env: platformEnv({
|
|
99374
|
+
...databaseEnv,
|
|
99375
|
+
CTX_AUTH_SKIP_VERIFY_JWT: "true",
|
|
99376
|
+
CTX_PLATFORM_PORT: String(port)
|
|
99377
|
+
}),
|
|
99378
|
+
stdio: [
|
|
99379
|
+
"ignore",
|
|
99380
|
+
"pipe",
|
|
99381
|
+
"pipe"
|
|
99382
|
+
]
|
|
99383
|
+
});
|
|
99384
|
+
proc.stderr?.on("data", (c) => process.stderr.write(c));
|
|
99385
|
+
const exited = new Promise((resolve, reject) => {
|
|
99386
|
+
proc.once("exit", (code) => resolve(code));
|
|
99387
|
+
proc.once("error", reject);
|
|
99388
|
+
});
|
|
99389
|
+
const platformUrl = `http://127.0.0.1:${port}`;
|
|
99390
|
+
const exitedBeforeReady = exited.then((code) => {
|
|
99391
|
+
throw new Error(`platform exited before ready (code ${code})`);
|
|
99392
|
+
});
|
|
99393
|
+
await Promise.race([exitedBeforeReady, waitForHttpReady(`${platformUrl}/doc`, 3e4)]);
|
|
99394
|
+
return {
|
|
99395
|
+
close: async () => {
|
|
99396
|
+
proc.kill("SIGTERM");
|
|
99397
|
+
await exited;
|
|
99398
|
+
},
|
|
99399
|
+
platformUrl
|
|
99400
|
+
};
|
|
99401
|
+
}
|
|
99402
|
+
async function waitForHttpReady(url, timeoutMs) {
|
|
99403
|
+
const deadline = Date.now() + timeoutMs;
|
|
99404
|
+
let last;
|
|
99405
|
+
while (Date.now() < deadline) {
|
|
99406
|
+
try {
|
|
99407
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(2e3) });
|
|
99408
|
+
if (res.status < 500) return;
|
|
99409
|
+
last = /* @__PURE__ */ new Error(`HTTP ${res.status}`);
|
|
99410
|
+
} catch (e) {
|
|
99411
|
+
last = e;
|
|
99412
|
+
}
|
|
99413
|
+
await new Promise((r) => setTimeout(r, 250));
|
|
99414
|
+
}
|
|
99415
|
+
throw new Error(`${url} not ready in ${timeoutMs}ms (last: ${last instanceof Error ? last.message : String(last)})`);
|
|
99416
|
+
}
|
|
99417
|
+
async function seedWorkspaceViaSdk(opts) {
|
|
99418
|
+
return (await new SlateAPIClient({
|
|
99419
|
+
environment: opts.platformUrl,
|
|
99420
|
+
...ctxAuthHeaders(() => Promise.resolve(opts.token))
|
|
99421
|
+
}).workspaces.createWorkspace({
|
|
99422
|
+
baseIds: opts.baseIds ?? [],
|
|
99423
|
+
model: opts.model ?? "haiku",
|
|
99424
|
+
name: opts.name ?? "capstone-test",
|
|
99425
|
+
...opts.claudeToken ? { claudeOauthTokenSecret: opts.claudeToken } : {}
|
|
99426
|
+
})).workspaceId;
|
|
99427
|
+
}
|
|
99428
|
+
strictObject$1({
|
|
99429
|
+
bases: array$1(strictObject$1({
|
|
99430
|
+
base_id: string$5().uuid(),
|
|
99431
|
+
dsn: string$5().min(1),
|
|
99432
|
+
name: string$5().min(1)
|
|
99433
|
+
})),
|
|
99434
|
+
model: string$5().min(1).nullable(),
|
|
99435
|
+
name: string$5().min(1),
|
|
99436
|
+
platform_origin: string$5().min(1),
|
|
99437
|
+
pulled_at: string$5().min(1),
|
|
99438
|
+
slug: string$5().min(1),
|
|
99439
|
+
workspace_id: string$5().uuid()
|
|
99440
|
+
});
|
|
99441
|
+
async function pushRepo(platformUrl, token, repoId, files) {
|
|
99442
|
+
const base = await mkdtemp(path.join(os.tmpdir(), "seed-push-"));
|
|
99443
|
+
try {
|
|
99444
|
+
const repo = await resolveRepo({
|
|
99445
|
+
platformUrl,
|
|
99446
|
+
repoId,
|
|
99447
|
+
token
|
|
99448
|
+
}, base);
|
|
99449
|
+
if (await remoteHead(repo.remote) !== null) await cloneRepo(repo);
|
|
99450
|
+
for (const [rel, content] of Object.entries(files)) {
|
|
99451
|
+
await mkdir(path.join(repo.hostDir, path.dirname(rel)), { recursive: true });
|
|
99452
|
+
await writeFile(path.join(repo.hostDir, rel), content);
|
|
99453
|
+
}
|
|
99454
|
+
await pushSnapshot(repo, { message: `seed ${repoId}` });
|
|
99455
|
+
} finally {
|
|
99456
|
+
await rm(base, {
|
|
99457
|
+
force: true,
|
|
99458
|
+
recursive: true
|
|
99459
|
+
});
|
|
99460
|
+
}
|
|
99461
|
+
}
|
|
99462
|
+
async function pushDocsTree(opts) {
|
|
99463
|
+
const repoId = buildRepoId({
|
|
99464
|
+
kind: "workspace",
|
|
99465
|
+
owner: "slate",
|
|
99466
|
+
workspaceId: opts.workspaceId
|
|
99467
|
+
});
|
|
99468
|
+
await pushRepo(opts.platformUrl, opts.token, repoId, opts.files);
|
|
99469
|
+
}
|
|
99470
|
+
async function pushClaudeHome(opts) {
|
|
99471
|
+
const repoId = buildRepoId({
|
|
99472
|
+
kind: "claude",
|
|
99473
|
+
owner: "slate",
|
|
99474
|
+
userId: opts.userId,
|
|
99475
|
+
workspaceId: opts.workspaceId
|
|
99476
|
+
});
|
|
99477
|
+
await pushRepo(opts.platformUrl, opts.token, repoId, opts.files);
|
|
99478
|
+
}
|
|
99479
|
+
function turnPrompt(turn) {
|
|
99480
|
+
return typeof turn === "string" ? turn : turn.prompt;
|
|
99481
|
+
}
|
|
99482
|
+
function turnInterruptPhase(turn) {
|
|
99483
|
+
return typeof turn === "string" ? void 0 : turn.interrupt;
|
|
99484
|
+
}
|
|
99059
99485
|
const PARITY_SCENARIOS = [
|
|
99060
99486
|
{
|
|
99061
99487
|
name: "text-only",
|
|
@@ -99107,6 +99533,13 @@ const PARITY_SCENARIOS = [
|
|
|
99107
99533
|
"Summarize this conversation in one short sentence.",
|
|
99108
99534
|
"Reply with exactly one word: bye"
|
|
99109
99535
|
]
|
|
99536
|
+
},
|
|
99537
|
+
{
|
|
99538
|
+
name: "interrupted-text",
|
|
99539
|
+
turns: [{
|
|
99540
|
+
interrupt: "text",
|
|
99541
|
+
prompt: "Write a detailed 1500-word essay on the history of the bicycle. Plain prose only, no tools, no lists, no headings."
|
|
99542
|
+
}, "Reply with exactly one word: continued"]
|
|
99110
99543
|
}
|
|
99111
99544
|
];
|
|
99112
99545
|
function resolveGoldensDir() {
|
|
@@ -99119,45 +99552,96 @@ function resolveGoldensDir() {
|
|
|
99119
99552
|
dir = parent;
|
|
99120
99553
|
}
|
|
99121
99554
|
}
|
|
99555
|
+
const keychainClaudeCredentialsSchema = object$4({ claudeAiOauth: object$4({
|
|
99556
|
+
accessToken: string$5().min(1),
|
|
99557
|
+
expiresAt: number$4()
|
|
99558
|
+
}) });
|
|
99559
|
+
async function resolveClaudeHostCredential() {
|
|
99560
|
+
const exported = process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
99561
|
+
if (exported) return {
|
|
99562
|
+
source: "env",
|
|
99563
|
+
token: exported
|
|
99564
|
+
};
|
|
99565
|
+
const raw = await readClaudeCodeCredentialsFromKeychain({ platform: process.platform });
|
|
99566
|
+
if (raw === null) throw new Error("no Claude credentials for the claude tier: export CLAUDE_CODE_OAUTH_TOKEN, or log in to Claude Code on this Mac (the keychain fallback found nothing).");
|
|
99567
|
+
const creds = keychainClaudeCredentialsSchema.parse(JSON.parse(raw));
|
|
99568
|
+
if (creds.claudeAiOauth.expiresAt <= Date.now()) throw new Error("the keychain's Claude Code token has expired: run any claude command to refresh it, or export CLAUDE_CODE_OAUTH_TOKEN.");
|
|
99569
|
+
return {
|
|
99570
|
+
expiresAt: creds.claudeAiOauth.expiresAt,
|
|
99571
|
+
source: "keychain",
|
|
99572
|
+
token: creds.claudeAiOauth.accessToken
|
|
99573
|
+
};
|
|
99574
|
+
}
|
|
99122
99575
|
|
|
99123
99576
|
//#endregion
|
|
99124
99577
|
//#region ../slate-bridge/dist/index.mjs
|
|
99578
|
+
const execFileAsync = promisify(execFile);
|
|
99125
99579
|
async function writeJsonAtomic(filePath, value) {
|
|
99126
99580
|
const tmp = `${filePath}.tmp`;
|
|
99127
99581
|
await writeFile(tmp, `${JSON.stringify(value, null, 2)}\n`);
|
|
99128
99582
|
await rename(tmp, filePath);
|
|
99129
99583
|
}
|
|
99130
|
-
|
|
99131
|
-
|
|
99132
|
-
|
|
99584
|
+
async function formatScenarioGoldens(scenarioDir) {
|
|
99585
|
+
await execFileAsync(path.join(REPO_ROOT, "node_modules", ".bin", "biome"), [
|
|
99586
|
+
"check",
|
|
99587
|
+
"--write",
|
|
99588
|
+
scenarioDir
|
|
99589
|
+
], { cwd: REPO_ROOT });
|
|
99590
|
+
}
|
|
99591
|
+
const FIRST_FRAME_BUDGET_MS = 3e5;
|
|
99592
|
+
const TURN_SILENCE_BUDGET_MS = 6e4;
|
|
99593
|
+
const KNOWN_SCENARIO_NAMES = new Set(PARITY_SCENARIOS.map((scenario) => scenario.name));
|
|
99594
|
+
const generateParityGoldensOptionsSchema = strictObject$1({ only: array$1(string$5().refine((name) => KNOWN_SCENARIO_NAMES.has(name), { error: `unknown parity scenario; expected one of: ${[...KNOWN_SCENARIO_NAMES].join(", ")}` })) });
|
|
99595
|
+
async function readFinalizedTranscript(sessionId, claudeHomeDir) {
|
|
99596
|
+
const transcriptPath = await findSessionFile(claudeHomeDir, sessionId);
|
|
99597
|
+
if (transcriptPath === null) throw new Error(`[parity] session ${sessionId}: finalized transcript is missing`);
|
|
99598
|
+
return readFile(transcriptPath, "utf-8");
|
|
99599
|
+
}
|
|
99600
|
+
async function readFinalizedHistory(sessionId, claudeHomeDir) {
|
|
99601
|
+
return getSessionMessages(sessionId, { sessionStore: singleSessionStore(sessionId, parseSessionStoreJsonl(await readFinalizedTranscript(sessionId, claudeHomeDir), "throw")) });
|
|
99602
|
+
}
|
|
99603
|
+
function transcriptRowText(row) {
|
|
99604
|
+
const message = row.message;
|
|
99605
|
+
if (typeof message !== "object" || message === null) return "";
|
|
99606
|
+
const content = message.content;
|
|
99607
|
+
if (typeof content === "string") return content;
|
|
99608
|
+
if (!Array.isArray(content)) return "";
|
|
99609
|
+
return content.map((block) => typeof block === "object" && block !== null && "text" in block ? String(block.text ?? "") : "").join("\n");
|
|
99133
99610
|
}
|
|
99134
|
-
|
|
99135
|
-
|
|
99136
|
-
|
|
99137
|
-
|
|
99138
|
-
|
|
99139
|
-
|
|
99140
|
-
|
|
99141
|
-
|
|
99142
|
-
|
|
99143
|
-
|
|
99144
|
-
|
|
99145
|
-
|
|
99146
|
-
|
|
99611
|
+
const INTERRUPT_MARKER = {
|
|
99612
|
+
text: "[Request interrupted by user]",
|
|
99613
|
+
tool: "[Request interrupted by user for tool use]"
|
|
99614
|
+
};
|
|
99615
|
+
function assertInterruptPersisted(scenario, history) {
|
|
99616
|
+
const phases = new Set(scenario.turns.map(turnInterruptPhase).filter((phase) => phase !== void 0));
|
|
99617
|
+
for (const phase of phases) {
|
|
99618
|
+
const marker = INTERRUPT_MARKER[phase];
|
|
99619
|
+
if (!history.some((row) => transcriptRowText(row).includes(marker))) throw new Error(`[parity] scenario "${scenario.name}": declared interrupt:"${phase}" but the captured transcript carries no ${marker} row — the stream aborted without the transcript recording it`);
|
|
99620
|
+
}
|
|
99621
|
+
}
|
|
99622
|
+
function isInterruptTrigger(message, phase) {
|
|
99623
|
+
if (phase === "text") return message.type === "stream_event" && message.event.type === "content_block_delta" && message.event.delta.type === "text_delta";
|
|
99624
|
+
return message.type === "user";
|
|
99625
|
+
}
|
|
99626
|
+
function assertTurnInterruptionOutcome(scenario, turnNumber, result, expectedInterruptPhase) {
|
|
99627
|
+
const where = `[parity] scenario "${scenario.name}" turn ${turnNumber}/${scenario.turns.length}`;
|
|
99628
|
+
if (expectedInterruptPhase === void 0) {
|
|
99629
|
+
if (result.subtype !== "success") throw new Error(`${where} ended with ${result.subtype}: ${result.errors.join("; ")}`);
|
|
99630
|
+
return;
|
|
99147
99631
|
}
|
|
99148
|
-
|
|
99632
|
+
if (result.subtype === "success") throw new Error(`${where} declared interrupt:"${expectedInterruptPhase}" but ended success — the interrupt did not land`);
|
|
99633
|
+
if (result.terminal_reason !== "aborted_streaming" && result.terminal_reason !== "aborted_tools") throw new Error(`${where} declared interrupt:"${expectedInterruptPhase}" but ended ${result.subtype} with terminal_reason ${String(result.terminal_reason)} — that is a failure, not an interrupt`);
|
|
99149
99634
|
}
|
|
99150
|
-
async function
|
|
99635
|
+
async function captureScenarioStream(server, scenario, options) {
|
|
99151
99636
|
const ac = new AbortController();
|
|
99152
99637
|
let iter;
|
|
99153
99638
|
try {
|
|
99154
|
-
const workspaceId = crypto.randomUUID();
|
|
99155
99639
|
const sessionId = crypto.randomUUID();
|
|
99156
|
-
const url = `ws://127.0.0.1:${server.port}/bridge/workspaces/${workspaceId}/sessions/${sessionId}/wss?token=${encodeURIComponent(
|
|
99640
|
+
const url = `ws://127.0.0.1:${server.port}/bridge/workspaces/${options.workspaceId}/sessions/${sessionId}/wss?token=${encodeURIComponent(options.ctxToken)}`;
|
|
99157
99641
|
const queue = [];
|
|
99158
99642
|
let resolveNext = null;
|
|
99159
99643
|
const pushTurn = (text) => {
|
|
99160
|
-
const
|
|
99644
|
+
const message = {
|
|
99161
99645
|
message: {
|
|
99162
99646
|
content: text,
|
|
99163
99647
|
role: "user"
|
|
@@ -99168,8 +99652,8 @@ async function captureScenario(server, scenario, rootDir) {
|
|
|
99168
99652
|
if (resolveNext) {
|
|
99169
99653
|
const resolve = resolveNext;
|
|
99170
99654
|
resolveNext = null;
|
|
99171
|
-
resolve(
|
|
99172
|
-
} else queue.push(
|
|
99655
|
+
resolve(message);
|
|
99656
|
+
} else queue.push(message);
|
|
99173
99657
|
};
|
|
99174
99658
|
async function* promptGen() {
|
|
99175
99659
|
while (true) {
|
|
@@ -99180,27 +99664,33 @@ async function captureScenario(server, scenario, rootDir) {
|
|
|
99180
99664
|
});
|
|
99181
99665
|
}
|
|
99182
99666
|
}
|
|
99183
|
-
|
|
99667
|
+
const claudeQuery = query({
|
|
99184
99668
|
abortController: ac,
|
|
99185
99669
|
prompt: promptGen(),
|
|
99186
99670
|
websocket: { url }
|
|
99187
99671
|
});
|
|
99672
|
+
iter = claudeQuery;
|
|
99188
99673
|
const stream = [];
|
|
99189
|
-
|
|
99190
|
-
let
|
|
99191
|
-
|
|
99192
|
-
|
|
99674
|
+
let expectedInterruptPhase;
|
|
99675
|
+
let interruptFired = false;
|
|
99676
|
+
let sentTurnCount = 0;
|
|
99677
|
+
const sendNextTurn = () => {
|
|
99678
|
+
const turn = scenario.turns[sentTurnCount];
|
|
99193
99679
|
if (turn === void 0) return false;
|
|
99194
|
-
pushTurn(turn);
|
|
99195
|
-
|
|
99680
|
+
pushTurn(turnPrompt(turn));
|
|
99681
|
+
expectedInterruptPhase = turnInterruptPhase(turn);
|
|
99682
|
+
interruptFired = false;
|
|
99683
|
+
sentTurnCount += 1;
|
|
99196
99684
|
return true;
|
|
99197
99685
|
};
|
|
99198
|
-
|
|
99686
|
+
sendNextTurn();
|
|
99199
99687
|
let finished = false;
|
|
99200
99688
|
while (!finished) {
|
|
99689
|
+
const awaitingFirstFrame = stream.length === 0;
|
|
99690
|
+
const budgetMs = awaitingFirstFrame ? FIRST_FRAME_BUDGET_MS : TURN_SILENCE_BUDGET_MS;
|
|
99201
99691
|
let timer;
|
|
99202
99692
|
const stalled = new Promise((_resolve, reject) => {
|
|
99203
|
-
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`[parity] scenario "${scenario.name}": no SDK
|
|
99693
|
+
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(awaitingFirstFrame ? `[parity] scenario "${scenario.name}": no first SDK frame for ${FIRST_FRAME_BUDGET_MS}ms during guest acquisition and boot for turn ${sentTurnCount}/${scenario.turns.length} — a cold OCI image pull is a likely cause` : `[parity] scenario "${scenario.name}": no SDK frame for ${TURN_SILENCE_BUDGET_MS}ms while streaming turn ${sentTurnCount}/${scenario.turns.length} — running turn stalled or emitted no result`)), budgetMs);
|
|
99204
99694
|
});
|
|
99205
99695
|
let next;
|
|
99206
99696
|
try {
|
|
@@ -99208,55 +99698,113 @@ async function captureScenario(server, scenario, rootDir) {
|
|
|
99208
99698
|
} finally {
|
|
99209
99699
|
if (timer) clearTimeout(timer);
|
|
99210
99700
|
}
|
|
99211
|
-
if (next.done)
|
|
99701
|
+
if (next.done) throw new Error(`[parity] scenario "${scenario.name}": SDK stream ended while awaiting turn ${sentTurnCount}/${scenario.turns.length}`);
|
|
99212
99702
|
stream.push(next.value);
|
|
99213
|
-
if (
|
|
99703
|
+
if (expectedInterruptPhase !== void 0 && !interruptFired && isInterruptTrigger(next.value, expectedInterruptPhase)) {
|
|
99704
|
+
interruptFired = true;
|
|
99705
|
+
claudeQuery.interrupt();
|
|
99706
|
+
}
|
|
99707
|
+
if (next.value.type === "result") {
|
|
99708
|
+
assertTurnInterruptionOutcome(scenario, sentTurnCount, next.value, expectedInterruptPhase);
|
|
99709
|
+
if (!sendNextTurn()) finished = true;
|
|
99710
|
+
}
|
|
99214
99711
|
}
|
|
99215
99712
|
return {
|
|
99216
|
-
|
|
99713
|
+
sessionId,
|
|
99217
99714
|
stream
|
|
99218
99715
|
};
|
|
99219
99716
|
} finally {
|
|
99220
|
-
|
|
99221
|
-
|
|
99717
|
+
try {
|
|
99718
|
+
await iter?.return?.(void 0);
|
|
99719
|
+
} finally {
|
|
99720
|
+
ac.abort();
|
|
99721
|
+
}
|
|
99222
99722
|
}
|
|
99223
99723
|
}
|
|
99224
|
-
async function
|
|
99225
|
-
const
|
|
99226
|
-
|
|
99227
|
-
|
|
99228
|
-
|
|
99229
|
-
|
|
99230
|
-
}
|
|
99231
|
-
|
|
99232
|
-
|
|
99233
|
-
|
|
99234
|
-
|
|
99235
|
-
|
|
99236
|
-
scenario
|
|
99237
|
-
})));
|
|
99238
|
-
const server = await createBridgeServer({
|
|
99239
|
-
gitHostBaseDir: env$1.CTX_GIT_HOST_BASE_DIR,
|
|
99240
|
-
hostClaudeJsonPath: env$1.CTXS_HOST_CLAUDE_JSON_PATH,
|
|
99241
|
-
image: env$1.CTXS_CLAUDE_IMAGE,
|
|
99242
|
-
port: 0
|
|
99724
|
+
async function seedChatWorkspace(options) {
|
|
99725
|
+
const workspaceId = await seedWorkspaceViaSdk({
|
|
99726
|
+
claudeToken: options.claudeToken,
|
|
99727
|
+
name: options.name,
|
|
99728
|
+
platformUrl: options.platformUrl,
|
|
99729
|
+
token: options.ctxToken
|
|
99730
|
+
});
|
|
99731
|
+
await pushDocsTree({
|
|
99732
|
+
files: { "README.md": `parity scenario workspace: ${options.name}\n` },
|
|
99733
|
+
platformUrl: options.platformUrl,
|
|
99734
|
+
token: options.ctxToken,
|
|
99735
|
+
workspaceId
|
|
99243
99736
|
});
|
|
99737
|
+
await pushClaudeHome({
|
|
99738
|
+
files: { ".gitkeep": "" },
|
|
99739
|
+
platformUrl: options.platformUrl,
|
|
99740
|
+
token: options.ctxToken,
|
|
99741
|
+
userId: DEV_IDENTITY.sub,
|
|
99742
|
+
workspaceId
|
|
99743
|
+
});
|
|
99744
|
+
return workspaceId;
|
|
99745
|
+
}
|
|
99746
|
+
async function generateParityGoldens(options) {
|
|
99747
|
+
const { only: requestedScenarioNames } = generateParityGoldensOptionsSchema.parse(options);
|
|
99748
|
+
const selectedScenarios = requestedScenarioNames.length > 0 ? PARITY_SCENARIOS.filter((scenario) => requestedScenarioNames.includes(scenario.name)) : PARITY_SCENARIOS;
|
|
99749
|
+
for (const scenario of selectedScenarios) if (scenario.turns.length === 0 || scenario.turns.some((turn) => turnPrompt(turn).trim() === "")) throw new Error(`[parity] scenario "${scenario.name}" has an empty or missing turn`);
|
|
99750
|
+
const goldensDir = resolveGoldensDir();
|
|
99751
|
+
const claudeToken = (await resolveClaudeHostCredential()).token;
|
|
99752
|
+
const ctxToken = mintUnsignedCtxToken(DEV_IDENTITY.sub);
|
|
99753
|
+
const { databaseEnv, dropAll } = await provisionPlatformDatabases();
|
|
99244
99754
|
try {
|
|
99245
|
-
|
|
99246
|
-
|
|
99247
|
-
const
|
|
99248
|
-
|
|
99249
|
-
|
|
99250
|
-
|
|
99251
|
-
|
|
99252
|
-
|
|
99755
|
+
const platform = await bootPlatform(databaseEnv);
|
|
99756
|
+
try {
|
|
99757
|
+
const gitHostBaseDir = await mkdtemp(path.join(os.tmpdir(), "parity-git-host-"));
|
|
99758
|
+
try {
|
|
99759
|
+
for (const scenario of selectedScenarios) {
|
|
99760
|
+
console.log(`[parity] capturing "${scenario.name}" (${scenario.turns.length} turns)…`);
|
|
99761
|
+
const workspaceId = await seedChatWorkspace({
|
|
99762
|
+
claudeToken,
|
|
99763
|
+
ctxToken,
|
|
99764
|
+
name: `parity-${scenario.name}`,
|
|
99765
|
+
platformUrl: platform.platformUrl
|
|
99766
|
+
});
|
|
99767
|
+
const server = await createBridgeServer({
|
|
99768
|
+
gitHostBaseDir,
|
|
99769
|
+
hostClaudeJsonPath: env$1.CTXS_HOST_CLAUDE_JSON_PATH,
|
|
99770
|
+
image: env$1.CTXS_CLAUDE_IMAGE,
|
|
99771
|
+
platformUrl: platform.platformUrl,
|
|
99772
|
+
port: 0,
|
|
99773
|
+
verify: createDevJwtVerifier()
|
|
99774
|
+
});
|
|
99775
|
+
const { sessionId, stream } = await captureScenarioStream(server, scenario, {
|
|
99776
|
+
ctxToken,
|
|
99777
|
+
workspaceId
|
|
99778
|
+
}).finally(() => server.close());
|
|
99779
|
+
const history = await readFinalizedHistory(sessionId, (await resolveRepo({
|
|
99780
|
+
platformUrl: platform.platformUrl,
|
|
99781
|
+
repoId: buildRepoId({
|
|
99782
|
+
kind: "claude",
|
|
99783
|
+
owner: "slate",
|
|
99784
|
+
userId: DEV_IDENTITY.sub,
|
|
99785
|
+
workspaceId
|
|
99786
|
+
}),
|
|
99787
|
+
token: ctxToken
|
|
99788
|
+
}, gitHostBaseDir)).hostDir);
|
|
99789
|
+
assertInterruptPersisted(scenario, history);
|
|
99790
|
+
const scenarioDir = path.join(goldensDir, scenario.name);
|
|
99791
|
+
await mkdir(scenarioDir, { recursive: true });
|
|
99792
|
+
await writeJsonAtomic(path.join(scenarioDir, "stream.json"), stream);
|
|
99793
|
+
await writeJsonAtomic(path.join(scenarioDir, "history.json"), history);
|
|
99794
|
+
await formatScenarioGoldens(scenarioDir);
|
|
99795
|
+
console.log(`[parity] ${scenario.name}: stream=${stream.length} msgs, history=${history.length} rows → ${scenarioDir}`);
|
|
99796
|
+
}
|
|
99797
|
+
} finally {
|
|
99798
|
+
await rm(gitHostBaseDir, {
|
|
99799
|
+
force: true,
|
|
99800
|
+
recursive: true
|
|
99801
|
+
});
|
|
99802
|
+
}
|
|
99803
|
+
} finally {
|
|
99804
|
+
await platform.close();
|
|
99253
99805
|
}
|
|
99254
99806
|
} finally {
|
|
99255
|
-
await
|
|
99256
|
-
await Promise.all(scenarioRoots.map(({ rootDir }) => rm(rootDir, {
|
|
99257
|
-
force: true,
|
|
99258
|
-
recursive: true
|
|
99259
|
-
})));
|
|
99807
|
+
await dropAll();
|
|
99260
99808
|
}
|
|
99261
99809
|
}
|
|
99262
99810
|
|
|
@@ -103177,7 +103725,7 @@ function createProgram() {
|
|
|
103177
103725
|
program.command("bridge").description("Slate bridge commands").command("start").description("Start the slate bridge server in the foreground, bound to localhost on CTXS_BRIDGE_PORT (default 7777). Authenticates each connection's aud=ctx user token and resolves its workspace + credentials from the platform (CTX_WEB_URL verifies the token, CTX_PLATFORM_URL serves the plan + base DSN); serves the render endpoints + the per-session WebSocket that spawns claude inside a microsandbox sandbox. Blocks until SIGINT/SIGTERM.").action(async () => {
|
|
103178
103726
|
await createBridgeServer({});
|
|
103179
103727
|
});
|
|
103180
|
-
program.command("parity").description("Translator parity golden tooling (dev/maintainer)").command("generate [scenarios...]").description("Drive scripted multi-turn conversations through the real bridge + microsandbox + claude and (re)write the parity goldens consumed by slate-shared's parity test. Pass scenario names to capture only those (others keep their existing goldens); omit to regenerate all.
|
|
103728
|
+
program.command("parity").description("Translator parity golden tooling (dev/maintainer)").command("generate [scenarios...]").description("Drive scripted multi-turn conversations through the real bridge + microsandbox + claude and (re)write the parity goldens consumed by slate-shared's parity test. Pass scenario names to capture only those (others keep their existing goldens); omit to regenerate all. Consumes real Claude usage and requires local Claude auth, the microsandbox runtime, a pullable guest image, the host Claude trust file, and local dev Postgres. Never run from a gate.").action(async (scenarios) => {
|
|
103181
103729
|
await generateParityGoldens({ only: scenarios });
|
|
103182
103730
|
});
|
|
103183
103731
|
program.command("sandbox").allowUnknownOption(true).allowExcessArguments(true).argument("[command...]", "Command + args to run in the guest (default: uname -a)").requiredOption("--image <ref>", "Guest image to boot in the microVM").description("Boot a microsandbox microVM from --image, run a command inside it, print its output, and tear it down. A DB-free check that the host can boot guest microVMs (/dev/kvm in a container; HVF on macOS).").action(async (command, options) => {
|
|
@@ -103203,4 +103751,4 @@ runCli().catch((error) => {
|
|
|
103203
103751
|
//#endregion
|
|
103204
103752
|
export { createProgram, runCli };
|
|
103205
103753
|
//# sourceMappingURL=cli.mjs.map
|
|
103206
|
-
//# debugId=
|
|
103754
|
+
//# debugId=3205b84e-0fd0-5843-a715-326779c52b1a
|