@caplets/core 0.23.0 → 0.24.0
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/code-mode.d.ts +3 -0
- package/dist/code-mode/api.d.ts +3 -1
- package/dist/code-mode/diagnostics.d.ts +8 -0
- package/dist/code-mode/index.d.ts +1 -1
- package/dist/code-mode/journal.d.ts +103 -0
- package/dist/code-mode/runner.d.ts +5 -0
- package/dist/code-mode/runtime-api.generated.d.ts +1 -1
- package/dist/code-mode/sandbox.d.ts +14 -1
- package/dist/code-mode/sessions.d.ts +53 -0
- package/dist/code-mode/tool.d.ts +5 -0
- package/dist/code-mode/types.d.ts +30 -0
- package/dist/code-mode.js +3 -1
- package/dist/{completion-BC4BNWo0.js → completion-CzHdM9B_.js} +1 -1
- package/dist/index.js +93 -28
- package/dist/native/options.d.ts +3 -6
- package/dist/native/remote.d.ts +2 -0
- package/dist/native/service.d.ts +1 -0
- package/dist/native/tools.d.ts +1 -0
- package/dist/native.js +1 -1
- package/dist/remote/options.d.ts +1 -1
- package/dist/serve/session.d.ts +1 -0
- package/dist/{service-CSRCJfpA.js → service-BCT_Ls_3.js} +2175 -182
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ import { spawn } from "node:child_process";
|
|
|
9
9
|
import process$1 from "node:process";
|
|
10
10
|
import { PassThrough } from "node:stream";
|
|
11
11
|
import { createServer } from "node:http";
|
|
12
|
-
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
12
|
+
import { createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
13
13
|
import { homedir } from "node:os";
|
|
14
14
|
import { readFile } from "node:fs/promises";
|
|
15
15
|
import ts from "typescript";
|
|
@@ -28269,7 +28269,7 @@ async function writeMediaArtifact(input) {
|
|
|
28269
28269
|
const callId = safePathSegment(input.callId ?? defaultCallId(), "call");
|
|
28270
28270
|
const filename = safeFilename(input.suggestedFilename ?? (input.outputPath ? basename(input.outputPath) : "response.bin"));
|
|
28271
28271
|
const target = input.outputPath ? assertInsideRoot(rootDir, input.outputPath) : assertInsideRoot(rootDir, resolve(rootDir, capletId, callId, filename));
|
|
28272
|
-
rejectSymlinkPathComponents(rootDir, target, true);
|
|
28272
|
+
rejectSymlinkPathComponents$1(rootDir, target, true);
|
|
28273
28273
|
const uriParts = input.outputPath ? uriPartsForOutputPath(rootDir, target) : {
|
|
28274
28274
|
capletId,
|
|
28275
28275
|
callId,
|
|
@@ -28297,7 +28297,7 @@ function resolveMediaArtifact(uri, options = {}) {
|
|
|
28297
28297
|
const parsed = parseArtifactUri(uri);
|
|
28298
28298
|
const rootDir = resolve(options.artifactRoot ?? DEFAULT_ARTIFACT_DIR);
|
|
28299
28299
|
const path = assertInsideRoot(rootDir, resolve(rootDir, parsed.capletId, parsed.callId, parsed.filename));
|
|
28300
|
-
rejectSymlinkPathComponents(rootDir, path, true);
|
|
28300
|
+
rejectSymlinkPathComponents$1(rootDir, path, true);
|
|
28301
28301
|
if (!existsSync(path)) throw new CapletsError("REQUEST_INVALID", "Media artifact was not found");
|
|
28302
28302
|
const stat = statSync(path);
|
|
28303
28303
|
if (!stat.isFile()) throw new CapletsError("REQUEST_INVALID", "Media artifact must resolve to a file");
|
|
@@ -28356,9 +28356,9 @@ function assertInsideRoot(rootDir, candidate) {
|
|
|
28356
28356
|
if (rel.startsWith("..") || isAbsolute(rel)) throw new CapletsError("REQUEST_INVALID", "Media artifact outputPath must stay inside the artifact root");
|
|
28357
28357
|
return resolved;
|
|
28358
28358
|
}
|
|
28359
|
-
function rejectSymlinkPathComponents(rootDir, target, includeTarget) {
|
|
28359
|
+
function rejectSymlinkPathComponents$1(rootDir, target, includeTarget) {
|
|
28360
28360
|
const resolvedRoot = resolve(rootDir);
|
|
28361
|
-
rejectSymlinkRoot(resolvedRoot);
|
|
28361
|
+
rejectSymlinkRoot$1(resolvedRoot);
|
|
28362
28362
|
const parts = relative(resolvedRoot, resolve(target)).split(/[\\/]+/u).filter(Boolean);
|
|
28363
28363
|
let current = resolvedRoot;
|
|
28364
28364
|
const limit = includeTarget ? parts.length : Math.max(0, parts.length - 1);
|
|
@@ -28373,7 +28373,7 @@ function rejectSymlinkPathComponents(rootDir, target, includeTarget) {
|
|
|
28373
28373
|
}
|
|
28374
28374
|
}
|
|
28375
28375
|
}
|
|
28376
|
-
function rejectSymlinkRoot(rootDir) {
|
|
28376
|
+
function rejectSymlinkRoot$1(rootDir) {
|
|
28377
28377
|
try {
|
|
28378
28378
|
if (lstatSync(rootDir).isSymbolicLink()) throw new CapletsError("REQUEST_INVALID", "Media artifact root must not be a symlink");
|
|
28379
28379
|
} catch (error) {
|
|
@@ -63362,7 +63362,7 @@ var CapletsEngine = class {
|
|
|
63362
63362
|
}
|
|
63363
63363
|
}
|
|
63364
63364
|
async completeCliWords(words) {
|
|
63365
|
-
const { completeCliWords } = await import("./completion-
|
|
63365
|
+
const { completeCliWords } = await import("./completion-CzHdM9B_.js").then((n) => n.r);
|
|
63366
63366
|
return await completeCliWords(words, {
|
|
63367
63367
|
config: this.registry.config,
|
|
63368
63368
|
managers: {
|
|
@@ -63670,11 +63670,12 @@ function isRecord$2(value) {
|
|
|
63670
63670
|
}
|
|
63671
63671
|
//#endregion
|
|
63672
63672
|
//#region src/code-mode/runtime-api.generated.ts
|
|
63673
|
-
const CODE_MODE_RUNTIME_API_DECLARATION = "type JsonPrimitive=string|number|boolean|null;type JsonValue=JsonPrimitive|JsonValue[]|{[key:string]:JsonValue};interface CapletHandle<Id extends string>{readonly id:Id;/** Show this Caplet card,without tool/resource/prompt schemas. */ inspect():Promise<CapletCard<Id>>;/** Check backend readiness/auth;expected unavailable states return ok:false. */ check():Promise<CapletsResult<BackendCheckResult>>;/** List tool summaries for the discovery pass;may be empty. */ tools(input?:PageInput):Promise<Page<ToolSummary>>;/** Search tool summaries for the discovery pass;may be empty. */ searchTools(query:string,input?:PageInput):Promise<Page<ToolSummary>>;/** Get schema,callSignature,types,examples;prefer outputSchema/outputTypeScript over observed hints. */ describeTool(name:string):Promise<CapletsResult<ToolDescriptor>>;/** Call one tool;expected failures return ok:false. Filter bulky data in script before returning. */ callTool(name:string,args?:unknown):Promise<CapletsResult<unknown>>;/** List readable resources for the discovery pass;many backends expose none. */ resources(input?:PageInput):Promise<Page<ResourceSummary>>;/** Search readable resources for the discovery pass;many backends expose none. */ searchResources(query:string,input?:PageInput):Promise<Page<ResourceSummary>>;/** List resource templates for the discovery pass;many backends expose none. */ resourceTemplates(input?:PageInput):Promise<Page<ResourceTemplateSummary>>;/** Read one resource by URI;unsupported/missing resources return ok:false. */ readResource(uri:string):Promise<CapletsResult<ResourceReadResult>>;/** List reusable prompts for the discovery pass;many backends expose none. */ prompts(input?:PageInput):Promise<Page<PromptSummary>>;/** Search reusable prompts for the discovery pass;many backends expose none. */ searchPrompts(query:string,input?:PageInput):Promise<Page<PromptSummary>>;/** Get one prompt by name and args;unsupported/missing prompts return ok:false. */ getPrompt(name:string,args?:unknown):Promise<CapletsResult<PromptResult>>;/** Complete a prompt or resource-template argument. */ complete(input:CompleteInput):Promise<CapletsResult<CompleteResult>>;}interface DebugApi{readLogs(input:ReadLogsInput):Promise<ReadLogsResult>;}type CapletCard<Id extends string>={id:Id;name:string;description:string;useWhen?:string;avoidWhen?:string;tags?:string[];backend?:unknown;};type PageInput={limit?:number;cursor?:string};type Page<T>={items:T[];nextCursor?:string;truncated?:boolean};type CapletsResult<T>=|{ok:true;data:T;meta?:CapletsMeta}|{ok:false;error:CapletsError;meta?:CapletsMeta};type CapletsMeta={[key:string]:unknown};type CapletsError={code:string;message:string;details?:unknown};type BackendCheckResult=unknown;type ToolSummary={/** Exact downstream tool identifier for describeTool(name)and callTool(name,args). */ name:string;title?:string;description?:string;/** Optional author-supplied hint for when to prefer this tool. */ useWhen?:string;/** Optional author-supplied hint for when to avoid this tool. */ avoidWhen?:string;/** True when the tool declares that it only reads data. */ readOnlyHint?:boolean;/** True when the tool declares that it may perform destructive writes. */ destructiveHint?:boolean;};type ToolDescriptor={id?:string;tool?:unknown;inputSchema?:unknown;outputSchema?:unknown;callSignature?:string;inputTypeScript?:string;outputTypeScript?:string;observedOutputShape?:ObservedOutputShape;examples?:unknown[];};type ObservedOutputShape={version:1;source:\"observed\";observedAt:string;sampleCount:number;typeScript:string;jsonShape:JsonShape;truncated:boolean;};type JsonShape=|{kind:\"null\"}|{kind:\"boolean\"}|{kind:\"number\"}|{kind:\"string\"}|{kind:\"unknown\"}|{kind:\"array\";element?:JsonShape;truncated?:boolean}|{kind:\"object\";fields:Record<string,{optional:boolean;shape:JsonShape}>;truncated?:boolean;}|{kind:\"union\";variants:JsonShape[]};type ResourceSummary={uri?:string;name?:string;title?:string;description?:string};type ResourceTemplateSummary={uriTemplate?:string;name?:string;title?:string;description?:string;};type ResourceReadResult=unknown;type PromptSummary={name?:string;title?:string;description?:string};type PromptResult=unknown;type CompleteInput={ref:{type:\"prompt\";name:string}|{type:\"resourceTemplate\";uri:string};argument:{name:string;value:string};};type CompleteResult=unknown;type ReadLogsInput={logRef:string;cursor?:string;limit?:number};type ReadLogsResult={entries:CodeModeLogEntry[];nextCursor?:string};type CodeModeLogEntry={level:\"log\"|\"info\"|\"warn\"|\"error\"|\"debug\";message:string;timestamp:string;};interface Console{log(...values:unknown[]):void;info(...values:unknown[]):void;warn(...values:unknown[]):void;error(...values:unknown[]):void;debug(...values:unknown[]):void;}declare const console:Console;";
|
|
63673
|
+
const CODE_MODE_RUNTIME_API_DECLARATION = "type JsonPrimitive=string|number|boolean|null;type JsonValue=JsonPrimitive|JsonValue[]|{[key:string]:JsonValue};interface CapletHandle<Id extends string>{readonly id:Id;/** Show this Caplet card,without tool/resource/prompt schemas. */ inspect():Promise<CapletCard<Id>>;/** Check backend readiness/auth;expected unavailable states return ok:false. */ check():Promise<CapletsResult<BackendCheckResult>>;/** List tool summaries for the discovery pass;may be empty. */ tools(input?:PageInput):Promise<Page<ToolSummary>>;/** Search tool summaries for the discovery pass;may be empty. */ searchTools(query:string,input?:PageInput):Promise<Page<ToolSummary>>;/** Get schema,callSignature,types,examples;prefer outputSchema/outputTypeScript over observed hints. */ describeTool(name:string):Promise<CapletsResult<ToolDescriptor>>;/** Call one tool;expected failures return ok:false. Filter bulky data in script before returning. */ callTool(name:string,args?:unknown):Promise<CapletsResult<unknown>>;/** List readable resources for the discovery pass;many backends expose none. */ resources(input?:PageInput):Promise<Page<ResourceSummary>>;/** Search readable resources for the discovery pass;many backends expose none. */ searchResources(query:string,input?:PageInput):Promise<Page<ResourceSummary>>;/** List resource templates for the discovery pass;many backends expose none. */ resourceTemplates(input?:PageInput):Promise<Page<ResourceTemplateSummary>>;/** Read one resource by URI;unsupported/missing resources return ok:false. */ readResource(uri:string):Promise<CapletsResult<ResourceReadResult>>;/** List reusable prompts for the discovery pass;many backends expose none. */ prompts(input?:PageInput):Promise<Page<PromptSummary>>;/** Search reusable prompts for the discovery pass;many backends expose none. */ searchPrompts(query:string,input?:PageInput):Promise<Page<PromptSummary>>;/** Get one prompt by name and args;unsupported/missing prompts return ok:false. */ getPrompt(name:string,args?:unknown):Promise<CapletsResult<PromptResult>>;/** Complete a prompt or resource-template argument. */ complete(input:CompleteInput):Promise<CapletsResult<CompleteResult>>;}interface DebugApi{readLogs(input:ReadLogsInput):Promise<ReadLogsResult>;readRecovery(input:ReadCodeModeRecoveryInput):Promise<ReadCodeModeRecoveryResult>;}type CapletCard<Id extends string>={id:Id;name:string;description:string;useWhen?:string;avoidWhen?:string;tags?:string[];backend?:unknown;};type PageInput={limit?:number;cursor?:string};type Page<T>={items:T[];nextCursor?:string;truncated?:boolean};type CapletsResult<T>=|{ok:true;data:T;meta?:CapletsMeta}|{ok:false;error:CapletsError;meta?:CapletsMeta};type CapletsMeta={[key:string]:unknown};type CapletsError={code:string;message:string;details?:unknown};type BackendCheckResult=unknown;type ToolSummary={/** Exact downstream tool identifier for describeTool(name)and callTool(name,args). */ name:string;title?:string;description?:string;/** Optional author-supplied hint for when to prefer this tool. */ useWhen?:string;/** Optional author-supplied hint for when to avoid this tool. */ avoidWhen?:string;/** True when the tool declares that it only reads data. */ readOnlyHint?:boolean;/** True when the tool declares that it may perform destructive writes. */ destructiveHint?:boolean;};type ToolDescriptor={id?:string;tool?:unknown;inputSchema?:unknown;outputSchema?:unknown;callSignature?:string;inputTypeScript?:string;outputTypeScript?:string;observedOutputShape?:ObservedOutputShape;examples?:unknown[];};type ObservedOutputShape={version:1;source:\"observed\";observedAt:string;sampleCount:number;typeScript:string;jsonShape:JsonShape;truncated:boolean;};type JsonShape=|{kind:\"null\"}|{kind:\"boolean\"}|{kind:\"number\"}|{kind:\"string\"}|{kind:\"unknown\"}|{kind:\"array\";element?:JsonShape;truncated?:boolean}|{kind:\"object\";fields:Record<string,{optional:boolean;shape:JsonShape}>;truncated?:boolean;}|{kind:\"union\";variants:JsonShape[]};type ResourceSummary={uri?:string;name?:string;title?:string;description?:string};type ResourceTemplateSummary={uriTemplate?:string;name?:string;title?:string;description?:string;};type ResourceReadResult=unknown;type PromptSummary={name?:string;title?:string;description?:string};type PromptResult=unknown;type CompleteInput={ref:{type:\"prompt\";name:string}|{type:\"resourceTemplate\";uri:string};argument:{name:string;value:string};};type CompleteResult=unknown;type ReadLogsInput={logRef:string;cursor?:string;limit?:number};type ReadLogsResult={entries:CodeModeLogEntry[];nextCursor?:string};type ReadCodeModeRecoveryInput={recoveryRef:string;cursor?:string;limit?:number};type CodeModeDiagnostic={code:string;message:string;severity:\"error\"|\"warning\"|\"info\";line?:number;column?:number;};type CodeModeRecoveryClassification=\"setup_like\"|\"side_effecting\"|\"unknown\";type CodeModeRecoveryEntry={timestamp:string;code:string;declarationHash:string;outcome:{ok:true}|{ok:false;code:string;message:string};diagnostics:Array<Pick<CodeModeDiagnostic,\"code\"|\"severity\"|\"message\">>;recoveryClassification:CodeModeRecoveryClassification;logsStored?:boolean;summary?:string;};type ReadCodeModeRecoveryResult={entries:CodeModeRecoveryEntry[];nextCursor?:string};type CodeModeLogEntry={level:\"log\"|\"info\"|\"warn\"|\"error\"|\"debug\";message:string;timestamp:string;};type CodeModeSessionStatus=\"created\"|\"reused\";type CodeModeRunMeta={runId:string;traceId:string;declarationHash:string;durationMs:number;timeoutMs:number;maxTimeoutMs:number;sessionId?:string|null;sessionStatus?:CodeModeSessionStatus|null;recoveryRef?:string|null;};interface Console{log(...values:unknown[]):void;info(...values:unknown[]):void;warn(...values:unknown[]):void;error(...values:unknown[]):void;debug(...values:unknown[]):void;}declare const console:Console;";
|
|
63674
63674
|
//#endregion
|
|
63675
63675
|
//#region src/code-mode/declarations.ts
|
|
63676
63676
|
const JS_IDENTIFIER = /^[A-Za-z_$][\w$]*$/u;
|
|
63677
63677
|
const MAX_JSDOC_CHARS = 180;
|
|
63678
|
+
const CODE_MODE_REPL_GUIDANCE = "REPL reuse: omit `sessionId` to start a fresh reusable Code Mode session; after a successful run, keep `meta.sessionId` and pass it as `sessionId` on later calls when you want to reuse live state. Reused sessions preserve successful top-level `var` bindings, function declarations, and runtime state only while the live session remains available and compatible. A supplied `sessionId` that is unknown or no longer available fails before executing your code instead of starting an empty context. Use `meta.recoveryRef` with `caplets.debug.readRecovery({ recoveryRef })` for audit and manual reconstruction; do not automatically replay recovery history.";
|
|
63678
63679
|
function generateCodeModeDeclarations(input) {
|
|
63679
63680
|
const caplets = [...input.caplets].sort((left, right) => left.id.localeCompare(right.id));
|
|
63680
63681
|
const properties = caplets.map((caplet) => {
|
|
@@ -63694,6 +63695,7 @@ function generateCodeModeDeclarations(input) {
|
|
|
63694
63695
|
function generateCodeModeRunToolDescription(declaration) {
|
|
63695
63696
|
return [
|
|
63696
63697
|
"Run TypeScript with generated `caplets.<id>` handles and declaration hints below. Prefer a compact one-pass script for most tasks: discover, filter, execute, and synthesize inside Code Mode, then return only decision-ready JSON. Do not return full tool lists, full descriptors, schemas, raw tool payloads, or exploratory transcripts unless the user specifically needs them; keep bulky intermediate data inside the script. For discovery, use tools/searchTools for names and arg hints, then describeTool only for short-listed operations needing exact schemas, nested args, fields, or disambiguation. Never invent tool names, resource URIs, prompt names, input args, output fields, or schemas; use requiredArgs/acceptedArgs for simple calls, otherwise use describeTool for the exact callSignature/inputSchema/inputTypeScript. For fallback, check candidate handles first: `for(const h of candidates){const ready=await h.check();if(!ready.ok)continue;}`. For triage, list broad candidate records and filter in script before targeted searches so adjacent relevant items are not missed. Execute with exact args, handle `{ok:false}`, and derive final recommendations from all relevant records, not the first matching record. If records disagree or have ranges/statuses, compute the strictest applicable conclusion and preserve only the compact evidence used. Return summaries, key ids/names/titles/statuses/urls, derived fields, recommendation, caveats, and residual missing data. Before returning, remove unused descriptors/schemas/raw content. Pattern: `const h=caplets[\"caplet-id\"];const tools=await h.searchTools(\"query\");const d=needSchema?await h.describeTool(\"tool_name\"):undefined;const r=await h.callTool(\"tool_name\",args);return {facts:[...],evidence:[...]};`",
|
|
63698
|
+
CODE_MODE_REPL_GUIDANCE,
|
|
63697
63699
|
"",
|
|
63698
63700
|
"Generated declaration hints:",
|
|
63699
63701
|
"```ts",
|
|
@@ -63756,8 +63758,8 @@ function fnv1a32(value, seed) {
|
|
|
63756
63758
|
//#endregion
|
|
63757
63759
|
//#region src/code-mode/logs.ts
|
|
63758
63760
|
const DEFAULT_LOG_REF_TTL_MS = 3600 * 1e3;
|
|
63759
|
-
const DEFAULT_PAGE_LIMIT = 100;
|
|
63760
|
-
const MAX_PAGE_LIMIT = 500;
|
|
63761
|
+
const DEFAULT_PAGE_LIMIT$1 = 100;
|
|
63762
|
+
const MAX_PAGE_LIMIT$1 = 500;
|
|
63761
63763
|
const SECRET_KEY_VALUE_PATTERN = /\b(?:authorization|cookie|set-cookie|password|passphrase|secret|token|api[-_]?key|clientsecret|client_secret|privatekey|private_key|credential|refreshToken|accessToken)\b\s*[:=]\s*([^\s,;]+)/giu;
|
|
63762
63764
|
const BEARER_PATTERN = /\bbearer\s+([a-z0-9._~+/=-]{8,})/giu;
|
|
63763
63765
|
const BASIC_PATTERN = /\bbasic\s+([a-z0-9._~+/=-]{8,})/giu;
|
|
@@ -63798,8 +63800,8 @@ var CodeModeLogStore = class {
|
|
|
63798
63800
|
if (!existsSync(path)) return { entries: [] };
|
|
63799
63801
|
const parsed = parseStoredLogs(readFileSync(path, "utf8"));
|
|
63800
63802
|
if (!parsed || new Date(parsed.expiresAt).getTime() <= this.now().getTime()) return { entries: [] };
|
|
63801
|
-
const offset = parseCursor(input.cursor);
|
|
63802
|
-
const limit = Math.min(Math.max(input.limit ?? DEFAULT_PAGE_LIMIT, 0), MAX_PAGE_LIMIT);
|
|
63803
|
+
const offset = parseCursor$1(input.cursor);
|
|
63804
|
+
const limit = Math.min(Math.max(input.limit ?? DEFAULT_PAGE_LIMIT$1, 0), MAX_PAGE_LIMIT$1);
|
|
63803
63805
|
const entries = parsed.entries.slice(offset, offset + limit).map(redactEntry);
|
|
63804
63806
|
const nextOffset = offset + entries.length;
|
|
63805
63807
|
return nextOffset < parsed.entries.length ? {
|
|
@@ -63823,7 +63825,7 @@ function redactEntry(entry) {
|
|
|
63823
63825
|
message: redactCodeModeLogText(entry.message)
|
|
63824
63826
|
};
|
|
63825
63827
|
}
|
|
63826
|
-
function parseCursor(cursor) {
|
|
63828
|
+
function parseCursor$1(cursor) {
|
|
63827
63829
|
if (!cursor) return 0;
|
|
63828
63830
|
const parsed = Number.parseInt(cursor, 10);
|
|
63829
63831
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
@@ -63847,6 +63849,373 @@ function isLogEntry(value) {
|
|
|
63847
63849
|
return (entry.level === "log" || entry.level === "info" || entry.level === "warn" || entry.level === "error" || entry.level === "debug") && typeof entry.message === "string" && typeof entry.timestamp === "string";
|
|
63848
63850
|
}
|
|
63849
63851
|
//#endregion
|
|
63852
|
+
//#region src/code-mode/journal.ts
|
|
63853
|
+
const DEFAULT_JOURNAL_RETENTION_MS = 10080 * 60 * 1e3;
|
|
63854
|
+
const DEFAULT_MAX_ENTRIES = 100;
|
|
63855
|
+
const DEFAULT_MAX_CODE_BYTES = 64 * 1024;
|
|
63856
|
+
const DEFAULT_MAX_SUMMARY_BYTES = 16 * 1024;
|
|
63857
|
+
const DEFAULT_PAGE_LIMIT = 25;
|
|
63858
|
+
const MAX_PAGE_LIMIT = 100;
|
|
63859
|
+
const JOURNAL_VERSION = 1;
|
|
63860
|
+
var CodeModeJournalStore = class {
|
|
63861
|
+
stateDir;
|
|
63862
|
+
now;
|
|
63863
|
+
retentionMs;
|
|
63864
|
+
maxEntries;
|
|
63865
|
+
maxCodeBytes;
|
|
63866
|
+
maxSummaryBytes;
|
|
63867
|
+
configuredSecret;
|
|
63868
|
+
secret;
|
|
63869
|
+
recoveryRefs = /* @__PURE__ */ new Map();
|
|
63870
|
+
sessionRecoveryRefs = /* @__PURE__ */ new Map();
|
|
63871
|
+
nextPruneAt = 0;
|
|
63872
|
+
constructor(options = {}) {
|
|
63873
|
+
this.stateDir = options.stateDir ?? join(defaultStateBaseDir(), "caplets");
|
|
63874
|
+
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
63875
|
+
this.retentionMs = options.retentionMs ?? DEFAULT_JOURNAL_RETENTION_MS;
|
|
63876
|
+
this.maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
63877
|
+
this.maxCodeBytes = options.maxCodeBytes ?? DEFAULT_MAX_CODE_BYTES;
|
|
63878
|
+
this.maxSummaryBytes = options.maxSummaryBytes ?? DEFAULT_MAX_SUMMARY_BYTES;
|
|
63879
|
+
this.configuredSecret = options.secret;
|
|
63880
|
+
}
|
|
63881
|
+
async store(input) {
|
|
63882
|
+
this.ensureJournalDir();
|
|
63883
|
+
this.pruneExpired();
|
|
63884
|
+
const now = this.now();
|
|
63885
|
+
const expiresAt = new Date(now.getTime() + this.retentionMs).toISOString();
|
|
63886
|
+
const journalKey = this.journalKey(input.sessionId, input.journalScope);
|
|
63887
|
+
const recoveryRef = this.recoveryRefs.get(journalKey) ?? this.recoveryRefForJournalKey(journalKey);
|
|
63888
|
+
this.recoveryRefs.set(journalKey, recoveryRef);
|
|
63889
|
+
this.sessionRecoveryRefs.set(input.sessionId, {
|
|
63890
|
+
recoveryRef,
|
|
63891
|
+
expiresAt
|
|
63892
|
+
});
|
|
63893
|
+
const recoveryRefHash = this.recoveryRefHash(recoveryRef);
|
|
63894
|
+
const path = this.journalPath(journalKey);
|
|
63895
|
+
const existing = this.readJournalPath(path);
|
|
63896
|
+
const entry = this.entryFromInput(input, now, recoveryRef);
|
|
63897
|
+
const stored = {
|
|
63898
|
+
version: JOURNAL_VERSION,
|
|
63899
|
+
journalKey,
|
|
63900
|
+
sessionIdHash: this.sessionIdHash(input.sessionId),
|
|
63901
|
+
recoveryRefHashes: [...new Set([...existing?.recoveryRefHashes ?? [], recoveryRefHash])],
|
|
63902
|
+
createdAt: existing?.createdAt ?? now.toISOString(),
|
|
63903
|
+
updatedAt: now.toISOString(),
|
|
63904
|
+
expiresAt,
|
|
63905
|
+
entries: [...existing?.entries ?? [], entry].slice(-this.maxEntries)
|
|
63906
|
+
};
|
|
63907
|
+
this.writeJournal(path, stored);
|
|
63908
|
+
this.writeIndex(this.recoveryIndexPath(recoveryRefHash), stored);
|
|
63909
|
+
this.writeIndex(this.sessionIndexPath(stored.sessionIdHash), stored);
|
|
63910
|
+
return {
|
|
63911
|
+
recoveryRef,
|
|
63912
|
+
expiresAt,
|
|
63913
|
+
journalKey
|
|
63914
|
+
};
|
|
63915
|
+
}
|
|
63916
|
+
async lookupSession(sessionId) {
|
|
63917
|
+
this.ensureJournalDir();
|
|
63918
|
+
this.pruneExpired();
|
|
63919
|
+
const retained = this.sessionRecoveryRefs.get(sessionId);
|
|
63920
|
+
if (retained && new Date(retained.expiresAt).getTime() > this.now().getTime()) return retained;
|
|
63921
|
+
const scopedJournal = this.findBySessionIdHash(this.sessionIdHash(sessionId));
|
|
63922
|
+
if (scopedJournal && !this.isExpired(scopedJournal)) return {
|
|
63923
|
+
expiresAt: scopedJournal.expiresAt,
|
|
63924
|
+
recoveryRef: this.recoveryRefForJournalKey(scopedJournal.journalKey)
|
|
63925
|
+
};
|
|
63926
|
+
const journal = this.readJournalPath(this.journalPath(this.journalKey(sessionId)));
|
|
63927
|
+
if (!journal || this.isExpired(journal)) return void 0;
|
|
63928
|
+
return { expiresAt: journal.expiresAt };
|
|
63929
|
+
}
|
|
63930
|
+
async lookupRecoveryRef(recoveryRef) {
|
|
63931
|
+
if (!isRecoveryRef(recoveryRef)) return void 0;
|
|
63932
|
+
this.ensureJournalDir();
|
|
63933
|
+
this.pruneExpired();
|
|
63934
|
+
const journal = this.findByRecoveryRefHash(this.recoveryRefHash(recoveryRef));
|
|
63935
|
+
if (!journal || this.isExpired(journal)) return void 0;
|
|
63936
|
+
return { expiresAt: journal.expiresAt };
|
|
63937
|
+
}
|
|
63938
|
+
async readRecovery(input) {
|
|
63939
|
+
if (!isRecoveryRef(input.recoveryRef)) return { entries: [] };
|
|
63940
|
+
this.ensureJournalDir();
|
|
63941
|
+
this.pruneExpired();
|
|
63942
|
+
const recoveryRefHash = this.recoveryRefHash(input.recoveryRef);
|
|
63943
|
+
const journal = this.findByRecoveryRefHash(recoveryRefHash);
|
|
63944
|
+
if (!journal || this.isExpired(journal)) return { entries: [] };
|
|
63945
|
+
const offset = parseCursor(input.cursor);
|
|
63946
|
+
if (input.limit !== void 0 && input.limit <= 0) return { entries: [] };
|
|
63947
|
+
const limit = Math.min(Math.max(input.limit ?? DEFAULT_PAGE_LIMIT, 0), MAX_PAGE_LIMIT);
|
|
63948
|
+
const entries = journal.entries.slice(offset, offset + limit);
|
|
63949
|
+
const nextOffset = offset + entries.length;
|
|
63950
|
+
return nextOffset < journal.entries.length ? {
|
|
63951
|
+
entries,
|
|
63952
|
+
nextCursor: String(nextOffset)
|
|
63953
|
+
} : { entries };
|
|
63954
|
+
}
|
|
63955
|
+
entryFromInput(input, now, recoveryRef) {
|
|
63956
|
+
const exactSecrets = [
|
|
63957
|
+
input.sessionId,
|
|
63958
|
+
recoveryRef,
|
|
63959
|
+
input.logRef
|
|
63960
|
+
].filter((value) => Boolean(value));
|
|
63961
|
+
return {
|
|
63962
|
+
timestamp: now.toISOString(),
|
|
63963
|
+
code: truncateUtf8(redactJournalText(input.code, exactSecrets), this.maxCodeBytes),
|
|
63964
|
+
declarationHash: input.declarationHash,
|
|
63965
|
+
outcome: input.outcome.ok === true ? { ok: true } : {
|
|
63966
|
+
ok: false,
|
|
63967
|
+
code: input.outcome.code,
|
|
63968
|
+
message: truncateUtf8(redactJournalText(input.outcome.message, exactSecrets), 2e3)
|
|
63969
|
+
},
|
|
63970
|
+
diagnostics: input.diagnostics.map((diagnostic) => ({
|
|
63971
|
+
code: diagnostic.code,
|
|
63972
|
+
severity: diagnostic.severity,
|
|
63973
|
+
message: truncateUtf8(redactJournalText(diagnostic.message, exactSecrets), 2e3)
|
|
63974
|
+
})),
|
|
63975
|
+
recoveryClassification: input.recoveryClassification,
|
|
63976
|
+
...input.logRef ? { logsStored: true } : {},
|
|
63977
|
+
...input.summary ? { summary: truncateUtf8(redactJournalText(input.summary, exactSecrets), this.maxSummaryBytes) } : {}
|
|
63978
|
+
};
|
|
63979
|
+
}
|
|
63980
|
+
findByRecoveryRefHash(recoveryRefHash) {
|
|
63981
|
+
const indexed = this.readIndexPath(this.recoveryIndexPath(recoveryRefHash));
|
|
63982
|
+
if (indexed) return this.readJournalPath(this.journalPath(indexed.journalKey));
|
|
63983
|
+
return this.findByRecoveryRefHashSlow(recoveryRefHash);
|
|
63984
|
+
}
|
|
63985
|
+
findBySessionIdHash(sessionIdHash) {
|
|
63986
|
+
const indexed = this.readIndexPath(this.sessionIndexPath(sessionIdHash));
|
|
63987
|
+
if (indexed) return this.readJournalPath(this.journalPath(indexed.journalKey));
|
|
63988
|
+
return this.findBySessionIdHashSlow(sessionIdHash);
|
|
63989
|
+
}
|
|
63990
|
+
findByRecoveryRefHashSlow(recoveryRefHash) {
|
|
63991
|
+
for (const filename of readdirSync(this.journalDir())) {
|
|
63992
|
+
if (!filename.endsWith(".json")) continue;
|
|
63993
|
+
const journal = this.readJournalPath(join(this.journalDir(), filename));
|
|
63994
|
+
if (journal?.recoveryRefHashes.includes(recoveryRefHash)) return journal;
|
|
63995
|
+
}
|
|
63996
|
+
}
|
|
63997
|
+
findBySessionIdHashSlow(sessionIdHash) {
|
|
63998
|
+
const journals = [];
|
|
63999
|
+
for (const filename of readdirSync(this.journalDir())) {
|
|
64000
|
+
if (!filename.endsWith(".json")) continue;
|
|
64001
|
+
const journal = this.readJournalPath(join(this.journalDir(), filename));
|
|
64002
|
+
if (journal?.sessionIdHash === sessionIdHash) journals.push(journal);
|
|
64003
|
+
}
|
|
64004
|
+
return journals.sort((left, right) => new Date(right.updatedAt).getTime() - new Date(left.updatedAt).getTime())[0];
|
|
64005
|
+
}
|
|
64006
|
+
writeIndex(path, journal) {
|
|
64007
|
+
const index = {
|
|
64008
|
+
version: JOURNAL_VERSION,
|
|
64009
|
+
journalKey: journal.journalKey,
|
|
64010
|
+
updatedAt: journal.updatedAt
|
|
64011
|
+
};
|
|
64012
|
+
rejectSymlinkPathComponents(this.journalDir(), path, true);
|
|
64013
|
+
mkdirSync(dirname(path), {
|
|
64014
|
+
recursive: true,
|
|
64015
|
+
mode: 448
|
|
64016
|
+
});
|
|
64017
|
+
chmodSync(dirname(path), 448);
|
|
64018
|
+
const tempPath = `${path}.${randomBytes(8).toString("hex")}.tmp`;
|
|
64019
|
+
writeFileSync(tempPath, `${JSON.stringify(index, null, 2)}\n`, { mode: 384 });
|
|
64020
|
+
chmodSync(tempPath, 384);
|
|
64021
|
+
renameSync(tempPath, path);
|
|
64022
|
+
chmodSync(path, 384);
|
|
64023
|
+
}
|
|
64024
|
+
readIndexPath(path) {
|
|
64025
|
+
try {
|
|
64026
|
+
rejectSymlinkPathComponents(this.journalDir(), path, true);
|
|
64027
|
+
if (!existsSync(path)) return void 0;
|
|
64028
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
64029
|
+
if (parsed.version !== JOURNAL_VERSION || typeof parsed.journalKey !== "string" || typeof parsed.updatedAt !== "string") return;
|
|
64030
|
+
return {
|
|
64031
|
+
version: JOURNAL_VERSION,
|
|
64032
|
+
journalKey: parsed.journalKey,
|
|
64033
|
+
updatedAt: parsed.updatedAt
|
|
64034
|
+
};
|
|
64035
|
+
} catch {
|
|
64036
|
+
return;
|
|
64037
|
+
}
|
|
64038
|
+
}
|
|
64039
|
+
readJournalPath(path) {
|
|
64040
|
+
try {
|
|
64041
|
+
rejectSymlinkPathComponents(this.journalDir(), path, true);
|
|
64042
|
+
if (!existsSync(path)) return void 0;
|
|
64043
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
64044
|
+
if (parsed.version !== JOURNAL_VERSION || typeof parsed.journalKey !== "string" || !Array.isArray(parsed.recoveryRefHashes) || typeof parsed.createdAt !== "string" || typeof parsed.updatedAt !== "string" || typeof parsed.expiresAt !== "string" || !Array.isArray(parsed.entries)) return;
|
|
64045
|
+
return {
|
|
64046
|
+
version: JOURNAL_VERSION,
|
|
64047
|
+
journalKey: parsed.journalKey,
|
|
64048
|
+
...typeof parsed.sessionIdHash === "string" ? { sessionIdHash: parsed.sessionIdHash } : {},
|
|
64049
|
+
recoveryRefHashes: parsed.recoveryRefHashes.filter((hash) => typeof hash === "string"),
|
|
64050
|
+
createdAt: parsed.createdAt,
|
|
64051
|
+
updatedAt: parsed.updatedAt,
|
|
64052
|
+
expiresAt: parsed.expiresAt,
|
|
64053
|
+
entries: parsed.entries.filter(isJournalEntry)
|
|
64054
|
+
};
|
|
64055
|
+
} catch {
|
|
64056
|
+
return;
|
|
64057
|
+
}
|
|
64058
|
+
}
|
|
64059
|
+
writeJournal(path, journal) {
|
|
64060
|
+
rejectSymlinkPathComponents(this.journalDir(), path, true);
|
|
64061
|
+
mkdirSync(dirname(path), {
|
|
64062
|
+
recursive: true,
|
|
64063
|
+
mode: 448
|
|
64064
|
+
});
|
|
64065
|
+
chmodSync(dirname(path), 448);
|
|
64066
|
+
const tempPath = `${path}.${randomBytes(8).toString("hex")}.tmp`;
|
|
64067
|
+
writeFileSync(tempPath, `${JSON.stringify(journal, null, 2)}\n`, { mode: 384 });
|
|
64068
|
+
chmodSync(tempPath, 384);
|
|
64069
|
+
renameSync(tempPath, path);
|
|
64070
|
+
chmodSync(path, 384);
|
|
64071
|
+
}
|
|
64072
|
+
pruneExpired() {
|
|
64073
|
+
const dir = this.journalDir();
|
|
64074
|
+
if (!existsSync(dir)) return;
|
|
64075
|
+
const now = this.now().getTime();
|
|
64076
|
+
if (now < this.nextPruneAt) return;
|
|
64077
|
+
this.nextPruneAt = now + 6e4;
|
|
64078
|
+
for (const filename of readdirSync(dir)) {
|
|
64079
|
+
if (!filename.endsWith(".json")) continue;
|
|
64080
|
+
const path = join(dir, filename);
|
|
64081
|
+
const journal = this.readJournalPath(path);
|
|
64082
|
+
if (!journal || this.isExpired(journal)) rmSync(path, { force: true });
|
|
64083
|
+
}
|
|
64084
|
+
}
|
|
64085
|
+
isExpired(journal) {
|
|
64086
|
+
return new Date(journal.expiresAt).getTime() <= this.now().getTime();
|
|
64087
|
+
}
|
|
64088
|
+
journalKey(sessionId, journalScope = "default") {
|
|
64089
|
+
return this.hmac(`journal:${sessionId}:${journalScope}`);
|
|
64090
|
+
}
|
|
64091
|
+
recoveryRefHash(recoveryRef) {
|
|
64092
|
+
return this.hmac(`recovery-ref:${recoveryRef}`);
|
|
64093
|
+
}
|
|
64094
|
+
recoveryRefForJournalKey(journalKey) {
|
|
64095
|
+
return this.hmac(`recovery-ref-material:${journalKey}`).slice(0, 48);
|
|
64096
|
+
}
|
|
64097
|
+
sessionIdHash(sessionId) {
|
|
64098
|
+
return this.hmac(`session-id:${sessionId}`);
|
|
64099
|
+
}
|
|
64100
|
+
hmac(value) {
|
|
64101
|
+
return createHmac("sha256", this.loadSecret()).update(value).digest("hex");
|
|
64102
|
+
}
|
|
64103
|
+
loadSecret() {
|
|
64104
|
+
if (this.configuredSecret) return this.configuredSecret;
|
|
64105
|
+
if (this.secret) return this.secret;
|
|
64106
|
+
this.ensureJournalDir();
|
|
64107
|
+
const path = this.secretPath();
|
|
64108
|
+
rejectSymlinkPathComponents(this.journalDir(), path, true);
|
|
64109
|
+
if (existsSync(path)) {
|
|
64110
|
+
this.secret = readFileSync(path, "utf8").trim();
|
|
64111
|
+
return this.secret;
|
|
64112
|
+
}
|
|
64113
|
+
this.secret = randomBytes(32).toString("hex");
|
|
64114
|
+
writeFileSync(path, `${this.secret}\n`, { mode: 384 });
|
|
64115
|
+
chmodSync(path, 384);
|
|
64116
|
+
return this.secret;
|
|
64117
|
+
}
|
|
64118
|
+
ensureJournalDir() {
|
|
64119
|
+
const dir = this.journalDir();
|
|
64120
|
+
rejectSymlinkRoot(resolve(this.stateDir));
|
|
64121
|
+
rejectSymlinkPathComponents(resolve(this.stateDir), dir, true);
|
|
64122
|
+
mkdirSync(dir, {
|
|
64123
|
+
recursive: true,
|
|
64124
|
+
mode: 448
|
|
64125
|
+
});
|
|
64126
|
+
rejectSymlinkPathComponents(resolve(this.stateDir), dir, true);
|
|
64127
|
+
chmodSync(dir, 448);
|
|
64128
|
+
}
|
|
64129
|
+
journalDir() {
|
|
64130
|
+
return join(this.stateDir, "code-mode", "journal");
|
|
64131
|
+
}
|
|
64132
|
+
journalPath(journalKey) {
|
|
64133
|
+
return join(this.journalDir(), `${journalKey}.json`);
|
|
64134
|
+
}
|
|
64135
|
+
recoveryIndexPath(recoveryRefHash) {
|
|
64136
|
+
return join(this.journalDir(), "recovery-index", `${recoveryRefHash}.json`);
|
|
64137
|
+
}
|
|
64138
|
+
sessionIndexPath(sessionIdHash) {
|
|
64139
|
+
return join(this.journalDir(), "session-index", `${sessionIdHash ?? "unknown"}.json`);
|
|
64140
|
+
}
|
|
64141
|
+
secretPath() {
|
|
64142
|
+
return join(this.journalDir(), "secret.key");
|
|
64143
|
+
}
|
|
64144
|
+
};
|
|
64145
|
+
function classifyCodeModeRecovery(input) {
|
|
64146
|
+
if (input.invokedCaplet) return "side_effecting";
|
|
64147
|
+
if (input.sessionDisposedAfterRun) return "unknown";
|
|
64148
|
+
return /\b(?:function|var|let|const|class)\b/u.test(input.code) ? "setup_like" : "unknown";
|
|
64149
|
+
}
|
|
64150
|
+
function isRecoveryRef(value) {
|
|
64151
|
+
return /^[a-f0-9]{48}$/u.test(value);
|
|
64152
|
+
}
|
|
64153
|
+
function parseCursor(cursor) {
|
|
64154
|
+
if (!cursor) return 0;
|
|
64155
|
+
const parsed = Number.parseInt(cursor, 10);
|
|
64156
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
64157
|
+
}
|
|
64158
|
+
function truncateUtf8(value, maxBytes) {
|
|
64159
|
+
let bytes = 0;
|
|
64160
|
+
let output = "";
|
|
64161
|
+
for (const char of value) {
|
|
64162
|
+
const next = Buffer.byteLength(char, "utf8");
|
|
64163
|
+
if (bytes + next > maxBytes) break;
|
|
64164
|
+
output += char;
|
|
64165
|
+
bytes += next;
|
|
64166
|
+
}
|
|
64167
|
+
return output;
|
|
64168
|
+
}
|
|
64169
|
+
function redactJournalText(text, exactSecrets) {
|
|
64170
|
+
let redacted = redactCodeModeLogText(text);
|
|
64171
|
+
for (const secret of exactSecrets) {
|
|
64172
|
+
if (!secret) continue;
|
|
64173
|
+
redacted = redacted.replaceAll(secret, "[REDACTED:capability]");
|
|
64174
|
+
}
|
|
64175
|
+
return redacted.replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/giu, "[REDACTED:capability]");
|
|
64176
|
+
}
|
|
64177
|
+
function isJournalEntry(value) {
|
|
64178
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
64179
|
+
const entry = value;
|
|
64180
|
+
return typeof entry.timestamp === "string" && typeof entry.code === "string" && typeof entry.declarationHash === "string" && isJournalOutcome(entry.outcome) && Array.isArray(entry.diagnostics) && entry.diagnostics.every(isJournalDiagnostic) && (entry.recoveryClassification === "setup_like" || entry.recoveryClassification === "side_effecting" || entry.recoveryClassification === "unknown") && (entry.logsStored === void 0 || typeof entry.logsStored === "boolean") && (entry.summary === void 0 || typeof entry.summary === "string");
|
|
64181
|
+
}
|
|
64182
|
+
function isJournalOutcome(value) {
|
|
64183
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
64184
|
+
const outcome = value;
|
|
64185
|
+
return outcome.ok === true || outcome.ok === false && typeof outcome.code === "string";
|
|
64186
|
+
}
|
|
64187
|
+
function isJournalDiagnostic(value) {
|
|
64188
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
64189
|
+
const diagnostic = value;
|
|
64190
|
+
return typeof diagnostic.code === "string" && typeof diagnostic.message === "string" && (diagnostic.severity === "error" || diagnostic.severity === "warning" || diagnostic.severity === "info");
|
|
64191
|
+
}
|
|
64192
|
+
function rejectSymlinkPathComponents(rootDir, target, includeTarget) {
|
|
64193
|
+
const resolvedRoot = resolve(rootDir);
|
|
64194
|
+
rejectSymlinkRoot(resolvedRoot);
|
|
64195
|
+
const rel = relative(resolvedRoot, resolve(target));
|
|
64196
|
+
if (rel.startsWith("..") || rel === "") return;
|
|
64197
|
+
const parts = rel.split(/[\\/]+/u).filter(Boolean);
|
|
64198
|
+
let current = resolvedRoot;
|
|
64199
|
+
const limit = includeTarget ? parts.length : Math.max(0, parts.length - 1);
|
|
64200
|
+
for (let index = 0; index < limit; index += 1) {
|
|
64201
|
+
current = resolve(current, parts[index]);
|
|
64202
|
+
try {
|
|
64203
|
+
if (lstatSync(current).isSymbolicLink()) throw new Error("Code Mode journal path must not contain symlinks.");
|
|
64204
|
+
} catch (error) {
|
|
64205
|
+
if (error.code === "ENOENT") return;
|
|
64206
|
+
throw error;
|
|
64207
|
+
}
|
|
64208
|
+
}
|
|
64209
|
+
}
|
|
64210
|
+
function rejectSymlinkRoot(rootDir) {
|
|
64211
|
+
try {
|
|
64212
|
+
if (lstatSync(rootDir).isSymbolicLink()) throw new Error("Code Mode journal root must not be a symlink.");
|
|
64213
|
+
} catch (error) {
|
|
64214
|
+
if (error.code === "ENOENT") return;
|
|
64215
|
+
throw error;
|
|
64216
|
+
}
|
|
64217
|
+
}
|
|
64218
|
+
//#endregion
|
|
63850
64219
|
//#region src/code-mode/api.ts
|
|
63851
64220
|
const MAX_TOOL_TEXT_CHARS = 2e3;
|
|
63852
64221
|
const MAX_ERROR_MESSAGE_CHARS = 1e3;
|
|
@@ -63870,7 +64239,10 @@ function dedupeCallableCaplets(caplets) {
|
|
|
63870
64239
|
function createCodeModeCapletsApi(input) {
|
|
63871
64240
|
const api = {};
|
|
63872
64241
|
for (const caplet of listCodeModeCallableCaplets(input.service)) api[caplet.id] = createHandle(input.service, caplet.id);
|
|
63873
|
-
const debugApi = {
|
|
64242
|
+
const debugApi = {
|
|
64243
|
+
readLogs: input.readLogs ?? defaultReadLogs,
|
|
64244
|
+
readRecovery: input.readRecovery ?? defaultReadRecovery
|
|
64245
|
+
};
|
|
63874
64246
|
api.debug = "debug" in api ? Object.assign(api.debug, debugApi) : debugApi;
|
|
63875
64247
|
return api;
|
|
63876
64248
|
}
|
|
@@ -64199,6 +64571,9 @@ async function defaultReadLogs() {
|
|
|
64199
64571
|
timestamp: (/* @__PURE__ */ new Date(0)).toISOString()
|
|
64200
64572
|
}] };
|
|
64201
64573
|
}
|
|
64574
|
+
async function defaultReadRecovery() {
|
|
64575
|
+
return { entries: [] };
|
|
64576
|
+
}
|
|
64202
64577
|
function resultIsError(result) {
|
|
64203
64578
|
if (!isPlainObject$1(result)) return false;
|
|
64204
64579
|
if (result.isError === true) return true;
|
|
@@ -77011,18 +77386,7 @@ function diagnoseCodeModeTypeScript(input) {
|
|
|
77011
77386
|
const startedAt = Date.now();
|
|
77012
77387
|
const diagnostics = [...preflightDiagnostics(input.code)];
|
|
77013
77388
|
if (diagnostics.length >= maxDiagnostics) return diagnostics.slice(0, maxDiagnostics);
|
|
77014
|
-
const compilerOptions =
|
|
77015
|
-
target: ts.ScriptTarget.ES2022,
|
|
77016
|
-
module: ts.ModuleKind.ESNext,
|
|
77017
|
-
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
77018
|
-
lib: ["lib.es2022.d.ts"],
|
|
77019
|
-
types: [],
|
|
77020
|
-
strict: true,
|
|
77021
|
-
noEmit: true,
|
|
77022
|
-
skipLibCheck: true,
|
|
77023
|
-
noErrorTruncation: true,
|
|
77024
|
-
allowJs: false
|
|
77025
|
-
};
|
|
77389
|
+
const compilerOptions = codeModeCompilerOptions();
|
|
77026
77390
|
const wrappedCode = [
|
|
77027
77391
|
"async function __capletsCodeModeMain(): Promise<unknown> {",
|
|
77028
77392
|
input.code,
|
|
@@ -77031,7 +77395,7 @@ function diagnoseCodeModeTypeScript(input) {
|
|
|
77031
77395
|
const host = createVirtualCompilerHost(compilerOptions, {
|
|
77032
77396
|
[CODE_FILE]: wrappedCode,
|
|
77033
77397
|
[DECLARATION_FILE]: input.declaration,
|
|
77034
|
-
[AMBIENT_FILE]: CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION
|
|
77398
|
+
[AMBIENT_FILE]: [CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION, input.session?.declaration() ?? ""].join("\n")
|
|
77035
77399
|
});
|
|
77036
77400
|
const program = ts.createProgram([
|
|
77037
77401
|
CODE_FILE,
|
|
@@ -77062,6 +77426,172 @@ function diagnoseCodeModeTypeScript(input) {
|
|
|
77062
77426
|
}
|
|
77063
77427
|
return diagnostics.slice(0, maxDiagnostics);
|
|
77064
77428
|
}
|
|
77429
|
+
function codeModeCompilerOptions() {
|
|
77430
|
+
return {
|
|
77431
|
+
target: ts.ScriptTarget.ES2022,
|
|
77432
|
+
module: ts.ModuleKind.ESNext,
|
|
77433
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
77434
|
+
lib: ["lib.es2022.d.ts"],
|
|
77435
|
+
types: [],
|
|
77436
|
+
strict: true,
|
|
77437
|
+
noEmit: true,
|
|
77438
|
+
skipLibCheck: true,
|
|
77439
|
+
noErrorTruncation: true,
|
|
77440
|
+
allowJs: false
|
|
77441
|
+
};
|
|
77442
|
+
}
|
|
77443
|
+
var CodeModeDiagnosticsSession = class {
|
|
77444
|
+
#declarations = /* @__PURE__ */ new Map();
|
|
77445
|
+
declaration() {
|
|
77446
|
+
return [...this.#declarations.values()].join("\n");
|
|
77447
|
+
}
|
|
77448
|
+
recordSuccessfulCell(code, declaration = "") {
|
|
77449
|
+
const source = ts.createSourceFile("/caplets-code-mode/session-cell.ts", code, ts.ScriptTarget.ES2022, true);
|
|
77450
|
+
const compilerOptions = codeModeCompilerOptions();
|
|
77451
|
+
const ambientDeclarations = [
|
|
77452
|
+
CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION,
|
|
77453
|
+
declaration,
|
|
77454
|
+
this.declaration()
|
|
77455
|
+
].join("\n");
|
|
77456
|
+
const host = createVirtualCompilerHost(compilerOptions, {
|
|
77457
|
+
[CODE_FILE]: code,
|
|
77458
|
+
[AMBIENT_FILE]: ambientDeclarations
|
|
77459
|
+
});
|
|
77460
|
+
const program = ts.createProgram([CODE_FILE, AMBIENT_FILE], compilerOptions, host);
|
|
77461
|
+
const checker = program.getTypeChecker();
|
|
77462
|
+
const programSource = program.getSourceFile(CODE_FILE) ?? source;
|
|
77463
|
+
for (const statement of programSource.statements) if (ts.isFunctionDeclaration(statement) && statement.name) {
|
|
77464
|
+
const typeParameters = statement.typeParameters ? `<${statement.typeParameters.map((typeParameter) => typeParameter.getText(programSource)).join(", ")}>` : "";
|
|
77465
|
+
const params = statement.parameters.map((parameter) => ambientParameter(parameter, programSource));
|
|
77466
|
+
const signature = checker.getSignatureFromDeclaration(statement);
|
|
77467
|
+
const inferredReturnType = signature ? safeAmbientFunctionReturnType(checker.getReturnTypeOfSignature(signature), checker, ambientDeclarations) : "unknown";
|
|
77468
|
+
const returnType = statement.type ? statement.type.getText(programSource) : inferredReturnType;
|
|
77469
|
+
this.#declarations.set(statement.name.text, `declare function ${statement.name.text}${typeParameters}(${params.join(", ")}): ${returnType};`);
|
|
77470
|
+
}
|
|
77471
|
+
const previousBindingNames = new Set(this.#declarations.keys());
|
|
77472
|
+
const assignedNames = collectFunctionScopedAssignedNames(programSource);
|
|
77473
|
+
for (const binding of collectFunctionScopedVarBindings(programSource, checker, {
|
|
77474
|
+
ambientDeclarationFor: (name) => [
|
|
77475
|
+
CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION,
|
|
77476
|
+
declaration,
|
|
77477
|
+
this.declarationExcluding(name)
|
|
77478
|
+
].filter(Boolean).join("\n"),
|
|
77479
|
+
assignedNames,
|
|
77480
|
+
previousBindingNames
|
|
77481
|
+
})) this.#declarations.set(binding.name, `declare var ${binding.name}: ${binding.type};`);
|
|
77482
|
+
}
|
|
77483
|
+
clear() {
|
|
77484
|
+
this.#declarations.clear();
|
|
77485
|
+
}
|
|
77486
|
+
declarationExcluding(name) {
|
|
77487
|
+
const declarations = [CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION];
|
|
77488
|
+
for (const [declarationName, declaration] of this.#declarations) if (declarationName !== name) declarations.push(declaration);
|
|
77489
|
+
return declarations.join("\n");
|
|
77490
|
+
}
|
|
77491
|
+
};
|
|
77492
|
+
function collectFunctionScopedVarBindings(source, checker, options) {
|
|
77493
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
77494
|
+
const visit = (node) => {
|
|
77495
|
+
if (node !== source && (ts.isFunctionLike(node) || ts.isClassLike(node))) return;
|
|
77496
|
+
if (ts.isVariableStatement(node)) collectVarDeclarationListBindings(node.declarationList, checker, bindings, options);
|
|
77497
|
+
if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer)) collectVarDeclarationListBindings(node.initializer, checker, bindings, options);
|
|
77498
|
+
ts.forEachChild(node, visit);
|
|
77499
|
+
};
|
|
77500
|
+
visit(source);
|
|
77501
|
+
return [...bindings.entries()].map(([name, type]) => ({
|
|
77502
|
+
name,
|
|
77503
|
+
type
|
|
77504
|
+
}));
|
|
77505
|
+
}
|
|
77506
|
+
function collectVarDeclarationListBindings(declarationList, checker, bindings, options) {
|
|
77507
|
+
if (!((ts.getCombinedNodeFlags(declarationList) & ts.NodeFlags.BlockScoped) === 0)) return;
|
|
77508
|
+
for (const declaration of declarationList.declarations) for (const name of bindingNames$1(declaration.name)) {
|
|
77509
|
+
const type = ambientTypeForBindingName(name, checker, options.ambientDeclarationFor(name.text));
|
|
77510
|
+
if (options.previousBindingNames.has(name.text) && declaration.initializer === void 0 && !options.assignedNames.has(name.text)) continue;
|
|
77511
|
+
bindings.set(name.text, type);
|
|
77512
|
+
}
|
|
77513
|
+
}
|
|
77514
|
+
function bindingNames$1(name) {
|
|
77515
|
+
if (ts.isIdentifier(name)) return [name];
|
|
77516
|
+
return name.elements.flatMap((element) => {
|
|
77517
|
+
if (ts.isOmittedExpression(element)) return [];
|
|
77518
|
+
return bindingNames$1(element.name);
|
|
77519
|
+
});
|
|
77520
|
+
}
|
|
77521
|
+
function collectFunctionScopedAssignedNames(source) {
|
|
77522
|
+
const names = /* @__PURE__ */ new Set();
|
|
77523
|
+
const visit = (node) => {
|
|
77524
|
+
if (node !== source && (ts.isFunctionLike(node) || ts.isClassLike(node))) return;
|
|
77525
|
+
if (ts.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) collectAssignedBindingNames(node.left, names);
|
|
77526
|
+
if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) && (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken)) collectAssignedBindingNames(node.operand, names);
|
|
77527
|
+
ts.forEachChild(node, visit);
|
|
77528
|
+
};
|
|
77529
|
+
visit(source);
|
|
77530
|
+
return names;
|
|
77531
|
+
}
|
|
77532
|
+
function isAssignmentOperator(kind) {
|
|
77533
|
+
return kind >= ts.SyntaxKind.FirstAssignment && kind <= ts.SyntaxKind.LastAssignment;
|
|
77534
|
+
}
|
|
77535
|
+
function collectAssignedBindingNames(node, names) {
|
|
77536
|
+
if (ts.isIdentifier(node)) {
|
|
77537
|
+
names.add(node.text);
|
|
77538
|
+
return;
|
|
77539
|
+
}
|
|
77540
|
+
if (ts.isPropertyAssignment(node)) {
|
|
77541
|
+
collectAssignedBindingNames(node.initializer, names);
|
|
77542
|
+
return;
|
|
77543
|
+
}
|
|
77544
|
+
if (ts.isShorthandPropertyAssignment(node)) {
|
|
77545
|
+
names.add(node.name.text);
|
|
77546
|
+
return;
|
|
77547
|
+
}
|
|
77548
|
+
if (ts.isSpreadAssignment(node)) {
|
|
77549
|
+
collectAssignedBindingNames(node.expression, names);
|
|
77550
|
+
return;
|
|
77551
|
+
}
|
|
77552
|
+
if (ts.isObjectLiteralExpression(node) || ts.isArrayLiteralExpression(node)) ts.forEachChild(node, (child) => collectAssignedBindingNames(child, names));
|
|
77553
|
+
}
|
|
77554
|
+
function ambientTypeForBindingName(name, checker, ambientDeclaration) {
|
|
77555
|
+
const type = checker.getTypeAtLocation(name);
|
|
77556
|
+
return safeAmbientType(name.text, type, checker, ambientDeclaration);
|
|
77557
|
+
}
|
|
77558
|
+
function safeAmbientType(name, type, checker, ambientDeclaration) {
|
|
77559
|
+
return safeAmbientTypeText(type, checker, ambientDeclaration, (typeText) => isSelfContainedAmbientDeclaration(`declare let ${name}: ${typeText};`, ambientDeclaration));
|
|
77560
|
+
}
|
|
77561
|
+
function safeAmbientFunctionReturnType(type, checker, ambientDeclaration) {
|
|
77562
|
+
return safeAmbientTypeText(type, checker, ambientDeclaration, (typeText) => isSelfContainedAmbientDeclaration(`declare function __caplets_return_probe__(): ${typeText};`, ambientDeclaration));
|
|
77563
|
+
}
|
|
77564
|
+
function safeAmbientTypeText(type, checker, ambientDeclaration, isSelfContained) {
|
|
77565
|
+
if (isUnsafeAmbientType(type)) return "unknown";
|
|
77566
|
+
const text = checker.typeToString(type, void 0, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | ts.TypeFormatFlags.WriteArrayAsGenericType);
|
|
77567
|
+
if (!text || text === "any" || text === "{}" || text === "never") return "unknown";
|
|
77568
|
+
if (text.length > 500) return "unknown";
|
|
77569
|
+
if (/\bimport\(/u.test(text)) return "unknown";
|
|
77570
|
+
if (!isSelfContained(text)) return "unknown";
|
|
77571
|
+
return text;
|
|
77572
|
+
}
|
|
77573
|
+
function isUnsafeAmbientType(type) {
|
|
77574
|
+
return Boolean(type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never));
|
|
77575
|
+
}
|
|
77576
|
+
function isSelfContainedAmbientDeclaration(candidateDeclaration, ambientDeclaration) {
|
|
77577
|
+
const compilerOptions = codeModeCompilerOptions();
|
|
77578
|
+
const host = createVirtualCompilerHost(compilerOptions, {
|
|
77579
|
+
[CODE_FILE]: candidateDeclaration,
|
|
77580
|
+
[AMBIENT_FILE]: ambientDeclaration
|
|
77581
|
+
});
|
|
77582
|
+
const program = ts.createProgram([CODE_FILE, AMBIENT_FILE], compilerOptions, host);
|
|
77583
|
+
return program.getSemanticDiagnostics(program.getSourceFile(CODE_FILE)).length === 0;
|
|
77584
|
+
}
|
|
77585
|
+
function ambientParameter(parameter, source) {
|
|
77586
|
+
return `${parameter.dotDotDotToken ? "..." : ""}${parameter.name.getText(source)}${parameter.questionToken || parameter.initializer ? "?" : ""}: ${parameter.type?.getText(source) ?? (parameter.initializer ? inferLiteralType(parameter.initializer) : "unknown")}`;
|
|
77587
|
+
}
|
|
77588
|
+
function inferLiteralType(initializer) {
|
|
77589
|
+
if (!initializer) return "unknown";
|
|
77590
|
+
if (ts.isNumericLiteral(initializer)) return "number";
|
|
77591
|
+
if (ts.isStringLiteral(initializer)) return "string";
|
|
77592
|
+
if (initializer.kind === ts.SyntaxKind.TrueKeyword || initializer.kind === ts.SyntaxKind.FalseKeyword) return "boolean";
|
|
77593
|
+
return "unknown";
|
|
77594
|
+
}
|
|
77065
77595
|
function preflightDiagnostics(code) {
|
|
77066
77596
|
const diagnostics = [];
|
|
77067
77597
|
if (!hasExecutableImport(code)) {} else diagnostics.push({
|
|
@@ -77192,10 +77722,393 @@ function resolveTimer(context, deferred, fired) {
|
|
|
77192
77722
|
const CODE_MODE_PLATFORM_RUNTIME_SOURCE = "(function() {\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/deserialize.js\n const env = typeof self === \"object\" ? self : globalThis;\n const guard = (name, init) => {\n switch (name) {\n case \"Function\":\n case \"SharedWorker\":\n case \"Worker\":\n case \"eval\":\n case \"setInterval\":\n case \"setTimeout\": throw new TypeError(\"unable to deserialize \" + name);\n }\n return new env[name](init);\n };\n const deserializer = ($, _) => {\n const as = (out, index) => {\n $.set(index, out);\n return out;\n };\n const unpair = (index) => {\n if ($.has(index)) return $.get(index);\n const [type, value] = _[index];\n switch (type) {\n case 0:\n case -1: return as(value, index);\n case 1: {\n const arr = as([], index);\n for (const index of value) arr.push(unpair(index));\n return arr;\n }\n case 2: {\n const object = as({}, index);\n for (const [key, index] of value) object[unpair(key)] = unpair(index);\n return object;\n }\n case 3: return as(new Date(value), index);\n case 4: {\n const { source, flags } = value;\n return as(new RegExp(source, flags), index);\n }\n case 5: {\n const map = as(/* @__PURE__ */ new Map(), index);\n for (const [key, index] of value) map.set(unpair(key), unpair(index));\n return map;\n }\n case 6: {\n const set = as(/* @__PURE__ */ new Set(), index);\n for (const index of value) set.add(unpair(index));\n return set;\n }\n case 7: {\n const { name, message } = value;\n return as(guard(name, message), index);\n }\n case 8: return as(BigInt(value), index);\n case \"BigInt\": return as(Object(BigInt(value)), index);\n case \"ArrayBuffer\": return as(new Uint8Array(value).buffer, value);\n case \"DataView\": {\n const { buffer } = new Uint8Array(value);\n return as(new DataView(buffer), value);\n }\n }\n return as(guard(type, value), index);\n };\n return unpair;\n };\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns a deserialized value from a serialized array of Records.\n * @param {Record[]} serialized a previously serialized value.\n * @returns {any}\n */\n const deserialize = (serialized) => deserializer(/* @__PURE__ */ new Map(), serialized)(0);\n //#endregion\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/serialize.js\n const EMPTY = \"\";\n const { toString } = {};\n const { keys } = Object;\n const typeOf = (value) => {\n const type = typeof value;\n if (type !== \"object\" || !value) return [0, type];\n const asString = toString.call(value).slice(8, -1);\n switch (asString) {\n case \"Array\": return [1, EMPTY];\n case \"Object\": return [2, EMPTY];\n case \"Date\": return [3, EMPTY];\n case \"RegExp\": return [4, EMPTY];\n case \"Map\": return [5, EMPTY];\n case \"Set\": return [6, EMPTY];\n case \"DataView\": return [1, asString];\n }\n if (asString.includes(\"Array\")) return [1, asString];\n if (asString.includes(\"Error\")) return [7, asString];\n return [2, asString];\n };\n const shouldSkip = ([TYPE, type]) => TYPE === 0 && (type === \"function\" || type === \"symbol\");\n const serializer = (strict, json, $, _) => {\n const as = (out, value) => {\n const index = _.push(out) - 1;\n $.set(value, index);\n return index;\n };\n const pair = (value) => {\n if ($.has(value)) return $.get(value);\n let [TYPE, type] = typeOf(value);\n switch (TYPE) {\n case 0: {\n let entry = value;\n switch (type) {\n case \"bigint\":\n TYPE = 8;\n entry = value.toString();\n break;\n case \"function\":\n case \"symbol\":\n if (strict) throw new TypeError(\"unable to serialize \" + type);\n entry = null;\n break;\n case \"undefined\": return as([-1], value);\n }\n return as([TYPE, entry], value);\n }\n case 1: {\n if (type) {\n let spread = value;\n if (type === \"DataView\") spread = new Uint8Array(value.buffer);\n else if (type === \"ArrayBuffer\") spread = new Uint8Array(value);\n return as([type, [...spread]], value);\n }\n const arr = [];\n const index = as([TYPE, arr], value);\n for (const entry of value) arr.push(pair(entry));\n return index;\n }\n case 2: {\n if (type) switch (type) {\n case \"BigInt\": return as([type, value.toString()], value);\n case \"Boolean\":\n case \"Number\":\n case \"String\": return as([type, value.valueOf()], value);\n }\n if (json && \"toJSON\" in value) return pair(value.toJSON());\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const key of keys(value)) if (strict || !shouldSkip(typeOf(value[key]))) entries.push([pair(key), pair(value[key])]);\n return index;\n }\n case 3: return as([TYPE, value.toISOString()], value);\n case 4: {\n const { source, flags } = value;\n return as([TYPE, {\n source,\n flags\n }], value);\n }\n case 5: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const [key, entry] of value) if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry)))) entries.push([pair(key), pair(entry)]);\n return index;\n }\n case 6: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const entry of value) if (strict || !shouldSkip(typeOf(entry))) entries.push(pair(entry));\n return index;\n }\n }\n const { message } = value;\n return as([TYPE, {\n name: type,\n message\n }], value);\n };\n return pair;\n };\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns an array of serialized Records.\n * @param {any} value a serializable value.\n * @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that,\n * if `true`, will not throw errors on incompatible types, and behave more\n * like JSON stringify would behave. Symbol and Function will be discarded.\n * @returns {Record[]}\n */\n const serialize = (value, { json, lossy } = {}) => {\n const _ = [];\n return serializer(!(json || lossy), !!json, /* @__PURE__ */ new Map(), _)(value), _;\n };\n //#endregion\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/index.js\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns an array of serialized Records.\n * @param {any} any a serializable value.\n * @param {{transfer?: any[], json?: boolean, lossy?: boolean}?} options an object with\n * a transfer option (ignored when polyfilled) and/or non standard fields that\n * fallback to the polyfill if present.\n * @returns {Record[]}\n */\n var esm_default = typeof structuredClone === \"function\" ? (any, options) => options && (\"json\" in options || \"lossy\" in options) ? deserialize(serialize(any, options)) : structuredClone(any) : (any, options) => deserialize(serialize(any, options));\n //#endregion\n //#region node_modules/.pnpm/formdata-node@6.0.3/node_modules/formdata-node/lib/form-data.js\n var __accessCheck = (obj, member, msg) => {\n if (!member.has(obj)) throw TypeError(\"Cannot \" + msg);\n };\n var __privateGet = (obj, member, getter) => {\n __accessCheck(obj, member, \"read from private field\");\n return getter ? getter.call(obj) : member.get(obj);\n };\n var __privateAdd = (obj, member, value) => {\n if (member.has(obj)) throw TypeError(\"Cannot add the same private member more than once\");\n member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n };\n var __privateSet = (obj, member, value, setter) => {\n __accessCheck(obj, member, \"write to private field\");\n setter ? setter.call(obj, value) : member.set(obj, value);\n return value;\n };\n var __privateMethod = (obj, member, method) => {\n __accessCheck(obj, member, \"access private method\");\n return method;\n };\n var isFunction = (value) => typeof value === \"function\";\n var isObject = (value) => typeof value === \"object\" && value != null && !Array.isArray(value);\n var isAsyncIterable = (value) => isObject(value) && isFunction(value[Symbol.asyncIterator]);\n var MAX_CHUNK_SIZE = 65536;\n async function* clonePart(value) {\n if (value.byteLength <= MAX_CHUNK_SIZE) {\n yield value;\n return;\n }\n let offset = 0;\n while (offset < value.byteLength) {\n const size = Math.min(value.byteLength - offset, MAX_CHUNK_SIZE);\n const buffer = value.buffer.slice(offset, offset + size);\n offset += buffer.byteLength;\n yield new Uint8Array(buffer);\n }\n }\n async function* readStream(readable) {\n const reader = readable.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n yield value;\n }\n }\n async function* chunkStream(stream) {\n for await (const value of stream) yield* clonePart(value);\n }\n var getStreamIterator = (source) => {\n if (isAsyncIterable(source)) return chunkStream(source);\n if (isFunction(source.getReader)) return chunkStream(readStream(source));\n throw new TypeError(\"Unsupported data source: Expected either ReadableStream or async iterable.\");\n };\n async function* consumeNodeBlob(blob) {\n let position = 0;\n while (position !== blob.size) {\n const buffer = await blob.slice(position, Math.min(blob.size, position + MAX_CHUNK_SIZE)).arrayBuffer();\n position += buffer.byteLength;\n yield new Uint8Array(buffer);\n }\n }\n async function* consumeBlobParts(parts, clone = false) {\n for (const part of parts) if (ArrayBuffer.isView(part)) if (clone) yield* clonePart(part);\n else yield part;\n else if (isFunction(part.stream)) yield* getStreamIterator(part.stream());\n else yield* consumeNodeBlob(part);\n }\n function* sliceBlob(blobParts, blobSize, start = 0, end) {\n end ??= blobSize;\n let relativeStart = start < 0 ? Math.max(blobSize + start, 0) : Math.min(start, blobSize);\n let relativeEnd = end < 0 ? Math.max(blobSize + end, 0) : Math.min(end, blobSize);\n const span = Math.max(relativeEnd - relativeStart, 0);\n let added = 0;\n for (const part of blobParts) {\n if (added >= span) break;\n const partSize = ArrayBuffer.isView(part) ? part.byteLength : part.size;\n if (relativeStart && partSize <= relativeStart) {\n relativeStart -= partSize;\n relativeEnd -= partSize;\n } else {\n let chunk;\n if (ArrayBuffer.isView(part)) {\n chunk = part.subarray(relativeStart, Math.min(partSize, relativeEnd));\n added += chunk.byteLength;\n } else {\n chunk = part.slice(relativeStart, Math.min(partSize, relativeEnd));\n added += chunk.size;\n }\n relativeEnd -= partSize;\n relativeStart = 0;\n yield chunk;\n }\n }\n }\n var _parts, _type, _size;\n var _Blob = class _Blob {\n /**\n * Returns a new [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object.\n * The content of the blob consists of the concatenation of the values given in the parameter array.\n *\n * @param blobParts An `Array` strings, or [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n * @param options An optional object of type `BlobPropertyBag`.\n */\n constructor(blobParts = [], options = {}) {\n /**\n * An `Array` of [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) or [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n __privateAdd(this, _parts, []);\n /**\n * Returns the [`MIME type`](https://developer.mozilla.org/en-US/docs/Glossary/MIME_type) of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n */\n __privateAdd(this, _type, \"\");\n /**\n * Returns the size of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) in bytes.\n */\n __privateAdd(this, _size, 0);\n options ??= {};\n if (typeof blobParts !== \"object\" || blobParts === null) throw new TypeError(\"Failed to construct 'Blob': The provided value cannot be converted to a sequence.\");\n if (!isFunction(blobParts[Symbol.iterator])) throw new TypeError(\"Failed to construct 'Blob': The object must have a callable @@iterator property.\");\n if (typeof options !== \"object\" && !isFunction(options)) throw new TypeError(\"Failed to construct 'Blob': parameter 2 cannot convert to dictionary.\");\n const encoder = new TextEncoder();\n for (const raw of blobParts) {\n let part;\n if (ArrayBuffer.isView(raw)) part = new Uint8Array(raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength));\n else if (raw instanceof ArrayBuffer) part = new Uint8Array(raw.slice(0));\n else if (raw instanceof _Blob) part = raw;\n else part = encoder.encode(String(raw));\n __privateSet(this, _size, __privateGet(this, _size) + (ArrayBuffer.isView(part) ? part.byteLength : part.size));\n __privateGet(this, _parts).push(part);\n }\n const type = options.type === void 0 ? \"\" : String(options.type);\n __privateSet(this, _type, /^[\\x20-\\x7E]*$/.test(type) ? type : \"\");\n }\n static [Symbol.hasInstance](value) {\n return Boolean(value && typeof value === \"object\" && isFunction(value.constructor) && (isFunction(value.stream) || isFunction(value.arrayBuffer)) && /^(Blob|File)$/.test(value[Symbol.toStringTag]));\n }\n /**\n * Returns the [`MIME type`](https://developer.mozilla.org/en-US/docs/Glossary/MIME_type) of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n */\n get type() {\n return __privateGet(this, _type);\n }\n /**\n * Returns the size of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) in bytes.\n */\n get size() {\n return __privateGet(this, _size);\n }\n /**\n * Creates and returns a new [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object which contains data from a subset of the blob on which it's called.\n *\n * @param start An index into the Blob indicating the first byte to include in the new Blob. If you specify a negative value, it's treated as an offset from the end of the Blob toward the beginning. For example, -10 would be the 10th from last byte in the Blob. The default value is 0. If you specify a value for start that is larger than the size of the source Blob, the returned Blob has size 0 and contains no data.\n * @param end An index into the Blob indicating the first byte that will *not* be included in the new Blob (i.e. the byte exactly at this index is not included). If you specify a negative value, it's treated as an offset from the end of the Blob toward the beginning. For example, -10 would be the 10th from last byte in the Blob. The default value is size.\n * @param contentType The content type to assign to the new Blob; this will be the value of its type property. The default value is an empty string.\n */\n slice(start, end, contentType) {\n return new _Blob(sliceBlob(__privateGet(this, _parts), this.size, start, end), { type: contentType });\n }\n /**\n * Returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves with a string containing the contents of the blob, interpreted as UTF-8.\n */\n async text() {\n const decoder = new TextDecoder();\n let result = \"\";\n for await (const chunk of consumeBlobParts(__privateGet(this, _parts))) result += decoder.decode(chunk, { stream: true });\n result += decoder.decode();\n return result;\n }\n /**\n * Returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves with the contents of the blob as binary data contained in an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).\n */\n async arrayBuffer() {\n const view = new Uint8Array(this.size);\n let offset = 0;\n for await (const chunk of consumeBlobParts(__privateGet(this, _parts))) {\n view.set(chunk, offset);\n offset += chunk.length;\n }\n return view.buffer;\n }\n /**\n * Returns a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) which upon reading returns the data contained within the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n stream() {\n const iterator = consumeBlobParts(__privateGet(this, _parts), true);\n return new ReadableStream({\n async pull(controller) {\n const { value, done } = await iterator.next();\n if (done) return queueMicrotask(() => controller.close());\n controller.enqueue(value);\n },\n async cancel() {\n await iterator.return();\n }\n });\n }\n get [Symbol.toStringTag]() {\n return \"Blob\";\n }\n };\n _parts = /* @__PURE__ */ new WeakMap();\n _type = /* @__PURE__ */ new WeakMap();\n _size = /* @__PURE__ */ new WeakMap();\n var Blob = _Blob;\n Object.defineProperties(Blob.prototype, {\n type: { enumerable: true },\n size: { enumerable: true },\n slice: { enumerable: true },\n stream: { enumerable: true },\n text: { enumerable: true },\n arrayBuffer: { enumerable: true }\n });\n var isBlob = (value) => value instanceof Blob;\n var _name, _lastModified;\n var File = class extends Blob {\n /**\n * Creates a new File instance.\n *\n * @param fileBits An `Array` strings, or [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n * @param name The name of the file.\n * @param options An options object containing optional attributes for the file.\n */\n constructor(fileBits, name, options = {}) {\n super(fileBits, options);\n /**\n * Returns the name of the file referenced by the File object.\n */\n __privateAdd(this, _name, void 0);\n /**\n * The last modified date of the file as the number of milliseconds since the Unix epoch (January 1, 1970 at midnight). Files without a known last modified date return the current date.\n */\n __privateAdd(this, _lastModified, 0);\n if (arguments.length < 2) throw new TypeError(`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`);\n __privateSet(this, _name, String(name));\n const lastModified = options.lastModified === void 0 ? Date.now() : Number(options.lastModified);\n if (!Number.isNaN(lastModified)) __privateSet(this, _lastModified, lastModified);\n }\n static [Symbol.hasInstance](value) {\n return value instanceof Blob && value[Symbol.toStringTag] === \"File\" && typeof value.name === \"string\";\n }\n /**\n * Name of the file referenced by the File object.\n */\n get name() {\n return __privateGet(this, _name);\n }\n /* c8 ignore next 3 */\n get webkitRelativePath() {\n return \"\";\n }\n /**\n * The last modified date of the file as the number of milliseconds since the Unix epoch (January 1, 1970 at midnight). Files without a known last modified date return the current date.\n */\n get lastModified() {\n return __privateGet(this, _lastModified);\n }\n get [Symbol.toStringTag]() {\n return \"File\";\n }\n };\n _name = /* @__PURE__ */ new WeakMap();\n _lastModified = /* @__PURE__ */ new WeakMap();\n var isFile = (value) => value instanceof File;\n var _entries, _setEntry, setEntry_fn;\n var FormData = class {\n constructor() {\n __privateAdd(this, _setEntry);\n /**\n * Stores internal data for every entry\n */\n __privateAdd(this, _entries, /* @__PURE__ */ new Map());\n }\n static [Symbol.hasInstance](value) {\n if (!value) return false;\n const val = value;\n return Boolean(isFunction(val.constructor) && val[Symbol.toStringTag] === \"FormData\" && isFunction(val.append) && isFunction(val.set) && isFunction(val.get) && isFunction(val.getAll) && isFunction(val.has) && isFunction(val.delete) && isFunction(val.entries) && isFunction(val.values) && isFunction(val.keys) && isFunction(val[Symbol.iterator]) && isFunction(val.forEach));\n }\n /**\n * Appends a new value onto an existing key inside a FormData object,\n * or adds the key if it does not already exist.\n *\n * The difference between `set()` and `append()` is that if the specified key already exists, `set()` will overwrite all existing values with the new one, whereas `append()` will append the new value onto the end of the existing set of values.\n *\n * @param name The name of the field whose data is contained in `value`.\n * @param value The field's value. This can be [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). If none of these are specified the value is converted to a string.\n * @param fileName The filename reported to the server, when a Blob or File is passed as the second parameter. The default filename for Blob objects is \"blob\". The default filename for File objects is the file's filename.\n */\n append(name, value, fileName) {\n __privateMethod(this, _setEntry, setEntry_fn).call(this, {\n name,\n fileName,\n append: true,\n rawValue: value,\n argsLength: arguments.length\n });\n }\n /**\n * Set a new value for an existing key inside FormData,\n * or add the new field if it does not already exist.\n *\n * @param name The name of the field whose data is contained in `value`.\n * @param value The field's value. This can be [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). If none of these are specified the value is converted to a string.\n * @param fileName The filename reported to the server, when a Blob or File is passed as the second parameter. The default filename for Blob objects is \"blob\". The default filename for File objects is the file's filename.\n *\n */\n set(name, value, fileName) {\n __privateMethod(this, _setEntry, setEntry_fn).call(this, {\n name,\n fileName,\n append: false,\n rawValue: value,\n argsLength: arguments.length\n });\n }\n /**\n * Returns the first value associated with a given key from within a `FormData` object.\n * If you expect multiple values and want all of them, use the `getAll()` method instead.\n *\n * @param {string} name A name of the value you want to retrieve.\n *\n * @returns A `FormDataEntryValue` containing the value. If the key doesn't exist, the method returns null.\n */\n get(name) {\n const field = __privateGet(this, _entries).get(String(name));\n if (!field) return null;\n return field[0];\n }\n /**\n * Returns all the values associated with a given key from within a `FormData` object.\n *\n * @param {string} name A name of the value you want to retrieve.\n *\n * @returns An array of `FormDataEntryValue` whose key matches the value passed in the `name` parameter. If the key doesn't exist, the method returns an empty list.\n */\n getAll(name) {\n const field = __privateGet(this, _entries).get(String(name));\n if (!field) return [];\n return field.slice();\n }\n /**\n * Returns a boolean stating whether a `FormData` object contains a certain key.\n *\n * @param name A string representing the name of the key you want to test for.\n *\n * @return A boolean value.\n */\n has(name) {\n return __privateGet(this, _entries).has(String(name));\n }\n /**\n * Deletes a key and its value(s) from a `FormData` object.\n *\n * @param name The name of the key you want to delete.\n */\n delete(name) {\n __privateGet(this, _entries).delete(String(name));\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through all keys contained in this `FormData` object.\n * Each key is a `string`.\n */\n *keys() {\n for (const key of __privateGet(this, _entries).keys()) yield key;\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through the `FormData` key/value pairs.\n * The key of each pair is a string; the value is a [`FormDataValue`](https://developer.mozilla.org/en-US/docs/Web/API/FormDataEntryValue).\n */\n *entries() {\n for (const name of this.keys()) {\n const values = this.getAll(name);\n for (const value of values) yield [name, value];\n }\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through all values contained in this object `FormData` object.\n * Each value is a [`FormDataValue`](https://developer.mozilla.org/en-US/docs/Web/API/FormDataEntryValue).\n */\n *values() {\n for (const [, value] of this) yield value;\n }\n /**\n * An alias for FormData#entries()\n */\n [Symbol.iterator]() {\n return this.entries();\n }\n /**\n * Executes given callback function for each field of the FormData instance\n */\n forEach(callback, thisArg) {\n for (const [name, value] of this) callback.call(thisArg, value, name, this);\n }\n get [Symbol.toStringTag]() {\n return \"FormData\";\n }\n };\n _entries = /* @__PURE__ */ new WeakMap();\n _setEntry = /* @__PURE__ */ new WeakSet();\n setEntry_fn = function({ name, rawValue, append, fileName, argsLength }) {\n const methodName = append ? \"append\" : \"set\";\n if (argsLength < 2) throw new TypeError(`Failed to execute '${methodName}' on 'FormData': 2 arguments required, but only ${argsLength} present.`);\n name = String(name);\n let value;\n if (isFile(rawValue)) value = fileName === void 0 ? rawValue : new File([rawValue], fileName, {\n type: rawValue.type,\n lastModified: rawValue.lastModified\n });\n else if (isBlob(rawValue)) value = new File([rawValue], fileName === void 0 ? \"blob\" : fileName, { type: rawValue.type });\n else if (fileName) throw new TypeError(`Failed to execute '${methodName}' on 'FormData': parameter 2 is not of type 'Blob'.`);\n else value = String(rawValue);\n const values = __privateGet(this, _entries).get(name);\n if (!values) {\n __privateGet(this, _entries).set(name, [value]);\n return;\n }\n if (!append) {\n __privateGet(this, _entries).set(name, [value]);\n return;\n }\n values.push(value);\n };\n /*! Based on fetch-blob. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> & David Frank */\n //#endregion\n //#region node_modules/.pnpm/set-cookie-parser@3.1.0/node_modules/set-cookie-parser/lib/set-cookie.js\n var defaultParseOptions = {\n decodeValues: true,\n map: false,\n silent: false,\n split: \"auto\"\n };\n function isForbiddenKey(key) {\n return typeof key !== \"string\" || key in {};\n }\n function createNullObj() {\n return Object.create(null);\n }\n function isNonEmptyString(str) {\n return typeof str === \"string\" && !!str.trim();\n }\n function parseString(setCookieValue, options) {\n var parts = setCookieValue.split(\";\").filter(isNonEmptyString);\n var parsed = parseNameValuePair(parts.shift());\n var name = parsed.name;\n var value = parsed.value;\n options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;\n if (isForbiddenKey(name)) return null;\n try {\n value = options.decodeValues ? decodeURIComponent(value) : value;\n } catch (e) {\n console.error(\"set-cookie-parser: failed to decode cookie value. Set options.decodeValues=false to disable decoding.\", e);\n }\n var cookie = createNullObj();\n cookie.name = name;\n cookie.value = value;\n parts.forEach(function(part) {\n var sides = part.split(\"=\");\n var key = sides.shift().trimLeft().toLowerCase();\n if (isForbiddenKey(key)) return;\n var value = sides.join(\"=\");\n if (key === \"expires\") cookie.expires = new Date(value);\n else if (key === \"max-age\") {\n var n = parseInt(value, 10);\n if (!Number.isNaN(n)) cookie.maxAge = n;\n } else if (key === \"secure\") cookie.secure = true;\n else if (key === \"httponly\") cookie.httpOnly = true;\n else if (key === \"samesite\") cookie.sameSite = value;\n else if (key === \"partitioned\") cookie.partitioned = true;\n else if (key) cookie[key] = value;\n });\n return cookie;\n }\n function parseNameValuePair(nameValuePairStr) {\n var name = \"\";\n var value = \"\";\n var nameValueArr = nameValuePairStr.split(\"=\");\n if (nameValueArr.length > 1) {\n name = nameValueArr.shift();\n value = nameValueArr.join(\"=\");\n } else value = nameValuePairStr;\n return {\n name,\n value\n };\n }\n function parseSetCookie(input, options) {\n options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;\n if (!input) if (!options.map) return [];\n else return createNullObj();\n if (input.headers) if (typeof input.headers.getSetCookie === \"function\") input = input.headers.getSetCookie();\n else if (input.headers[\"set-cookie\"]) input = input.headers[\"set-cookie\"];\n else {\n var sch = input.headers[Object.keys(input.headers).find(function(key) {\n return key.toLowerCase() === \"set-cookie\";\n })];\n if (!sch && input.headers.cookie && !options.silent) console.warn(\"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning.\");\n input = sch;\n }\n var split = options.split;\n var isArray = Array.isArray(input);\n if (split === \"auto\") split = !isArray;\n if (!isArray) input = [input];\n input = input.filter(isNonEmptyString);\n if (split) input = input.map(splitCookiesString).flat();\n if (!options.map) return input.map(function(str) {\n return parseString(str, options);\n }).filter(Boolean);\n else {\n var cookies = createNullObj();\n return input.reduce(function(cookies, str) {\n var cookie = parseString(str, options);\n if (cookie && !isForbiddenKey(cookie.name)) cookies[cookie.name] = cookie;\n return cookies;\n }, cookies);\n }\n }\n function splitCookiesString(cookiesString) {\n if (Array.isArray(cookiesString)) return cookiesString;\n if (typeof cookiesString !== \"string\") return [];\n var cookiesStrings = [];\n var pos = 0;\n var start;\n var ch;\n var lastComma;\n var nextStart;\n var cookiesSeparatorFound;\n function skipWhitespace() {\n while (pos < cookiesString.length && /\\s/.test(cookiesString.charAt(pos))) pos += 1;\n return pos < cookiesString.length;\n }\n function notSpecialChar() {\n ch = cookiesString.charAt(pos);\n return ch !== \"=\" && ch !== \";\" && ch !== \",\";\n }\n while (pos < cookiesString.length) {\n start = pos;\n cookiesSeparatorFound = false;\n while (skipWhitespace()) {\n ch = cookiesString.charAt(pos);\n if (ch === \",\") {\n lastComma = pos;\n pos += 1;\n skipWhitespace();\n nextStart = pos;\n while (pos < cookiesString.length && notSpecialChar()) pos += 1;\n if (pos < cookiesString.length && cookiesString.charAt(pos) === \"=\") {\n cookiesSeparatorFound = true;\n pos = nextStart;\n cookiesStrings.push(cookiesString.substring(start, lastComma));\n start = pos;\n } else pos = lastComma + 1;\n } else pos += 1;\n }\n if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.substring(start, cookiesString.length));\n }\n return cookiesStrings;\n }\n parseSetCookie.parseSetCookie = parseSetCookie;\n parseSetCookie.parse = parseSetCookie;\n parseSetCookie.parseString = parseString;\n parseSetCookie.splitCookiesString = splitCookiesString;\n //#endregion\n //#region node_modules/.pnpm/headers-polyfill@5.0.1/node_modules/headers-polyfill/lib/index.mjs\n const HEADERS_INVALID_CHARACTERS = /[^a-z0-9\\-#$%&'*+.^_`|~]/i;\n function normalizeHeaderName(name) {\n if (HEADERS_INVALID_CHARACTERS.test(name) || name.trim() === \"\") throw new TypeError(\"Invalid character in header field name\");\n return name.trim().toLowerCase();\n }\n const charCodesToRemove = [\n String.fromCharCode(10),\n String.fromCharCode(13),\n String.fromCharCode(9),\n String.fromCharCode(32)\n ];\n const HEADER_VALUE_REMOVE_REGEXP = new RegExp(`(^[${charCodesToRemove.join(\"\")}]|$[${charCodesToRemove.join(\"\")}])`, \"g\");\n /**\n * Normalize the given header value.\n * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize\n */\n function normalizeHeaderValue(value) {\n return value.replace(HEADER_VALUE_REMOVE_REGEXP, \"\");\n }\n /**\n * Validate the given header name.\n * @see https://fetch.spec.whatwg.org/#header-name\n */\n function isValidHeaderName(value) {\n if (typeof value !== \"string\") return false;\n if (value.length === 0) return false;\n for (let i = 0; i < value.length; i++) {\n const character = value.charCodeAt(i);\n if (character > 127 || !isToken(character)) return false;\n }\n return true;\n }\n function isToken(value) {\n return ![\n 127,\n 32,\n \"(\",\n \")\",\n \"<\",\n \">\",\n \"@\",\n \",\",\n \";\",\n \":\",\n \"\\\\\",\n \"\\\"\",\n \"/\",\n \"[\",\n \"]\",\n \"?\",\n \"=\",\n \"{\",\n \"}\"\n ].includes(value);\n }\n /**\n * Validate the given header value.\n * @see https://fetch.spec.whatwg.org/#header-value\n */\n function isValidHeaderValue(value) {\n if (typeof value !== \"string\") return false;\n if (value.trim() !== value) return false;\n for (let i = 0; i < value.length; i++) {\n const character = value.charCodeAt(i);\n if (character === 0 || character === 10 || character === 13) return false;\n }\n return true;\n }\n let _Symbol$toStringTag;\n const NORMALIZED_HEADERS = Symbol(\"normalizedHeaders\");\n const RAW_HEADER_NAMES = Symbol(\"rawHeaderNames\");\n const HEADER_VALUE_DELIMITER = \", \";\n var Headers = class Headers {\n constructor(init) {\n this[NORMALIZED_HEADERS] = {};\n this[RAW_HEADER_NAMES] = /* @__PURE__ */ new Map();\n this[_Symbol$toStringTag] = \"Headers\";\n /**\n * @note Cannot necessarily check if the `init` is an instance of the\n * `Headers` because that class may not be defined in Node or jsdom.\n */\n if ([\"Headers\", \"HeadersPolyfill\"].includes(init?.constructor?.name) || init instanceof Headers || typeof globalThis.Headers !== \"undefined\" && init instanceof globalThis.Headers) init.forEach((value, name) => {\n this.append(name, value);\n }, this);\n else if (Array.isArray(init)) init.forEach(([name, value]) => {\n this.append(name, Array.isArray(value) ? value.join(HEADER_VALUE_DELIMITER) : value);\n });\n else if (init) Object.getOwnPropertyNames(init).forEach((name) => {\n const value = init[name];\n this.append(name, Array.isArray(value) ? value.join(HEADER_VALUE_DELIMITER) : value);\n });\n }\n [(_Symbol$toStringTag = Symbol.toStringTag, Symbol.iterator)]() {\n return this.entries();\n }\n *keys() {\n for (const [name] of this.entries()) yield name;\n }\n *values() {\n for (const [, value] of this.entries()) yield value;\n }\n *entries() {\n let sortedKeys = Object.keys(this[NORMALIZED_HEADERS]).sort((a, b) => a.localeCompare(b));\n for (const name of sortedKeys) if (name === \"set-cookie\") for (const value of this.getSetCookie()) yield [name, value];\n else yield [name, this.get(name)];\n }\n /**\n * Returns a boolean stating whether a `Headers` object contains a certain header.\n */\n has(name) {\n if (!isValidHeaderName(name)) throw new TypeError(`Invalid header name \"${name}\"`);\n return this[NORMALIZED_HEADERS].hasOwnProperty(normalizeHeaderName(name));\n }\n /**\n * Returns a `ByteString` sequence of all the values of a header with a given name.\n */\n get(name) {\n if (!isValidHeaderName(name)) throw TypeError(`Invalid header name \"${name}\"`);\n return this[NORMALIZED_HEADERS][normalizeHeaderName(name)] ?? null;\n }\n /**\n * Sets a new value for an existing header inside a `Headers` object, or adds the header if it does not already exist.\n */\n set(name, value) {\n if (!isValidHeaderName(name) || !isValidHeaderValue(value)) return;\n const normalizedName = normalizeHeaderName(name);\n const normalizedValue = normalizeHeaderValue(value);\n this[NORMALIZED_HEADERS][normalizedName] = normalizeHeaderValue(normalizedValue);\n this[RAW_HEADER_NAMES].set(normalizedName, name);\n }\n /**\n * Appends a new value onto an existing header inside a `Headers` object, or adds the header if it does not already exist.\n */\n append(name, value) {\n if (!isValidHeaderName(name) || !isValidHeaderValue(value)) return;\n const normalizedName = normalizeHeaderName(name);\n const normalizedValue = normalizeHeaderValue(value);\n let resolvedValue = this.has(normalizedName) ? `${this.get(normalizedName)}, ${normalizedValue}` : normalizedValue;\n this.set(name, resolvedValue);\n }\n /**\n * Deletes a header from the `Headers` object.\n */\n delete(name) {\n if (!isValidHeaderName(name)) return;\n if (!this.has(name)) return;\n const normalizedName = normalizeHeaderName(name);\n delete this[NORMALIZED_HEADERS][normalizedName];\n this[RAW_HEADER_NAMES].delete(normalizedName);\n }\n /**\n * Traverses the `Headers` object,\n * calling the given callback for each header.\n */\n forEach(callback, thisArg) {\n for (const [name, value] of this.entries()) callback.call(thisArg, value, name, this);\n }\n /**\n * Returns an array containing the values\n * of all Set-Cookie headers associated\n * with a response\n */\n getSetCookie() {\n const setCookieHeader = this.get(\"set-cookie\");\n if (setCookieHeader === null) return [];\n if (setCookieHeader === \"\") return [\"\"];\n return splitCookiesString(setCookieHeader);\n }\n };\n //#endregion\n //#region packages/core/src/code-mode/platform-entry.ts\n const platformBridgeGlobalThis = globalThis;\n const capletsPlatformHost = {\n randomUUID: platformBridgeGlobalThis.__caplets_platform_random_uuid,\n randomValues: platformBridgeGlobalThis.__caplets_platform_random_values,\n sleep: platformBridgeGlobalThis.__caplets_platform_sleep,\n clearTimer: platformBridgeGlobalThis.__caplets_platform_clear_timer\n };\n delete platformBridgeGlobalThis.__caplets_platform_random_uuid;\n delete platformBridgeGlobalThis.__caplets_platform_random_values;\n delete platformBridgeGlobalThis.__caplets_platform_sleep;\n delete platformBridgeGlobalThis.__caplets_platform_clear_timer;\n const DISABLED_FETCH_MESSAGE = \"Direct fetch is not available in Code Mode; use a Caplet instead.\";\n const BASE64_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n const base64Lookup = new Map(BASE64_ALPHABET.split(\"\").map((char, index) => [char, index]));\n function utf8Encode(input) {\n const encoded = encodeURIComponent(input);\n const bytes = [];\n for (let index = 0; index < encoded.length; index += 1) {\n if (encoded[index] === \"%\") {\n bytes.push(Number.parseInt(encoded.slice(index + 1, index + 3), 16));\n index += 2;\n continue;\n }\n bytes.push(encoded.charCodeAt(index));\n }\n return Uint8Array.from(bytes);\n }\n function utf8Decode(input) {\n let output = \"\";\n for (let index = 0; index < input.length; index += 1) {\n const first = input[index] ?? 0;\n if (first < 128) {\n output += String.fromCharCode(first);\n continue;\n }\n if (first >= 194 && first <= 223) {\n const second = input[index + 1];\n if (isUtf8Continuation(second)) {\n output += String.fromCodePoint((first & 31) << 6 | second & 63);\n index += 1;\n continue;\n }\n output += \"�\";\n continue;\n }\n if (first >= 224 && first <= 239) {\n const second = input[index + 1];\n const third = input[index + 2];\n if (isValidUtf8SecondForThreeByte(first, second) && isUtf8Continuation(third)) {\n output += String.fromCodePoint((first & 15) << 12 | (second & 63) << 6 | third & 63);\n index += 2;\n continue;\n }\n output += \"�\";\n if (isValidUtf8SecondForThreeByte(first, second)) index += 1;\n continue;\n }\n if (first >= 240 && first <= 244) {\n const second = input[index + 1];\n const third = input[index + 2];\n const fourth = input[index + 3];\n if (isValidUtf8SecondForFourByte(first, second) && isUtf8Continuation(third) && isUtf8Continuation(fourth)) {\n output += String.fromCodePoint((first & 7) << 18 | (second & 63) << 12 | (third & 63) << 6 | fourth & 63);\n index += 3;\n continue;\n }\n output += \"�\";\n if (isValidUtf8SecondForFourByte(first, second)) index += isUtf8Continuation(third) ? 2 : 1;\n continue;\n }\n output += \"�\";\n }\n return output;\n }\n function isUtf8Continuation(value) {\n return value !== void 0 && value >= 128 && value <= 191;\n }\n function isValidUtf8SecondForThreeByte(first, second) {\n if (second === void 0) return false;\n if (first === 224) return second >= 160 && second <= 191;\n if (first === 237) return second >= 128 && second <= 159;\n return second >= 128 && second <= 191;\n }\n function isValidUtf8SecondForFourByte(first, second) {\n if (second === void 0) return false;\n if (first === 240) return second >= 144 && second <= 191;\n if (first === 244) return second >= 128 && second <= 143;\n return second >= 128 && second <= 191;\n }\n var TextEncoderShim = class {\n encoding = \"utf-8\";\n encode(input = \"\") {\n return utf8Encode(String(input));\n }\n };\n var TextDecoderShim = class {\n encoding;\n constructor(label = \"utf-8\") {\n const normalized = label.toLowerCase();\n if (![\n \"utf-8\",\n \"utf8\",\n \"unicode-1-1-utf-8\"\n ].includes(normalized)) throw new TypeError(`Unsupported encoding: ${label}`);\n this.encoding = \"utf-8\";\n }\n decode(input) {\n if (input === void 0) return \"\";\n return utf8Decode(copyBytes(input));\n }\n };\n const textEncoder = new TextEncoderShim();\n const textDecoder = new TextDecoderShim();\n var URLSearchParamsShim = class URLSearchParamsShim {\n #entries = [];\n #onChange;\n constructor(init = \"\", onChange) {\n this.#onChange = onChange;\n if (typeof init === \"string\") {\n const source = init.startsWith(\"?\") ? init.slice(1) : init;\n if (!source) return;\n for (const pair of source.split(\"&\")) {\n if (!pair) continue;\n const separatorIndex = pair.indexOf(\"=\");\n const key = separatorIndex >= 0 ? pair.slice(0, separatorIndex) : pair;\n const value = separatorIndex >= 0 ? pair.slice(separatorIndex + 1) : \"\";\n this.#entries.push([decodeUrlParam(key), decodeUrlParam(value)]);\n }\n return;\n }\n if (init instanceof URLSearchParamsShim) {\n this.#entries = [...init.#entries];\n return;\n }\n if (Array.isArray(init)) {\n this.#entries = init.map(([key, value]) => [String(key), String(value)]);\n return;\n }\n this.#entries = Object.entries(init).map(([key, value]) => [key, String(value)]);\n }\n append(name, value) {\n this.#entries.push([String(name), String(value)]);\n this.#onChange?.();\n }\n delete(name) {\n const normalized = String(name);\n this.#entries = this.#entries.filter(([key]) => key !== normalized);\n this.#onChange?.();\n }\n entries() {\n return this.#entries[Symbol.iterator]();\n }\n forEach(callback) {\n for (const [key, value] of this.#entries) callback(value, key, this);\n }\n get(name) {\n return this.#entries.find(([key]) => key === String(name))?.[1] ?? null;\n }\n getAll(name) {\n return this.#entries.filter(([key]) => key === String(name)).map(([, value]) => value);\n }\n has(name) {\n return this.#entries.some(([key]) => key === String(name));\n }\n keys() {\n return this.#entries.map(([key]) => key)[Symbol.iterator]();\n }\n set(name, value) {\n const normalizedName = String(name);\n const normalizedValue = String(value);\n const next = [];\n let replaced = false;\n for (const entry of this.#entries) {\n if (entry[0] !== normalizedName) {\n next.push(entry);\n continue;\n }\n if (!replaced) {\n next.push([normalizedName, normalizedValue]);\n replaced = true;\n }\n }\n if (!replaced) next.push([normalizedName, normalizedValue]);\n this.#entries = next;\n this.#onChange?.();\n }\n toString() {\n return this.#entries.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join(\"&\");\n }\n values() {\n return this.#entries.map(([, value]) => value)[Symbol.iterator]();\n }\n [Symbol.iterator]() {\n return this.entries();\n }\n };\n function decodeUrlParam(value) {\n return decodeURIComponent(value.replace(/\\+/gu, \" \"));\n }\n function parseAbsoluteUrl(input) {\n const match = /^(?<protocol>[a-zA-Z][a-zA-Z\\d+.-]*:)\\/\\/(?<host>[^/?#]*)(?<pathname>[^?#]*)?(?<search>\\?[^#]*)?(?<hash>#.*)?$/u.exec(input);\n if (!match?.groups?.protocol || !match.groups.host) return;\n return {\n protocol: match.groups.protocol,\n host: match.groups.host,\n pathname: match.groups.pathname || \"/\",\n search: match.groups.search || \"\",\n hash: match.groups.hash || \"\"\n };\n }\n function normalizePathname(pathname) {\n const segments = [];\n for (const part of pathname.split(\"/\")) {\n if (!part || part === \".\") continue;\n if (part === \"..\") {\n segments.pop();\n continue;\n }\n segments.push(part);\n }\n return `/${segments.join(\"/\")}`;\n }\n function resolveUrl(input, base) {\n const absolute = parseAbsoluteUrl(input);\n if (absolute) return absolute;\n if (base === void 0) throw new TypeError(`Invalid URL: ${input}`);\n const baseUrl = base instanceof URLShim ? base : new URLShim(String(base));\n const basePath = baseUrl.pathname.endsWith(\"/\") ? baseUrl.pathname : baseUrl.pathname.slice(0, baseUrl.pathname.lastIndexOf(\"/\") + 1);\n const [beforeHash, rawHash = \"\"] = input.split(\"#\");\n const hasExplicitSearch = beforeHash?.includes(\"?\") ?? false;\n const [rawPath, rawSearch = \"\"] = (beforeHash ?? \"\").split(\"?\");\n const pathname = rawPath === \"\" && (input === \"\" || input.startsWith(\"?\") || input.startsWith(\"#\")) ? baseUrl.pathname : rawPath?.startsWith(\"/\") ? rawPath : `${basePath}${rawPath || \"\"}`;\n return {\n protocol: baseUrl.protocol,\n host: baseUrl.host,\n pathname: normalizePathname(pathname),\n search: hasExplicitSearch ? `?${rawSearch}` : rawPath === \"\" && (input === \"\" || input.startsWith(\"#\")) ? baseUrl.search : \"\",\n hash: rawHash ? `#${rawHash}` : \"\"\n };\n }\n var URLShim = class {\n host;\n hostname;\n origin;\n password = \"\";\n port;\n protocol;\n searchParams;\n username = \"\";\n hash;\n pathname;\n #search;\n constructor(input, base) {\n const parsed = resolveUrl(String(input), base);\n this.protocol = parsed.protocol;\n this.host = parsed.host;\n const portIndex = this.host.lastIndexOf(\":\");\n this.hostname = portIndex >= 0 ? this.host.slice(0, portIndex) : this.host;\n this.port = portIndex >= 0 ? this.host.slice(portIndex + 1) : \"\";\n this.pathname = parsed.pathname;\n this.#search = parsed.search;\n this.hash = parsed.hash;\n this.origin = `${this.protocol}//${this.host}`;\n this.searchParams = new URLSearchParamsShim(this.#search, () => {\n const next = this.searchParams.toString();\n this.#search = next ? `?${next}` : \"\";\n });\n }\n get href() {\n return `${this.origin}${this.pathname}${this.#search}${this.hash}`;\n }\n get search() {\n return this.#search;\n }\n toString() {\n return this.href;\n }\n toJSON() {\n return this.href;\n }\n };\n var ReadableStreamShim = class {\n #queue = [];\n #closed = false;\n #pulling = false;\n #source;\n #controller;\n #pending;\n constructor(source = {}) {\n this.#source = source;\n this.#controller = {\n enqueue: (value) => {\n if (this.#pending) {\n this.#pending.resolve({\n done: false,\n value\n });\n this.#pending = void 0;\n return;\n }\n this.#queue.push(value);\n },\n close: () => {\n this.#closed = true;\n if (this.#pending) {\n this.#pending.resolve({ done: true });\n this.#pending = void 0;\n }\n }\n };\n source.start?.(this.#controller);\n }\n async #pull() {\n if (this.#pulling || this.#closed || !this.#source.pull) return;\n this.#pulling = true;\n try {\n await this.#source.pull(this.#controller);\n } finally {\n this.#pulling = false;\n }\n }\n getReader() {\n return { read: async () => {\n if (this.#queue.length > 0) return {\n done: false,\n value: this.#queue.shift()\n };\n await this.#pull();\n if (this.#queue.length > 0) return {\n done: false,\n value: this.#queue.shift()\n };\n if (this.#closed) return {\n done: true,\n value: void 0\n };\n return await new Promise((resolve) => {\n this.#pending = { resolve };\n this.#pull();\n });\n } };\n }\n };\n var WritableStreamShim = class {\n #sink;\n constructor(sink = {}) {\n this.#sink = sink;\n }\n getWriter() {\n return {\n write: async (chunk) => {\n await this.#sink.write?.(chunk);\n },\n close: async () => {\n await this.#sink.close?.();\n }\n };\n }\n };\n var TransformStreamShim = class {\n readable;\n writable;\n constructor(transformer = {}) {\n const queue = [];\n let closed = false;\n let pending;\n const controller = {\n enqueue: (value) => {\n if (pending) {\n pending.resolve({\n done: false,\n value\n });\n pending = void 0;\n return;\n }\n queue.push(value);\n },\n close: () => {\n closed = true;\n if (pending) {\n pending.resolve({ done: true });\n pending = void 0;\n }\n }\n };\n this.readable = { getReader() {\n return { read: async () => {\n if (queue.length > 0) return {\n done: false,\n value: queue.shift()\n };\n if (closed) return {\n done: true,\n value: void 0\n };\n return await new Promise((resolve) => {\n pending = { resolve };\n });\n } };\n } };\n this.writable = new WritableStreamShim({\n write: async (chunk) => {\n transformer.transform?.(chunk, controller);\n },\n close: async () => {\n transformer.flush?.(controller);\n controller.close();\n }\n });\n }\n };\n function definePlatformGlobal(name, value, options = {}) {\n if (!options.overwrite && name in globalThis) return;\n Object.defineProperty(globalThis, name, {\n value,\n writable: true,\n configurable: true\n });\n }\n function formatLogArg(value) {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n function formatLogLine(args) {\n return args.map(formatLogArg).join(\" \");\n }\n const platformConsole = {\n log: (...args) => __caplets_log(\"log\", formatLogLine(args)),\n info: (...args) => __caplets_log(\"info\", formatLogLine(args)),\n warn: (...args) => __caplets_log(\"warn\", formatLogLine(args)),\n error: (...args) => __caplets_log(\"error\", formatLogLine(args)),\n debug: (...args) => __caplets_log(\"debug\", formatLogLine(args))\n };\n function normalizeEncoding(encoding) {\n const normalized = (encoding ?? \"utf8\").toLowerCase();\n switch (normalized) {\n case \"utf8\":\n case \"utf-8\":\n case \"base64\":\n case \"base64url\":\n case \"hex\": return normalized;\n default: throw new TypeError(`Unsupported Buffer encoding: ${encoding}`);\n }\n }\n function hexToBytes(value) {\n if (value.length % 2 !== 0) throw new TypeError(\"Invalid hex string length\");\n const bytes = new Uint8Array(value.length / 2);\n for (let index = 0; index < value.length; index += 2) {\n const parsed = Number.parseInt(value.slice(index, index + 2), 16);\n if (Number.isNaN(parsed)) throw new TypeError(\"Invalid hex string\");\n bytes[index / 2] = parsed;\n }\n return bytes;\n }\n function bytesToHex(bytes) {\n return Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n }\n function base64ToBytes(value, encoding) {\n let normalized = value.replace(/\\s+/gu, \"\");\n if (encoding === \"base64url\") normalized = normalized.replace(/-/gu, \"+\").replace(/_/gu, \"/\");\n const padding = normalized.length % 4;\n if (padding === 1) throw new TypeError(\"Invalid base64 string\");\n if (padding > 0) normalized = normalized.padEnd(normalized.length + (4 - padding), \"=\");\n const output = [];\n for (let index = 0; index < normalized.length; index += 4) {\n const values = normalized.slice(index, index + 4).split(\"\").map((char) => char === \"=\" ? 64 : base64Lookup.get(char) ?? NaN);\n if (values.some((entry) => Number.isNaN(entry))) throw new TypeError(\"Invalid base64 string\");\n const [a = 0, b = 0, c = 64, d = 64] = values;\n const triple = a << 18 | b << 12 | (c & 63) << 6 | d & 63;\n output.push(triple >> 16 & 255);\n if (c !== 64) output.push(triple >> 8 & 255);\n if (d !== 64) output.push(triple & 255);\n }\n return Uint8Array.from(output);\n }\n function bytesToBase64(bytes, encoding) {\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const a = bytes[index] ?? 0;\n const b = bytes[index + 1] ?? 0;\n const c = bytes[index + 2] ?? 0;\n const triple = a << 16 | b << 8 | c;\n output += BASE64_ALPHABET[triple >> 18 & 63];\n output += BASE64_ALPHABET[triple >> 12 & 63];\n output += index + 1 < bytes.length ? BASE64_ALPHABET[triple >> 6 & 63] : \"=\";\n output += index + 2 < bytes.length ? BASE64_ALPHABET[triple & 63] : \"=\";\n }\n if (encoding === \"base64url\") return output.replace(/\\+/gu, \"-\").replace(/\\//gu, \"_\").replace(/=+$/gu, \"\");\n return output;\n }\n function copyBytes(input) {\n if (input instanceof ArrayBuffer) return new Uint8Array(input.slice(0));\n return new Uint8Array(input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength));\n }\n function toBytes(input, encoding) {\n if (input instanceof BufferShim) return input.toUint8Array();\n if (typeof input === \"string\") switch (normalizeEncoding(encoding)) {\n case \"utf8\":\n case \"utf-8\": return textEncoder.encode(input);\n case \"base64\":\n case \"base64url\": return base64ToBytes(input, normalizeEncoding(encoding));\n case \"hex\": return hexToBytes(input);\n }\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return copyBytes(input);\n if (Array.isArray(input)) return Uint8Array.from(input);\n throw new TypeError(\"Buffer.from only supports strings, arrays, ArrayBuffers, and typed arrays\");\n }\n var BufferShim = class BufferShim {\n #bytes;\n byteLength;\n length;\n constructor(bytes) {\n this.#bytes = bytes;\n this.byteLength = bytes.byteLength;\n this.length = bytes.length;\n }\n static from(input, encoding) {\n return new BufferShim(toBytes(input, encoding));\n }\n static isBuffer(value) {\n return value instanceof BufferShim;\n }\n static byteLength(input, encoding) {\n return toBytes(input, encoding).byteLength;\n }\n toUint8Array() {\n return new Uint8Array(this.#bytes);\n }\n toString(encoding) {\n switch (normalizeEncoding(encoding)) {\n case \"utf8\":\n case \"utf-8\": return textDecoder.decode(this.#bytes);\n case \"base64\":\n case \"base64url\": return bytesToBase64(this.#bytes, normalizeEncoding(encoding));\n case \"hex\": return bytesToHex(this.#bytes);\n }\n }\n };\n function atobShim(input) {\n return Array.from(base64ToBytes(String(input), \"base64\"), (value) => String.fromCharCode(value)).join(\"\");\n }\n function btoaShim(input) {\n const bytes = new Uint8Array(input.length);\n for (let index = 0; index < input.length; index += 1) {\n const codePoint = input.charCodeAt(index);\n if (codePoint > 255) throw new TypeError(\"The string to be encoded contains characters outside of Latin1\");\n bytes[index] = codePoint;\n }\n return bytesToBase64(bytes, \"base64\");\n }\n function queueMicrotaskShim(callback) {\n Promise.resolve().then(callback);\n }\n var AbortSignalShim = class AbortSignalShim {\n aborted = false;\n reason;\n onabort = null;\n #listeners = /* @__PURE__ */ new Set();\n addEventListener(type, listener) {\n if (type === \"abort\" && listener) this.#listeners.add(listener);\n }\n removeEventListener(type, listener) {\n if (type === \"abort\" && listener) this.#listeners.delete(listener);\n }\n dispatchEvent(event) {\n if (event.type !== \"abort\") return true;\n this.onabort?.(event);\n for (const listener of this.#listeners) listener(event);\n return true;\n }\n throwIfAborted() {\n if (this.aborted) throw this.reason ?? /* @__PURE__ */ new Error(\"Operation was aborted\");\n }\n static abort(reason) {\n const signal = new AbortSignalShim();\n signal.abort(reason);\n return signal;\n }\n abort(reason) {\n if (this.aborted) return;\n this.aborted = true;\n this.reason = reason;\n this.dispatchEvent({\n type: \"abort\",\n target: this\n });\n }\n };\n var AbortControllerShim = class {\n signal = new AbortSignalShim();\n abort(reason) {\n this.signal.abort(reason);\n }\n };\n function cloneFormData(input) {\n const clone = new FormData();\n for (const [name, value] of input.entries()) {\n if (value instanceof File) {\n clone.append(name, new File([value], value.name, { type: value.type }), value.name);\n continue;\n }\n clone.append(name, value);\n }\n return clone;\n }\n function cloneBodyValue(input) {\n if (input === null || input === void 0 || typeof input === \"string\") return input;\n if (input instanceof FormData) return cloneFormData(input);\n if (input instanceof Blob) return input.slice(0, input.size, input.type);\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return copyBytes(input);\n return input;\n }\n function blobFromBody(input) {\n if (input instanceof Blob) return input;\n if (typeof input === \"string\") return new Blob([input], { type: \"text/plain;charset=utf-8\" });\n if (input instanceof FormData) throw new TypeError(\"FormData body reading is not supported in Code Mode\");\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return new Blob([copyBytes(input)]);\n return new Blob([]);\n }\n var BodyMixin = class {\n _bodyInit;\n bodyUsed = false;\n body = null;\n constructor(body) {\n this._bodyInit = cloneBodyValue(body);\n }\n async arrayBuffer() {\n this.bodyUsed = true;\n return await blobFromBody(this._bodyInit).arrayBuffer();\n }\n async blob() {\n this.bodyUsed = true;\n return blobFromBody(this._bodyInit);\n }\n async formData() {\n this.bodyUsed = true;\n if (this._bodyInit instanceof FormData) return cloneFormData(this._bodyInit);\n throw new TypeError(\"Body does not contain FormData\");\n }\n async json() {\n return JSON.parse(await this.text());\n }\n async text() {\n this.bodyUsed = true;\n return await blobFromBody(this._bodyInit).text();\n }\n };\n function toHeaders(init) {\n return init instanceof Headers ? new Headers(init) : new Headers(init ?? {});\n }\n function normalizeMethod(method) {\n return String(method ?? \"GET\").toUpperCase();\n }\n var RequestShim = class RequestShim extends BodyMixin {\n headers;\n method;\n signal;\n url;\n constructor(input, init = {}) {\n const sourceBody = input instanceof RequestShim ? input._bodyInit : void 0;\n super(init.body ?? sourceBody);\n if (input instanceof RequestShim) this.url = input.url;\n else this.url = input instanceof URLShim ? input.href : new URLShim(String(input)).href;\n this.method = normalizeMethod(init.method ?? (input instanceof RequestShim ? input.method : \"GET\"));\n this.headers = toHeaders(init.headers ?? (input instanceof RequestShim ? input.headers : void 0));\n this.signal = init.signal ?? (input instanceof RequestShim ? input.signal : new AbortControllerShim().signal);\n }\n clone() {\n return new RequestShim(this, {\n method: this.method,\n headers: this.headers,\n body: this._bodyInit,\n signal: this.signal\n });\n }\n };\n var ResponseShim = class ResponseShim extends BodyMixin {\n headers;\n ok;\n redirected = false;\n status;\n statusText;\n type = \"default\";\n url = \"\";\n constructor(body, init = {}) {\n super(body);\n this.status = init.status ?? 200;\n this.statusText = init.statusText ?? \"\";\n this.headers = toHeaders(init.headers);\n this.ok = this.status >= 200 && this.status <= 299;\n }\n clone() {\n return new ResponseShim(this._bodyInit, {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText\n });\n }\n static json(data, init) {\n const headers = toHeaders(init?.headers);\n if (!headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n const responseInit = { headers };\n if (init?.status !== void 0) responseInit.status = init.status;\n if (init?.statusText !== void 0) responseInit.statusText = init.statusText;\n return new ResponseShim(JSON.stringify(data), responseInit);\n }\n };\n function disabledFetch() {\n throw new Error(DISABLED_FETCH_MESSAGE);\n }\n const integerTypedArrayConstructors = new Set([\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n typeof BigInt64Array === \"undefined\" ? void 0 : BigInt64Array,\n typeof BigUint64Array === \"undefined\" ? void 0 : BigUint64Array\n ]);\n var QuotaExceededErrorShim = class extends Error {\n constructor(message) {\n super(message);\n this.name = \"QuotaExceededError\";\n }\n };\n const platformCrypto = {\n randomUUID() {\n const randomUUID = capletsPlatformHost.randomUUID;\n if (!randomUUID) throw new Error(\"Code Mode platform random UUID bridge is not installed\");\n return randomUUID();\n },\n getRandomValues(typedArray) {\n if (!ArrayBuffer.isView(typedArray) || typedArray instanceof DataView) throw new TypeError(\"crypto.getRandomValues requires an integer typed array\");\n if (!integerTypedArrayConstructors.has(typedArray.constructor)) throw new TypeError(\"crypto.getRandomValues requires an integer typed array\");\n if (typedArray.byteLength > 65536) throw new QuotaExceededErrorShim(\"crypto.getRandomValues cannot generate more than 65,536 bytes\");\n const randomValues = capletsPlatformHost.randomValues;\n if (!randomValues) throw new Error(\"Code Mode platform random values bridge is not installed\");\n const bytes = randomValues(typedArray.byteLength);\n new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength).set(bytes);\n return typedArray;\n }\n };\n let nextTimerId = 1;\n const activeTimers = /* @__PURE__ */ new Set();\n function normalizeTimerDelay(delay) {\n const value = Number(delay ?? 0);\n if (!Number.isFinite(value) || value <= 0) return 0;\n return Math.trunc(value);\n }\n function setTimeoutShim(callback, delay, ...args) {\n if (typeof callback !== \"function\") throw new TypeError(\"setTimeout callback must be a function\");\n const timerId = nextTimerId++;\n activeTimers.add(timerId);\n const sleep = capletsPlatformHost.sleep;\n if (!sleep) throw new Error(\"Code Mode platform sleep bridge is not installed\");\n sleep(timerId, normalizeTimerDelay(delay)).then((fired) => {\n activeTimers.delete(timerId);\n if (fired) callback(...args);\n });\n return timerId;\n }\n function clearTimeoutShim(timerId) {\n const id = Number(timerId);\n activeTimers.delete(id);\n capletsPlatformHost.clearTimer?.(id);\n }\n function setIntervalShim(callback, delay, ...args) {\n if (typeof callback !== \"function\") throw new TypeError(\"setInterval callback must be a function\");\n const timerId = nextTimerId++;\n const intervalDelay = normalizeTimerDelay(delay);\n activeTimers.add(timerId);\n const tick = () => {\n const sleep = capletsPlatformHost.sleep;\n if (!sleep) throw new Error(\"Code Mode platform sleep bridge is not installed\");\n sleep(timerId, intervalDelay).then((fired) => {\n if (!fired || !activeTimers.has(timerId)) {\n activeTimers.delete(timerId);\n return;\n }\n callback(...args);\n if (activeTimers.has(timerId)) tick();\n });\n };\n tick();\n return timerId;\n }\n function clearIntervalShim(timerId) {\n clearTimeoutShim(timerId);\n }\n definePlatformGlobal(\"atob\", atobShim);\n definePlatformGlobal(\"btoa\", btoaShim);\n definePlatformGlobal(\"Buffer\", BufferShim);\n definePlatformGlobal(\"TextEncoder\", TextEncoderShim);\n definePlatformGlobal(\"TextDecoder\", TextDecoderShim);\n definePlatformGlobal(\"URL\", URLShim);\n definePlatformGlobal(\"URLSearchParams\", URLSearchParamsShim);\n definePlatformGlobal(\"structuredClone\", esm_default);\n definePlatformGlobal(\"Headers\", Headers);\n definePlatformGlobal(\"Blob\", Blob);\n definePlatformGlobal(\"File\", File);\n definePlatformGlobal(\"FormData\", FormData);\n definePlatformGlobal(\"ReadableStream\", ReadableStreamShim);\n definePlatformGlobal(\"WritableStream\", WritableStreamShim);\n definePlatformGlobal(\"TransformStream\", TransformStreamShim);\n definePlatformGlobal(\"AbortController\", AbortControllerShim);\n definePlatformGlobal(\"AbortSignal\", AbortSignalShim);\n definePlatformGlobal(\"Request\", RequestShim);\n definePlatformGlobal(\"Response\", ResponseShim);\n definePlatformGlobal(\"crypto\", platformCrypto);\n definePlatformGlobal(\"setTimeout\", setTimeoutShim);\n definePlatformGlobal(\"clearTimeout\", clearTimeoutShim);\n definePlatformGlobal(\"setInterval\", setIntervalShim);\n definePlatformGlobal(\"clearInterval\", clearIntervalShim);\n definePlatformGlobal(\"queueMicrotask\", queueMicrotaskShim);\n definePlatformGlobal(\"console\", platformConsole);\n definePlatformGlobal(\"fetch\", disabledFetch, { overwrite: true });\n //#endregion\n})();";
|
|
77193
77723
|
//#endregion
|
|
77194
77724
|
//#region src/code-mode/sandbox.ts
|
|
77725
|
+
const CODE_MODE_SANDBOX_METHODS = new Set([
|
|
77726
|
+
"inspect",
|
|
77727
|
+
"check",
|
|
77728
|
+
"tools",
|
|
77729
|
+
"searchTools",
|
|
77730
|
+
"describeTool",
|
|
77731
|
+
"callTool",
|
|
77732
|
+
"resources",
|
|
77733
|
+
"searchResources",
|
|
77734
|
+
"resourceTemplates",
|
|
77735
|
+
"readResource",
|
|
77736
|
+
"prompts",
|
|
77737
|
+
"searchPrompts",
|
|
77738
|
+
"getPrompt",
|
|
77739
|
+
"complete",
|
|
77740
|
+
"readLogs",
|
|
77741
|
+
"readRecovery"
|
|
77742
|
+
]);
|
|
77743
|
+
const CODE_MODE_DEBUG_METHODS = new Set(["readLogs", "readRecovery"]);
|
|
77195
77744
|
var QuickJsCodeModeSandbox = class {
|
|
77196
77745
|
async run(input) {
|
|
77197
77746
|
return await evaluateInQuickJs(input);
|
|
77198
77747
|
}
|
|
77748
|
+
async createSession() {
|
|
77749
|
+
return new QuickJsCodeModeReplSession((await getQuickJS()).newRuntime());
|
|
77750
|
+
}
|
|
77751
|
+
};
|
|
77752
|
+
var QuickJsCodeModeReplSession = class {
|
|
77753
|
+
#runtime;
|
|
77754
|
+
#context;
|
|
77755
|
+
#pendingDeferreds = /* @__PURE__ */ new Set();
|
|
77756
|
+
#pendingInvokes = /* @__PURE__ */ new Set();
|
|
77757
|
+
#platformHost;
|
|
77758
|
+
#capletIds = /* @__PURE__ */ new Set();
|
|
77759
|
+
#persistentNames = /* @__PURE__ */ new Set();
|
|
77760
|
+
#invoke = async () => {
|
|
77761
|
+
throw new Error("Code Mode invoke bridge is not initialized.");
|
|
77762
|
+
};
|
|
77763
|
+
#deadlineMs = 0;
|
|
77764
|
+
#timeoutMs = 0;
|
|
77765
|
+
#logs = [];
|
|
77766
|
+
#disposed = false;
|
|
77767
|
+
#running = false;
|
|
77768
|
+
#disposeRequested = false;
|
|
77769
|
+
#globalNameCheckpoint = /* @__PURE__ */ new Set();
|
|
77770
|
+
#persistDescriptorCheckpoint = "";
|
|
77771
|
+
#checkpointToken = randomUUID();
|
|
77772
|
+
constructor(runtime) {
|
|
77773
|
+
this.#runtime = runtime;
|
|
77774
|
+
this.#runtime.setMemoryLimit(64 * 1024 * 1024);
|
|
77775
|
+
this.#runtime.setMaxStackSize(1 * 1024 * 1024);
|
|
77776
|
+
this.#context = runtime.newContext();
|
|
77777
|
+
this.#installStableBridges();
|
|
77778
|
+
this.#platformHost = installCodeModePlatformHost(this.#context, this.#pendingDeferreds, {});
|
|
77779
|
+
this.#evalInitSource();
|
|
77780
|
+
}
|
|
77781
|
+
async run(input) {
|
|
77782
|
+
if (this.#disposed) return {
|
|
77783
|
+
ok: false,
|
|
77784
|
+
error: "Code Mode session is disposed.",
|
|
77785
|
+
logs: []
|
|
77786
|
+
};
|
|
77787
|
+
if (this.#disposeRequested) return {
|
|
77788
|
+
ok: false,
|
|
77789
|
+
error: "Code Mode session is disposed.",
|
|
77790
|
+
logs: []
|
|
77791
|
+
};
|
|
77792
|
+
if (this.#running) return {
|
|
77793
|
+
ok: false,
|
|
77794
|
+
error: "Code Mode session is already running.",
|
|
77795
|
+
logs: []
|
|
77796
|
+
};
|
|
77797
|
+
this.#running = true;
|
|
77798
|
+
const timeoutMs = Math.max(100, input.timeoutMs);
|
|
77799
|
+
const deadlineMs = Date.now() + timeoutMs;
|
|
77800
|
+
this.#runtime.setInterruptHandler(shouldInterruptAfterDeadline(deadlineMs));
|
|
77801
|
+
this.#logs = [];
|
|
77802
|
+
let shouldDispose = false;
|
|
77803
|
+
try {
|
|
77804
|
+
this.#refreshInvokeBridge(input.invoke, deadlineMs, timeoutMs);
|
|
77805
|
+
const bridgeResult = this.#context.evalCode(buildBridgeRefreshSource(input.capletIds, [...this.#capletIds]));
|
|
77806
|
+
if (bridgeResult.error) {
|
|
77807
|
+
const error = this.#context.dump(bridgeResult.error);
|
|
77808
|
+
bridgeResult.error.dispose();
|
|
77809
|
+
const result = {
|
|
77810
|
+
ok: false,
|
|
77811
|
+
error: normalizeError(error, deadlineMs, timeoutMs),
|
|
77812
|
+
logs: this.#logs,
|
|
77813
|
+
...optionalStack(stackFromDump(error))
|
|
77814
|
+
};
|
|
77815
|
+
shouldDispose = isTimeoutMessage(result.error, timeoutMs);
|
|
77816
|
+
return result;
|
|
77817
|
+
}
|
|
77818
|
+
bridgeResult.value.dispose();
|
|
77819
|
+
this.#capletIds = new Set(input.capletIds);
|
|
77820
|
+
const cell = buildSessionCellSource(input.code, input.capletIds, [...this.#persistentNames], this.#checkpointToken);
|
|
77821
|
+
const resetResult = this.#context.evalCode(buildPlatformResetSource());
|
|
77822
|
+
if (resetResult.error) {
|
|
77823
|
+
const error = this.#context.dump(resetResult.error);
|
|
77824
|
+
resetResult.error.dispose();
|
|
77825
|
+
const result = {
|
|
77826
|
+
ok: false,
|
|
77827
|
+
error: `Code Mode session state is corrupted: ${normalizeError(error, deadlineMs, timeoutMs)}`,
|
|
77828
|
+
logs: this.#logs,
|
|
77829
|
+
...optionalStack(stackFromDump(error))
|
|
77830
|
+
};
|
|
77831
|
+
shouldDispose = true;
|
|
77832
|
+
return result;
|
|
77833
|
+
}
|
|
77834
|
+
resetResult.value.dispose();
|
|
77835
|
+
this.#snapshotGlobalNames();
|
|
77836
|
+
this.#snapshotPersistDescriptors();
|
|
77837
|
+
this.#snapshotPersistentNames([...this.#persistentNames]);
|
|
77838
|
+
let pendingInvokePersistentValuesChanged = false;
|
|
77839
|
+
const result = await evaluateCellInContext({
|
|
77840
|
+
code: input.code,
|
|
77841
|
+
compiledSource: cell.source,
|
|
77842
|
+
context: this.#context,
|
|
77843
|
+
runtime: this.#runtime,
|
|
77844
|
+
pendingDeferreds: this.#pendingDeferreds,
|
|
77845
|
+
pendingInvokes: this.#pendingInvokes,
|
|
77846
|
+
deadlineMs,
|
|
77847
|
+
timeoutMs,
|
|
77848
|
+
logs: this.#logs,
|
|
77849
|
+
session: true,
|
|
77850
|
+
afterPendingInvokesDrained: () => {
|
|
77851
|
+
pendingInvokePersistentValuesChanged = this.#persistentValuesDivergedFromPersist(cell.persistentNames);
|
|
77852
|
+
this.#snapshotPersistentNames(cell.persistentNames);
|
|
77853
|
+
}
|
|
77854
|
+
});
|
|
77855
|
+
if (result.ok) {
|
|
77856
|
+
for (const name of cell.persistentNames) this.#persistentNames.add(name);
|
|
77857
|
+
this.#snapshotPersistentNames(cell.persistentNames);
|
|
77858
|
+
} else {
|
|
77859
|
+
this.#restorePersistentNames([...this.#persistentNames]);
|
|
77860
|
+
this.#rollbackNewPersistentNames(cell.newNames);
|
|
77861
|
+
}
|
|
77862
|
+
const platformRestored = result.ok ? this.#restorePlatformAfterRun() : true;
|
|
77863
|
+
const persistenceDescriptorsOk = result.ok && platformRestored ? this.#persistentDescriptorsOk(cell.persistentNames) : true;
|
|
77864
|
+
const persistentGlobalDescriptorsOk = this.#persistentGlobalDescriptorsOk(result.ok ? cell.persistentNames : [...this.#persistentNames]);
|
|
77865
|
+
const hasGlobalNameAdditions = this.#hasGlobalNameAdditions(result.ok ? cell.persistentNames : []);
|
|
77866
|
+
const directPersistAccess = this.#isPersistTainted();
|
|
77867
|
+
const persistDescriptorsChanged = this.#persistDescriptorsChanged(result.ok ? cell.snapshotNames : []);
|
|
77868
|
+
const hasObjectLikePersistentState = this.#hasObjectLikePersistentState();
|
|
77869
|
+
shouldDispose = result.ok ? pendingInvokePersistentValuesChanged || this.#pendingDeferreds.size > 0 || hasGlobalNameAdditions || directPersistAccess || persistDescriptorsChanged || !this.#isGlobalExtensible() || !persistentGlobalDescriptorsOk || !persistenceDescriptorsOk || !platformRestored : isTimeoutMessage(result.error, timeoutMs) || this.#pendingDeferreds.size > 0 || cell.newNames.length > 0 || hasGlobalNameAdditions || directPersistAccess || persistDescriptorsChanged || hasObjectLikePersistentState || !persistentGlobalDescriptorsOk || !this.#isGlobalExtensible();
|
|
77870
|
+
if (!shouldDispose) this.#clearPendingDeferreds();
|
|
77871
|
+
return result;
|
|
77872
|
+
} catch (error) {
|
|
77873
|
+
const result = {
|
|
77874
|
+
ok: false,
|
|
77875
|
+
error: normalizeError(error, deadlineMs, timeoutMs),
|
|
77876
|
+
logs: this.#logs,
|
|
77877
|
+
...optionalStack(stackFromError(error))
|
|
77878
|
+
};
|
|
77879
|
+
shouldDispose = true;
|
|
77880
|
+
return result;
|
|
77881
|
+
} finally {
|
|
77882
|
+
this.#running = false;
|
|
77883
|
+
if (!this.#disposed) this.#runtime.setInterruptHandler(() => false);
|
|
77884
|
+
if (shouldDispose) this.dispose();
|
|
77885
|
+
if (this.#disposeRequested) this.#disposeNow();
|
|
77886
|
+
}
|
|
77887
|
+
}
|
|
77888
|
+
dispose() {
|
|
77889
|
+
if (this.#disposed) return;
|
|
77890
|
+
if (this.#running) {
|
|
77891
|
+
this.#disposeRequested = true;
|
|
77892
|
+
return;
|
|
77893
|
+
}
|
|
77894
|
+
this.#disposeNow();
|
|
77895
|
+
}
|
|
77896
|
+
isDisposed() {
|
|
77897
|
+
return this.#disposed;
|
|
77898
|
+
}
|
|
77899
|
+
#disposeNow() {
|
|
77900
|
+
if (this.#disposed) return;
|
|
77901
|
+
this.#disposeRequested = false;
|
|
77902
|
+
this.#disposed = true;
|
|
77903
|
+
this.#platformHost.dispose();
|
|
77904
|
+
for (const deferred of this.#pendingDeferreds) if (deferred.alive) deferred.dispose();
|
|
77905
|
+
this.#pendingDeferreds.clear();
|
|
77906
|
+
this.#pendingInvokes.clear();
|
|
77907
|
+
this.#context.dispose();
|
|
77908
|
+
this.#runtime.dispose();
|
|
77909
|
+
}
|
|
77910
|
+
#installStableBridges() {
|
|
77911
|
+
const logBridge = this.#context.newFunction("__caplets_log", (levelHandle, messageHandle) => {
|
|
77912
|
+
this.#logs.push({
|
|
77913
|
+
level: logLevel(this.#context.getString(levelHandle)),
|
|
77914
|
+
message: this.#context.getString(messageHandle),
|
|
77915
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
77916
|
+
});
|
|
77917
|
+
return this.#context.undefined;
|
|
77918
|
+
});
|
|
77919
|
+
this.#context.setProp(this.#context.global, "__caplets_log", logBridge);
|
|
77920
|
+
logBridge.dispose();
|
|
77921
|
+
const invokeBridge = createInvokeJsonBridge(this.#context, this.#pendingDeferreds, this.#pendingInvokes, () => this.#invoke, () => this.#deadlineMs, () => this.#timeoutMs, (capletId) => this.#capletIds.has(capletId));
|
|
77922
|
+
this.#context.setProp(this.#context.global, "__caplets_invoke_json", invokeBridge);
|
|
77923
|
+
invokeBridge.dispose();
|
|
77924
|
+
const activeCapletBridge = this.#context.newFunction("__caplets_is_active_id", (capletIdHandle) => this.#capletIds.has(this.#context.getString(capletIdHandle)) ? this.#context.true : this.#context.false);
|
|
77925
|
+
this.#context.setProp(this.#context.global, "__caplets_is_active_id", activeCapletBridge);
|
|
77926
|
+
activeCapletBridge.dispose();
|
|
77927
|
+
const protectInvokeBridge = this.#context.evalCode([
|
|
77928
|
+
"Object.defineProperty(globalThis, '__caplets_log', { configurable: false, writable: false, value: globalThis.__caplets_log });",
|
|
77929
|
+
"Object.defineProperty(globalThis, '__caplets_invoke_json', { configurable: false, writable: false, value: globalThis.__caplets_invoke_json });",
|
|
77930
|
+
"Object.defineProperty(globalThis, '__caplets_is_active_id', { configurable: false, writable: false, value: globalThis.__caplets_is_active_id });"
|
|
77931
|
+
].join("\n"));
|
|
77932
|
+
if (protectInvokeBridge.error) {
|
|
77933
|
+
const error = this.#context.dump(protectInvokeBridge.error);
|
|
77934
|
+
protectInvokeBridge.error.dispose();
|
|
77935
|
+
throw new Error(errorMessage$2(error));
|
|
77936
|
+
}
|
|
77937
|
+
protectInvokeBridge.value.dispose();
|
|
77938
|
+
}
|
|
77939
|
+
#evalInitSource() {
|
|
77940
|
+
const result = this.#context.evalCode(buildSessionInitSource(this.#checkpointToken));
|
|
77941
|
+
if (result.error) {
|
|
77942
|
+
const error = this.#context.dump(result.error);
|
|
77943
|
+
result.error.dispose();
|
|
77944
|
+
throw new Error(errorMessage$2(error));
|
|
77945
|
+
}
|
|
77946
|
+
result.value.dispose();
|
|
77947
|
+
}
|
|
77948
|
+
#refreshInvokeBridge(invoke, deadlineMs, timeoutMs) {
|
|
77949
|
+
this.#invoke = invoke;
|
|
77950
|
+
this.#deadlineMs = deadlineMs;
|
|
77951
|
+
this.#timeoutMs = timeoutMs;
|
|
77952
|
+
}
|
|
77953
|
+
#rollbackNewPersistentNames(names) {
|
|
77954
|
+
if (names.length === 0 || this.#disposed) return;
|
|
77955
|
+
const result = this.#context.evalCode(names.map((name) => `(0, eval)(${JSON.stringify(`${name} = undefined;`)});`).join("\n"));
|
|
77956
|
+
if (result.error) {
|
|
77957
|
+
result.error.dispose();
|
|
77958
|
+
return;
|
|
77959
|
+
}
|
|
77960
|
+
result.value.dispose();
|
|
77961
|
+
}
|
|
77962
|
+
#clearPendingDeferreds() {
|
|
77963
|
+
this.#platformHost.dispose();
|
|
77964
|
+
for (const deferred of this.#pendingDeferreds) if (deferred.alive) deferred.dispose();
|
|
77965
|
+
this.#pendingDeferreds.clear();
|
|
77966
|
+
}
|
|
77967
|
+
#snapshotGlobalNames() {
|
|
77968
|
+
if (this.#disposed) return;
|
|
77969
|
+
const result = this.#context.evalCode("__caplets_global_keys()");
|
|
77970
|
+
if (result.error) {
|
|
77971
|
+
result.error.dispose();
|
|
77972
|
+
return;
|
|
77973
|
+
}
|
|
77974
|
+
const names = this.#context.dump(result.value);
|
|
77975
|
+
this.#globalNameCheckpoint = new Set(names.filter((name) => !this.#isInternalGlobalName(name)));
|
|
77976
|
+
result.value.dispose();
|
|
77977
|
+
}
|
|
77978
|
+
#snapshotPersistDescriptors() {
|
|
77979
|
+
if (this.#disposed) return;
|
|
77980
|
+
const result = this.#context.evalCode("__caplets_persist_descriptor_fingerprint()");
|
|
77981
|
+
if (result.error) {
|
|
77982
|
+
result.error.dispose();
|
|
77983
|
+
this.#persistDescriptorCheckpoint = "";
|
|
77984
|
+
return;
|
|
77985
|
+
}
|
|
77986
|
+
this.#persistDescriptorCheckpoint = String(this.#context.dump(result.value));
|
|
77987
|
+
result.value.dispose();
|
|
77988
|
+
}
|
|
77989
|
+
#persistDescriptorsChanged(allowedNames = []) {
|
|
77990
|
+
if (this.#disposed) return false;
|
|
77991
|
+
const result = this.#context.evalCode(`__caplets_persist_descriptor_fingerprint(${JSON.stringify(allowedNames)})`);
|
|
77992
|
+
if (result.error) {
|
|
77993
|
+
result.error.dispose();
|
|
77994
|
+
return true;
|
|
77995
|
+
}
|
|
77996
|
+
const fingerprint = String(this.#context.dump(result.value));
|
|
77997
|
+
result.value.dispose();
|
|
77998
|
+
return fingerprint !== filterPersistDescriptorFingerprint(this.#persistDescriptorCheckpoint, allowedNames);
|
|
77999
|
+
}
|
|
78000
|
+
#hasGlobalNameAdditions(allowedNames = []) {
|
|
78001
|
+
if (this.#disposed) return false;
|
|
78002
|
+
const result = this.#context.evalCode("__caplets_global_keys()");
|
|
78003
|
+
if (result.error) {
|
|
78004
|
+
result.error.dispose();
|
|
78005
|
+
return true;
|
|
78006
|
+
}
|
|
78007
|
+
const names = this.#context.dump(result.value);
|
|
78008
|
+
const allowedTokens = new Set(allowedNames.map((name) => `string:${name}`));
|
|
78009
|
+
const hasAdditions = names.filter((name) => !this.#isInternalGlobalName(name)).filter((name) => !allowedTokens.has(name)).some((name) => !this.#globalNameCheckpoint.has(name));
|
|
78010
|
+
result.value.dispose();
|
|
78011
|
+
return hasAdditions;
|
|
78012
|
+
}
|
|
78013
|
+
#isGlobalExtensible() {
|
|
78014
|
+
if (this.#disposed) return false;
|
|
78015
|
+
const result = this.#context.evalCode("__caplets_is_global_extensible()");
|
|
78016
|
+
if (result.error) {
|
|
78017
|
+
result.error.dispose();
|
|
78018
|
+
return false;
|
|
78019
|
+
}
|
|
78020
|
+
const isExtensible = this.#context.dump(result.value) === true;
|
|
78021
|
+
result.value.dispose();
|
|
78022
|
+
return isExtensible;
|
|
78023
|
+
}
|
|
78024
|
+
#restorePlatformAfterRun() {
|
|
78025
|
+
if (this.#disposed) return false;
|
|
78026
|
+
const result = this.#context.evalCode(buildPlatformResetSource());
|
|
78027
|
+
if (result.error) {
|
|
78028
|
+
result.error.dispose();
|
|
78029
|
+
return false;
|
|
78030
|
+
}
|
|
78031
|
+
result.value.dispose();
|
|
78032
|
+
return true;
|
|
78033
|
+
}
|
|
78034
|
+
#persistentDescriptorsOk(names) {
|
|
78035
|
+
if (names.length === 0 || this.#disposed) return true;
|
|
78036
|
+
const result = this.#context.evalCode(`__caplets_persist_descriptors_ok(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(names)})`);
|
|
78037
|
+
if (result.error) {
|
|
78038
|
+
result.error.dispose();
|
|
78039
|
+
return false;
|
|
78040
|
+
}
|
|
78041
|
+
const ok = this.#context.dump(result.value) === true;
|
|
78042
|
+
result.value.dispose();
|
|
78043
|
+
return ok;
|
|
78044
|
+
}
|
|
78045
|
+
#isPersistTainted() {
|
|
78046
|
+
if (this.#disposed) return false;
|
|
78047
|
+
const result = this.#context.evalCode(`__caplets_persist_is_tainted(${JSON.stringify(this.#checkpointToken)})`);
|
|
78048
|
+
if (result.error) {
|
|
78049
|
+
result.error.dispose();
|
|
78050
|
+
return true;
|
|
78051
|
+
}
|
|
78052
|
+
const tainted = this.#context.dump(result.value) === true;
|
|
78053
|
+
result.value.dispose();
|
|
78054
|
+
return tainted;
|
|
78055
|
+
}
|
|
78056
|
+
#hasObjectLikePersistentState() {
|
|
78057
|
+
if (this.#disposed || this.#persistentNames.size === 0) return false;
|
|
78058
|
+
const result = this.#context.evalCode(`__caplets_persist_has_object_like_values(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify([...this.#persistentNames])})`);
|
|
78059
|
+
if (result.error) {
|
|
78060
|
+
result.error.dispose();
|
|
78061
|
+
return true;
|
|
78062
|
+
}
|
|
78063
|
+
const hasObjectLike = this.#context.dump(result.value) === true;
|
|
78064
|
+
result.value.dispose();
|
|
78065
|
+
return hasObjectLike;
|
|
78066
|
+
}
|
|
78067
|
+
#persistentGlobalDescriptorsOk(names) {
|
|
78068
|
+
if (names.length === 0 || this.#disposed) return true;
|
|
78069
|
+
const result = this.#context.evalCode(`__caplets_persist_global_descriptors_ok(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(names)})`);
|
|
78070
|
+
if (result.error) {
|
|
78071
|
+
result.error.dispose();
|
|
78072
|
+
return false;
|
|
78073
|
+
}
|
|
78074
|
+
const ok = this.#context.dump(result.value) === true;
|
|
78075
|
+
result.value.dispose();
|
|
78076
|
+
return ok;
|
|
78077
|
+
}
|
|
78078
|
+
#isInternalGlobalName(name) {
|
|
78079
|
+
return name === "string:__caplets_log" || name === "string:__caplets_invoke_json" || name === "string:__caplets_is_active_id" || name === "string:__caplets_restore_platform" || name === "string:__caplets_global_keys" || name === "string:__caplets_assert_active_id" || name === "string:__caplets_handle" || name === "string:__caplets_persist" || name === "string:__caplets_persist_descriptor_fingerprint" || name === "string:__caplets_persist_descriptors_ok" || name === "string:__caplets_persist_is_tainted" || name === "string:__caplets_persist_has_object_like_values" || name === "string:__caplets_persist_global_descriptors_ok" || name === "string:__caplets_get_persist" || name === "string:__caplets_set_persist" || name === "string:__caplets_snapshot_persist" || name === "string:__caplets_checkpoint_value" || name === "string:__caplets_observe_promise" || name === "string:__caplets_json_parse";
|
|
78080
|
+
}
|
|
78081
|
+
#snapshotPersistentNames(names) {
|
|
78082
|
+
if (names.length === 0 || this.#disposed) return;
|
|
78083
|
+
const result = this.#context.evalCode(`globalThis.__caplets_snapshot_persist(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(names)});`);
|
|
78084
|
+
if (result.error) {
|
|
78085
|
+
result.error.dispose();
|
|
78086
|
+
return;
|
|
78087
|
+
}
|
|
78088
|
+
result.value.dispose();
|
|
78089
|
+
}
|
|
78090
|
+
#persistentValuesDivergedFromPersist(names) {
|
|
78091
|
+
if (this.#disposed || names.length === 0) return false;
|
|
78092
|
+
const result = this.#context.evalCode(`(${JSON.stringify(names)}).some((name) => !Object.is((0, eval)(name), globalThis.__caplets_get_persist(${JSON.stringify(this.#checkpointToken)}, name)))`);
|
|
78093
|
+
if (result.error) {
|
|
78094
|
+
result.error.dispose();
|
|
78095
|
+
return true;
|
|
78096
|
+
}
|
|
78097
|
+
try {
|
|
78098
|
+
return this.#context.dump(result.value) === true;
|
|
78099
|
+
} finally {
|
|
78100
|
+
result.value.dispose();
|
|
78101
|
+
}
|
|
78102
|
+
}
|
|
78103
|
+
#restorePersistentNames(names) {
|
|
78104
|
+
if (names.length === 0 || this.#disposed) return;
|
|
78105
|
+
const result = this.#context.evalCode(names.map((name) => [`globalThis.__caplets_set_persist(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(name)}, globalThis.__caplets_checkpoint_value(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(name)}));`, `(0, eval)(${JSON.stringify(`${name} = globalThis.__caplets_checkpoint_value(${JSON.stringify(this.#checkpointToken)}, ${JSON.stringify(name)});`)});`].join("\n")).join("\n"));
|
|
78106
|
+
if (result.error) {
|
|
78107
|
+
result.error.dispose();
|
|
78108
|
+
return;
|
|
78109
|
+
}
|
|
78110
|
+
result.value.dispose();
|
|
78111
|
+
}
|
|
77199
78112
|
};
|
|
77200
78113
|
async function evaluateInQuickJs(input) {
|
|
77201
78114
|
const timeoutMs = Math.max(100, input.timeoutMs);
|
|
@@ -77223,62 +78136,20 @@ async function evaluateInQuickJs(input) {
|
|
|
77223
78136
|
const invokeBridge = createInvokeBridge(context, pendingDeferreds, input.invoke, deadlineMs, timeoutMs);
|
|
77224
78137
|
context.setProp(context.global, "__caplets_invoke", invokeBridge);
|
|
77225
78138
|
invokeBridge.dispose();
|
|
77226
|
-
const evaluated = context.evalCode(buildExecutionSource(input.code, input.capletIds));
|
|
77227
|
-
if (evaluated.error) {
|
|
77228
|
-
const error = context.dump(evaluated.error);
|
|
77229
|
-
evaluated.error.dispose();
|
|
77230
|
-
return {
|
|
77231
|
-
ok: false,
|
|
77232
|
-
error: normalizeError(error, deadlineMs, timeoutMs),
|
|
77233
|
-
logs,
|
|
77234
|
-
...optionalStack(stackFromDump(error))
|
|
77235
|
-
};
|
|
77236
|
-
}
|
|
77237
|
-
context.setProp(context.global, "__caplets_result", evaluated.value);
|
|
77238
|
-
evaluated.value.dispose();
|
|
77239
|
-
const stateResult = context.evalCode([
|
|
77240
|
-
"(function(p) {",
|
|
77241
|
-
" var s = { settled: false, value: void 0, error: void 0 };",
|
|
77242
|
-
" var formatError = function(e) {",
|
|
77243
|
-
" if (e && typeof e === 'object' && typeof e.message === 'string') return e.message;",
|
|
77244
|
-
" return String(e);",
|
|
77245
|
-
" };",
|
|
77246
|
-
" p.then(function(value) { s.value = value; s.settled = true; },",
|
|
77247
|
-
" function(error) { s.error = formatError(error); s.settled = true; });",
|
|
77248
|
-
" return s;",
|
|
77249
|
-
"})(__caplets_result)"
|
|
77250
|
-
].join("\n"));
|
|
77251
|
-
if (stateResult.error) {
|
|
77252
|
-
const error = context.dump(stateResult.error);
|
|
77253
|
-
stateResult.error.dispose();
|
|
77254
|
-
return {
|
|
77255
|
-
ok: false,
|
|
77256
|
-
error: normalizeError(error, deadlineMs, timeoutMs),
|
|
77257
|
-
logs,
|
|
77258
|
-
...optionalStack(stackFromDump(error))
|
|
77259
|
-
};
|
|
77260
|
-
}
|
|
77261
|
-
const stateHandle = stateResult.value;
|
|
77262
78139
|
try {
|
|
77263
|
-
await
|
|
77264
|
-
|
|
77265
|
-
|
|
77266
|
-
|
|
77267
|
-
|
|
77268
|
-
|
|
77269
|
-
|
|
77270
|
-
|
|
77271
|
-
|
|
77272
|
-
|
|
77273
|
-
|
|
77274
|
-
};
|
|
77275
|
-
return {
|
|
77276
|
-
ok: true,
|
|
77277
|
-
value: readProp(context, stateHandle, "value"),
|
|
77278
|
-
logs
|
|
77279
|
-
};
|
|
78140
|
+
return await evaluateCellInContext({
|
|
78141
|
+
code: input.code,
|
|
78142
|
+
capletIds: input.capletIds,
|
|
78143
|
+
context,
|
|
78144
|
+
runtime,
|
|
78145
|
+
pendingDeferreds,
|
|
78146
|
+
pendingInvokes: pendingDeferreds,
|
|
78147
|
+
deadlineMs,
|
|
78148
|
+
timeoutMs,
|
|
78149
|
+
logs,
|
|
78150
|
+
session: false
|
|
78151
|
+
});
|
|
77280
78152
|
} finally {
|
|
77281
|
-
stateHandle.dispose();
|
|
77282
78153
|
platformHost.dispose();
|
|
77283
78154
|
}
|
|
77284
78155
|
} finally {
|
|
@@ -77297,6 +78168,96 @@ async function evaluateInQuickJs(input) {
|
|
|
77297
78168
|
runtime.dispose();
|
|
77298
78169
|
}
|
|
77299
78170
|
}
|
|
78171
|
+
async function evaluateCellInContext(input) {
|
|
78172
|
+
const observerResult = input.context.evalCode(buildPromiseObserverSource());
|
|
78173
|
+
if (observerResult.error) {
|
|
78174
|
+
const error = input.context.dump(observerResult.error);
|
|
78175
|
+
observerResult.error.dispose();
|
|
78176
|
+
return {
|
|
78177
|
+
ok: false,
|
|
78178
|
+
error: normalizeError(error, input.deadlineMs, input.timeoutMs),
|
|
78179
|
+
logs: input.logs,
|
|
78180
|
+
...optionalStack(stackFromDump(error))
|
|
78181
|
+
};
|
|
78182
|
+
}
|
|
78183
|
+
observerResult.value.dispose();
|
|
78184
|
+
const evaluated = input.context.evalCode(input.compiledSource ?? (input.session ? buildSessionCellSource(input.code, input.capletIds ?? []).source : buildExecutionSource(input.code, input.capletIds ?? [])));
|
|
78185
|
+
if (evaluated.error) {
|
|
78186
|
+
const error = input.context.dump(evaluated.error);
|
|
78187
|
+
evaluated.error.dispose();
|
|
78188
|
+
return {
|
|
78189
|
+
ok: false,
|
|
78190
|
+
error: normalizeError(error, input.deadlineMs, input.timeoutMs),
|
|
78191
|
+
logs: input.logs,
|
|
78192
|
+
...optionalStack(stackFromDump(error))
|
|
78193
|
+
};
|
|
78194
|
+
}
|
|
78195
|
+
const resultName = `__caplets_result_${randomUUID().replace(/-/gu, "_")}`;
|
|
78196
|
+
input.context.setProp(input.context.global, resultName, evaluated.value);
|
|
78197
|
+
evaluated.value.dispose();
|
|
78198
|
+
const stateResult = input.context.evalCode(buildPromiseStateSource(JSON.stringify(resultName)));
|
|
78199
|
+
cleanupTemporaryGlobals(input.context, JSON.stringify(resultName));
|
|
78200
|
+
if (stateResult.error) {
|
|
78201
|
+
const error = input.context.dump(stateResult.error);
|
|
78202
|
+
stateResult.error.dispose();
|
|
78203
|
+
return {
|
|
78204
|
+
ok: false,
|
|
78205
|
+
error: normalizeError(error, input.deadlineMs, input.timeoutMs),
|
|
78206
|
+
logs: input.logs,
|
|
78207
|
+
...optionalStack(stackFromDump(error))
|
|
78208
|
+
};
|
|
78209
|
+
}
|
|
78210
|
+
const stateHandle = stateResult.value;
|
|
78211
|
+
try {
|
|
78212
|
+
if (input.session) {
|
|
78213
|
+
if (input.pendingInvokes.size > 0) {
|
|
78214
|
+
await drainAsync(input.context, input.runtime, input.pendingInvokes, input.deadlineMs, input.timeoutMs);
|
|
78215
|
+
await drainAsync(input.context, input.runtime, input.pendingDeferreds, input.deadlineMs, input.timeoutMs);
|
|
78216
|
+
await Promise.resolve();
|
|
78217
|
+
drainJobs(input.context, input.runtime, input.deadlineMs, input.timeoutMs);
|
|
78218
|
+
input.afterPendingInvokesDrained?.();
|
|
78219
|
+
} else drainJobs(input.context, input.runtime, input.deadlineMs, input.timeoutMs);
|
|
78220
|
+
const earlyResult = readSettledPromiseState(input.context, stateHandle, input.logs);
|
|
78221
|
+
if (earlyResult) return earlyResult;
|
|
78222
|
+
}
|
|
78223
|
+
await drainAsync(input.context, input.runtime, input.pendingDeferreds, input.deadlineMs, input.timeoutMs);
|
|
78224
|
+
if (!(readProp(input.context, stateHandle, "settled") === true)) return {
|
|
78225
|
+
ok: false,
|
|
78226
|
+
error: timeoutMessage(input.timeoutMs),
|
|
78227
|
+
logs: input.logs
|
|
78228
|
+
};
|
|
78229
|
+
return readSettledPromiseState(input.context, stateHandle, input.logs) ?? {
|
|
78230
|
+
ok: false,
|
|
78231
|
+
error: timeoutMessage(input.timeoutMs),
|
|
78232
|
+
logs: input.logs
|
|
78233
|
+
};
|
|
78234
|
+
} finally {
|
|
78235
|
+
stateHandle.dispose();
|
|
78236
|
+
}
|
|
78237
|
+
}
|
|
78238
|
+
function cleanupTemporaryGlobals(context, ...names) {
|
|
78239
|
+
if (names.length === 0) return;
|
|
78240
|
+
const result = context.evalCode(names.map((name) => `delete globalThis[${name}];`).join("\n"));
|
|
78241
|
+
if (result.error) {
|
|
78242
|
+
result.error.dispose();
|
|
78243
|
+
return;
|
|
78244
|
+
}
|
|
78245
|
+
result.value.dispose();
|
|
78246
|
+
}
|
|
78247
|
+
function readSettledPromiseState(context, stateHandle, logs) {
|
|
78248
|
+
if (!(readProp(context, stateHandle, "settled") === true)) return;
|
|
78249
|
+
const error = readProp(context, stateHandle, "error");
|
|
78250
|
+
if (typeof error !== "undefined") return {
|
|
78251
|
+
ok: false,
|
|
78252
|
+
error: errorMessage$2(error),
|
|
78253
|
+
logs
|
|
78254
|
+
};
|
|
78255
|
+
return {
|
|
78256
|
+
ok: true,
|
|
78257
|
+
value: readProp(context, stateHandle, "value"),
|
|
78258
|
+
logs
|
|
78259
|
+
};
|
|
78260
|
+
}
|
|
77300
78261
|
function createInvokeBridge(context, pendingDeferreds, invoke, deadlineMs, timeoutMs) {
|
|
77301
78262
|
return context.newFunction("__caplets_invoke", (capletHandle, methodHandle, argsHandle) => {
|
|
77302
78263
|
const capletId = context.getString(capletHandle);
|
|
@@ -77304,7 +78265,10 @@ function createInvokeBridge(context, pendingDeferreds, invoke, deadlineMs, timeo
|
|
|
77304
78265
|
const args = context.dump(argsHandle);
|
|
77305
78266
|
const deferred = context.newPromise();
|
|
77306
78267
|
pendingDeferreds.add(deferred);
|
|
77307
|
-
deferred.settled.finally(() =>
|
|
78268
|
+
deferred.settled.finally(() => {
|
|
78269
|
+
pendingDeferreds.delete(deferred);
|
|
78270
|
+
if (deferred.alive) deferred.dispose();
|
|
78271
|
+
});
|
|
77308
78272
|
invoke({
|
|
77309
78273
|
capletId,
|
|
77310
78274
|
method,
|
|
@@ -77331,6 +78295,78 @@ function createInvokeBridge(context, pendingDeferreds, invoke, deadlineMs, timeo
|
|
|
77331
78295
|
return deferred.handle;
|
|
77332
78296
|
});
|
|
77333
78297
|
}
|
|
78298
|
+
function createInvokeJsonBridge(context, pendingDeferreds, pendingInvokes, invoke, deadlineMs, timeoutMs, isCapletActive) {
|
|
78299
|
+
return context.newFunction("__caplets_invoke_json", (capletHandle, methodHandle, argsHandle) => {
|
|
78300
|
+
const capletId = context.getString(capletHandle);
|
|
78301
|
+
const method = context.getString(methodHandle);
|
|
78302
|
+
const args = context.dump(argsHandle);
|
|
78303
|
+
const deferred = context.newPromise();
|
|
78304
|
+
pendingDeferreds.add(deferred);
|
|
78305
|
+
pendingInvokes.add(deferred);
|
|
78306
|
+
deferred.settled.finally(() => {
|
|
78307
|
+
pendingDeferreds.delete(deferred);
|
|
78308
|
+
pendingInvokes.delete(deferred);
|
|
78309
|
+
if (deferred.alive) deferred.dispose();
|
|
78310
|
+
});
|
|
78311
|
+
const debugMethod = CODE_MODE_DEBUG_METHODS.has(method);
|
|
78312
|
+
const debugCapletActive = capletId === "debug" && isCapletActive("debug");
|
|
78313
|
+
if (!isCodeModeSandboxMethod(method) || capletId === "debug" && !debugMethod && !debugCapletActive || capletId !== "debug" && debugMethod) {
|
|
78314
|
+
const errorHandle = context.newError(`Method ${method} is not available in this Code Mode session cell.`);
|
|
78315
|
+
deferred.reject(errorHandle);
|
|
78316
|
+
errorHandle.dispose();
|
|
78317
|
+
return deferred.handle;
|
|
78318
|
+
}
|
|
78319
|
+
if (!(capletId === "debug" && debugMethod) && !isCapletActive(capletId)) {
|
|
78320
|
+
const errorHandle = context.newError(`Caplet ${capletId} is not available in this Code Mode session cell.`);
|
|
78321
|
+
deferred.reject(errorHandle);
|
|
78322
|
+
errorHandle.dispose();
|
|
78323
|
+
return deferred.handle;
|
|
78324
|
+
}
|
|
78325
|
+
invoke()({
|
|
78326
|
+
capletId,
|
|
78327
|
+
method,
|
|
78328
|
+
args
|
|
78329
|
+
}).then((value) => {
|
|
78330
|
+
if (!deferred.alive) return;
|
|
78331
|
+
let valueHandle;
|
|
78332
|
+
try {
|
|
78333
|
+
const serialized = JSON.stringify(value);
|
|
78334
|
+
const parsed = context.evalCode(`globalThis.__caplets_json_parse(${JSON.stringify(serialized ?? "null")})`);
|
|
78335
|
+
if (parsed.error) {
|
|
78336
|
+
const error = context.dump(parsed.error);
|
|
78337
|
+
parsed.error.dispose();
|
|
78338
|
+
throw new Error(errorMessage$2(error));
|
|
78339
|
+
}
|
|
78340
|
+
valueHandle = parsed.value;
|
|
78341
|
+
deferred.resolve(valueHandle);
|
|
78342
|
+
} catch (error) {
|
|
78343
|
+
const errorHandle = context.newError(errorMessage$2(error));
|
|
78344
|
+
deferred.reject(errorHandle);
|
|
78345
|
+
errorHandle.dispose();
|
|
78346
|
+
} finally {
|
|
78347
|
+
valueHandle?.dispose();
|
|
78348
|
+
}
|
|
78349
|
+
}, (error) => {
|
|
78350
|
+
if (!deferred.alive) return;
|
|
78351
|
+
const message = Date.now() >= deadlineMs() ? timeoutMessage(timeoutMs()) : errorMessage$2(error);
|
|
78352
|
+
const errorHandle = context.newError(message);
|
|
78353
|
+
deferred.reject(errorHandle);
|
|
78354
|
+
errorHandle.dispose();
|
|
78355
|
+
});
|
|
78356
|
+
return deferred.handle;
|
|
78357
|
+
});
|
|
78358
|
+
}
|
|
78359
|
+
function isCodeModeSandboxMethod(method) {
|
|
78360
|
+
return CODE_MODE_SANDBOX_METHODS.has(method);
|
|
78361
|
+
}
|
|
78362
|
+
function filterPersistDescriptorFingerprint(fingerprint, allowedNames) {
|
|
78363
|
+
if (!fingerprint || allowedNames.length === 0) return fingerprint;
|
|
78364
|
+
const allowedTokens = new Set(allowedNames.map((name) => `string:${name}`));
|
|
78365
|
+
return fingerprint.split("|").filter((entry) => {
|
|
78366
|
+
const token = entry.startsWith("string:") ? entry.slice(0, entry.indexOf(":", 7)) : entry.startsWith("symbol:") ? entry.slice(0, entry.indexOf(":", 7)) : entry;
|
|
78367
|
+
return !allowedTokens.has(token);
|
|
78368
|
+
}).join("|");
|
|
78369
|
+
}
|
|
77334
78370
|
function buildExecutionSource(code, capletIds) {
|
|
77335
78371
|
const javascript = ts.transpileModule(code, { compilerOptions: {
|
|
77336
78372
|
target: ts.ScriptTarget.ES2022,
|
|
@@ -77362,11 +78398,546 @@ function buildExecutionSource(code, capletIds) {
|
|
|
77362
78398
|
...capletIds.map((capletId) => `caplets[${JSON.stringify(capletId)}] = __handle(${JSON.stringify(capletId)});`),
|
|
77363
78399
|
"caplets.debug = caplets.debug || {};",
|
|
77364
78400
|
"caplets.debug.readLogs = (input) => __invoke('debug', 'readLogs', [input]);",
|
|
78401
|
+
"caplets.debug.readRecovery = (input) => __invoke('debug', 'readRecovery', [input]);",
|
|
77365
78402
|
"(async () => {",
|
|
77366
78403
|
javascript,
|
|
77367
78404
|
"})()"
|
|
77368
78405
|
].join("\n");
|
|
77369
78406
|
}
|
|
78407
|
+
function buildSessionInitSource(checkpointToken) {
|
|
78408
|
+
return [
|
|
78409
|
+
CODE_MODE_PLATFORM_RUNTIME_SOURCE,
|
|
78410
|
+
"const __caplets_restore_platform = (() => {",
|
|
78411
|
+
" const defineProperty = Object.defineProperty.bind(Object);",
|
|
78412
|
+
" const defineProperties = Object.defineProperties.bind(Object);",
|
|
78413
|
+
" const getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors.bind(Object);",
|
|
78414
|
+
" const getPrototypeOf = Object.getPrototypeOf.bind(Object);",
|
|
78415
|
+
" const setPrototypeOf = Object.setPrototypeOf.bind(Object);",
|
|
78416
|
+
" const isExtensible = Object.isExtensible.bind(Object);",
|
|
78417
|
+
" const ownKeys = Reflect.ownKeys.bind(Reflect);",
|
|
78418
|
+
" const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);",
|
|
78419
|
+
" const arrayPush = Function.prototype.call.bind(Array.prototype.push);",
|
|
78420
|
+
" const globalSymbolIds = new Map();",
|
|
78421
|
+
" let nextGlobalSymbolId = 1;",
|
|
78422
|
+
" const keyToken = (key) => {",
|
|
78423
|
+
" if (typeof key !== 'symbol') return `string:${key}`;",
|
|
78424
|
+
" if (!globalSymbolIds.has(key)) globalSymbolIds.set(key, nextGlobalSymbolId++);",
|
|
78425
|
+
" return `symbol:${globalSymbolIds.get(key)}`;",
|
|
78426
|
+
" };",
|
|
78427
|
+
" const platformGlobals = [];",
|
|
78428
|
+
" const globalPrototypeSnapshot = getPrototypeOf(globalThis);",
|
|
78429
|
+
" const platformExtraObjects = [",
|
|
78430
|
+
" ['AsyncFunction.prototype', getPrototypeOf(async function() {})],",
|
|
78431
|
+
" ['AsyncFunctionConstructor', getPrototypeOf(async function() {}).constructor],",
|
|
78432
|
+
" ['GeneratorFunction.prototype', getPrototypeOf(function*() {})],",
|
|
78433
|
+
" ['GeneratorFunctionConstructor', getPrototypeOf(function*() {}).constructor],",
|
|
78434
|
+
" ['AsyncGeneratorFunction.prototype', getPrototypeOf(async function*() {})],",
|
|
78435
|
+
" ['AsyncGeneratorFunctionConstructor', getPrototypeOf(async function*() {}).constructor],",
|
|
78436
|
+
" ['GeneratorObjectPrototype', getPrototypeOf((function*() {})())],",
|
|
78437
|
+
" ['GeneratorObjectPrototypeParent', getPrototypeOf(getPrototypeOf((function*() {})()))],",
|
|
78438
|
+
" ['AsyncGeneratorObjectPrototype', getPrototypeOf((async function*() {})())],",
|
|
78439
|
+
" ['AsyncGeneratorObjectPrototypeParent', getPrototypeOf(getPrototypeOf((async function*() {})()))],",
|
|
78440
|
+
" ['ArrayIteratorPrototype', getPrototypeOf([][Symbol.iterator]())],",
|
|
78441
|
+
" ['IteratorPrototype', getPrototypeOf(getPrototypeOf([][Symbol.iterator]()))],",
|
|
78442
|
+
" ['StringIteratorPrototype', getPrototypeOf(''[Symbol.iterator]())],",
|
|
78443
|
+
" ['RegExpStringIteratorPrototype', getPrototypeOf(''.matchAll(/(?:)/g))],",
|
|
78444
|
+
" ['RegExpStringIteratorPrototypeParent', getPrototypeOf(getPrototypeOf(''.matchAll(/(?:)/g)))],",
|
|
78445
|
+
" ['MapIteratorPrototype', getPrototypeOf(new Map()[Symbol.iterator]())],",
|
|
78446
|
+
" ['SetIteratorPrototype', getPrototypeOf(new Set()[Symbol.iterator]())],",
|
|
78447
|
+
" ['TypedArrayConstructor', getPrototypeOf(Int8Array)],",
|
|
78448
|
+
" ['TypedArrayPrototype', getPrototypeOf(Int8Array.prototype)],",
|
|
78449
|
+
" ['AsyncFunctionPrototypeParent', getPrototypeOf(getPrototypeOf(async function() {}))],",
|
|
78450
|
+
" ['GeneratorFunctionPrototypeParent', getPrototypeOf(getPrototypeOf(function*() {}))],",
|
|
78451
|
+
" ['AsyncGeneratorFunctionPrototypeParent', getPrototypeOf(getPrototypeOf(async function*() {}))],",
|
|
78452
|
+
" ];",
|
|
78453
|
+
" const platformExtraSnapshot = Object.create(null);",
|
|
78454
|
+
" const platformExtraPrototypeSnapshot = Object.create(null);",
|
|
78455
|
+
" const platformExtraExtensibleSnapshot = Object.create(null);",
|
|
78456
|
+
" const platformGlobalNames = ownKeys(globalThis);",
|
|
78457
|
+
" for (const name of platformGlobalNames) {",
|
|
78458
|
+
" const record = {",
|
|
78459
|
+
" name,",
|
|
78460
|
+
" descriptor: Object.getOwnPropertyDescriptor(globalThis, name),",
|
|
78461
|
+
" value: globalThis[name],",
|
|
78462
|
+
" objectPrototype: undefined,",
|
|
78463
|
+
" properties: undefined,",
|
|
78464
|
+
" prototypeProperties: undefined,",
|
|
78465
|
+
" prototypeChain: undefined,",
|
|
78466
|
+
" extensible: undefined,",
|
|
78467
|
+
" prototypeExtensible: undefined,",
|
|
78468
|
+
" };",
|
|
78469
|
+
" const value = globalThis[name];",
|
|
78470
|
+
" if (value !== globalThis && ((typeof value === 'object' && value !== null) || typeof value === 'function')) {",
|
|
78471
|
+
" record.objectPrototype = getPrototypeOf(value);",
|
|
78472
|
+
" record.properties = getOwnPropertyDescriptors(value);",
|
|
78473
|
+
" record.extensible = isExtensible(value);",
|
|
78474
|
+
" const prototype = value.prototype;",
|
|
78475
|
+
" if ((typeof prototype === 'object' && prototype !== null) || typeof prototype === 'function') {",
|
|
78476
|
+
" record.prototypeChain = getPrototypeOf(prototype);",
|
|
78477
|
+
" record.prototypeProperties = getOwnPropertyDescriptors(prototype);",
|
|
78478
|
+
" record.prototypeExtensible = isExtensible(prototype);",
|
|
78479
|
+
" }",
|
|
78480
|
+
" }",
|
|
78481
|
+
" arrayPush(platformGlobals, record);",
|
|
78482
|
+
" }",
|
|
78483
|
+
" for (const [name, value] of platformExtraObjects) {",
|
|
78484
|
+
" if ((typeof value === 'object' && value !== null) || typeof value === 'function') {",
|
|
78485
|
+
" platformExtraSnapshot[name] = getOwnPropertyDescriptors(value);",
|
|
78486
|
+
" platformExtraPrototypeSnapshot[name] = getPrototypeOf(value);",
|
|
78487
|
+
" platformExtraExtensibleSnapshot[name] = isExtensible(value);",
|
|
78488
|
+
" }",
|
|
78489
|
+
" }",
|
|
78490
|
+
" const globalKeys = () => {",
|
|
78491
|
+
" const keys = ownKeys(globalThis);",
|
|
78492
|
+
" const tokens = [];",
|
|
78493
|
+
" for (let index = 0; index < keys.length; index += 1) {",
|
|
78494
|
+
" const key = keys[index];",
|
|
78495
|
+
" arrayPush(tokens, keyToken(key));",
|
|
78496
|
+
" }",
|
|
78497
|
+
" return tokens;",
|
|
78498
|
+
" };",
|
|
78499
|
+
" const restore = () => {",
|
|
78500
|
+
" if (getPrototypeOf(globalThis) !== globalPrototypeSnapshot) {",
|
|
78501
|
+
" try { setPrototypeOf(globalThis, globalPrototypeSnapshot); } catch { throw new Error('Code Mode global prototype chain is not restorable'); }",
|
|
78502
|
+
" }",
|
|
78503
|
+
" for (const record of platformGlobals) {",
|
|
78504
|
+
" const name = record.name;",
|
|
78505
|
+
" try {",
|
|
78506
|
+
" defineProperty(globalThis, name, record.descriptor);",
|
|
78507
|
+
" const descriptors = record.properties;",
|
|
78508
|
+
" const value = globalThis[name];",
|
|
78509
|
+
" if (descriptors && ((typeof value === 'object' && value !== null) || typeof value === 'function')) {",
|
|
78510
|
+
" if (record.extensible && !isExtensible(value)) throw new Error(`Code Mode platform global ${String(name)} is non-extensible`);",
|
|
78511
|
+
" if (getPrototypeOf(value) !== record.objectPrototype) {",
|
|
78512
|
+
" try { setPrototypeOf(value, record.objectPrototype); } catch { throw new Error(`Code Mode platform global ${String(name)} prototype chain is not restorable`); }",
|
|
78513
|
+
" }",
|
|
78514
|
+
" for (const key of ownKeys(value)) {",
|
|
78515
|
+
" if (!hasOwn(descriptors, key)) {",
|
|
78516
|
+
" try { delete value[key]; } catch {}",
|
|
78517
|
+
" if (hasOwn(value, key)) throw new Error(`Code Mode platform global ${String(name)} has non-restorable property ${String(key)}`);",
|
|
78518
|
+
" }",
|
|
78519
|
+
" }",
|
|
78520
|
+
" defineProperties(value, descriptors);",
|
|
78521
|
+
" const prototypeDescriptors = record.prototypeProperties;",
|
|
78522
|
+
" const prototype = value.prototype;",
|
|
78523
|
+
" if (prototypeDescriptors && ((typeof prototype === 'object' && prototype !== null) || typeof prototype === 'function')) {",
|
|
78524
|
+
" if (record.prototypeExtensible && !isExtensible(prototype)) throw new Error(`Code Mode platform prototype ${String(name)}.prototype is non-extensible`);",
|
|
78525
|
+
" if (getPrototypeOf(prototype) !== record.prototypeChain) {",
|
|
78526
|
+
" try { setPrototypeOf(prototype, record.prototypeChain); } catch { throw new Error(`Code Mode platform prototype ${String(name)}.prototype chain is not restorable`); }",
|
|
78527
|
+
" }",
|
|
78528
|
+
" for (const key of ownKeys(prototype)) {",
|
|
78529
|
+
" if (!hasOwn(prototypeDescriptors, key)) {",
|
|
78530
|
+
" try { delete prototype[key]; } catch {}",
|
|
78531
|
+
" if (hasOwn(prototype, key)) throw new Error(`Code Mode platform prototype ${String(name)}.prototype has non-restorable property ${String(key)}`);",
|
|
78532
|
+
" }",
|
|
78533
|
+
" }",
|
|
78534
|
+
" defineProperties(prototype, prototypeDescriptors);",
|
|
78535
|
+
" }",
|
|
78536
|
+
" }",
|
|
78537
|
+
" } catch (error) {",
|
|
78538
|
+
" throw new Error(`Code Mode platform global ${String(name)} is not restorable: ${String(error && error.message ? error.message : error)}`);",
|
|
78539
|
+
" }",
|
|
78540
|
+
" }",
|
|
78541
|
+
" for (const [name, value] of platformExtraObjects) {",
|
|
78542
|
+
" const descriptors = platformExtraSnapshot[name];",
|
|
78543
|
+
" if (!descriptors || !((typeof value === 'object' && value !== null) || typeof value === 'function')) continue;",
|
|
78544
|
+
" if (platformExtraExtensibleSnapshot[name] && !isExtensible(value)) throw new Error(`Code Mode platform intrinsic ${name} is non-extensible`);",
|
|
78545
|
+
" if (getPrototypeOf(value) !== platformExtraPrototypeSnapshot[name]) {",
|
|
78546
|
+
" try { setPrototypeOf(value, platformExtraPrototypeSnapshot[name]); } catch { throw new Error(`Code Mode platform intrinsic ${name} prototype chain is not restorable`); }",
|
|
78547
|
+
" }",
|
|
78548
|
+
" for (const key of ownKeys(value)) {",
|
|
78549
|
+
" if (!hasOwn(descriptors, key)) {",
|
|
78550
|
+
" try { delete value[key]; } catch {}",
|
|
78551
|
+
" if (hasOwn(value, key)) throw new Error(`Code Mode platform intrinsic ${name} has non-restorable property ${String(key)}`);",
|
|
78552
|
+
" }",
|
|
78553
|
+
" }",
|
|
78554
|
+
" defineProperties(value, descriptors);",
|
|
78555
|
+
" }",
|
|
78556
|
+
" };",
|
|
78557
|
+
" return { restore, globalKeys, isGlobalExtensible: () => isExtensible(globalThis) };",
|
|
78558
|
+
"})();",
|
|
78559
|
+
"Object.defineProperty(globalThis, '__caplets_restore_platform', { configurable: false, writable: false, value: __caplets_restore_platform.restore });",
|
|
78560
|
+
"Object.defineProperty(globalThis, '__caplets_global_keys', { configurable: false, writable: false, value: __caplets_restore_platform.globalKeys });",
|
|
78561
|
+
"Object.defineProperty(globalThis, '__caplets_is_global_extensible', { configurable: false, writable: false, value: __caplets_restore_platform.isGlobalExtensible });",
|
|
78562
|
+
"Object.defineProperty(globalThis, '__caplets_assert_active_id', { configurable: false, writable: false, value: (capletId) => {",
|
|
78563
|
+
" if (capletId === 'debug' && !__caplets_is_active_id(capletId)) return;",
|
|
78564
|
+
" if (!__caplets_is_active_id(capletId)) throw new Error(`Caplet ${capletId} is not available in this Code Mode session cell.`);",
|
|
78565
|
+
"} });",
|
|
78566
|
+
"Object.defineProperty(globalThis, '__caplets_handle', { configurable: false, writable: false, value: (capletId) => ({",
|
|
78567
|
+
" id: capletId,",
|
|
78568
|
+
" inspect: () => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'inspect', [])),",
|
|
78569
|
+
" check: () => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'check', [])),",
|
|
78570
|
+
" tools: (input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'tools', [input])),",
|
|
78571
|
+
" searchTools: (query, input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'searchTools', [query, input])),",
|
|
78572
|
+
" describeTool: (name) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'describeTool', [name])),",
|
|
78573
|
+
" callTool: (name, args) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'callTool', [name, args])),",
|
|
78574
|
+
" resources: (input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'resources', [input])),",
|
|
78575
|
+
" searchResources: (query, input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'searchResources', [query, input])),",
|
|
78576
|
+
" resourceTemplates: (input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'resourceTemplates', [input])),",
|
|
78577
|
+
" readResource: (uri) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'readResource', [uri])),",
|
|
78578
|
+
" prompts: (input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'prompts', [input])),",
|
|
78579
|
+
" searchPrompts: (query, input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'searchPrompts', [query, input])),",
|
|
78580
|
+
" getPrompt: (name, args) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'getPrompt', [name, args])),",
|
|
78581
|
+
" complete: (input) => (__caplets_assert_active_id(capletId), __caplets_invoke_json(capletId, 'complete', [input])),",
|
|
78582
|
+
"}) });",
|
|
78583
|
+
"(() => {",
|
|
78584
|
+
` const checkpointToken = ${JSON.stringify(checkpointToken)};`,
|
|
78585
|
+
" const persistBacking = Object.create(null);",
|
|
78586
|
+
" let persistTainted = false;",
|
|
78587
|
+
" const checkpointState = { current: Object.create(null) };",
|
|
78588
|
+
" const ownKeys = Reflect.ownKeys.bind(Reflect);",
|
|
78589
|
+
" const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor.bind(Object);",
|
|
78590
|
+
" const defineProperty = Object.defineProperty.bind(Object);",
|
|
78591
|
+
" const getPrototypeOf = Object.getPrototypeOf.bind(Object);",
|
|
78592
|
+
" const reflectGet = Reflect.get.bind(Reflect);",
|
|
78593
|
+
" const reflectSet = Reflect.set.bind(Reflect);",
|
|
78594
|
+
" const reflectDefineProperty = Reflect.defineProperty.bind(Reflect);",
|
|
78595
|
+
" const reflectDeleteProperty = Reflect.deleteProperty.bind(Reflect);",
|
|
78596
|
+
" const reflectSetPrototypeOf = Reflect.setPrototypeOf.bind(Reflect);",
|
|
78597
|
+
" const reflectPreventExtensions = Reflect.preventExtensions.bind(Reflect);",
|
|
78598
|
+
" const reflectGetOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor.bind(Reflect);",
|
|
78599
|
+
" const reflectOwnKeys = Reflect.ownKeys.bind(Reflect);",
|
|
78600
|
+
" const hasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);",
|
|
78601
|
+
" const objectIds = new WeakMap();",
|
|
78602
|
+
" let nextObjectId = 1;",
|
|
78603
|
+
" const keyToken = (key) => typeof key === 'symbol' ? `symbol:${String(key)}` : `string:${key}`;",
|
|
78604
|
+
" const valueToken = (value) => {",
|
|
78605
|
+
" const type = typeof value;",
|
|
78606
|
+
" if ((type === 'object' && value !== null) || type === 'function') {",
|
|
78607
|
+
" if (!objectIds.has(value)) objectIds.set(value, nextObjectId++);",
|
|
78608
|
+
" return `${type}:${objectIds.get(value)}`;",
|
|
78609
|
+
" }",
|
|
78610
|
+
" return `${type}:${String(value)}`;",
|
|
78611
|
+
" };",
|
|
78612
|
+
" const descriptorToken = (descriptor) => {",
|
|
78613
|
+
" if (!descriptor) return 'missing';",
|
|
78614
|
+
" return [",
|
|
78615
|
+
" hasOwn(descriptor, 'value') ? 'data' : 'accessor',",
|
|
78616
|
+
" descriptor.writable === true ? 'w' : 'nw',",
|
|
78617
|
+
" descriptor.configurable === true ? 'c' : 'nc',",
|
|
78618
|
+
" descriptor.enumerable === true ? 'e' : 'ne',",
|
|
78619
|
+
" typeof descriptor.get,",
|
|
78620
|
+
" typeof descriptor.set,",
|
|
78621
|
+
" ].join(':');",
|
|
78622
|
+
" };",
|
|
78623
|
+
" const assertToken = (token) => {",
|
|
78624
|
+
" if (token !== checkpointToken) throw new Error('Code Mode persistence checkpoint token is invalid.');",
|
|
78625
|
+
" };",
|
|
78626
|
+
" const persistProxy = new Proxy(persistBacking, {",
|
|
78627
|
+
" get(target, key, receiver) { persistTainted = true; return reflectGet(target, key, receiver); },",
|
|
78628
|
+
" set(target, key, value, receiver) { persistTainted = true; return reflectSet(target, key, value, receiver); },",
|
|
78629
|
+
" defineProperty(target, key, descriptor) { persistTainted = true; return reflectDefineProperty(target, key, descriptor); },",
|
|
78630
|
+
" deleteProperty(target, key) { persistTainted = true; return reflectDeleteProperty(target, key); },",
|
|
78631
|
+
" setPrototypeOf(target, prototype) { persistTainted = true; return reflectSetPrototypeOf(target, prototype); },",
|
|
78632
|
+
" preventExtensions(target) { persistTainted = true; return reflectPreventExtensions(target); },",
|
|
78633
|
+
" getOwnPropertyDescriptor(target, key) { persistTainted = true; return reflectGetOwnPropertyDescriptor(target, key); },",
|
|
78634
|
+
" ownKeys(target) { persistTainted = true; return reflectOwnKeys(target); },",
|
|
78635
|
+
" getPrototypeOf(target) { persistTainted = true; return getPrototypeOf(target); },",
|
|
78636
|
+
" });",
|
|
78637
|
+
" Object.defineProperty(globalThis, '__caplets_persist', { configurable: false, writable: false, value: persistProxy });",
|
|
78638
|
+
" Object.defineProperty(globalThis, '__caplets_get_persist', { configurable: false, writable: false, value: (token, name) => {",
|
|
78639
|
+
" assertToken(token);",
|
|
78640
|
+
" return hasOwn(persistBacking, name) ? persistBacking[name] : undefined;",
|
|
78641
|
+
" } });",
|
|
78642
|
+
" Object.defineProperty(globalThis, '__caplets_set_persist', { configurable: false, writable: false, value: (token, name, value) => {",
|
|
78643
|
+
" assertToken(token);",
|
|
78644
|
+
" defineProperty(persistBacking, name, { value, writable: true, configurable: true, enumerable: true });",
|
|
78645
|
+
" return value;",
|
|
78646
|
+
" } });",
|
|
78647
|
+
" Object.defineProperty(globalThis, '__caplets_persist_is_tainted', { configurable: false, writable: false, value: (token) => {",
|
|
78648
|
+
" assertToken(token);",
|
|
78649
|
+
" return persistTainted;",
|
|
78650
|
+
" } });",
|
|
78651
|
+
" Object.defineProperty(globalThis, '__caplets_persist_has_object_like_values', { configurable: false, writable: false, value: (token, names) => {",
|
|
78652
|
+
" assertToken(token);",
|
|
78653
|
+
" for (const name of names) {",
|
|
78654
|
+
" if (!hasOwn(persistBacking, name)) continue;",
|
|
78655
|
+
" const value = persistBacking[name];",
|
|
78656
|
+
" if ((typeof value === 'object' && value !== null) || typeof value === 'function') return true;",
|
|
78657
|
+
" }",
|
|
78658
|
+
" return false;",
|
|
78659
|
+
" } });",
|
|
78660
|
+
" Object.defineProperty(globalThis, '__caplets_persist_global_descriptors_ok', { configurable: false, writable: false, value: (token, names) => {",
|
|
78661
|
+
" assertToken(token);",
|
|
78662
|
+
" for (const name of names) {",
|
|
78663
|
+
" const descriptor = getOwnPropertyDescriptor(globalThis, name);",
|
|
78664
|
+
" if (!descriptor || !hasOwn(descriptor, 'value') || descriptor.writable !== true) return false;",
|
|
78665
|
+
" }",
|
|
78666
|
+
" return true;",
|
|
78667
|
+
" } });",
|
|
78668
|
+
" Object.defineProperty(globalThis, '__caplets_persist_descriptor_fingerprint', { configurable: false, writable: false, value: (allowedNames = []) => {",
|
|
78669
|
+
" const allowed = new Set(allowedNames.map((name) => `string:${name}`));",
|
|
78670
|
+
" const prototype = getPrototypeOf(persistBacking);",
|
|
78671
|
+
" const keys = ownKeys(persistBacking).map((key) => keyToken(key)).filter((token) => !allowed.has(token)).sort();",
|
|
78672
|
+
" return keys.map((token) => {",
|
|
78673
|
+
" const key = token.startsWith('symbol:') ? ownKeys(persistBacking).find((candidate) => keyToken(candidate) === token) : token.slice('string:'.length);",
|
|
78674
|
+
" const descriptor = getOwnPropertyDescriptor(persistBacking, key);",
|
|
78675
|
+
" const value = descriptor && hasOwn(descriptor, 'value') ? valueToken(descriptor.value) : 'accessor';",
|
|
78676
|
+
" return `${token}:${descriptorToken(descriptor)}:${value}`;",
|
|
78677
|
+
" }).concat(`[[Prototype]]:${valueToken(prototype)}`).join('|');",
|
|
78678
|
+
" } });",
|
|
78679
|
+
" Object.defineProperty(globalThis, '__caplets_persist_descriptors_ok', { configurable: false, writable: false, value: (token, names) => {",
|
|
78680
|
+
" assertToken(token);",
|
|
78681
|
+
" if (getPrototypeOf(persistBacking) !== null) return false;",
|
|
78682
|
+
" for (const name of names) {",
|
|
78683
|
+
" const descriptor = getOwnPropertyDescriptor(persistBacking, name);",
|
|
78684
|
+
" if (!descriptor || !hasOwn(descriptor, 'value')) return false;",
|
|
78685
|
+
" if (descriptor.get || descriptor.set || descriptor.writable !== true || descriptor.configurable !== true) return false;",
|
|
78686
|
+
" }",
|
|
78687
|
+
" return true;",
|
|
78688
|
+
" } });",
|
|
78689
|
+
" Object.defineProperty(globalThis, '__caplets_snapshot_persist', { configurable: false, writable: false, value: (token, names) => {",
|
|
78690
|
+
" assertToken(token);",
|
|
78691
|
+
" const next = Object.create(null);",
|
|
78692
|
+
" for (const name of names) {",
|
|
78693
|
+
" try { next[name] = (0, eval)(name); }",
|
|
78694
|
+
" catch { next[name] = hasOwn(globalThis, name) ? globalThis[name] : hasOwn(persistBacking, name) ? persistBacking[name] : undefined; }",
|
|
78695
|
+
" }",
|
|
78696
|
+
" checkpointState.current = next;",
|
|
78697
|
+
" } });",
|
|
78698
|
+
" Object.defineProperty(globalThis, '__caplets_checkpoint_value', { configurable: false, writable: false, value: (token, name) => {",
|
|
78699
|
+
" assertToken(token);",
|
|
78700
|
+
" return checkpointState.current[name];",
|
|
78701
|
+
" } });",
|
|
78702
|
+
"})();",
|
|
78703
|
+
"Object.defineProperty(globalThis, '__caplets_json_parse', { configurable: false, writable: false, value: JSON.parse.bind(JSON) });"
|
|
78704
|
+
].join("\n");
|
|
78705
|
+
}
|
|
78706
|
+
function buildBridgeRefreshSource(_capletIds, _previousCapletIds = []) {
|
|
78707
|
+
return "";
|
|
78708
|
+
}
|
|
78709
|
+
function buildSessionCellSource(code, capletIds, existingNames = [], checkpointToken = "") {
|
|
78710
|
+
const javascript = ts.transpileModule(code, { compilerOptions: {
|
|
78711
|
+
target: ts.ScriptTarget.ES2022,
|
|
78712
|
+
module: ts.ModuleKind.ESNext,
|
|
78713
|
+
importsNotUsedAsValues: ts.ImportsNotUsedAsValues.Remove
|
|
78714
|
+
} }).outputText;
|
|
78715
|
+
const split = splitPersistentPrelude(javascript, existingNames, checkpointToken);
|
|
78716
|
+
return {
|
|
78717
|
+
source: [
|
|
78718
|
+
split.prelude,
|
|
78719
|
+
"(async () => {",
|
|
78720
|
+
"\"use strict\";",
|
|
78721
|
+
buildPlatformResetSource(),
|
|
78722
|
+
buildPlatformShadowRestoreSource(existingNames, checkpointToken),
|
|
78723
|
+
buildCellCapletsSource(capletIds),
|
|
78724
|
+
split.body,
|
|
78725
|
+
split.postlude,
|
|
78726
|
+
"})()"
|
|
78727
|
+
].join("\n"),
|
|
78728
|
+
persistentNames: split.persistentNames,
|
|
78729
|
+
newNames: split.newNames,
|
|
78730
|
+
snapshotNames: split.snapshotNames
|
|
78731
|
+
};
|
|
78732
|
+
}
|
|
78733
|
+
function buildPlatformResetSource() {
|
|
78734
|
+
return "globalThis.__caplets_restore_platform();";
|
|
78735
|
+
}
|
|
78736
|
+
function buildPlatformShadowRestoreSource(existingNames, checkpointToken) {
|
|
78737
|
+
return existingNames.map((name) => `(0, eval)(${JSON.stringify(`${name} = globalThis.__caplets_get_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)});`)});`).join("\n");
|
|
78738
|
+
}
|
|
78739
|
+
function buildCellCapletsSource(capletIds) {
|
|
78740
|
+
return [
|
|
78741
|
+
"const caplets = {};",
|
|
78742
|
+
...capletIds.map((capletId) => `caplets[${JSON.stringify(capletId)}] = __caplets_handle(${JSON.stringify(capletId)});`),
|
|
78743
|
+
"caplets.debug = caplets.debug ?? {};",
|
|
78744
|
+
"caplets.debug.readLogs = (input) => __caplets_invoke_json('debug', 'readLogs', [input]);",
|
|
78745
|
+
"caplets.debug.readRecovery = (input) => __caplets_invoke_json('debug', 'readRecovery', [input]);"
|
|
78746
|
+
].join("\n");
|
|
78747
|
+
}
|
|
78748
|
+
function splitPersistentPrelude(javascript, existingNames = [], checkpointToken = "") {
|
|
78749
|
+
const source = ts.createSourceFile("/caplets-code-mode/session-cell.js", javascript, ts.ScriptTarget.ES2022, true);
|
|
78750
|
+
const ranges = [];
|
|
78751
|
+
const names = collectPersistentBindingNames(source);
|
|
78752
|
+
const lexicalNames = collectTopLevelLexicalBindingNames(source);
|
|
78753
|
+
const allNames = [...new Set([...existingNames, ...names])];
|
|
78754
|
+
const snapshotNames = allNames.filter((name) => !lexicalNames.has(name));
|
|
78755
|
+
const returnTempName = uniqueInternalName("__caplets_return", allNames);
|
|
78756
|
+
const postlude = snapshotNames.map((name) => persistentBindingPostlude(name, checkpointToken)).join("\n");
|
|
78757
|
+
for (const statement of source.statements) {
|
|
78758
|
+
collectPersistentVarRewriteRanges(statement, source, lexicalNames, ranges);
|
|
78759
|
+
collectPersistentReturnRanges(statement, source, snapshotNames, ranges, returnTempName, checkpointToken);
|
|
78760
|
+
collectPersistentFinallyRanges(statement, snapshotNames, ranges, checkpointToken);
|
|
78761
|
+
}
|
|
78762
|
+
ranges.sort((left, right) => left.start - right.start);
|
|
78763
|
+
const prelude = [...allNames.map((name) => `var ${name} = globalThis.__caplets_get_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)});`), ...ranges.map((range) => range.prelude)].filter(Boolean).join("\n");
|
|
78764
|
+
let body = "";
|
|
78765
|
+
let cursor = 0;
|
|
78766
|
+
for (const range of ranges) {
|
|
78767
|
+
body += javascript.slice(cursor, range.start);
|
|
78768
|
+
body += range.body;
|
|
78769
|
+
cursor = range.end;
|
|
78770
|
+
}
|
|
78771
|
+
body += javascript.slice(cursor);
|
|
78772
|
+
if (postlude) body += `\n${postlude}`;
|
|
78773
|
+
return {
|
|
78774
|
+
prelude,
|
|
78775
|
+
body,
|
|
78776
|
+
postlude,
|
|
78777
|
+
persistentNames: allNames,
|
|
78778
|
+
newNames: names.filter((name) => !existingNames.includes(name)),
|
|
78779
|
+
snapshotNames
|
|
78780
|
+
};
|
|
78781
|
+
}
|
|
78782
|
+
function collectPersistentReturnRanges(node, source, snapshotNames, ranges, returnTempName, checkpointToken, shadowedNames = /* @__PURE__ */ new Set()) {
|
|
78783
|
+
if (snapshotNames.length === 0) return;
|
|
78784
|
+
if (ts.isFunctionLike(node) || ts.isClassLike(node)) return;
|
|
78785
|
+
const declared = lexicalNamesDeclaredByNode(node);
|
|
78786
|
+
const activeShadowedNames = declared.size === 0 ? shadowedNames : new Set([...shadowedNames, ...declared]);
|
|
78787
|
+
if (ts.isReturnStatement(node)) {
|
|
78788
|
+
const expression = node.expression?.getText(source);
|
|
78789
|
+
const postludeExpression = snapshotNames.filter((name) => !activeShadowedNames.has(name)).map((name) => persistentBindingExpression(name, checkpointToken)).join(", ");
|
|
78790
|
+
ranges.push({
|
|
78791
|
+
start: node.getFullStart(),
|
|
78792
|
+
end: node.end,
|
|
78793
|
+
prelude: "",
|
|
78794
|
+
body: returnWithPersistenceExpression(expression, postludeExpression, returnTempName)
|
|
78795
|
+
});
|
|
78796
|
+
return;
|
|
78797
|
+
}
|
|
78798
|
+
ts.forEachChild(node, (child) => collectPersistentReturnRanges(child, source, snapshotNames, ranges, returnTempName, checkpointToken, activeShadowedNames));
|
|
78799
|
+
}
|
|
78800
|
+
function lexicalNamesDeclaredByNode(node) {
|
|
78801
|
+
const names = /* @__PURE__ */ new Set();
|
|
78802
|
+
if (ts.isBlock(node) || ts.isCaseClause(node) || ts.isDefaultClause(node)) for (const statement of node.statements) {
|
|
78803
|
+
if (ts.isVariableStatement(statement) && !isVarDeclarationList(statement.declarationList)) for (const name of declarationListBindingNames(statement.declarationList)) names.add(name);
|
|
78804
|
+
if ((ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement)) && statement.name) names.add(statement.name.text);
|
|
78805
|
+
if (ts.isFunctionDeclaration(statement) && statement.name) names.add(statement.name.text);
|
|
78806
|
+
}
|
|
78807
|
+
if (ts.isSwitchStatement(node)) for (const clause of node.caseBlock.clauses) for (const statement of clause.statements) {
|
|
78808
|
+
if (ts.isVariableStatement(statement) && !isVarDeclarationList(statement.declarationList)) for (const name of declarationListBindingNames(statement.declarationList)) names.add(name);
|
|
78809
|
+
if ((ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement)) && statement.name) names.add(statement.name.text);
|
|
78810
|
+
if (ts.isFunctionDeclaration(statement) && statement.name) names.add(statement.name.text);
|
|
78811
|
+
}
|
|
78812
|
+
if (ts.isCatchClause(node) && node.variableDeclaration) for (const name of bindingNames(node.variableDeclaration.name)) names.add(name);
|
|
78813
|
+
if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer) && !isVarDeclarationList(node.initializer)) for (const name of declarationListBindingNames(node.initializer)) names.add(name);
|
|
78814
|
+
return names;
|
|
78815
|
+
}
|
|
78816
|
+
function returnWithPersistenceExpression(expression, postludeExpression, returnTempName) {
|
|
78817
|
+
if (!postludeExpression) return expression ? `return ${expression};` : "return;";
|
|
78818
|
+
return expression ? `return (async (${returnTempName}) => { await Promise.resolve(); ${postludeExpression}; return ${returnTempName}; })((${expression}));` : `await Promise.resolve();\nreturn void (${postludeExpression});`;
|
|
78819
|
+
}
|
|
78820
|
+
function uniqueInternalName(baseName, unavailableNames) {
|
|
78821
|
+
const unavailable = new Set(unavailableNames);
|
|
78822
|
+
let name = baseName;
|
|
78823
|
+
while (unavailable.has(name)) name = `_${name}`;
|
|
78824
|
+
return name;
|
|
78825
|
+
}
|
|
78826
|
+
function collectPersistentVarRewriteRanges(node, source, lexicalNames, ranges) {
|
|
78827
|
+
if (ts.isFunctionLike(node) || ts.isClassLike(node)) return;
|
|
78828
|
+
if (ts.isVariableStatement(node) && isVarDeclarationList(node.declarationList)) {
|
|
78829
|
+
if (!declarationListBindingNames(node.declarationList).some((name) => lexicalNames.has(name))) ranges.push({
|
|
78830
|
+
start: node.getFullStart(),
|
|
78831
|
+
end: node.end,
|
|
78832
|
+
prelude: "",
|
|
78833
|
+
body: varStatementAssignments(node.declarationList, source)
|
|
78834
|
+
});
|
|
78835
|
+
return;
|
|
78836
|
+
}
|
|
78837
|
+
if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer) && isVarDeclarationList(node.initializer)) {
|
|
78838
|
+
if (!declarationListBindingNames(node.initializer).some((name) => lexicalNames.has(name))) ranges.push({
|
|
78839
|
+
start: node.initializer.getStart(source),
|
|
78840
|
+
end: node.initializer.end,
|
|
78841
|
+
prelude: "",
|
|
78842
|
+
body: forInitializerAssignment(node.initializer, source)
|
|
78843
|
+
});
|
|
78844
|
+
}
|
|
78845
|
+
ts.forEachChild(node, (child) => collectPersistentVarRewriteRanges(child, source, lexicalNames, ranges));
|
|
78846
|
+
}
|
|
78847
|
+
function collectPersistentFinallyRanges(node, snapshotNames, ranges, checkpointToken, shadowedNames = /* @__PURE__ */ new Set()) {
|
|
78848
|
+
if (snapshotNames.length === 0) return;
|
|
78849
|
+
if (ts.isFunctionLike(node) || ts.isClassLike(node)) return;
|
|
78850
|
+
const declared = lexicalNamesDeclaredByNode(node);
|
|
78851
|
+
const activeShadowedNames = declared.size === 0 ? shadowedNames : new Set([...shadowedNames, ...declared]);
|
|
78852
|
+
if (ts.isTryStatement(node) && node.finallyBlock) {
|
|
78853
|
+
const finallyDeclared = lexicalNamesDeclaredByNode(node.finallyBlock);
|
|
78854
|
+
const finallyShadowedNames = finallyDeclared.size === 0 ? activeShadowedNames : new Set([...activeShadowedNames, ...finallyDeclared]);
|
|
78855
|
+
const postlude = snapshotNames.filter((name) => !finallyShadowedNames.has(name)).map((name) => persistentBindingPostlude(name, checkpointToken)).join("\n");
|
|
78856
|
+
if (postlude) ranges.push({
|
|
78857
|
+
start: node.finallyBlock.end - 1,
|
|
78858
|
+
end: node.finallyBlock.end - 1,
|
|
78859
|
+
prelude: "",
|
|
78860
|
+
body: `\n${postlude}\n`
|
|
78861
|
+
});
|
|
78862
|
+
}
|
|
78863
|
+
ts.forEachChild(node, (child) => collectPersistentFinallyRanges(child, snapshotNames, ranges, checkpointToken, activeShadowedNames));
|
|
78864
|
+
}
|
|
78865
|
+
function collectPersistentBindingNames(source) {
|
|
78866
|
+
const names = /* @__PURE__ */ new Set();
|
|
78867
|
+
const visit = (node) => {
|
|
78868
|
+
if (ts.isFunctionDeclaration(node) && node.name && node.parent === source) names.add(node.name.text);
|
|
78869
|
+
if (node !== source && (ts.isFunctionLike(node) || ts.isClassLike(node))) return;
|
|
78870
|
+
if (ts.isVariableStatement(node)) collectVarDeclarationListNames(node.declarationList, names);
|
|
78871
|
+
if ((ts.isForStatement(node) || ts.isForInStatement(node) || ts.isForOfStatement(node)) && node.initializer && ts.isVariableDeclarationList(node.initializer)) collectVarDeclarationListNames(node.initializer, names);
|
|
78872
|
+
ts.forEachChild(node, visit);
|
|
78873
|
+
};
|
|
78874
|
+
visit(source);
|
|
78875
|
+
return [...names];
|
|
78876
|
+
}
|
|
78877
|
+
function collectTopLevelLexicalBindingNames(source) {
|
|
78878
|
+
const names = /* @__PURE__ */ new Set();
|
|
78879
|
+
for (const statement of source.statements) {
|
|
78880
|
+
if (ts.isVariableStatement(statement) && !isVarDeclarationList(statement.declarationList)) for (const name of declarationListBindingNames(statement.declarationList)) names.add(name);
|
|
78881
|
+
if ((ts.isClassDeclaration(statement) || ts.isEnumDeclaration(statement)) && statement.name) names.add(statement.name.text);
|
|
78882
|
+
}
|
|
78883
|
+
return names;
|
|
78884
|
+
}
|
|
78885
|
+
function collectVarDeclarationListNames(declarationList, names) {
|
|
78886
|
+
if (!((ts.getCombinedNodeFlags(declarationList) & ts.NodeFlags.BlockScoped) === 0)) return;
|
|
78887
|
+
for (const declaration of declarationList.declarations) for (const name of bindingNames(declaration.name)) names.add(name);
|
|
78888
|
+
}
|
|
78889
|
+
function isVarDeclarationList(declarationList) {
|
|
78890
|
+
return (ts.getCombinedNodeFlags(declarationList) & ts.NodeFlags.BlockScoped) === 0;
|
|
78891
|
+
}
|
|
78892
|
+
function declarationListBindingNames(declarationList) {
|
|
78893
|
+
return declarationList.declarations.flatMap((declaration) => bindingNames(declaration.name));
|
|
78894
|
+
}
|
|
78895
|
+
function varStatementAssignments(declarationList, source) {
|
|
78896
|
+
return declarationList.declarations.map((declaration) => declaration.initializer ? assignmentStatement(declaration.name, declaration.initializer, source) : "").filter(Boolean).join("\n");
|
|
78897
|
+
}
|
|
78898
|
+
function forInitializerAssignment(declarationList, source) {
|
|
78899
|
+
return declarationList.declarations.map((declaration) => declaration.initializer ? assignmentExpression(declaration.name, declaration.initializer, source) : declaration.name.getText(source)).join(", ");
|
|
78900
|
+
}
|
|
78901
|
+
function persistentBindingPostlude(name, checkpointToken) {
|
|
78902
|
+
return [`globalThis.__caplets_set_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)}, ${name});`, `(0, eval)(${JSON.stringify(`${name} = globalThis.__caplets_get_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)});`)});`].join("\n");
|
|
78903
|
+
}
|
|
78904
|
+
function persistentBindingExpression(name, checkpointToken) {
|
|
78905
|
+
return [`globalThis.__caplets_set_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)}, ${name})`, `(0, eval)(${JSON.stringify(`${name} = globalThis.__caplets_get_persist(${JSON.stringify(checkpointToken)}, ${JSON.stringify(name)});`)})`].join(", ");
|
|
78906
|
+
}
|
|
78907
|
+
function bindingNames(name) {
|
|
78908
|
+
if (ts.isIdentifier(name)) return [name.text];
|
|
78909
|
+
return name.elements.flatMap((element) => {
|
|
78910
|
+
if (ts.isOmittedExpression(element)) return [];
|
|
78911
|
+
return bindingNames(element.name);
|
|
78912
|
+
});
|
|
78913
|
+
}
|
|
78914
|
+
function assignmentStatement(name, initializer, source) {
|
|
78915
|
+
const expression = assignmentExpression(name, initializer, source);
|
|
78916
|
+
return ts.isObjectBindingPattern(name) ? `(${expression});` : `${expression};`;
|
|
78917
|
+
}
|
|
78918
|
+
function assignmentExpression(name, initializer, source) {
|
|
78919
|
+
return `${name.getText(source)} = ${initializer.getText(source)}`;
|
|
78920
|
+
}
|
|
78921
|
+
function buildPromiseObserverSource() {
|
|
78922
|
+
return [
|
|
78923
|
+
"(() => {",
|
|
78924
|
+
" const then = Promise.prototype.then;",
|
|
78925
|
+
" const formatError = function(e) {",
|
|
78926
|
+
" if (e && typeof e === 'object' && typeof e.message === 'string') return e.message;",
|
|
78927
|
+
" return String(e);",
|
|
78928
|
+
" };",
|
|
78929
|
+
" try { Object.defineProperty(globalThis, '__caplets_observe_promise', { configurable: false, writable: false, value: function(p) {",
|
|
78930
|
+
" var s = { settled: false, value: void 0, error: void 0 };",
|
|
78931
|
+
" then.call(p, function(value) { s.value = value; s.settled = true; },",
|
|
78932
|
+
" function(error) { s.error = formatError(error); s.settled = true; });",
|
|
78933
|
+
" return s;",
|
|
78934
|
+
" } }); } catch {}",
|
|
78935
|
+
"})()"
|
|
78936
|
+
].join("\n");
|
|
78937
|
+
}
|
|
78938
|
+
function buildPromiseStateSource(resultName) {
|
|
78939
|
+
return [`globalThis.__caplets_observe_promise(globalThis[${resultName}])`].join("\n");
|
|
78940
|
+
}
|
|
77370
78941
|
async function drainAsync(context, runtime, pendingDeferreds, deadlineMs, timeoutMs) {
|
|
77371
78942
|
drainJobs(context, runtime, deadlineMs, timeoutMs);
|
|
77372
78943
|
while (pendingDeferreds.size > 0) {
|
|
@@ -77409,6 +78980,9 @@ function readProp(context, handle, key) {
|
|
|
77409
78980
|
function timeoutMessage(timeoutMs) {
|
|
77410
78981
|
return `Code Mode execution timed out after ${timeoutMs}ms`;
|
|
77411
78982
|
}
|
|
78983
|
+
function isTimeoutMessage(message, timeoutMs) {
|
|
78984
|
+
return message === timeoutMessage(timeoutMs);
|
|
78985
|
+
}
|
|
77412
78986
|
function normalizeError(error, deadlineMs, timeoutMs) {
|
|
77413
78987
|
const message = errorMessage$2(error);
|
|
77414
78988
|
return Date.now() >= deadlineMs && /\binterrupted\b/iu.test(message) ? timeoutMessage(timeoutMs) : message;
|
|
@@ -77431,6 +79005,181 @@ function optionalStack(stack) {
|
|
|
77431
79005
|
function logLevel(value) {
|
|
77432
79006
|
return value === "info" || value === "warn" || value === "error" || value === "debug" || value === "log" ? value : "log";
|
|
77433
79007
|
}
|
|
79008
|
+
var CodeModeSessionManager = class {
|
|
79009
|
+
ttlMs;
|
|
79010
|
+
maxSessions;
|
|
79011
|
+
#sessions = /* @__PURE__ */ new Map();
|
|
79012
|
+
#idGenerator;
|
|
79013
|
+
#now;
|
|
79014
|
+
#sandboxFactory;
|
|
79015
|
+
#closed = false;
|
|
79016
|
+
constructor(options = {}) {
|
|
79017
|
+
this.ttlMs = options.ttlMs ?? 18e5;
|
|
79018
|
+
this.maxSessions = options.maxSessions ?? 32;
|
|
79019
|
+
this.#idGenerator = options.idGenerator ?? randomUUID;
|
|
79020
|
+
this.#now = options.now ?? Date.now;
|
|
79021
|
+
this.#sandboxFactory = options.sandboxFactory ?? (() => new QuickJsCodeModeSandbox());
|
|
79022
|
+
}
|
|
79023
|
+
async run(input) {
|
|
79024
|
+
if (this.#closed) return {
|
|
79025
|
+
ok: false,
|
|
79026
|
+
sessionId: input.sessionId ?? "",
|
|
79027
|
+
sessionStatus: null,
|
|
79028
|
+
error: "closed"
|
|
79029
|
+
};
|
|
79030
|
+
this.#evictExpired();
|
|
79031
|
+
const compatibilityKey = compatibilityKeyFor(input.compatibility);
|
|
79032
|
+
const requestedSessionId = input.sessionId;
|
|
79033
|
+
let record;
|
|
79034
|
+
let sessionStatus;
|
|
79035
|
+
if (requestedSessionId) {
|
|
79036
|
+
record = this.#sessions.get(requestedSessionId);
|
|
79037
|
+
if (!record) return {
|
|
79038
|
+
ok: false,
|
|
79039
|
+
sessionId: requestedSessionId,
|
|
79040
|
+
sessionStatus: null,
|
|
79041
|
+
error: "not_found"
|
|
79042
|
+
};
|
|
79043
|
+
if (record.busy) return {
|
|
79044
|
+
ok: false,
|
|
79045
|
+
sessionId: requestedSessionId,
|
|
79046
|
+
sessionStatus: null,
|
|
79047
|
+
error: "busy"
|
|
79048
|
+
};
|
|
79049
|
+
if (record.compatibilityKey !== compatibilityKey) {
|
|
79050
|
+
this.#disposeRecord(record.id);
|
|
79051
|
+
return {
|
|
79052
|
+
ok: false,
|
|
79053
|
+
sessionId: requestedSessionId,
|
|
79054
|
+
sessionStatus: null,
|
|
79055
|
+
error: "not_found"
|
|
79056
|
+
};
|
|
79057
|
+
} else sessionStatus = "reused";
|
|
79058
|
+
} else {
|
|
79059
|
+
const sessionId = this.#nextSessionId();
|
|
79060
|
+
record = await this.#createRecord(sessionId, compatibilityKey);
|
|
79061
|
+
if (!record) return this.#closedResult(sessionId);
|
|
79062
|
+
sessionStatus = "created";
|
|
79063
|
+
}
|
|
79064
|
+
this.#evictToLimit(record.id);
|
|
79065
|
+
record.busy = true;
|
|
79066
|
+
try {
|
|
79067
|
+
const result = await record.session.run({
|
|
79068
|
+
...input,
|
|
79069
|
+
invoke: async (invokeInput) => {
|
|
79070
|
+
if (this.#closed) throw new Error("Code Mode session manager is closed.");
|
|
79071
|
+
return await input.invoke(invokeInput);
|
|
79072
|
+
}
|
|
79073
|
+
});
|
|
79074
|
+
record.lastUsedAt = this.#now();
|
|
79075
|
+
const sessionDisposedAfterRun = record.session.isDisposed();
|
|
79076
|
+
if (sessionDisposedAfterRun) this.#sessions.delete(record.id);
|
|
79077
|
+
else if (result.ok) input.onSuccessfulCell?.(record.id, input.code);
|
|
79078
|
+
return {
|
|
79079
|
+
ok: true,
|
|
79080
|
+
sessionId: record.id,
|
|
79081
|
+
sessionStatus,
|
|
79082
|
+
sessionDisposedAfterRun,
|
|
79083
|
+
compatibilityKey: record.compatibilityKey,
|
|
79084
|
+
result
|
|
79085
|
+
};
|
|
79086
|
+
} finally {
|
|
79087
|
+
record.busy = false;
|
|
79088
|
+
this.#evictToLimit(record.id);
|
|
79089
|
+
}
|
|
79090
|
+
}
|
|
79091
|
+
close() {
|
|
79092
|
+
this.#closed = true;
|
|
79093
|
+
for (const record of this.#sessions.values()) record.session.dispose();
|
|
79094
|
+
this.#sessions.clear();
|
|
79095
|
+
}
|
|
79096
|
+
has(sessionId) {
|
|
79097
|
+
this.#evictExpired();
|
|
79098
|
+
return this.#sessions.has(sessionId);
|
|
79099
|
+
}
|
|
79100
|
+
compatibilityKey(sessionId) {
|
|
79101
|
+
this.#evictExpired();
|
|
79102
|
+
return this.#sessions.get(sessionId)?.compatibilityKey;
|
|
79103
|
+
}
|
|
79104
|
+
diagnosticsSession(sessionId, compatibility) {
|
|
79105
|
+
this.#evictExpired();
|
|
79106
|
+
const record = this.#sessions.get(sessionId);
|
|
79107
|
+
if (!record) return void 0;
|
|
79108
|
+
const compatibilityKey = compatibilityKeyFor(compatibility);
|
|
79109
|
+
if (record.compatibilityKey !== compatibilityKey) {
|
|
79110
|
+
this.#disposeRecord(sessionId);
|
|
79111
|
+
return;
|
|
79112
|
+
}
|
|
79113
|
+
return record.diagnosticsSession;
|
|
79114
|
+
}
|
|
79115
|
+
isBusy(sessionId, compatibility) {
|
|
79116
|
+
this.#evictExpired();
|
|
79117
|
+
const record = this.#sessions.get(sessionId);
|
|
79118
|
+
if (!record) return false;
|
|
79119
|
+
const compatibilityKey = compatibilityKeyFor(compatibility);
|
|
79120
|
+
if (record.compatibilityKey !== compatibilityKey) return false;
|
|
79121
|
+
return record.busy;
|
|
79122
|
+
}
|
|
79123
|
+
recordSuccessfulCell(sessionId, code, declaration = "") {
|
|
79124
|
+
this.#sessions.get(sessionId)?.diagnosticsSession.recordSuccessfulCell(code, declaration);
|
|
79125
|
+
}
|
|
79126
|
+
async #createRecord(id, compatibilityKey) {
|
|
79127
|
+
if (this.#closed) return;
|
|
79128
|
+
const session = await this.#sandboxFactory().createSession();
|
|
79129
|
+
if (this.#closed) {
|
|
79130
|
+
session.dispose();
|
|
79131
|
+
return;
|
|
79132
|
+
}
|
|
79133
|
+
const record = {
|
|
79134
|
+
id,
|
|
79135
|
+
session,
|
|
79136
|
+
diagnosticsSession: new CodeModeDiagnosticsSession(),
|
|
79137
|
+
compatibilityKey,
|
|
79138
|
+
lastUsedAt: this.#now(),
|
|
79139
|
+
busy: false
|
|
79140
|
+
};
|
|
79141
|
+
this.#sessions.set(id, record);
|
|
79142
|
+
return record;
|
|
79143
|
+
}
|
|
79144
|
+
#nextSessionId() {
|
|
79145
|
+
let id = this.#idGenerator();
|
|
79146
|
+
while (this.#sessions.has(id)) id = this.#idGenerator();
|
|
79147
|
+
return id;
|
|
79148
|
+
}
|
|
79149
|
+
#evictExpired() {
|
|
79150
|
+
const now = this.#now();
|
|
79151
|
+
for (const record of this.#sessions.values()) if (!record.busy && now - record.lastUsedAt > this.ttlMs) this.#disposeRecord(record.id);
|
|
79152
|
+
}
|
|
79153
|
+
#evictToLimit(protectedId) {
|
|
79154
|
+
while (this.#sessions.size > this.maxSessions) {
|
|
79155
|
+
const candidate = [...this.#sessions.values()].filter((record) => !record.busy && record.id !== protectedId).sort((left, right) => left.lastUsedAt - right.lastUsedAt)[0];
|
|
79156
|
+
if (!candidate) return;
|
|
79157
|
+
this.#disposeRecord(candidate.id);
|
|
79158
|
+
}
|
|
79159
|
+
}
|
|
79160
|
+
#disposeRecord(id) {
|
|
79161
|
+
const record = this.#sessions.get(id);
|
|
79162
|
+
if (!record) return;
|
|
79163
|
+
record.session.dispose();
|
|
79164
|
+
this.#sessions.delete(id);
|
|
79165
|
+
}
|
|
79166
|
+
#closedResult(sessionId) {
|
|
79167
|
+
return {
|
|
79168
|
+
ok: false,
|
|
79169
|
+
sessionId,
|
|
79170
|
+
sessionStatus: null,
|
|
79171
|
+
error: "closed"
|
|
79172
|
+
};
|
|
79173
|
+
}
|
|
79174
|
+
};
|
|
79175
|
+
function compatibilityKeyFor(input) {
|
|
79176
|
+
return JSON.stringify({
|
|
79177
|
+
declarationHash: input.declarationHash,
|
|
79178
|
+
platformRuntimeHash: input.platformRuntimeHash,
|
|
79179
|
+
runtimeScope: input.runtimeScope,
|
|
79180
|
+
version: input.version ?? 1
|
|
79181
|
+
});
|
|
79182
|
+
}
|
|
77434
79183
|
//#endregion
|
|
77435
79184
|
//#region src/code-mode/runner.ts
|
|
77436
79185
|
const DEFAULT_TIMEOUT_MS = 1e4;
|
|
@@ -77443,45 +79192,126 @@ async function runCodeMode(input) {
|
|
|
77443
79192
|
const callable = listCodeModeCallableCaplets(input.service);
|
|
77444
79193
|
const declaration = generateCodeModeDeclarations({ caplets: callable });
|
|
77445
79194
|
const declarationHash = codeModeDeclarationHash(declaration);
|
|
79195
|
+
const sessionCompatibility = {
|
|
79196
|
+
declarationHash,
|
|
79197
|
+
platformRuntimeHash: codeModeDeclarationHash(CODE_MODE_PLATFORM_RUNTIME_SOURCE),
|
|
79198
|
+
runtimeScope: input.runtimeScope ?? "",
|
|
79199
|
+
version: 1
|
|
79200
|
+
};
|
|
79201
|
+
const diagnosticsSession = input.sessionManager && input.sessionId ? input.sessionManager.diagnosticsSession(input.sessionId, sessionCompatibility) : void 0;
|
|
77446
79202
|
const metaBase = {
|
|
77447
79203
|
runId: randomUUID(),
|
|
77448
79204
|
traceId: randomUUID(),
|
|
77449
79205
|
declarationHash,
|
|
77450
79206
|
timeoutMs,
|
|
77451
|
-
maxTimeoutMs
|
|
79207
|
+
maxTimeoutMs,
|
|
79208
|
+
sessionId: input.sessionManager ? null : input.sessionId ?? null,
|
|
79209
|
+
sessionStatus: null,
|
|
79210
|
+
recoveryRef: null
|
|
77452
79211
|
};
|
|
77453
|
-
const
|
|
77454
|
-
|
|
77455
|
-
|
|
77456
|
-
message: `timeoutMs must be <= ${maxTimeoutMs}.`
|
|
77457
|
-
}] : diagnoseCodeModeTypeScript({
|
|
77458
|
-
code: input.code,
|
|
77459
|
-
declaration
|
|
79212
|
+
const meta = () => ({
|
|
79213
|
+
...metaBase,
|
|
79214
|
+
durationMs: Date.now() - startedAt
|
|
77460
79215
|
});
|
|
77461
|
-
if (
|
|
79216
|
+
if (input.sessionId !== void 0 && !input.sessionManager) return {
|
|
77462
79217
|
ok: false,
|
|
77463
79218
|
error: {
|
|
77464
|
-
code: "
|
|
77465
|
-
message: "Code Mode
|
|
79219
|
+
code: "SESSION_NOT_FOUND",
|
|
79220
|
+
message: "Code Mode session reuse is not available in this runtime. Omit sessionId to run one-shot."
|
|
77466
79221
|
},
|
|
77467
|
-
diagnostics,
|
|
79222
|
+
diagnostics: [],
|
|
79223
|
+
logs: emptyLogs(),
|
|
79224
|
+
meta: meta()
|
|
79225
|
+
};
|
|
79226
|
+
if (input.sessionManager && input.sessionId && input.sessionManager.isBusy(input.sessionId, sessionCompatibility)) return {
|
|
79227
|
+
ok: false,
|
|
79228
|
+
error: {
|
|
79229
|
+
code: "SESSION_BUSY",
|
|
79230
|
+
message: `Code Mode session ${input.sessionId} is already running.`
|
|
79231
|
+
},
|
|
79232
|
+
diagnostics: [],
|
|
77468
79233
|
logs: emptyLogs(),
|
|
77469
79234
|
meta: {
|
|
77470
|
-
...
|
|
77471
|
-
|
|
79235
|
+
...meta(),
|
|
79236
|
+
sessionId: input.sessionId,
|
|
79237
|
+
sessionStatus: null
|
|
77472
79238
|
}
|
|
77473
79239
|
};
|
|
79240
|
+
const diagnostics = timeoutMs > maxTimeoutMs ? [{
|
|
79241
|
+
code: "TIMEOUT_POLICY_EXCEEDED",
|
|
79242
|
+
severity: "error",
|
|
79243
|
+
message: `timeoutMs must be <= ${maxTimeoutMs}.`
|
|
79244
|
+
}] : diagnoseCodeModeTypeScript({
|
|
79245
|
+
code: input.code,
|
|
79246
|
+
declaration,
|
|
79247
|
+
...diagnosticsSession === void 0 ? {} : { session: diagnosticsSession }
|
|
79248
|
+
});
|
|
79249
|
+
if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
|
|
79250
|
+
const diagnosticJournalScope = input.sessionManager && input.sessionId ? input.sessionManager.compatibilityKey(input.sessionId) : void 0;
|
|
79251
|
+
if (input.sessionManager && input.sessionId && diagnosticJournalScope === void 0) {
|
|
79252
|
+
const recoveryRef = await recoveryRefForSession(input, input.sessionId);
|
|
79253
|
+
return {
|
|
79254
|
+
ok: false,
|
|
79255
|
+
error: {
|
|
79256
|
+
code: "SESSION_NOT_FOUND",
|
|
79257
|
+
message: `Code Mode session ${input.sessionId} was not found.`
|
|
79258
|
+
},
|
|
79259
|
+
diagnostics,
|
|
79260
|
+
logs: emptyLogs(),
|
|
79261
|
+
meta: {
|
|
79262
|
+
...meta(),
|
|
79263
|
+
sessionId: input.sessionId,
|
|
79264
|
+
sessionStatus: null,
|
|
79265
|
+
...recoveryMeta(recoveryRef)
|
|
79266
|
+
}
|
|
79267
|
+
};
|
|
79268
|
+
}
|
|
79269
|
+
const recoveryRef = await journalRun(input, {
|
|
79270
|
+
sessionId: input.sessionId ?? null,
|
|
79271
|
+
code: input.code,
|
|
79272
|
+
declarationHash,
|
|
79273
|
+
diagnostics,
|
|
79274
|
+
logs: emptyLogs(),
|
|
79275
|
+
outcome: {
|
|
79276
|
+
ok: false,
|
|
79277
|
+
code: "diagnostic_blocked",
|
|
79278
|
+
message: "Code Mode diagnostics failed before execution."
|
|
79279
|
+
},
|
|
79280
|
+
invokedCaplet: false,
|
|
79281
|
+
sessionDisposedAfterRun: false,
|
|
79282
|
+
journalScope: diagnosticJournalScope
|
|
79283
|
+
});
|
|
79284
|
+
if (input.sessionManager && input.sessionId) {
|
|
79285
|
+
metaBase.sessionId = input.sessionId;
|
|
79286
|
+
metaBase.sessionStatus = "reused";
|
|
79287
|
+
}
|
|
79288
|
+
if (recoveryRef && !input.sessionManager) setRecoveryMeta(metaBase, recoveryRef);
|
|
79289
|
+
return {
|
|
79290
|
+
ok: false,
|
|
79291
|
+
error: {
|
|
79292
|
+
code: "diagnostic_blocked",
|
|
79293
|
+
message: "Code Mode diagnostics failed before execution."
|
|
79294
|
+
},
|
|
79295
|
+
diagnostics,
|
|
79296
|
+
logs: emptyLogs(),
|
|
79297
|
+
meta: meta()
|
|
79298
|
+
};
|
|
79299
|
+
}
|
|
77474
79300
|
const capturedLogs = [];
|
|
79301
|
+
let invokedCaplet = false;
|
|
77475
79302
|
const api = createCodeModeCapletsApi({
|
|
77476
79303
|
service: input.service,
|
|
77477
|
-
readLogs: async (readInput) => input.logStore?.read(readInput) ?? { entries: [] }
|
|
79304
|
+
readLogs: async (readInput) => input.logStore?.read(readInput) ?? { entries: [] },
|
|
79305
|
+
readRecovery: async (readInput) => input.journalStore?.readRecovery(readInput) ?? { entries: [] }
|
|
77478
79306
|
});
|
|
77479
|
-
const
|
|
79307
|
+
const sandboxInput = {
|
|
77480
79308
|
code: input.code,
|
|
77481
79309
|
capletIds: callable.map((caplet) => caplet.id),
|
|
77482
79310
|
timeoutMs,
|
|
77483
79311
|
invoke: async ({ capletId, method, args }) => {
|
|
77484
79312
|
if (method === "readLogs") return await api.debug.readLogs(args[0]);
|
|
79313
|
+
if (method === "readRecovery") return await api.debug.readRecovery(args[0]);
|
|
79314
|
+
invokedCaplet = true;
|
|
77485
79315
|
const handle = api[capletId];
|
|
77486
79316
|
if (!handle || !("callTool" in handle)) throw new Error(`Caplet ${capletId} is not available.`);
|
|
77487
79317
|
if (method === "inspect") return await handle.inspect();
|
|
@@ -77500,19 +79330,66 @@ async function runCodeMode(input) {
|
|
|
77500
79330
|
if (method === "complete") return await handle.complete(args[0]);
|
|
77501
79331
|
throw new Error(`Unknown Code Mode CapletHandle method: ${method}.`);
|
|
77502
79332
|
}
|
|
77503
|
-
}
|
|
79333
|
+
};
|
|
79334
|
+
const sessionRun = input.sessionManager ? await input.sessionManager.run({
|
|
79335
|
+
...sandboxInput,
|
|
79336
|
+
...input.sessionId === void 0 ? {} : { sessionId: input.sessionId },
|
|
79337
|
+
compatibility: sessionCompatibility,
|
|
79338
|
+
onSuccessfulCell: (sessionId, code) => {
|
|
79339
|
+
input.sessionManager?.recordSuccessfulCell(sessionId, code, declaration);
|
|
79340
|
+
}
|
|
79341
|
+
}) : void 0;
|
|
79342
|
+
if (sessionRun && !sessionRun.ok) {
|
|
79343
|
+
const recoveryRef = sessionRun.error === "not_found" ? await recoveryRefForSession(input, sessionRun.sessionId) : void 0;
|
|
79344
|
+
return {
|
|
79345
|
+
ok: false,
|
|
79346
|
+
error: {
|
|
79347
|
+
code: sessionRun.error === "not_found" ? "SESSION_NOT_FOUND" : sessionRun.error === "closed" ? "SESSION_CLOSED" : "SESSION_BUSY",
|
|
79348
|
+
message: sessionRun.error === "not_found" ? `Code Mode session ${sessionRun.sessionId} was not found.` : sessionRun.error === "closed" ? "Code Mode session manager is closed." : `Code Mode session ${sessionRun.sessionId} is already running.`
|
|
79349
|
+
},
|
|
79350
|
+
diagnostics,
|
|
79351
|
+
logs: emptyLogs(),
|
|
79352
|
+
meta: {
|
|
79353
|
+
...meta(),
|
|
79354
|
+
sessionId: sessionRun.sessionId,
|
|
79355
|
+
sessionStatus: null,
|
|
79356
|
+
...recoveryMeta(recoveryRef)
|
|
79357
|
+
}
|
|
79358
|
+
};
|
|
79359
|
+
}
|
|
79360
|
+
const result = sessionRun?.result ?? await (input.sandbox ?? new QuickJsCodeModeSandbox()).run(sandboxInput);
|
|
79361
|
+
const sessionId = sessionRun?.sessionId ?? metaBase.sessionId ?? null;
|
|
79362
|
+
const sessionStatus = sessionRun?.sessionStatus ?? metaBase.sessionStatus ?? null;
|
|
79363
|
+
const exposeRecoveryRef = !input.sessionManager || sessionStatus === "created";
|
|
79364
|
+
metaBase.sessionId = sessionRun?.sessionDisposedAfterRun ? null : sessionId;
|
|
79365
|
+
metaBase.sessionStatus = sessionRun?.sessionDisposedAfterRun ? null : sessionStatus;
|
|
77504
79366
|
capturedLogs.push(...result.logs.map(redactLogEntry));
|
|
77505
79367
|
const logs = await buildLogs(capturedLogs, input.logStore, input.returnedLogBytes);
|
|
77506
|
-
if (!result.ok)
|
|
77507
|
-
|
|
77508
|
-
|
|
77509
|
-
|
|
77510
|
-
|
|
77511
|
-
|
|
77512
|
-
|
|
77513
|
-
|
|
77514
|
-
|
|
77515
|
-
|
|
79368
|
+
if (!result.ok) {
|
|
79369
|
+
const recoveryRef = await journalRun(input, {
|
|
79370
|
+
sessionId,
|
|
79371
|
+
code: input.code,
|
|
79372
|
+
declarationHash,
|
|
79373
|
+
diagnostics,
|
|
79374
|
+
logs,
|
|
79375
|
+
outcome: {
|
|
79376
|
+
ok: false,
|
|
79377
|
+
code: runtimeErrorCode(result.error),
|
|
79378
|
+
message: result.error
|
|
79379
|
+
},
|
|
79380
|
+
invokedCaplet,
|
|
79381
|
+
sessionDisposedAfterRun: sessionRun?.sessionDisposedAfterRun ?? false,
|
|
79382
|
+
journalScope: sessionRun?.compatibilityKey
|
|
79383
|
+
});
|
|
79384
|
+
if (recoveryRef && exposeRecoveryRef) setRecoveryMeta(metaBase, recoveryRef);
|
|
79385
|
+
return {
|
|
79386
|
+
ok: false,
|
|
79387
|
+
error: codeModeRuntimeError(result.error, result.stack),
|
|
79388
|
+
diagnostics,
|
|
79389
|
+
logs,
|
|
79390
|
+
meta: meta()
|
|
79391
|
+
};
|
|
79392
|
+
}
|
|
77516
79393
|
const serialized = serializeJsonValue(result.value);
|
|
77517
79394
|
if (!serialized.ok) {
|
|
77518
79395
|
const serializationDiagnostic = {
|
|
@@ -77520,6 +79397,22 @@ async function runCodeMode(input) {
|
|
|
77520
79397
|
severity: "error",
|
|
77521
79398
|
message: serialized.message
|
|
77522
79399
|
};
|
|
79400
|
+
const recoveryRef = await journalRun(input, {
|
|
79401
|
+
sessionId,
|
|
79402
|
+
code: input.code,
|
|
79403
|
+
declarationHash,
|
|
79404
|
+
diagnostics: [...diagnostics, serializationDiagnostic],
|
|
79405
|
+
logs,
|
|
79406
|
+
outcome: {
|
|
79407
|
+
ok: false,
|
|
79408
|
+
code: "SERIALIZATION_ERROR",
|
|
79409
|
+
message: serialized.message
|
|
79410
|
+
},
|
|
79411
|
+
invokedCaplet,
|
|
79412
|
+
sessionDisposedAfterRun: sessionRun?.sessionDisposedAfterRun ?? false,
|
|
79413
|
+
journalScope: sessionRun?.compatibilityKey
|
|
79414
|
+
});
|
|
79415
|
+
if (recoveryRef && exposeRecoveryRef) setRecoveryMeta(metaBase, recoveryRef);
|
|
77523
79416
|
return {
|
|
77524
79417
|
ok: false,
|
|
77525
79418
|
error: {
|
|
@@ -77528,23 +79421,60 @@ async function runCodeMode(input) {
|
|
|
77528
79421
|
},
|
|
77529
79422
|
diagnostics: [...diagnostics, serializationDiagnostic],
|
|
77530
79423
|
logs,
|
|
77531
|
-
meta:
|
|
77532
|
-
...metaBase,
|
|
77533
|
-
durationMs: Date.now() - startedAt
|
|
77534
|
-
}
|
|
79424
|
+
meta: meta()
|
|
77535
79425
|
};
|
|
77536
79426
|
}
|
|
79427
|
+
const recoveryRef = await journalRun(input, {
|
|
79428
|
+
sessionId,
|
|
79429
|
+
code: input.code,
|
|
79430
|
+
declarationHash,
|
|
79431
|
+
diagnostics,
|
|
79432
|
+
logs,
|
|
79433
|
+
outcome: { ok: true },
|
|
79434
|
+
invokedCaplet,
|
|
79435
|
+
sessionDisposedAfterRun: sessionRun?.sessionDisposedAfterRun ?? false,
|
|
79436
|
+
journalScope: sessionRun?.compatibilityKey
|
|
79437
|
+
});
|
|
79438
|
+
if (recoveryRef && exposeRecoveryRef) setRecoveryMeta(metaBase, recoveryRef);
|
|
77537
79439
|
return {
|
|
77538
79440
|
ok: true,
|
|
77539
79441
|
value: serialized.value,
|
|
77540
79442
|
diagnostics,
|
|
77541
79443
|
logs,
|
|
77542
|
-
meta:
|
|
77543
|
-
...metaBase,
|
|
77544
|
-
durationMs: Date.now() - startedAt
|
|
77545
|
-
}
|
|
79444
|
+
meta: meta()
|
|
77546
79445
|
};
|
|
77547
79446
|
}
|
|
79447
|
+
async function journalRun(input, run) {
|
|
79448
|
+
if (!input.journalStore || !run.sessionId) return void 0;
|
|
79449
|
+
try {
|
|
79450
|
+
return (await input.journalStore.store({
|
|
79451
|
+
sessionId: run.sessionId,
|
|
79452
|
+
...run.journalScope === void 0 ? {} : { journalScope: run.journalScope },
|
|
79453
|
+
code: run.code,
|
|
79454
|
+
declarationHash: run.declarationHash,
|
|
79455
|
+
outcome: run.outcome,
|
|
79456
|
+
diagnostics: run.diagnostics,
|
|
79457
|
+
recoveryClassification: classifyCodeModeRecovery({
|
|
79458
|
+
code: run.code,
|
|
79459
|
+
invokedCaplet: run.invokedCaplet,
|
|
79460
|
+
sessionDisposedAfterRun: run.sessionDisposedAfterRun
|
|
79461
|
+
}),
|
|
79462
|
+
...run.logs.logRef ? { logRef: run.logs.logRef } : {}
|
|
79463
|
+
})).recoveryRef;
|
|
79464
|
+
} catch {
|
|
79465
|
+
return;
|
|
79466
|
+
}
|
|
79467
|
+
}
|
|
79468
|
+
function setRecoveryMeta(metaBase, recoveryRef) {
|
|
79469
|
+
metaBase.recoveryRef = recoveryRef;
|
|
79470
|
+
}
|
|
79471
|
+
async function recoveryRefForSession(input, sessionId) {
|
|
79472
|
+
return (await input.journalStore?.lookupSession(sessionId))?.recoveryRef;
|
|
79473
|
+
}
|
|
79474
|
+
function recoveryMeta(recoveryRef) {
|
|
79475
|
+
if (!recoveryRef) return { recoveryRef: null };
|
|
79476
|
+
return { recoveryRef };
|
|
79477
|
+
}
|
|
77548
79478
|
function codeModeRuntimeError(message, stack) {
|
|
77549
79479
|
const location = userCodeLocation(stack);
|
|
77550
79480
|
const stackPreview = location === void 0 ? void 0 : [`at user code line ${location.line} column ${location.column}`];
|
|
@@ -77636,9 +79566,11 @@ function redactLogEntry(entry) {
|
|
|
77636
79566
|
}
|
|
77637
79567
|
//#endregion
|
|
77638
79568
|
//#region src/code-mode/tool.ts
|
|
79569
|
+
const CODE_MODE_SESSION_ID_DESCRIPTION = "Optional Code Mode session identifier. Omit to create a fresh reusable session; pass a known live session ID from meta.sessionId to reuse existing REPL state. Unknown or unavailable session IDs fail before code execution instead of starting an empty context.";
|
|
77639
79570
|
const codeModeRunInputSchema = object$1({
|
|
77640
79571
|
code: string().describe("TypeScript Code Mode source to execute."),
|
|
77641
|
-
timeoutMs: number$1().int().positive().optional().describe("Optional execution timeout in milliseconds.")
|
|
79572
|
+
timeoutMs: number$1().int().positive().optional().describe("Optional execution timeout in milliseconds."),
|
|
79573
|
+
sessionId: string().min(1).optional().describe(CODE_MODE_SESSION_ID_DESCRIPTION)
|
|
77642
79574
|
});
|
|
77643
79575
|
const codeModeRunParamsSchema = codeModeRunInputSchema.shape;
|
|
77644
79576
|
function codeModeRunInputJsonSchema() {
|
|
@@ -77653,12 +79585,30 @@ function codeModeRunInputJsonSchema() {
|
|
|
77653
79585
|
type: "integer",
|
|
77654
79586
|
minimum: 1,
|
|
77655
79587
|
description: "Optional execution timeout in milliseconds."
|
|
79588
|
+
},
|
|
79589
|
+
sessionId: {
|
|
79590
|
+
type: "string",
|
|
79591
|
+
minLength: 1,
|
|
79592
|
+
description: CODE_MODE_SESSION_ID_DESCRIPTION
|
|
77656
79593
|
}
|
|
77657
79594
|
},
|
|
77658
79595
|
required: ["code"],
|
|
77659
79596
|
additionalProperties: false
|
|
77660
79597
|
};
|
|
77661
79598
|
}
|
|
79599
|
+
function emptyCodeModeRunMeta() {
|
|
79600
|
+
return {
|
|
79601
|
+
runId: "",
|
|
79602
|
+
traceId: "",
|
|
79603
|
+
declarationHash: "",
|
|
79604
|
+
durationMs: 0,
|
|
79605
|
+
timeoutMs: 0,
|
|
79606
|
+
maxTimeoutMs: 0,
|
|
79607
|
+
sessionId: null,
|
|
79608
|
+
sessionStatus: null,
|
|
79609
|
+
recoveryRef: null
|
|
79610
|
+
};
|
|
79611
|
+
}
|
|
77662
79612
|
//#endregion
|
|
77663
79613
|
//#region src/native/tools.ts
|
|
77664
79614
|
const nativeCodeModeToolId = "code_mode";
|
|
@@ -77676,12 +79626,23 @@ function nativeCapletsSystemGuidance(toolNames) {
|
|
|
77676
79626
|
toolNames.length > 0 ? toolNames.map((tool) => `- ${tool}`).join("\n") : "- none",
|
|
77677
79627
|
"",
|
|
77678
79628
|
`${nativeCodeModeToolName} executes Caplets Code Mode: TypeScript with generated caplets.<id> handles for multi-step discovery, tool calls, filtering, and compact synthesis in one native call.`,
|
|
79629
|
+
...nativeCodeModePromptGuidance(),
|
|
77679
79630
|
"Flow: inspect when the domain is unfamiliar; use tools/search_tools for downstream names, arg hints, and callTemplate; call_tool directly from callTemplate/argsTemplate for simple calls; reserve describe_tool for complex schemas, nested args, fields, or uncertainty.",
|
|
77680
79631
|
"Do not guess downstream tool names, resource URIs, prompt names, input args, output fields, or schemas. Do not infer input/output schemas from memory.",
|
|
77681
79632
|
"Prefer list/read/search operations for triage and avoid broad provider searches that can return huge payloads or hit rate limits.",
|
|
77682
79633
|
"When output shaping matters, inspect one tool with describe_tool and follow its fieldSelection hint."
|
|
77683
79634
|
].join("\n");
|
|
77684
79635
|
}
|
|
79636
|
+
function nativeCodeModePromptGuidance() {
|
|
79637
|
+
return [
|
|
79638
|
+
`Use ${nativeCodeModeToolName} to run Caplets Code Mode TypeScript with generated caplets.<id> handles.`,
|
|
79639
|
+
"Prefer Code Mode for multi-step Caplet discovery, tool calls, filtering, joins, and compact synthesis.",
|
|
79640
|
+
"For REPL reuse, omit sessionId to start fresh, then pass the returned meta.sessionId on later calls that should reuse live state.",
|
|
79641
|
+
"Reused sessions preserve successful top-level var bindings, function declarations, and runtime state only while the live session remains available and compatible.",
|
|
79642
|
+
"Unknown or unavailable sessionId values fail before code execution; use meta.recoveryRef with caplets.debug.readRecovery({ recoveryRef }) for audit and manual reconstruction, not automatic replay.",
|
|
79643
|
+
"Return decision-ready JSON from Code Mode rather than raw bulky provider payloads."
|
|
79644
|
+
];
|
|
79645
|
+
}
|
|
77685
79646
|
function nativeCapletPromptGuidance(toolName, caplet) {
|
|
77686
79647
|
const descriptorFirst = "Use tools/search_tools callTemplate/arg hints for simple calls; reserve describe_tool for exact schemas, nested args, fields, or uncertainty. call_tool.args must match inputSchema exactly. Do not guess tool names or schemas.";
|
|
77687
79648
|
return caplet.backend === "mcp" ? [
|
|
@@ -77702,16 +79663,6 @@ function nativeCapletToolDescription(toolName, caplet) {
|
|
|
77702
79663
|
//#endregion
|
|
77703
79664
|
//#region src/server/options.ts
|
|
77704
79665
|
const DEFAULT_SERVER_USER = "caplets";
|
|
77705
|
-
function resolveCapletsMode(input = {}, env = process.env) {
|
|
77706
|
-
const mode = parseCapletsMode$1(input.mode ?? env.CAPLETS_MODE ?? "auto");
|
|
77707
|
-
if (mode === "local") return { mode: "local" };
|
|
77708
|
-
const rawUrl = nonEmpty$1(input.serverUrl, "serverUrl") ?? nonEmpty$1(env.CAPLETS_SERVER_URL, "CAPLETS_SERVER_URL");
|
|
77709
|
-
if (mode === "remote") {
|
|
77710
|
-
if (rawUrl === void 0) throw new CapletsError("REQUEST_INVALID", "CAPLETS_MODE=remote requires CAPLETS_SERVER_URL or serverUrl.");
|
|
77711
|
-
return { mode: "remote" };
|
|
77712
|
-
}
|
|
77713
|
-
return rawUrl === void 0 ? { mode: "local" } : { mode: "remote" };
|
|
77714
|
-
}
|
|
77715
79666
|
function resolveCapletsServer(input = {}, env = process.env) {
|
|
77716
79667
|
const rawUrl = nonEmpty$1(input.url, "url") ?? nonEmpty$1(env.CAPLETS_SERVER_URL, "CAPLETS_SERVER_URL");
|
|
77717
79668
|
if (rawUrl === void 0) throw new CapletsError("REQUEST_INVALID", "CAPLETS_SERVER_URL or url is required.");
|
|
@@ -77773,10 +79724,6 @@ function isLoopbackHost(host) {
|
|
|
77773
79724
|
const normalized = host.toLocaleLowerCase();
|
|
77774
79725
|
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1" || normalized === "[::1]";
|
|
77775
79726
|
}
|
|
77776
|
-
function parseCapletsMode$1(value) {
|
|
77777
|
-
if (value === "auto" || value === "local" || value === "remote") return value;
|
|
77778
|
-
throw new CapletsError("REQUEST_INVALID", `Expected CAPLETS_MODE to be auto, local, or remote, got ${value}`);
|
|
77779
|
-
}
|
|
77780
79727
|
function basicAuthHeader$1(user, password) {
|
|
77781
79728
|
return `Basic ${Buffer$1.from(`${user}:${password}`).toString("base64")}`;
|
|
77782
79729
|
}
|
|
@@ -77936,15 +79883,11 @@ const DEFAULT_PRESENCE_HEARTBEAT_INTERVAL_MS = 3e4;
|
|
|
77936
79883
|
function resolveNativeCapletsServiceOptions(input = {}, env = process.env) {
|
|
77937
79884
|
const mode = resolveRemoteMode({
|
|
77938
79885
|
...input.mode ? { mode: input.mode } : {},
|
|
77939
|
-
...input.
|
|
79886
|
+
...input.remote?.url ? { remoteUrl: input.remote.url } : {}
|
|
77940
79887
|
}, env);
|
|
77941
79888
|
if (mode.mode === "local") return { mode: "local" };
|
|
77942
|
-
const
|
|
77943
|
-
const
|
|
77944
|
-
...input.server,
|
|
77945
|
-
...serverFetch ? { fetch: serverFetch } : {}
|
|
77946
|
-
};
|
|
77947
|
-
const server = mode.mode === "cloud" ? resolveNativeHostedCloudRemote(input.server?.url ?? env.CAPLETS_REMOTE_URL ?? "", optionalWorkspace(input, env).workspace, serverFetch) : resolveCapletsRemote(serverInput, env);
|
|
79889
|
+
const remoteFetch = input.remote?.fetch;
|
|
79890
|
+
const server = mode.mode === "cloud" ? resolveNativeHostedCloudRemote(input.remote?.url ?? env.CAPLETS_REMOTE_URL ?? "", optionalWorkspace(input, env).workspace, remoteFetch) : resolveCapletsRemote(input.remote, env);
|
|
77948
79891
|
const cloud = resolveNativeCloudPresence(input.remote?.cloud, env);
|
|
77949
79892
|
return {
|
|
77950
79893
|
mode: mode.mode,
|
|
@@ -77966,7 +79909,7 @@ function resolveNativeHostedCloudRemote(url, workspace, fetch) {
|
|
|
77966
79909
|
});
|
|
77967
79910
|
}
|
|
77968
79911
|
function optionalWorkspace(input, env) {
|
|
77969
|
-
const workspace = input.remote?.cloud?.workspaceId ?? env.CAPLETS_REMOTE_WORKSPACE ?? env.CAPLETS_CLOUD_WORKSPACE_ID;
|
|
79912
|
+
const workspace = input.remote?.cloud?.workspaceId ?? input.remote?.workspace ?? env.CAPLETS_REMOTE_WORKSPACE ?? env.CAPLETS_CLOUD_WORKSPACE_ID;
|
|
77970
79913
|
return workspace ? { workspace } : {};
|
|
77971
79914
|
}
|
|
77972
79915
|
function nativeAuthFromRemoteAuth$1(auth) {
|
|
@@ -78394,6 +80337,7 @@ var RemoteNativeCapletsService = class {
|
|
|
78394
80337
|
client;
|
|
78395
80338
|
unsubscribeRemote;
|
|
78396
80339
|
pollTimer;
|
|
80340
|
+
codeModeSessions = new CodeModeSessionManager();
|
|
78397
80341
|
closed = false;
|
|
78398
80342
|
resetInFlight;
|
|
78399
80343
|
constructor(options) {
|
|
@@ -78410,7 +80354,7 @@ var RemoteNativeCapletsService = class {
|
|
|
78410
80354
|
return [...this.tools];
|
|
78411
80355
|
}
|
|
78412
80356
|
async execute(capletId, request) {
|
|
78413
|
-
if (capletId === "code_mode") return await executeCodeModeRunRemote(this, request);
|
|
80357
|
+
if (capletId === "code_mode") return await executeCodeModeRunRemote(this, request, this.codeModeSessions);
|
|
78414
80358
|
const remoteToolId = this.toolRoutes.get(capletId) ?? capletId;
|
|
78415
80359
|
try {
|
|
78416
80360
|
return await this.client.callTool(remoteToolId, request);
|
|
@@ -78428,6 +80372,16 @@ var RemoteNativeCapletsService = class {
|
|
|
78428
80372
|
throw error;
|
|
78429
80373
|
}
|
|
78430
80374
|
}
|
|
80375
|
+
codeModeService() {
|
|
80376
|
+
return {
|
|
80377
|
+
listTools: () => remoteCodeModeCallableNativeTools$1(this.listTools()),
|
|
80378
|
+
execute: async (capletId, request) => await this.execute(capletId, request),
|
|
80379
|
+
codeModeService: () => this.codeModeService(),
|
|
80380
|
+
reload: async () => await this.reload(),
|
|
80381
|
+
onToolsChanged: () => () => void 0,
|
|
80382
|
+
close: async () => void 0
|
|
80383
|
+
};
|
|
80384
|
+
}
|
|
78431
80385
|
async reload() {
|
|
78432
80386
|
if (this.closed) return false;
|
|
78433
80387
|
try {
|
|
@@ -78454,6 +80408,7 @@ var RemoteNativeCapletsService = class {
|
|
|
78454
80408
|
if (this.closed) return;
|
|
78455
80409
|
this.closed = true;
|
|
78456
80410
|
clearInterval(this.pollTimer);
|
|
80411
|
+
this.codeModeSessions.close();
|
|
78457
80412
|
this.unsubscribeRemote();
|
|
78458
80413
|
this.listeners.clear();
|
|
78459
80414
|
await this.client.close();
|
|
@@ -78508,6 +80463,7 @@ function remoteToolToNativeTool(tool) {
|
|
|
78508
80463
|
const toolName = tool.codeModeRun ? nativeCodeModeToolName : nativeCapletToolName(capletId);
|
|
78509
80464
|
const inputSchema = isPlainObject(tool.inputSchema) ? tool.inputSchema : generatedToolInputJsonSchemaForCaplet({ backend: "tool" });
|
|
78510
80465
|
const operationNames = tool.sourceCapletId === void 0 && !tool.codeModeRun ? operationNamesFromSchema(inputSchema) : void 0;
|
|
80466
|
+
const description = tool.codeModeRun ? remoteCodeModeToolDescription(tool) : tool.description;
|
|
78511
80467
|
return {
|
|
78512
80468
|
caplet: capletId,
|
|
78513
80469
|
...sourceCaplet && sourceCaplet !== capletId ? { sourceCaplet } : {},
|
|
@@ -78515,12 +80471,12 @@ function remoteToolToNativeTool(tool) {
|
|
|
78515
80471
|
toolName,
|
|
78516
80472
|
title: tool.title ?? capletId,
|
|
78517
80473
|
description: [
|
|
78518
|
-
|
|
80474
|
+
description ?? "Remote Caplets tool.",
|
|
78519
80475
|
"",
|
|
78520
80476
|
`Native tool name: ${toolName}`,
|
|
78521
80477
|
`Remote Caplet ID: ${capletId}`
|
|
78522
80478
|
].join("\n"),
|
|
78523
|
-
promptGuidance: [`Use ${toolName} through the remote Caplets service.`],
|
|
80479
|
+
promptGuidance: tool.codeModeRun ? nativeCodeModePromptGuidance() : [`Use ${toolName} through the remote Caplets service.`],
|
|
78524
80480
|
...tool.codeModeRun || capletId === "code_mode" ? { codeModeRun: true } : {},
|
|
78525
80481
|
...tool.codeModeCaplets ? { codeModeCaplets: tool.codeModeCaplets.map((caplet) => ({
|
|
78526
80482
|
id: caplet.capletId,
|
|
@@ -78534,6 +80490,34 @@ function remoteToolToNativeTool(tool) {
|
|
|
78534
80490
|
...operationNames ? { operationNames } : {}
|
|
78535
80491
|
};
|
|
78536
80492
|
}
|
|
80493
|
+
function remoteCodeModeToolDescription(tool) {
|
|
80494
|
+
if (!tool.codeModeCaplets || tool.codeModeCaplets.length === 0) return tool.description;
|
|
80495
|
+
return generateCodeModeRunToolDescription(generateCodeModeDeclarations({ caplets: tool.codeModeCaplets.map((caplet) => ({
|
|
80496
|
+
id: caplet.capletId,
|
|
80497
|
+
name: caplet.name,
|
|
80498
|
+
description: caplet.description ?? "",
|
|
80499
|
+
shadowing: caplet.shadowing
|
|
80500
|
+
})) }));
|
|
80501
|
+
}
|
|
80502
|
+
function remoteCodeModeCallableNativeTools$1(tools) {
|
|
80503
|
+
const codeModeCaplets = tools.flatMap((tool) => tool.codeModeCaplets ?? []);
|
|
80504
|
+
const hasExplicitCodeModeManifest = tools.some((tool) => tool.codeModeCaplets !== void 0);
|
|
80505
|
+
if (codeModeCaplets.length === 0) return hasExplicitCodeModeManifest ? [] : tools.filter((tool) => tool.codeModeRun !== true);
|
|
80506
|
+
const byId = new Map(tools.map((tool) => [tool.caplet, tool]));
|
|
80507
|
+
return codeModeCaplets.map((caplet) => {
|
|
80508
|
+
const tool = byId.get(caplet.id);
|
|
80509
|
+
return {
|
|
80510
|
+
caplet: caplet.id,
|
|
80511
|
+
toolName: tool?.toolName ?? nativeCapletToolName(caplet.id),
|
|
80512
|
+
title: caplet.name,
|
|
80513
|
+
description: caplet.description,
|
|
80514
|
+
...caplet.shadowing ? { shadowing: caplet.shadowing } : {},
|
|
80515
|
+
...caplet.useWhen ? { useWhen: caplet.useWhen } : {},
|
|
80516
|
+
...caplet.avoidWhen ? { avoidWhen: caplet.avoidWhen } : {},
|
|
80517
|
+
promptGuidance: tool?.promptGuidance ?? []
|
|
80518
|
+
};
|
|
80519
|
+
});
|
|
80520
|
+
}
|
|
78537
80521
|
function nativeToolRouteId(tool) {
|
|
78538
80522
|
return tool.codeModeRun ? nativeCodeModeToolId : tool.name;
|
|
78539
80523
|
}
|
|
@@ -78659,8 +80643,9 @@ function primitiveInvokeInput(capletId, operation, input) {
|
|
|
78659
80643
|
return input;
|
|
78660
80644
|
}
|
|
78661
80645
|
function toolsFromManifest(manifest) {
|
|
78662
|
-
const
|
|
78663
|
-
const
|
|
80646
|
+
const codeModeCaplets = manifest.codeModeCaplets ?? [];
|
|
80647
|
+
const codeModeMarker = attachCodeModeMarker(codeModeCaplets);
|
|
80648
|
+
const codeModeShadowing = codeModeCaplets.some((entry) => entry.shadowing === "forbid") ? "forbid" : "allow";
|
|
78664
80649
|
return [
|
|
78665
80650
|
...manifest.caplets.map((entry) => ({
|
|
78666
80651
|
name: entry.capletId,
|
|
@@ -78684,20 +80669,20 @@ function toolsFromManifest(manifest) {
|
|
|
78684
80669
|
...codeModeMarker
|
|
78685
80670
|
})),
|
|
78686
80671
|
...primitiveToolsFromManifest(manifest, codeModeMarker),
|
|
78687
|
-
...
|
|
80672
|
+
...codeModeCaplets.length > 0 ? [{
|
|
78688
80673
|
name: nativeCodeModeToolId,
|
|
78689
80674
|
capletId: nativeCodeModeToolId,
|
|
78690
80675
|
title: "Code Mode",
|
|
78691
80676
|
description: "Remote Caplets available to locally-run attached Code Mode.",
|
|
78692
80677
|
codeModeRun: true,
|
|
78693
|
-
codeModeCaplets
|
|
80678
|
+
codeModeCaplets,
|
|
78694
80679
|
shadowing: codeModeShadowing,
|
|
78695
80680
|
inputSchema: codeModeRunInputJsonSchema()
|
|
78696
80681
|
}] : []
|
|
78697
80682
|
];
|
|
78698
80683
|
}
|
|
78699
|
-
function attachCodeModeMarker(
|
|
78700
|
-
return
|
|
80684
|
+
function attachCodeModeMarker(codeModeCaplets = []) {
|
|
80685
|
+
return codeModeCaplets.length === 0 ? { codeModeCaplets: [] } : {};
|
|
78701
80686
|
}
|
|
78702
80687
|
function primitiveToolsFromManifest(manifest, codeModeMarker) {
|
|
78703
80688
|
const directToolNames = new Set(manifest.tools.map((entry) => entry.name));
|
|
@@ -78806,7 +80791,7 @@ function exportMapFor(manifest) {
|
|
|
78806
80791
|
mapped.set(entry.name, entry);
|
|
78807
80792
|
}
|
|
78808
80793
|
for (const entry of manifest.tools) mapped.set(entry.name, entry);
|
|
78809
|
-
for (const entry of manifest.codeModeCaplets) {
|
|
80794
|
+
for (const entry of manifest.codeModeCaplets ?? []) {
|
|
78810
80795
|
setIfAbsent(entry.capletId, entry);
|
|
78811
80796
|
setIfAbsent(entry.name, entry);
|
|
78812
80797
|
}
|
|
@@ -78866,7 +80851,7 @@ function startAttachEvents(attachUrl, requestInit, fetchImpl, listeners, onClose
|
|
|
78866
80851
|
})();
|
|
78867
80852
|
return abort;
|
|
78868
80853
|
}
|
|
78869
|
-
async function executeCodeModeRunRemote(service, request) {
|
|
80854
|
+
async function executeCodeModeRunRemote(service, request, sessionManager) {
|
|
78870
80855
|
const parsed = codeModeRunInputSchema.safeParse(request);
|
|
78871
80856
|
if (!parsed.success) return {
|
|
78872
80857
|
ok: false,
|
|
@@ -78881,20 +80866,16 @@ async function executeCodeModeRunRemote(service, request) {
|
|
|
78881
80866
|
truncated: false,
|
|
78882
80867
|
stored: false
|
|
78883
80868
|
},
|
|
78884
|
-
meta:
|
|
78885
|
-
runId: "",
|
|
78886
|
-
traceId: "",
|
|
78887
|
-
declarationHash: "",
|
|
78888
|
-
durationMs: 0,
|
|
78889
|
-
timeoutMs: 0,
|
|
78890
|
-
maxTimeoutMs: 0
|
|
78891
|
-
}
|
|
80869
|
+
meta: emptyCodeModeRunMeta()
|
|
78892
80870
|
};
|
|
78893
80871
|
return await runCodeMode({
|
|
78894
80872
|
code: parsed.data.code,
|
|
78895
80873
|
service,
|
|
78896
80874
|
...parsed.data.timeoutMs === void 0 ? {} : { timeoutMs: parsed.data.timeoutMs },
|
|
78897
|
-
|
|
80875
|
+
...parsed.data.sessionId === void 0 ? {} : { sessionId: parsed.data.sessionId },
|
|
80876
|
+
runtimeScope: process.env.CAPLETS_MODE?.trim() || "remote",
|
|
80877
|
+
journalStore: new CodeModeJournalStore(),
|
|
80878
|
+
...sessionManager === void 0 ? {} : { sessionManager }
|
|
78898
80879
|
});
|
|
78899
80880
|
}
|
|
78900
80881
|
function compatibleExport(manifest, previous) {
|
|
@@ -78905,7 +80886,7 @@ function compatibleExport(manifest, previous) {
|
|
|
78905
80886
|
...manifest.resourceTemplates,
|
|
78906
80887
|
...manifest.prompts,
|
|
78907
80888
|
...manifest.completions,
|
|
78908
|
-
...manifest.codeModeCaplets
|
|
80889
|
+
...manifest.codeModeCaplets ?? []
|
|
78909
80890
|
].find((entry) => entry.stableId === previous.stableId);
|
|
78910
80891
|
if (!next) return void 0;
|
|
78911
80892
|
if (next.kind !== previous.kind) return void 0;
|
|
@@ -79346,6 +81327,7 @@ var DefaultNativeCapletsService = class {
|
|
|
79346
81327
|
toolListeners = /* @__PURE__ */ new Set();
|
|
79347
81328
|
directToolRoutes = /* @__PURE__ */ new Map();
|
|
79348
81329
|
exposureSnapshot;
|
|
81330
|
+
codeModeSessions = new CodeModeSessionManager();
|
|
79349
81331
|
postReloadRefresh;
|
|
79350
81332
|
exposureRefreshGeneration = 0;
|
|
79351
81333
|
constructor(options) {
|
|
@@ -79383,7 +81365,7 @@ var DefaultNativeCapletsService = class {
|
|
|
79383
81365
|
];
|
|
79384
81366
|
}
|
|
79385
81367
|
async execute(capletId, request) {
|
|
79386
|
-
if (capletId === "code_mode") return await executeCodeModeRunNative(this.codeModeDelegate(), request);
|
|
81368
|
+
if (capletId === "code_mode") return await executeCodeModeRunNative(this.codeModeDelegate(), request, this.codeModeSessions);
|
|
79387
81369
|
const route = this.directToolRoutes.get(capletId);
|
|
79388
81370
|
if (route) {
|
|
79389
81371
|
if (isMcpPrimitiveRoute(route.operationName)) return await this.engine.execute(route.capletId, nativeMcpPrimitiveRequest(route.operationName, request));
|
|
@@ -79391,6 +81373,9 @@ var DefaultNativeCapletsService = class {
|
|
|
79391
81373
|
}
|
|
79392
81374
|
return await this.engine.execute(capletId, request);
|
|
79393
81375
|
}
|
|
81376
|
+
codeModeService() {
|
|
81377
|
+
return this.codeModeDelegate();
|
|
81378
|
+
}
|
|
79394
81379
|
async reload() {
|
|
79395
81380
|
const reloaded = await this.engine.reload();
|
|
79396
81381
|
await this.postReloadRefresh;
|
|
@@ -79404,6 +81389,7 @@ var DefaultNativeCapletsService = class {
|
|
|
79404
81389
|
}
|
|
79405
81390
|
async close() {
|
|
79406
81391
|
this.unsubscribeEngineReload();
|
|
81392
|
+
this.codeModeSessions.close();
|
|
79407
81393
|
this.toolListeners.clear();
|
|
79408
81394
|
await this.engine.close();
|
|
79409
81395
|
}
|
|
@@ -79630,11 +81616,7 @@ function codeModeRunNativeTool(capletTools) {
|
|
|
79630
81616
|
].join("\n"),
|
|
79631
81617
|
codeModeRun: true,
|
|
79632
81618
|
codeModeCaplets,
|
|
79633
|
-
promptGuidance:
|
|
79634
|
-
`Use ${nativeCodeModeToolName} to run Caplets Code Mode TypeScript with generated caplets.<id> handles.`,
|
|
79635
|
-
"Prefer Code Mode for multi-step Caplet discovery, tool calls, filtering, joins, and compact synthesis.",
|
|
79636
|
-
"Return decision-ready JSON from Code Mode rather than raw bulky provider payloads."
|
|
79637
|
-
],
|
|
81619
|
+
promptGuidance: nativeCodeModePromptGuidance(),
|
|
79638
81620
|
inputSchema: codeModeRunInputJsonSchema()
|
|
79639
81621
|
};
|
|
79640
81622
|
}
|
|
@@ -79657,7 +81639,7 @@ function codeModeCallableNativeTools(tools, options) {
|
|
|
79657
81639
|
};
|
|
79658
81640
|
});
|
|
79659
81641
|
}
|
|
79660
|
-
async function executeCodeModeRunNative(service, request) {
|
|
81642
|
+
async function executeCodeModeRunNative(service, request, sessionManager) {
|
|
79661
81643
|
const parsed = codeModeRunInputSchema.safeParse(request);
|
|
79662
81644
|
if (!parsed.success) return {
|
|
79663
81645
|
ok: false,
|
|
@@ -79672,20 +81654,16 @@ async function executeCodeModeRunNative(service, request) {
|
|
|
79672
81654
|
truncated: false,
|
|
79673
81655
|
stored: false
|
|
79674
81656
|
},
|
|
79675
|
-
meta:
|
|
79676
|
-
runId: "",
|
|
79677
|
-
traceId: "",
|
|
79678
|
-
declarationHash: "",
|
|
79679
|
-
durationMs: 0,
|
|
79680
|
-
timeoutMs: 0,
|
|
79681
|
-
maxTimeoutMs: 0
|
|
79682
|
-
}
|
|
81657
|
+
meta: emptyCodeModeRunMeta()
|
|
79683
81658
|
};
|
|
79684
81659
|
return await runCodeMode({
|
|
79685
81660
|
code: parsed.data.code,
|
|
79686
81661
|
service,
|
|
79687
81662
|
...parsed.data.timeoutMs === void 0 ? {} : { timeoutMs: parsed.data.timeoutMs },
|
|
79688
|
-
|
|
81663
|
+
...parsed.data.sessionId === void 0 ? {} : { sessionId: parsed.data.sessionId },
|
|
81664
|
+
runtimeScope: process.env.CAPLETS_MODE?.trim() || "local",
|
|
81665
|
+
journalStore: new CodeModeJournalStore(),
|
|
81666
|
+
...sessionManager === void 0 ? {} : { sessionManager }
|
|
79689
81667
|
});
|
|
79690
81668
|
}
|
|
79691
81669
|
function createDefaultNativeCapletsService(options) {
|
|
@@ -79727,11 +81705,14 @@ var CloudNativeCapletsService = class {
|
|
|
79727
81705
|
async execute(capletId, request) {
|
|
79728
81706
|
return await (this.delegate ?? this.local).execute(capletId, request);
|
|
79729
81707
|
}
|
|
81708
|
+
codeModeService() {
|
|
81709
|
+
return (this.delegate ?? this.local).codeModeService?.() ?? this.delegate ?? this.local;
|
|
81710
|
+
}
|
|
79730
81711
|
async reload() {
|
|
79731
81712
|
if (this.closed) return false;
|
|
79732
81713
|
if (!this.delegate) try {
|
|
79733
|
-
const cloudFetch = this.options.remote?.fetch
|
|
79734
|
-
const remoteUrl = this.options.
|
|
81714
|
+
const cloudFetch = this.options.remote?.fetch;
|
|
81715
|
+
const remoteUrl = this.options.remote?.url ?? this.baseRemote.url.toString().replace(/\/mcp$/u, "");
|
|
79735
81716
|
const selection = await resolveRemoteSelection({
|
|
79736
81717
|
mode: "cloud",
|
|
79737
81718
|
remoteUrl,
|
|
@@ -79807,6 +81788,7 @@ var CompositeNativeCapletsService = class {
|
|
|
79807
81788
|
tools = [];
|
|
79808
81789
|
closed = false;
|
|
79809
81790
|
batchingReload = false;
|
|
81791
|
+
codeModeSessions = new CodeModeSessionManager();
|
|
79810
81792
|
constructor(remote, local, options, presence) {
|
|
79811
81793
|
this.remote = remote;
|
|
79812
81794
|
this.local = local;
|
|
@@ -79822,10 +81804,20 @@ var CompositeNativeCapletsService = class {
|
|
|
79822
81804
|
return [...this.tools];
|
|
79823
81805
|
}
|
|
79824
81806
|
async execute(capletId, request) {
|
|
79825
|
-
if (capletId === "code_mode") return await executeCodeModeRunNative(this, request);
|
|
81807
|
+
if (capletId === "code_mode") return await executeCodeModeRunNative(this, request, this.codeModeSessions);
|
|
79826
81808
|
if (this.localCanExecute(capletId)) return await this.local.execute(capletId, request);
|
|
79827
81809
|
return await this.remote.execute(capletId, request);
|
|
79828
81810
|
}
|
|
81811
|
+
codeModeService() {
|
|
81812
|
+
return {
|
|
81813
|
+
listTools: () => codeModeCallableNativeTools(this.listTools(), { fallbackToVisible: false }),
|
|
81814
|
+
execute: async (capletId, request) => await this.execute(capletId, request),
|
|
81815
|
+
codeModeService: () => this.codeModeService(),
|
|
81816
|
+
reload: async () => await this.reload(),
|
|
81817
|
+
onToolsChanged: () => () => void 0,
|
|
81818
|
+
close: async () => void 0
|
|
81819
|
+
};
|
|
81820
|
+
}
|
|
79829
81821
|
async reload() {
|
|
79830
81822
|
if (this.closed) return false;
|
|
79831
81823
|
this.batchingReload = true;
|
|
@@ -79846,6 +81838,7 @@ var CompositeNativeCapletsService = class {
|
|
|
79846
81838
|
this.closed = true;
|
|
79847
81839
|
for (const unsubscribe of this.unsubscribers.splice(0)) unsubscribe();
|
|
79848
81840
|
this.listeners.clear();
|
|
81841
|
+
this.codeModeSessions.close();
|
|
79849
81842
|
await Promise.all([
|
|
79850
81843
|
this.remote.close(),
|
|
79851
81844
|
this.local.close(),
|
|
@@ -79917,7 +81910,7 @@ function localExecutionKeys(tools, capletId) {
|
|
|
79917
81910
|
function createProjectBindingSessionManager(cloud, local, options) {
|
|
79918
81911
|
if (!cloud) return;
|
|
79919
81912
|
const projectRoot = cloud.projectRoot ?? findProjectRoot();
|
|
79920
|
-
const cloudFetch = options.remote?.fetch
|
|
81913
|
+
const cloudFetch = options.remote?.fetch;
|
|
79921
81914
|
return new ProjectBindingSessionManager({
|
|
79922
81915
|
client: new CapletsCloudClient({
|
|
79923
81916
|
baseUrl: cloud.url,
|
|
@@ -79971,4 +81964,4 @@ function errorMessage(error) {
|
|
|
79971
81964
|
return error instanceof Error ? error.message : String(error);
|
|
79972
81965
|
}
|
|
79973
81966
|
//#endregion
|
|
79974
|
-
export {
|
|
81967
|
+
export { GoogleDiscoveryManager as $, ListPromptsRequestSchema as $t, emptyCodeModeRunMeta as A, ReadBuffer as At, codeModeDeclarationHash as B, CompleteRequestSchema as Bt, nativeCapletToolDescription as C, safeParse as Cn, defaultCacheBaseDir as Ct, nativeCodeModeToolName as D, resolveConfigPath as Dt, nativeCodeModeToolId as E, resolveCapletsRoot as Et, createCodeModeCapletsApi as F, Protocol as Ft, resolveExposure as G, ElicitResultSchema as Gt, generateCodeModeRunToolDescription as H, CreateMessageResultWithToolsSchema as Ht, listCodeModeCallableCaplets as I, mergeCapabilities as It, findProjectRoot as J, GetPromptRequestSchema as Jt, decodeDirectResourceUri as K, EmptyResultSchema as Kt, CodeModeJournalStore as L, toJsonSchemaCompat as Lt, CodeModeSessionManager as M, assertClientRequestTaskCapability as Mt, QuickJsCodeModeSandbox as N, assertToolsCallTaskCapability as Nt, codeModeRunInputSchema as O, resolveProjectCapletsRoot as Ot, diagnoseCodeModeTypeScript as P, AjvJsonSchemaValidator as Pt, capabilityDescription as Q, LATEST_PROTOCOL_VERSION as Qt, CodeModeLogStore as R, CallToolRequestSchema as Rt, nativeCapletPromptGuidance as S, objectFromShape as Sn, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as St, nativeCapletsSystemGuidance as T, __exportAll as Tn, defaultStateBaseDir as Tt, minifyCodeModeDeclarationText as U, CreateTaskResultSchema as Ut, generateCodeModeDeclarations as V, CreateMessageResultSchema as Vt, CapletsEngine as W, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as Wt, handleServerTool as X, InitializedNotificationSchema as Xt, fingerprintProjectRoot as Y, InitializeRequestSchema as Yt, ServerRegistry as Z, JSONRPCMessageSchema as Zt, resolveHostedCloudRemote as _, getParseErrorMessage as _n, deleteTokenBundle as _t, projectBindingError as a, McpError as an, parseConfig as at, parseServerBaseUrl as b, isZ4Schema as bn, DEFAULT_AUTH_DIR as bt, cloudAuthPath as c, SetLevelRequestSchema as cn, loadCapletFilesFromMap as ct, CloudAuthClient as d, isInitializeRequest as dn, markdownStructuredContent as dt, ListResourceTemplatesRequestSchema as en, loadConfig as et, RemoteNativeCapletsService as f, isJSONRPCErrorResponse as fn, refreshOAuthTokenBundle as ft, resolveCapletsRemote as g, getObjectShape as gn, startOAuthFlow as gt, resolveNativeCapletsServiceOptions as h, getLiteralValue as hn, startGenericOAuthFlow as ht, ProjectBindingError as i, LoggingLevelSchema as in, loadProjectConfig as it, runCodeMode as j, serializeMessage as jt, codeModeRunParamsSchema as k, resolveProjectConfigPath as kt, migrateCredentials as l, assertCompleteRequestPrompt as ln, hasRenderableStructuredContent as lt, buildProjectSyncManifest as m, isJSONRPCResultResponse as mn, runOAuthFlow as mt, resolveRemoteSelection as n, ListRootsResultSchema as nn, loadGlobalConfig as nt, projectBindingRecovery as o, ReadResourceRequestSchema as on, discoverCapletFiles as ot, createSdkRemoteCapletsClient as p, isJSONRPCRequest as pn, runGenericOAuthFlow as pt, directResourceUriMatchesTemplate as q, ErrorCode as qt, PROJECT_BINDING_ERROR_CODES as r, ListToolsRequestSchema as rn, loadLocalOverlayConfigWithSources as rt, CloudAuthStore as s, SUPPORTED_PROTOCOL_VERSIONS as sn, validateCapletFile as st, createNativeCapletsService as t, ListResourcesRequestSchema as tn, loadConfigWithSources as tt, redactedCloudAuthStatus as u, assertCompleteRequestResourceTemplate as un, markdownCallToolResultContent as ut, resolveRemoteMode as v, getSchemaDescription as vn, isTokenBundleExpired as vt, nativeCapletToolName as w, safeParseAsync as wn, defaultConfigBaseDir as wt, resolveCapletsServer as x, normalizeObjectSchema as xn, DEFAULT_COMPLETION_CACHE_DIR as xt, controlUrlForBase as y, isSchemaOptional as yn, readTokenBundle as yt, redactCodeModeLogText as z, CallToolResultSchema as zt };
|