@kmugalkhod/lightcode 0.15.0 → 0.17.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/README.md +66 -10
- package/assets/web/geist-LICENSE.txt +93 -0
- package/assets/web/geist-latin.woff2 +0 -0
- package/assets/web/index-1g5dqbda.js +149 -0
- package/assets/web/index-jx3m6bxd.css +1 -0
- package/assets/web/index.html +1 -1
- package/cli.js +261 -83
- package/lightcode.cjs +21 -16
- package/package.json +5 -5
- package/server.js +767 -173
- package/assets/web/index-qeqpc3cb.css +0 -1
- package/assets/web/index-yavzmb1c.js +0 -149
package/server.js
CHANGED
|
@@ -428,6 +428,9 @@ import {
|
|
|
428
428
|
} from "fs";
|
|
429
429
|
import path4 from "path";
|
|
430
430
|
import { z } from "zod";
|
|
431
|
+
function isAuthenticatedWebRequest(request) {
|
|
432
|
+
return authenticatedWebRequests.has(request);
|
|
433
|
+
}
|
|
431
434
|
function defaultExpectedOrigin(env = Bun.env) {
|
|
432
435
|
const configuredPort = env.PORT?.trim() || "4983";
|
|
433
436
|
return new URL(`http://127.0.0.1:${configuredPort}`).origin;
|
|
@@ -603,6 +606,9 @@ function createWebSecurityMiddleware(options = {}) {
|
|
|
603
606
|
if (!hasValidBearerToken(request, authState.token)) {
|
|
604
607
|
return jsonSecurityError(c, 401, "web_auth_required", "A valid Lightcode browser token is required.");
|
|
605
608
|
}
|
|
609
|
+
if (browserRequest) {
|
|
610
|
+
authenticatedWebRequests.add(request);
|
|
611
|
+
}
|
|
606
612
|
} else if (browserRequest || authState.configured) {
|
|
607
613
|
return jsonSecurityError(c, 503, "web_auth_unavailable", "Browser access is unavailable. Start Lightcode with `lightcode web`.");
|
|
608
614
|
} else if (!allowUnauthenticatedCli) {
|
|
@@ -615,7 +621,7 @@ function createWebSecurityMiddleware(options = {}) {
|
|
|
615
621
|
await next();
|
|
616
622
|
};
|
|
617
623
|
}
|
|
618
|
-
var webAuthFileEnvironmentVariable = "LIGHTCODE_WEB_AUTH_FILE", webAuthHandoffSchema, maximumHandoffBytes = 4096, maximumHandoffAgeMs, maximumHandoffClockSkewMs, defaultAuthState;
|
|
624
|
+
var webAuthFileEnvironmentVariable = "LIGHTCODE_WEB_AUTH_FILE", webAuthHandoffSchema, maximumHandoffBytes = 4096, maximumHandoffAgeMs, maximumHandoffClockSkewMs, authenticatedWebRequests, defaultAuthState;
|
|
619
625
|
var init_web_auth = __esm(() => {
|
|
620
626
|
webAuthHandoffSchema = z.object({
|
|
621
627
|
version: z.literal(1),
|
|
@@ -624,6 +630,7 @@ var init_web_auth = __esm(() => {
|
|
|
624
630
|
}).strict();
|
|
625
631
|
maximumHandoffAgeMs = 5 * 60 * 1000;
|
|
626
632
|
maximumHandoffClockSkewMs = 30 * 1000;
|
|
633
|
+
authenticatedWebRequests = new WeakSet;
|
|
627
634
|
defaultAuthState = loadWebAuthStateFromEnvironment();
|
|
628
635
|
});
|
|
629
636
|
|
|
@@ -2054,10 +2061,11 @@ var init_schema10 = __esm(() => {
|
|
|
2054
2061
|
|
|
2055
2062
|
// packages/ai/src/skills/schema.ts
|
|
2056
2063
|
import { z as z21 } from "zod";
|
|
2057
|
-
var skillDescription = "Load
|
|
2064
|
+
var skillDescription = "Load an installed skill by name before following its instructions. Use resource to read a supporting file relative to that skill's directory.", skillInputSchema, skillProviderInputSchema, skillSummarySchema, skillOutputSchema, skillListOutputSchema;
|
|
2058
2065
|
var init_schema11 = __esm(() => {
|
|
2059
2066
|
skillInputSchema = z21.object({
|
|
2060
|
-
name: z21.string().min(1).max(160)
|
|
2067
|
+
name: z21.string().min(1).max(160),
|
|
2068
|
+
resource: z21.string().min(1).max(1024).optional()
|
|
2061
2069
|
});
|
|
2062
2070
|
skillProviderInputSchema = skillInputSchema;
|
|
2063
2071
|
skillSummarySchema = z21.object({
|
|
@@ -2407,7 +2415,7 @@ var init_tool_registry = __esm(() => {
|
|
|
2407
2415
|
permissionMode: "read-only",
|
|
2408
2416
|
execution: "server",
|
|
2409
2417
|
availability: "skills",
|
|
2410
|
-
activation: "
|
|
2418
|
+
activation: "core",
|
|
2411
2419
|
outputPolicy: "artifact-if-large"
|
|
2412
2420
|
},
|
|
2413
2421
|
list_mcp_resources: {
|
|
@@ -3060,7 +3068,7 @@ ${environmentContext.trim()}` : "");
|
|
|
3060
3068
|
var cwdPromptPlaceholder = "{cwd}", defaultCodingAgentSystemPrompt, toolCallingDisciplineAddendum;
|
|
3061
3069
|
var init_coding_agent_prompt = __esm(() => {
|
|
3062
3070
|
init_coding_agent_modes();
|
|
3063
|
-
defaultCodingAgentSystemPrompt = "You are a coding agent working inside the user's project at this working directory: {cwd}. " + 'You can already see the project \u2014 proactively read it. When the user asks you to review, explain, or work on "my code"/"this", inspect the working directory yourself with list_files, glob_search, grep, and read_file; NEVER ask the user to paste or share code that lives in this directory \u2014 open it. ' + "Use tools for filesystem and codebase tasks instead of guessing, and only interact with files under the working directory. " + "Prefer dedicated tools \u2014 glob_search for paths, grep for text search, structured git tools for repository inspection \u2014 and bash only when those are not enough. " + `Inspect context before risky operations. Progress notes: before a major tool action you may emit ONE short note (one sentence, ~15 words) saying what you are about to do. After a tool returns, mention a finding only if it changes your plan, and state it as fact grounded in what the tool actually returned \u2014 cite the file/line/symbol. NEVER claim you found, changed, or fixed something before a tool result confirms it. Skip notes for routine reads, and do not restate the todo list in prose.
|
|
3071
|
+
defaultCodingAgentSystemPrompt = "You are a coding agent working inside the user's project at this working directory: {cwd}. " + 'You can already see the project \u2014 proactively read it. When the user asks you to review, explain, or work on "my code"/"this", inspect the working directory yourself with list_files, glob_search, grep, and read_file; NEVER ask the user to paste or share code that lives in this directory \u2014 open it. ' + "Use tools for filesystem and codebase tasks instead of guessing, and only interact with files under the working directory. " + "Prefer dedicated tools \u2014 glob_search for paths, grep for text search, structured git tools for repository inspection \u2014 and bash only when those are not enough. " + "Check the available skill descriptions for every task. When a skill is explicitly named or clearly matches the task, load it with the skill tool before acting and follow its instructions within the user's scope and tool permissions. Skill files may be installed outside the workspace; use the skill tool to read their relative supporting resources. Never claim to have used a skill you have not loaded. " + `Inspect context before risky operations. Progress notes: before a major tool action you may emit ONE short note (one sentence, ~15 words) saying what you are about to do. After a tool returns, mention a finding only if it changes your plan, and state it as fact grounded in what the tool actually returned \u2014 cite the file/line/symbol. NEVER claim you found, changed, or fixed something before a tool result confirms it. Skip notes for routine reads, and do not restate the todo list in prose.
|
|
3064
3072
|
|
|
3065
3073
|
` + `Task list discipline \u2014 use the todo_write tool to keep a visible, evolving checklist:
|
|
3066
3074
|
` + `- Create the list FIRST. For any task with roughly three or more distinct steps, or any multi-file or multi-stage work, call todo_write as your very first action \u2014 before reading or editing \u2014 with every step listed and all of them set to pending.
|
|
@@ -5309,103 +5317,145 @@ var init_runtime10 = __esm(() => {
|
|
|
5309
5317
|
});
|
|
5310
5318
|
|
|
5311
5319
|
// packages/ai/src/skills/runtime.ts
|
|
5312
|
-
import {
|
|
5320
|
+
import { readFileSync as readFileSync2, readdirSync as readdirSync2, realpathSync as realpathSync2, statSync as statSync2 } from "fs";
|
|
5313
5321
|
import os from "os";
|
|
5314
5322
|
import path11 from "path";
|
|
5315
|
-
function defaultSkillRoots(cwd) {
|
|
5323
|
+
function defaultSkillRoots(cwd, home, env) {
|
|
5316
5324
|
return [
|
|
5317
5325
|
{ source: "project", path: path11.join(cwd, ".lightcode", "skills") },
|
|
5318
5326
|
{ source: "project", path: path11.join(cwd, ".agents", "skills") },
|
|
5319
|
-
|
|
5327
|
+
...[".claude", ".codex", ".opencode"].map((dir) => ({
|
|
5328
|
+
source: "project",
|
|
5329
|
+
path: path11.join(cwd, dir, "skills")
|
|
5330
|
+
})),
|
|
5331
|
+
...[".lightcode", ".agents", ".claude"].map((dir) => ({
|
|
5332
|
+
source: "user",
|
|
5333
|
+
path: path11.join(home, dir, "skills")
|
|
5334
|
+
})),
|
|
5335
|
+
{
|
|
5336
|
+
source: "user",
|
|
5337
|
+
path: path11.join(env.CODEX_HOME || path11.join(home, ".codex"), "skills")
|
|
5338
|
+
},
|
|
5339
|
+
{
|
|
5340
|
+
source: "user",
|
|
5341
|
+
path: path11.join(env.XDG_CONFIG_HOME || path11.join(home, ".config"), "opencode", "skills")
|
|
5342
|
+
},
|
|
5343
|
+
...(env.LIGHTCODE_SKILL_PATHS ?? "").split(path11.delimiter).filter(Boolean).map((root) => ({
|
|
5344
|
+
source: "user",
|
|
5345
|
+
path: path11.resolve(cwd, root)
|
|
5346
|
+
}))
|
|
5320
5347
|
];
|
|
5321
5348
|
}
|
|
5322
5349
|
function normalizeSkillName(value) {
|
|
5323
5350
|
return value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-");
|
|
5324
5351
|
}
|
|
5325
5352
|
function parseBasicFrontmatter(content) {
|
|
5326
|
-
|
|
5353
|
+
const match = /^\uFEFF?---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(content);
|
|
5354
|
+
if (!match)
|
|
5327
5355
|
return {};
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
---`, 3);
|
|
5331
|
-
if (endIndex === -1) {
|
|
5356
|
+
const parsed = Bun.YAML.parse(match[1]);
|
|
5357
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
5332
5358
|
return {};
|
|
5333
|
-
|
|
5334
|
-
const frontmatter = content.slice(3, endIndex).trim();
|
|
5335
|
-
return Object.fromEntries(frontmatter.split(/\r?\n/).map((line) => line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/)).filter((match) => match !== null).map((match) => [
|
|
5336
|
-
match[1],
|
|
5337
|
-
match[2].replace(/^["']|["']$/g, "").trim()
|
|
5338
|
-
]));
|
|
5359
|
+
return Object.fromEntries(Object.entries(parsed).filter((entry) => typeof entry[1] === "string"));
|
|
5339
5360
|
}
|
|
5340
5361
|
function findSkillFiles(root) {
|
|
5341
|
-
if (!existsSync4(root.path)) {
|
|
5342
|
-
return [];
|
|
5343
|
-
}
|
|
5344
5362
|
const files = [];
|
|
5363
|
+
const visited = new Set;
|
|
5345
5364
|
const visit = (directory, depth) => {
|
|
5346
|
-
if (depth >
|
|
5365
|
+
if (depth > 8 || visited.size >= 2000) {
|
|
5366
|
+
return;
|
|
5367
|
+
}
|
|
5368
|
+
let entries;
|
|
5369
|
+
try {
|
|
5370
|
+
const real = realpathSync2(directory);
|
|
5371
|
+
if (visited.has(real))
|
|
5372
|
+
return;
|
|
5373
|
+
visited.add(real);
|
|
5374
|
+
entries = readdirSync2(directory).sort();
|
|
5375
|
+
} catch {
|
|
5347
5376
|
return;
|
|
5348
5377
|
}
|
|
5349
|
-
for (const entry of
|
|
5378
|
+
for (const entry of entries) {
|
|
5350
5379
|
const entryPath = path11.join(directory, entry);
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5380
|
+
try {
|
|
5381
|
+
const stat3 = statSync2(entryPath);
|
|
5382
|
+
if (stat3.isDirectory()) {
|
|
5383
|
+
visit(entryPath, depth + 1);
|
|
5384
|
+
} else if (stat3.isFile() && stat3.size <= 1048576 && entry.toLowerCase() === "skill.md") {
|
|
5385
|
+
files.push(entryPath);
|
|
5386
|
+
}
|
|
5387
|
+
} catch {}
|
|
5357
5388
|
}
|
|
5358
5389
|
};
|
|
5359
5390
|
visit(root.path, 0);
|
|
5360
5391
|
return files;
|
|
5361
5392
|
}
|
|
5362
5393
|
function listSkills({
|
|
5363
|
-
cwd = process.cwd()
|
|
5394
|
+
cwd = process.cwd(),
|
|
5395
|
+
home = os.homedir(),
|
|
5396
|
+
env = process.env
|
|
5364
5397
|
} = {}) {
|
|
5365
|
-
const
|
|
5398
|
+
const roots = defaultSkillRoots(path11.resolve(cwd), home, env);
|
|
5399
|
+
const cacheKey = JSON.stringify(roots);
|
|
5400
|
+
const cached = skillsCache.get(cacheKey);
|
|
5366
5401
|
if (cached && cached.expiresAt > Date.now()) {
|
|
5367
5402
|
return cached.skills;
|
|
5368
5403
|
}
|
|
5369
|
-
const skills = listSkillsUncached(
|
|
5370
|
-
skillsCache.
|
|
5404
|
+
const skills = listSkillsUncached(roots);
|
|
5405
|
+
if (skillsCache.size >= 100)
|
|
5406
|
+
skillsCache.delete(skillsCache.keys().next().value);
|
|
5407
|
+
skillsCache.set(cacheKey, {
|
|
5371
5408
|
expiresAt: Date.now() + skillsCacheTtlMs,
|
|
5372
5409
|
skills
|
|
5373
5410
|
});
|
|
5374
5411
|
return skills;
|
|
5375
5412
|
}
|
|
5376
|
-
function listSkillsUncached(
|
|
5413
|
+
function listSkillsUncached(roots) {
|
|
5377
5414
|
const seen = new Set;
|
|
5378
5415
|
const summaries = [];
|
|
5379
|
-
for (const root of
|
|
5416
|
+
for (const root of roots) {
|
|
5380
5417
|
for (const skillPath of findSkillFiles(root)) {
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5418
|
+
try {
|
|
5419
|
+
const content = readFileSync2(skillPath, "utf8");
|
|
5420
|
+
const frontmatter = parseBasicFrontmatter(content);
|
|
5421
|
+
const fallbackName = path11.basename(path11.dirname(skillPath));
|
|
5422
|
+
const name = normalizeSkillName(frontmatter.name ?? fallbackName);
|
|
5423
|
+
if (!name || name.length > 160 || seen.has(name)) {
|
|
5424
|
+
continue;
|
|
5425
|
+
}
|
|
5426
|
+
seen.add(name);
|
|
5427
|
+
summaries.push({
|
|
5428
|
+
name,
|
|
5429
|
+
description: frontmatter.description || null,
|
|
5430
|
+
path: skillPath,
|
|
5431
|
+
source: root.source
|
|
5432
|
+
});
|
|
5433
|
+
} catch {}
|
|
5395
5434
|
}
|
|
5396
5435
|
}
|
|
5397
5436
|
return summaries.sort((left, right) => left.name.localeCompare(right.name));
|
|
5398
5437
|
}
|
|
5399
|
-
function loadSkill(input,
|
|
5438
|
+
function loadSkill(input, options = {}) {
|
|
5400
5439
|
const parsedInput = skillInputSchema.parse(input);
|
|
5401
5440
|
const normalizedName = normalizeSkillName(parsedInput.name);
|
|
5402
|
-
const skill = listSkills(
|
|
5441
|
+
const skill = listSkills(options).find((candidate) => normalizeSkillName(candidate.name) === normalizedName);
|
|
5403
5442
|
if (!skill) {
|
|
5404
5443
|
throw new Error(`Skill not found: ${parsedInput.name}`);
|
|
5405
5444
|
}
|
|
5445
|
+
const root = realpathSync2(path11.dirname(skill.path));
|
|
5446
|
+
const target = parsedInput.resource ? realpathSync2(path11.resolve(root, parsedInput.resource)) : skill.path;
|
|
5447
|
+
if (parsedInput.resource) {
|
|
5448
|
+
const relative = path11.relative(root, target);
|
|
5449
|
+
if (relative === ".." || relative.startsWith(`..${path11.sep}`) || path11.isAbsolute(relative)) {
|
|
5450
|
+
throw new Error("Skill resources must stay inside the installed skill directory.");
|
|
5451
|
+
}
|
|
5452
|
+
}
|
|
5453
|
+
const stat3 = statSync2(target);
|
|
5454
|
+
if (!stat3.isFile() || stat3.size > 1048576)
|
|
5455
|
+
throw new Error("Skill resource must be a file smaller than 1 MiB.");
|
|
5406
5456
|
return skillOutputSchema.parse({
|
|
5407
5457
|
skill,
|
|
5408
|
-
content: readFileSync2(
|
|
5458
|
+
content: readFileSync2(target, "utf8")
|
|
5409
5459
|
});
|
|
5410
5460
|
}
|
|
5411
5461
|
var skillsCacheTtlMs = 30000, skillsCache;
|
|
@@ -7079,7 +7129,7 @@ var init_context = __esm(() => {
|
|
|
7079
7129
|
});
|
|
7080
7130
|
|
|
7081
7131
|
// packages/ai/src/config/lightcode-config.ts
|
|
7082
|
-
import { existsSync as
|
|
7132
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
7083
7133
|
import os2 from "os";
|
|
7084
7134
|
import path13 from "path";
|
|
7085
7135
|
import { z as z34 } from "zod";
|
|
@@ -7090,7 +7140,7 @@ function getDefaultUserConfigPath(env) {
|
|
|
7090
7140
|
return path13.join(os2.homedir(), ".lightcode", "settings.json");
|
|
7091
7141
|
}
|
|
7092
7142
|
function readConfigFile(scope, configPath) {
|
|
7093
|
-
if (!
|
|
7143
|
+
if (!existsSync4(configPath)) {
|
|
7094
7144
|
return {
|
|
7095
7145
|
config: {},
|
|
7096
7146
|
file: {
|
|
@@ -7552,17 +7602,101 @@ var init_runtime12 = __esm(() => {
|
|
|
7552
7602
|
init_schema8();
|
|
7553
7603
|
});
|
|
7554
7604
|
|
|
7605
|
+
// packages/shared/src/network-fetch.ts
|
|
7606
|
+
import { readFileSync as readFileSync4, statSync as statSync3 } from "fs";
|
|
7607
|
+
import { X509Certificate } from "crypto";
|
|
7608
|
+
import * as tls from "tls";
|
|
7609
|
+
function isCertificateError(error) {
|
|
7610
|
+
const seen = new Set;
|
|
7611
|
+
let current = error;
|
|
7612
|
+
while (current && typeof current === "object" && !seen.has(current) && seen.size < 12) {
|
|
7613
|
+
seen.add(current);
|
|
7614
|
+
const record = current;
|
|
7615
|
+
if (certificateErrorPattern.test(`${record.code ?? ""} ${record.message ?? ""}`))
|
|
7616
|
+
return true;
|
|
7617
|
+
current = record.cause;
|
|
7618
|
+
}
|
|
7619
|
+
return false;
|
|
7620
|
+
}
|
|
7621
|
+
function createNetworkFetch({
|
|
7622
|
+
env = process.env,
|
|
7623
|
+
fetchImpl
|
|
7624
|
+
} = {}) {
|
|
7625
|
+
let cachedKey = "";
|
|
7626
|
+
let cachedCa;
|
|
7627
|
+
let checkedAt = 0;
|
|
7628
|
+
const resolveCa = () => {
|
|
7629
|
+
const paths = [
|
|
7630
|
+
...new Set([env.LIGHTCODE_CA_CERTS, env.NODE_EXTRA_CA_CERTS, env.SSL_CERT_FILE].map((value) => value?.trim()).filter((value) => Boolean(value)))
|
|
7631
|
+
];
|
|
7632
|
+
const key = JSON.stringify(paths);
|
|
7633
|
+
if (key === cachedKey && Date.now() - checkedAt < 30000)
|
|
7634
|
+
return cachedCa;
|
|
7635
|
+
const extra = [];
|
|
7636
|
+
for (const file of paths) {
|
|
7637
|
+
try {
|
|
7638
|
+
if (statSync3(file).size > 4 * 1024 * 1024)
|
|
7639
|
+
throw new Error("CA bundle exceeds 4 MiB");
|
|
7640
|
+
const certificates = readFileSync4(file, "utf8").match(certificatePattern);
|
|
7641
|
+
if (!certificates?.length)
|
|
7642
|
+
throw new Error("No PEM certificates found");
|
|
7643
|
+
for (const cert of certificates)
|
|
7644
|
+
new X509Certificate(cert);
|
|
7645
|
+
extra.push(...certificates);
|
|
7646
|
+
} catch (cause) {
|
|
7647
|
+
throw new Error("Cannot load configured TLS CA certificate bundle. Check LIGHTCODE_CA_CERTS, NODE_EXTRA_CA_CERTS and SSL_CERT_FILE for readable PEM files.", { cause });
|
|
7648
|
+
}
|
|
7649
|
+
}
|
|
7650
|
+
let defaults = [...tls.rootCertificates];
|
|
7651
|
+
try {
|
|
7652
|
+
defaults.push(...tls.getCACertificates("default"), ...tls.getCACertificates("system"));
|
|
7653
|
+
} catch {}
|
|
7654
|
+
cachedCa = extra.length ? [...new Set([...defaults, ...extra])] : undefined;
|
|
7655
|
+
cachedKey = key;
|
|
7656
|
+
checkedAt = Date.now();
|
|
7657
|
+
return cachedCa;
|
|
7658
|
+
};
|
|
7659
|
+
return async (input, init) => {
|
|
7660
|
+
const url = new URL(input instanceof Request ? input.url : String(input));
|
|
7661
|
+
const ca = url.protocol === "https:" ? resolveCa() : undefined;
|
|
7662
|
+
const local = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
7663
|
+
try {
|
|
7664
|
+
return await (fetchImpl ?? globalThis.fetch)(input, {
|
|
7665
|
+
...init,
|
|
7666
|
+
...local && init?.proxy === undefined ? { proxy: "" } : {},
|
|
7667
|
+
...ca ? {
|
|
7668
|
+
tls: {
|
|
7669
|
+
...init?.tls,
|
|
7670
|
+
ca: init?.tls?.ca ?? ca,
|
|
7671
|
+
rejectUnauthorized: true
|
|
7672
|
+
}
|
|
7673
|
+
} : {}
|
|
7674
|
+
});
|
|
7675
|
+
} catch (cause) {
|
|
7676
|
+
if (isCertificateError(cause))
|
|
7677
|
+
throw new Error(certificateErrorHint, { cause });
|
|
7678
|
+
throw cause;
|
|
7679
|
+
}
|
|
7680
|
+
};
|
|
7681
|
+
}
|
|
7682
|
+
var certificatePattern, certificateErrorPattern, certificateErrorHint = "TLS certificate verification failed. Configure your company CA PEM with NODE_EXTRA_CA_CERTS or LIGHTCODE_CA_CERTS, then restart Lightcode. If a CA is already configured, check the server certificate hostname, expiry, and chain.", networkFetch;
|
|
7683
|
+
var init_network_fetch = __esm(() => {
|
|
7684
|
+
certificatePattern = /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g;
|
|
7685
|
+
certificateErrorPattern = /CERT_(?:HAS_EXPIRED|NOT_YET_VALID|REVOKED|UNTRUSTED|SIGNATURE_FAILURE)|CERTIFICATE_VERIFY_FAILED|UNABLE_TO_(?:GET_ISSUER_CERT(?:_LOCALLY)?|VERIFY_LEAF_SIGNATURE)|DEPTH_ZERO_SELF_SIGNED_CERT|SELF_SIGNED_CERT_IN_CHAIN|ERR_TLS_CERT_ALTNAME_INVALID|certificate|self.signed|unable to (?:get local issuer|verify the first)/i;
|
|
7686
|
+
networkFetch = createNetworkFetch();
|
|
7687
|
+
});
|
|
7688
|
+
|
|
7555
7689
|
// packages/ai/src/web-fetch/runtime.ts
|
|
7556
7690
|
function decodeHtmlEntities(value) {
|
|
7557
7691
|
return value.replace(/&(#x?[0-9a-f]+|[a-z]+);/gi, (match, entity) => {
|
|
7558
7692
|
const normalized = entity.toLowerCase();
|
|
7559
7693
|
if (normalized.startsWith("#x")) {
|
|
7560
7694
|
const codePoint = Number.parseInt(normalized.slice(2), 16);
|
|
7561
|
-
return Number.
|
|
7695
|
+
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : match;
|
|
7562
7696
|
}
|
|
7563
7697
|
if (normalized.startsWith("#")) {
|
|
7564
7698
|
const codePoint = Number.parseInt(normalized.slice(1), 10);
|
|
7565
|
-
return Number.
|
|
7699
|
+
return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 1114111 ? String.fromCodePoint(codePoint) : match;
|
|
7566
7700
|
}
|
|
7567
7701
|
return htmlEntityMap[normalized] ?? match;
|
|
7568
7702
|
});
|
|
@@ -7589,6 +7723,34 @@ function normalizeContentToText(content, contentType) {
|
|
|
7589
7723
|
return content.replace(/\r\n/g, `
|
|
7590
7724
|
`).trim();
|
|
7591
7725
|
}
|
|
7726
|
+
async function readBoundedBody(response) {
|
|
7727
|
+
if (!response.body)
|
|
7728
|
+
return { text: "", truncated: false };
|
|
7729
|
+
const reader = response.body.getReader();
|
|
7730
|
+
const decoder = new TextDecoder;
|
|
7731
|
+
let bytes = 0;
|
|
7732
|
+
let text = "";
|
|
7733
|
+
let truncated = false;
|
|
7734
|
+
try {
|
|
7735
|
+
for (;; ) {
|
|
7736
|
+
const { done, value } = await reader.read();
|
|
7737
|
+
if (done)
|
|
7738
|
+
break;
|
|
7739
|
+
const available = maxDownloadBytes - bytes;
|
|
7740
|
+
text += decoder.decode(value.subarray(0, available), { stream: true });
|
|
7741
|
+
bytes += value.byteLength;
|
|
7742
|
+
if (bytes >= maxDownloadBytes) {
|
|
7743
|
+
truncated = true;
|
|
7744
|
+
await reader.cancel();
|
|
7745
|
+
break;
|
|
7746
|
+
}
|
|
7747
|
+
}
|
|
7748
|
+
text += decoder.decode();
|
|
7749
|
+
return { text, truncated };
|
|
7750
|
+
} finally {
|
|
7751
|
+
reader.releaseLock();
|
|
7752
|
+
}
|
|
7753
|
+
}
|
|
7592
7754
|
function errorOutput({
|
|
7593
7755
|
parsedInput,
|
|
7594
7756
|
code,
|
|
@@ -7616,7 +7778,7 @@ async function executeWebFetch(input, options = {}) {
|
|
|
7616
7778
|
const timeoutSignal = AbortSignal.timeout(parsedInput.timeoutMs);
|
|
7617
7779
|
const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
|
|
7618
7780
|
try {
|
|
7619
|
-
const response = await (options.fetch ??
|
|
7781
|
+
const response = await (options.fetch ?? networkFetch)(parsedInput.url, {
|
|
7620
7782
|
redirect: "follow",
|
|
7621
7783
|
signal,
|
|
7622
7784
|
headers: {
|
|
@@ -7625,7 +7787,8 @@ async function executeWebFetch(input, options = {}) {
|
|
|
7625
7787
|
}
|
|
7626
7788
|
});
|
|
7627
7789
|
const contentType = response.headers.get("content-type");
|
|
7628
|
-
const
|
|
7790
|
+
const downloaded = await readBoundedBody(response);
|
|
7791
|
+
const rawText = downloaded.text;
|
|
7629
7792
|
const normalizedText = normalizeContentToText(rawText, contentType);
|
|
7630
7793
|
const truncated = truncateText(normalizedText, parsedInput.maxChars);
|
|
7631
7794
|
return webFetchOutputSchema.parse({
|
|
@@ -7637,7 +7800,7 @@ async function executeWebFetch(input, options = {}) {
|
|
|
7637
7800
|
contentType,
|
|
7638
7801
|
title: contentType?.toLowerCase().includes("html") ? extractTitle(rawText) : null,
|
|
7639
7802
|
text: truncated.text,
|
|
7640
|
-
truncated: truncated.truncated,
|
|
7803
|
+
truncated: truncated.truncated || downloaded.truncated,
|
|
7641
7804
|
fetchedAt: new Date().toISOString(),
|
|
7642
7805
|
error: response.ok ? null : {
|
|
7643
7806
|
code: "http_error",
|
|
@@ -7652,8 +7815,9 @@ async function executeWebFetch(input, options = {}) {
|
|
|
7652
7815
|
});
|
|
7653
7816
|
}
|
|
7654
7817
|
}
|
|
7655
|
-
var htmlEntityMap;
|
|
7818
|
+
var htmlEntityMap, maxDownloadBytes;
|
|
7656
7819
|
var init_runtime13 = __esm(() => {
|
|
7820
|
+
init_network_fetch();
|
|
7657
7821
|
init_output_utils();
|
|
7658
7822
|
init_schema14();
|
|
7659
7823
|
htmlEntityMap = {
|
|
@@ -7664,10 +7828,11 @@ var init_runtime13 = __esm(() => {
|
|
|
7664
7828
|
apos: "'",
|
|
7665
7829
|
nbsp: " "
|
|
7666
7830
|
};
|
|
7831
|
+
maxDownloadBytes = 2 * 1024 * 1024;
|
|
7667
7832
|
});
|
|
7668
7833
|
|
|
7669
7834
|
// packages/ai/src/config/credentials.ts
|
|
7670
|
-
import { chmodSync, existsSync as
|
|
7835
|
+
import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
7671
7836
|
import os3 from "os";
|
|
7672
7837
|
import path14 from "path";
|
|
7673
7838
|
import { z as z35 } from "zod";
|
|
@@ -7680,11 +7845,11 @@ function getCredentialsPath(env = process.env) {
|
|
|
7680
7845
|
}
|
|
7681
7846
|
function readStoredCredentials(env = process.env) {
|
|
7682
7847
|
const credentialsPath = getCredentialsPath(env);
|
|
7683
|
-
if (!
|
|
7848
|
+
if (!existsSync5(credentialsPath)) {
|
|
7684
7849
|
return {};
|
|
7685
7850
|
}
|
|
7686
7851
|
try {
|
|
7687
|
-
const parsed = storedCredentialsSchema.safeParse(JSON.parse(
|
|
7852
|
+
const parsed = storedCredentialsSchema.safeParse(JSON.parse(readFileSync5(credentialsPath, "utf8")));
|
|
7688
7853
|
return parsed.success ? parsed.data : {};
|
|
7689
7854
|
} catch {
|
|
7690
7855
|
return {};
|
|
@@ -7896,7 +8061,7 @@ async function executeWebSearch(input, options = {}) {
|
|
|
7896
8061
|
}
|
|
7897
8062
|
return await searchBrave(parsedInput, {
|
|
7898
8063
|
apiKey: keys.brave,
|
|
7899
|
-
fetch: options.fetch ??
|
|
8064
|
+
fetch: options.fetch ?? networkFetch,
|
|
7900
8065
|
signal,
|
|
7901
8066
|
maxCharactersPerResult: config2.maxCharactersPerResult
|
|
7902
8067
|
});
|
|
@@ -7912,7 +8077,7 @@ async function executeWebSearch(input, options = {}) {
|
|
|
7912
8077
|
}
|
|
7913
8078
|
return await searchTavily(parsedInput, {
|
|
7914
8079
|
apiKey: keys.tavily,
|
|
7915
|
-
fetch: options.fetch ??
|
|
8080
|
+
fetch: options.fetch ?? networkFetch,
|
|
7916
8081
|
signal,
|
|
7917
8082
|
maxCharactersPerResult: config2.maxCharactersPerResult
|
|
7918
8083
|
});
|
|
@@ -7953,6 +8118,7 @@ async function executeWebSearch(input, options = {}) {
|
|
|
7953
8118
|
}
|
|
7954
8119
|
var localUsesByTurn;
|
|
7955
8120
|
var init_runtime14 = __esm(() => {
|
|
8121
|
+
init_network_fetch();
|
|
7956
8122
|
init_lightcode_config();
|
|
7957
8123
|
init_credentials();
|
|
7958
8124
|
init_config2();
|
|
@@ -9479,7 +9645,7 @@ var init_schema18 = __esm(() => {
|
|
|
9479
9645
|
});
|
|
9480
9646
|
|
|
9481
9647
|
// packages/ai/src/plugins/runtime.ts
|
|
9482
|
-
import { existsSync as
|
|
9648
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync3 } from "fs";
|
|
9483
9649
|
import os4 from "os";
|
|
9484
9650
|
import path16 from "path";
|
|
9485
9651
|
function pluginRoots(cwd) {
|
|
@@ -9491,7 +9657,7 @@ function pluginRoots(cwd) {
|
|
|
9491
9657
|
function listPlugins({ cwd = process.cwd() } = {}) {
|
|
9492
9658
|
const plugins = [];
|
|
9493
9659
|
for (const root of pluginRoots(cwd)) {
|
|
9494
|
-
if (!
|
|
9660
|
+
if (!existsSync6(root)) {
|
|
9495
9661
|
continue;
|
|
9496
9662
|
}
|
|
9497
9663
|
for (const entry of readdirSync3(root, { withFileTypes: true })) {
|
|
@@ -9499,10 +9665,10 @@ function listPlugins({ cwd = process.cwd() } = {}) {
|
|
|
9499
9665
|
continue;
|
|
9500
9666
|
}
|
|
9501
9667
|
const manifestPath = path16.join(root, entry.name, "plugin.json");
|
|
9502
|
-
if (!
|
|
9668
|
+
if (!existsSync6(manifestPath)) {
|
|
9503
9669
|
continue;
|
|
9504
9670
|
}
|
|
9505
|
-
const manifest = pluginManifestSchema.parse(JSON.parse(
|
|
9671
|
+
const manifest = pluginManifestSchema.parse(JSON.parse(readFileSync6(manifestPath, "utf8")));
|
|
9506
9672
|
plugins.push({
|
|
9507
9673
|
id: manifest.id,
|
|
9508
9674
|
name: manifest.name,
|
|
@@ -9522,7 +9688,7 @@ var init_runtime16 = __esm(() => {
|
|
|
9522
9688
|
|
|
9523
9689
|
// packages/ai/src/workspace-browser.ts
|
|
9524
9690
|
import { z as z38 } from "zod";
|
|
9525
|
-
var workspaceLocationIdSchema, workspaceLocationStateSchema, workspaceLocationSchema, workspaceLocationsResponseSchema, workspaceBrowserOpenRequestSchema, workspaceBrowserIdSchema, workspaceBrowserOpenResponseSchema, workspacePathSegmentSchema, workspacePathSegmentsSchema, workspaceBrowserCursorSchema, workspaceBrowserEntriesRequestSchema, workspaceBrowserEntryKindSchema, workspaceBrowserSymlinkStateSchema, workspaceBrowserEntrySchema, workspaceBrowserEntriesResponseSchema, workspaceBrowserSelectRequestSchema, workspaceGrantIdSchema, workspaceGrantSchema, workspaceBrowserSelectResponseSchema, workspaceSessionPathParamsSchema, workspaceSessionCreateRequestSchema, workspaceBrowserPathParamsSchema, workspaceApiErrorCodeSchema, workspaceApiErrorResponseSchema;
|
|
9691
|
+
var workspaceLocationIdSchema, workspaceLocationStateSchema, workspaceLocationSchema, workspaceLocationsResponseSchema, workspaceBrowserOpenRequestSchema, workspaceBrowserIdSchema, workspaceBrowserOpenResponseSchema, workspacePathSegmentSchema, workspacePathSegmentsSchema, workspaceBrowserCursorSchema, workspaceBrowserEntriesRequestSchema, workspaceBrowserEntryKindSchema, workspaceBrowserSymlinkStateSchema, workspaceBrowserEntrySchema, workspaceBrowserEntriesResponseSchema, workspaceBrowserSelectRequestSchema, workspaceGrantIdSchema, workspaceGrantSchema, workspaceNativePickerRequestSchema, workspaceNativePickerResponseSchema, workspaceBrowserSelectResponseSchema, workspaceSessionPathParamsSchema, workspaceSessionCreateRequestSchema, workspaceBrowserPathParamsSchema, workspaceApiErrorCodeSchema, workspaceApiErrorResponseSchema;
|
|
9526
9692
|
var init_workspace_browser = __esm(() => {
|
|
9527
9693
|
init_coding_agent_modes();
|
|
9528
9694
|
init_permissions();
|
|
@@ -9604,6 +9770,16 @@ var init_workspace_browser = __esm(() => {
|
|
|
9604
9770
|
pathLabel: z38.string().min(1).max(4096),
|
|
9605
9771
|
createdAt: z38.string().min(1)
|
|
9606
9772
|
}).strict();
|
|
9773
|
+
workspaceNativePickerRequestSchema = z38.object({}).strict();
|
|
9774
|
+
workspaceNativePickerResponseSchema = z38.discriminatedUnion("outcome", [
|
|
9775
|
+
z38.object({
|
|
9776
|
+
outcome: z38.literal("selected"),
|
|
9777
|
+
workspace: workspaceGrantSchema
|
|
9778
|
+
}).strict(),
|
|
9779
|
+
z38.object({
|
|
9780
|
+
outcome: z38.literal("cancelled")
|
|
9781
|
+
}).strict()
|
|
9782
|
+
]);
|
|
9607
9783
|
workspaceBrowserSelectResponseSchema = z38.object({
|
|
9608
9784
|
workspace: workspaceGrantSchema
|
|
9609
9785
|
}).strict();
|
|
@@ -9631,7 +9807,10 @@ var init_workspace_browser = __esm(() => {
|
|
|
9631
9807
|
"browser_capability_expired",
|
|
9632
9808
|
"workspace_grant_not_found",
|
|
9633
9809
|
"invalid_cursor",
|
|
9634
|
-
"workspace_unavailable"
|
|
9810
|
+
"workspace_unavailable",
|
|
9811
|
+
"native_picker_busy",
|
|
9812
|
+
"native_picker_unavailable",
|
|
9813
|
+
"native_picker_failed"
|
|
9635
9814
|
]);
|
|
9636
9815
|
workspaceApiErrorResponseSchema = z38.object({
|
|
9637
9816
|
error: z38.string().min(1),
|
|
@@ -9988,6 +10167,9 @@ function classifyChatError(error) {
|
|
|
9988
10167
|
if (RetryError.isInstance(error) && error.lastError) {
|
|
9989
10168
|
return classifyChatError(error.lastError);
|
|
9990
10169
|
}
|
|
10170
|
+
if (!(APICallError.isInstance(error) && typeof error.statusCode === "number") && isCertificateError(error)) {
|
|
10171
|
+
return { kind: "network", retryable: false, message: certificateErrorHint };
|
|
10172
|
+
}
|
|
9991
10173
|
if (APICallError.isInstance(error)) {
|
|
9992
10174
|
const responseBody = error.responseBody ?? "";
|
|
9993
10175
|
const message2 = responseBody.length > 0 ? responseBody : error.message;
|
|
@@ -10086,6 +10268,7 @@ function logChatDisconnectEvent({
|
|
|
10086
10268
|
var chatFailureCounters, logger2, retryableStatusCodes, contextOverflowPattern, contextLimitPattern;
|
|
10087
10269
|
var init_chat_observability = __esm(() => {
|
|
10088
10270
|
init_src();
|
|
10271
|
+
init_network_fetch();
|
|
10089
10272
|
chatFailureCounters = {
|
|
10090
10273
|
provider_schema_rejection: 0,
|
|
10091
10274
|
provider_billing_quota: 0,
|
|
@@ -10301,8 +10484,8 @@ var config5;
|
|
|
10301
10484
|
var init_class = __esm(() => {
|
|
10302
10485
|
config5 = {
|
|
10303
10486
|
previewFeatures: [],
|
|
10304
|
-
clientVersion: "7.
|
|
10305
|
-
engineVersion: "
|
|
10487
|
+
clientVersion: "7.10.0",
|
|
10488
|
+
engineVersion: "0edf323efd1d98336f3f0a68684b56f689b900d3",
|
|
10306
10489
|
activeProvider: "sqlite",
|
|
10307
10490
|
inlineSchema: `generator client {
|
|
10308
10491
|
provider = "prisma-client"
|
|
@@ -10545,7 +10728,7 @@ model SubagentTask {
|
|
|
10545
10728
|
graph: ""
|
|
10546
10729
|
}
|
|
10547
10730
|
};
|
|
10548
|
-
config5.runtimeDataModel = JSON.parse('{"models":{"ChatSession":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"title","kind":"scalar","type":"String"},{"name":"autoTitled","kind":"scalar","type":"Boolean","dbName":"auto_titled"},{"name":"cwd","kind":"scalar","type":"String"},{"name":"workspaceDevice","kind":"scalar","type":"String","dbName":"workspace_device"},{"name":"workspaceInode","kind":"scalar","type":"String","dbName":"workspace_inode"},{"name":"mode","kind":"scalar","type":"String"},{"name":"permissionMode","kind":"scalar","type":"String","dbName":"permission_mode"},{"name":"model","kind":"scalar","type":"String"},{"name":"revision","kind":"scalar","type":"Int"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"messages","kind":"object","type":"ChatMessage","relationName":"ChatMessageToChatSession"},{"name":"interactions","kind":"object","type":"ChatInteraction","relationName":"ChatInteractionToChatSession"},{"name":"subagentTasks","kind":"object","type":"SubagentTask","relationName":"ChatSessionToSubagentTask"},{"name":"contextState","kind":"object","type":"SessionContextState","relationName":"ChatSessionToSessionContextState"},{"name":"runs","kind":"object","type":"ChatRun","relationName":"ChatRunToChatSession"},{"name":"turnReverts","kind":"object","type":"ChatTurnRevert","relationName":"ChatSessionToChatTurnRevert"}],"dbName":"sessions"},"SessionContextState":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"summary","kind":"scalar","type":"String"},{"name":"anchorMessageId","kind":"scalar","type":"String","dbName":"anchor_message_id"},{"name":"coveredMessageCount","kind":"scalar","type":"Int","dbName":"covered_message_count"},{"name":"estimatedTokens","kind":"scalar","type":"Int","dbName":"estimated_tokens"},{"name":"tier","kind":"scalar","type":"String"},{"name":"model","kind":"scalar","type":"String"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatSessionToSessionContextState"}],"dbName":"session_context_states"},"ChatMessage":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"messageId","kind":"scalar","type":"String","dbName":"message_id"},{"name":"role","kind":"enum","type":"MessageRole"},{"name":"model","kind":"scalar","type":"String"},{"name":"sequence","kind":"scalar","type":"Int"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatMessageToChatSession"},{"name":"parts","kind":"object","type":"ChatMessagePart","relationName":"ChatMessageToChatMessagePart"}],"dbName":"messages"},"ChatMessagePart":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"messageId","kind":"scalar","type":"String","dbName":"message_id"},{"name":"partIndex","kind":"scalar","type":"Int","dbName":"part_index"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"message","kind":"object","type":"ChatMessage","relationName":"ChatMessageToChatMessagePart"}],"dbName":"message_parts"},"ChatRun":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"clientTurnId","kind":"scalar","type":"String","dbName":"client_turn_id"},{"name":"status","kind":"enum","type":"ChatRunStatus"},{"name":"baseRevision","kind":"scalar","type":"Int","dbName":"base_revision"},{"name":"finalRevision","kind":"scalar","type":"Int","dbName":"final_revision"},{"name":"error","kind":"scalar","type":"String"},{"name":"startedAt","kind":"scalar","type":"DateTime","dbName":"started_at"},{"name":"finishedAt","kind":"scalar","type":"DateTime","dbName":"finished_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatRunToChatSession"},{"name":"events","kind":"object","type":"ChatRunEvent","relationName":"ChatRunToChatRunEvent"}],"dbName":"chat_runs"},"ChatRunEvent":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"runId","kind":"scalar","type":"String","dbName":"run_id"},{"name":"cursor","kind":"scalar","type":"Int"},{"name":"kind","kind":"scalar","type":"String"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"run","kind":"object","type":"ChatRun","relationName":"ChatRunToChatRunEvent"}],"dbName":"chat_run_events"},"ChatTurnRevert":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"turnKey","kind":"scalar","type":"String","dbName":"turn_key"},{"name":"messages","kind":"scalar","type":"Json"},{"name":"state","kind":"scalar","type":"String"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"reappliedAt","kind":"scalar","type":"DateTime","dbName":"reapplied_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatSessionToChatTurnRevert"}],"dbName":"chat_turn_reverts"},"ChatInteraction":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"toolCallId","kind":"scalar","type":"String","dbName":"tool_call_id"},{"name":"kind","kind":"enum","type":"ChatInteractionKind"},{"name":"status","kind":"enum","type":"ChatInteractionStatus"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"response","kind":"scalar","type":"Json"},{"name":"resolvedAt","kind":"scalar","type":"DateTime","dbName":"resolved_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatInteractionToChatSession"}],"dbName":"chat_interactions"},"SubagentTask":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"parentSessionId","kind":"scalar","type":"String","dbName":"parent_session_id"},{"name":"prompt","kind":"scalar","type":"String"},{"name":"status","kind":"enum","type":"SubagentTaskStatus"},{"name":"mode","kind":"scalar","type":"String"},{"name":"model","kind":"scalar","type":"String"},{"name":"allowedTools","kind":"scalar","type":"Json","dbName":"allowed_tools"},{"name":"output","kind":"scalar","type":"Json"},{"name":"error","kind":"scalar","type":"String"},{"name":"startedAt","kind":"scalar","type":"DateTime","dbName":"started_at"},{"name":"finishedAt","kind":"scalar","type":"DateTime","dbName":"finished_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"parentSession","kind":"object","type":"ChatSession","relationName":"ChatSessionToSubagentTask"}],"dbName":"subagent_tasks"}},"enums":{},"types":{}}');
|
|
10731
|
+
config5.runtimeDataModel = JSON.parse('{"models":{"ChatSession":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"title","kind":"scalar","type":"String"},{"name":"autoTitled","kind":"scalar","type":"Boolean","dbName":"auto_titled"},{"name":"cwd","kind":"scalar","type":"String"},{"name":"workspaceDevice","kind":"scalar","type":"String","dbName":"workspace_device"},{"name":"workspaceInode","kind":"scalar","type":"String","dbName":"workspace_inode"},{"name":"mode","kind":"scalar","type":"String"},{"name":"permissionMode","kind":"scalar","type":"String","dbName":"permission_mode"},{"name":"model","kind":"scalar","type":"String"},{"name":"revision","kind":"scalar","type":"Int"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"messages","kind":"object","type":"ChatMessage","relationName":"ChatMessageToChatSession"},{"name":"interactions","kind":"object","type":"ChatInteraction","relationName":"ChatInteractionToChatSession"},{"name":"subagentTasks","kind":"object","type":"SubagentTask","relationName":"ChatSessionToSubagentTask"},{"name":"contextState","kind":"object","type":"SessionContextState","relationName":"ChatSessionToSessionContextState"},{"name":"runs","kind":"object","type":"ChatRun","relationName":"ChatRunToChatSession"},{"name":"turnReverts","kind":"object","type":"ChatTurnRevert","relationName":"ChatSessionToChatTurnRevert"}],"dbName":"sessions","schema":null},"SessionContextState":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"summary","kind":"scalar","type":"String"},{"name":"anchorMessageId","kind":"scalar","type":"String","dbName":"anchor_message_id"},{"name":"coveredMessageCount","kind":"scalar","type":"Int","dbName":"covered_message_count"},{"name":"estimatedTokens","kind":"scalar","type":"Int","dbName":"estimated_tokens"},{"name":"tier","kind":"scalar","type":"String"},{"name":"model","kind":"scalar","type":"String"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatSessionToSessionContextState"}],"dbName":"session_context_states","schema":null},"ChatMessage":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"messageId","kind":"scalar","type":"String","dbName":"message_id"},{"name":"role","kind":"enum","type":"MessageRole"},{"name":"model","kind":"scalar","type":"String"},{"name":"sequence","kind":"scalar","type":"Int"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatMessageToChatSession"},{"name":"parts","kind":"object","type":"ChatMessagePart","relationName":"ChatMessageToChatMessagePart"}],"dbName":"messages","schema":null},"ChatMessagePart":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"messageId","kind":"scalar","type":"String","dbName":"message_id"},{"name":"partIndex","kind":"scalar","type":"Int","dbName":"part_index"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"message","kind":"object","type":"ChatMessage","relationName":"ChatMessageToChatMessagePart"}],"dbName":"message_parts","schema":null},"ChatRun":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"clientTurnId","kind":"scalar","type":"String","dbName":"client_turn_id"},{"name":"status","kind":"enum","type":"ChatRunStatus"},{"name":"baseRevision","kind":"scalar","type":"Int","dbName":"base_revision"},{"name":"finalRevision","kind":"scalar","type":"Int","dbName":"final_revision"},{"name":"error","kind":"scalar","type":"String"},{"name":"startedAt","kind":"scalar","type":"DateTime","dbName":"started_at"},{"name":"finishedAt","kind":"scalar","type":"DateTime","dbName":"finished_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatRunToChatSession"},{"name":"events","kind":"object","type":"ChatRunEvent","relationName":"ChatRunToChatRunEvent"}],"dbName":"chat_runs","schema":null},"ChatRunEvent":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"runId","kind":"scalar","type":"String","dbName":"run_id"},{"name":"cursor","kind":"scalar","type":"Int"},{"name":"kind","kind":"scalar","type":"String"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"run","kind":"object","type":"ChatRun","relationName":"ChatRunToChatRunEvent"}],"dbName":"chat_run_events","schema":null},"ChatTurnRevert":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"turnKey","kind":"scalar","type":"String","dbName":"turn_key"},{"name":"messages","kind":"scalar","type":"Json"},{"name":"state","kind":"scalar","type":"String"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"reappliedAt","kind":"scalar","type":"DateTime","dbName":"reapplied_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatSessionToChatTurnRevert"}],"dbName":"chat_turn_reverts","schema":null},"ChatInteraction":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"sessionId","kind":"scalar","type":"String","dbName":"session_id"},{"name":"toolCallId","kind":"scalar","type":"String","dbName":"tool_call_id"},{"name":"kind","kind":"enum","type":"ChatInteractionKind"},{"name":"status","kind":"enum","type":"ChatInteractionStatus"},{"name":"payload","kind":"scalar","type":"Json"},{"name":"response","kind":"scalar","type":"Json"},{"name":"resolvedAt","kind":"scalar","type":"DateTime","dbName":"resolved_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"session","kind":"object","type":"ChatSession","relationName":"ChatInteractionToChatSession"}],"dbName":"chat_interactions","schema":null},"SubagentTask":{"fields":[{"name":"id","kind":"scalar","type":"String"},{"name":"parentSessionId","kind":"scalar","type":"String","dbName":"parent_session_id"},{"name":"prompt","kind":"scalar","type":"String"},{"name":"status","kind":"enum","type":"SubagentTaskStatus"},{"name":"mode","kind":"scalar","type":"String"},{"name":"model","kind":"scalar","type":"String"},{"name":"allowedTools","kind":"scalar","type":"Json","dbName":"allowed_tools"},{"name":"output","kind":"scalar","type":"Json"},{"name":"error","kind":"scalar","type":"String"},{"name":"startedAt","kind":"scalar","type":"DateTime","dbName":"started_at"},{"name":"finishedAt","kind":"scalar","type":"DateTime","dbName":"finished_at"},{"name":"createdAt","kind":"scalar","type":"DateTime","dbName":"created_at"},{"name":"updatedAt","kind":"scalar","type":"DateTime","dbName":"updated_at"},{"name":"parentSession","kind":"object","type":"ChatSession","relationName":"ChatSessionToSubagentTask"}],"dbName":"subagent_tasks","schema":null}},"enums":{},"types":{}}');
|
|
10549
10732
|
config5.parameterizationSchema = {
|
|
10550
10733
|
strings: JSON.parse('["where","orderBy","cursor","session","message","parts","_count","messages","interactions","parentSession","subagentTasks","contextState","run","events","runs","turnReverts","ChatSession.findUnique","ChatSession.findUniqueOrThrow","ChatSession.findFirst","ChatSession.findFirstOrThrow","ChatSession.findMany","data","ChatSession.createOne","ChatSession.createMany","ChatSession.createManyAndReturn","ChatSession.updateOne","ChatSession.updateMany","ChatSession.updateManyAndReturn","create","update","ChatSession.upsertOne","ChatSession.deleteOne","ChatSession.deleteMany","having","_avg","_sum","_min","_max","ChatSession.groupBy","ChatSession.aggregate","SessionContextState.findUnique","SessionContextState.findUniqueOrThrow","SessionContextState.findFirst","SessionContextState.findFirstOrThrow","SessionContextState.findMany","SessionContextState.createOne","SessionContextState.createMany","SessionContextState.createManyAndReturn","SessionContextState.updateOne","SessionContextState.updateMany","SessionContextState.updateManyAndReturn","SessionContextState.upsertOne","SessionContextState.deleteOne","SessionContextState.deleteMany","SessionContextState.groupBy","SessionContextState.aggregate","ChatMessage.findUnique","ChatMessage.findUniqueOrThrow","ChatMessage.findFirst","ChatMessage.findFirstOrThrow","ChatMessage.findMany","ChatMessage.createOne","ChatMessage.createMany","ChatMessage.createManyAndReturn","ChatMessage.updateOne","ChatMessage.updateMany","ChatMessage.updateManyAndReturn","ChatMessage.upsertOne","ChatMessage.deleteOne","ChatMessage.deleteMany","ChatMessage.groupBy","ChatMessage.aggregate","ChatMessagePart.findUnique","ChatMessagePart.findUniqueOrThrow","ChatMessagePart.findFirst","ChatMessagePart.findFirstOrThrow","ChatMessagePart.findMany","ChatMessagePart.createOne","ChatMessagePart.createMany","ChatMessagePart.createManyAndReturn","ChatMessagePart.updateOne","ChatMessagePart.updateMany","ChatMessagePart.updateManyAndReturn","ChatMessagePart.upsertOne","ChatMessagePart.deleteOne","ChatMessagePart.deleteMany","ChatMessagePart.groupBy","ChatMessagePart.aggregate","ChatRun.findUnique","ChatRun.findUniqueOrThrow","ChatRun.findFirst","ChatRun.findFirstOrThrow","ChatRun.findMany","ChatRun.createOne","ChatRun.createMany","ChatRun.createManyAndReturn","ChatRun.updateOne","ChatRun.updateMany","ChatRun.updateManyAndReturn","ChatRun.upsertOne","ChatRun.deleteOne","ChatRun.deleteMany","ChatRun.groupBy","ChatRun.aggregate","ChatRunEvent.findUnique","ChatRunEvent.findUniqueOrThrow","ChatRunEvent.findFirst","ChatRunEvent.findFirstOrThrow","ChatRunEvent.findMany","ChatRunEvent.createOne","ChatRunEvent.createMany","ChatRunEvent.createManyAndReturn","ChatRunEvent.updateOne","ChatRunEvent.updateMany","ChatRunEvent.updateManyAndReturn","ChatRunEvent.upsertOne","ChatRunEvent.deleteOne","ChatRunEvent.deleteMany","ChatRunEvent.groupBy","ChatRunEvent.aggregate","ChatTurnRevert.findUnique","ChatTurnRevert.findUniqueOrThrow","ChatTurnRevert.findFirst","ChatTurnRevert.findFirstOrThrow","ChatTurnRevert.findMany","ChatTurnRevert.createOne","ChatTurnRevert.createMany","ChatTurnRevert.createManyAndReturn","ChatTurnRevert.updateOne","ChatTurnRevert.updateMany","ChatTurnRevert.updateManyAndReturn","ChatTurnRevert.upsertOne","ChatTurnRevert.deleteOne","ChatTurnRevert.deleteMany","ChatTurnRevert.groupBy","ChatTurnRevert.aggregate","ChatInteraction.findUnique","ChatInteraction.findUniqueOrThrow","ChatInteraction.findFirst","ChatInteraction.findFirstOrThrow","ChatInteraction.findMany","ChatInteraction.createOne","ChatInteraction.createMany","ChatInteraction.createManyAndReturn","ChatInteraction.updateOne","ChatInteraction.updateMany","ChatInteraction.updateManyAndReturn","ChatInteraction.upsertOne","ChatInteraction.deleteOne","ChatInteraction.deleteMany","ChatInteraction.groupBy","ChatInteraction.aggregate","SubagentTask.findUnique","SubagentTask.findUniqueOrThrow","SubagentTask.findFirst","SubagentTask.findFirstOrThrow","SubagentTask.findMany","SubagentTask.createOne","SubagentTask.createMany","SubagentTask.createManyAndReturn","SubagentTask.updateOne","SubagentTask.updateMany","SubagentTask.updateManyAndReturn","SubagentTask.upsertOne","SubagentTask.deleteOne","SubagentTask.deleteMany","SubagentTask.groupBy","SubagentTask.aggregate","AND","OR","NOT","id","parentSessionId","prompt","SubagentTaskStatus","status","mode","model","allowedTools","output","error","startedAt","finishedAt","createdAt","updatedAt","equals","in","notIn","lt","lte","gt","gte","not","string_contains","string_starts_with","string_ends_with","array_starts_with","array_ends_with","contains","startsWith","endsWith","sessionId","toolCallId","ChatInteractionKind","kind","ChatInteractionStatus","payload","response","resolvedAt","turnKey","state","reappliedAt","runId","clientTurnId","ChatRunStatus","baseRevision","finalRevision","messageId","partIndex","MessageRole","role","sequence","summary","anchorMessageId","coveredMessageCount","estimatedTokens","tier","title","autoTitled","cwd","workspaceDevice","workspaceInode","permissionMode","revision","every","some","none","runId_cursor","sessionId_clientTurnId","sessionId_toolCallId","messageId_partIndex","sessionId_messageId","sessionId_sequence","is","isNot","connectOrCreate","upsert","createMany","set","disconnect","delete","connect","updateMany","deleteMany","increment","decrement","multiply","divide"]'),
|
|
10551
10734
|
graph: "sgRYkAEVBwAArAIAIAgAAK0CACAKAACuAgAgCwAArwIAIA4AALACACAPAACxAgAgqAEAAKoCADCpAQAAKQAQqgEAAKoCADCrAQEAAAABsAEBAKECACGxAQEAowIAIbcBQACkAgAhuAFAAKQCACHjAQEAowIAIeQBIACrAgAh5QEBAKMCACHmAQEAowIAIecBAQCjAgAh6AEBAKMCACHpAQIAogIAIQEAAAABACAOAwAApQIAIAUAAMsCACCoAQAAyQIAMKkBAAADABCqAQAAyQIAMKsBAQChAgAhsQEBAKMCACG3AUAApAIAIbgBQACkAgAhyQEBAKECACHOAQAAswIAINkBAQChAgAh3AEAAMoC3AEi3QECAKICACEDAwAApgMAIAUAAIMEACCxAQAAzAIAIBADAAClAgAgBQAAywIAIKgBAADJAgAwqQEAAAMAEKoBAADJAgAwqwEBAAAAAbEBAQCjAgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAhzgEAALMCACDZAQEAoQIAIdwBAADKAtwBIt0BAgCiAgAh8QEAAMcCACDyAQAAyAIAIAMAAAADACABAAAEADACAAAFACAJBAAAxgIAIKgBAADFAgAwqQEAAAcAEKoBAADFAgAwqwEBAKECACG3AUAApAIAIc4BAACzAgAg2QEBAKECACHaAQIAogIAIQEEAACCBAAgCgQAAMYCACCoAQAAxQIAMKkBAAAHABCqAQAAxQIAMKsBAQAAAAG3AUAApAIAIc4BAACzAgAg2QEBAKECACHaAQIAogIAIfABAADEAgAgAwAAAAcAIAEAAAgAMAIAAAkAIAEAAAAHACAOAwAApQIAIKgBAADBAgAwqQEAAAwAEKoBAADBAgAwqwEBAKECACGvAQAAwwLOASK3AUAApAIAIbgBQACkAgAhyQEBAKECACHKAQEAoQIAIcwBAADCAswBIs4BAACzAgAgzwEAAL8CACDQAUAAtAIAIQMDAACmAwAgzwEAAMwCACDQAQAAzAIAIA8DAAClAgAgqAEAAMECADCpAQAADAAQqgEAAMECADCrAQEAAAABrwEAAMMCzgEitwFAAKQCACG4AUAApAIAIckBAQChAgAhygEBAKECACHMAQAAwgLMASLOAQAAswIAIM8BAAC_AgAg0AFAALQCACHvAQAAwAIAIAMAAAAMACABAAANADACAAAOACARCQAApQIAIKgBAAC9AgAwqQEAABAAEKoBAAC9AgAwqwEBAKECACGsAQEAoQIAIa0BAQChAgAhrwEAAL4CrwEisAEBAKECACGxAQEAowIAIbIBAACzAgAgswEAAL8CACC0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhBgkAAKYDACCxAQAAzAIAILMBAADMAgAgtAEAAMwCACC1AQAAzAIAILYBAADMAgAgEQkAAKUCACCoAQAAvQIAMKkBAAAQABCqAQAAvQIAMKsBAQAAAAGsAQEAoQIAIa0BAQChAgAhrwEAAL4CrwEisAEBAKECACGxAQEAowIAIbIBAACzAgAgswEAAL8CACC0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhAwAAABAAIAEAABEAMAIAABIAIA4DAAClAgAgqAEAAKACADCpAQAAFAAQqgEAAKACADCrAQEAoQIAIbEBAQCjAgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAh3gEBAKECACHfAQEAoQIAIeABAgCiAgAh4QECAKICACHiAQEAoQIAIQEAAAAUACAQAwAApQIAIA0AALwCACCoAQAAuQIAMKkBAAAWABCqAQAAuQIAMKsBAQChAgAhrwEAALoC1wEitAEBAKMCACG1AUAAtAIAIbYBQAC0AgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAh1QEBAKECACHXAQIAogIAIdgBAgC7AgAhBgMAAKYDACANAACBBAAgtAEAAMwCACC1AQAAzAIAILYBAADMAgAg2AEAAMwCACARAwAApQIAIA0AALwCACCoAQAAuQIAMKkBAAAWABCqAQAAuQIAMKsBAQAAAAGvAQAAugLXASK0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhyQEBAKECACHVAQEAoQIAIdcBAgCiAgAh2AECALsCACHuAQAAuAIAIAMAAAAWACABAAAXADACAAAYACAKAgIAogIAIQwAALcCACCoAQAAtgIAMKkBAAAaABCqAQAAtgIAMKsBAQChAgAhtwFAAKQCACHMAQEAoQIAIc4BAACzAgAg1AEBAKECACEBDAAAgAQAIAsCAgCiAgAhDAAAtwIAIKgBAAC2AgAwqQEAABoAEKoBAAC2AgAwqwEBAAAAAbcBQACkAgAhzAEBAKECACHOAQAAswIAINQBAQChAgAh7QEAALUCACADAAAAGgAgAQAAGwAwAgAAHAAgAQAAABoAIAsDAAClAgAgBwAAswIAIKgBAACyAgAwqQEAAB8AEKoBAACyAgAwqwEBAKECACG3AUAApAIAIckBAQChAgAh0QEBAKECACHSAQEAoQIAIdMBQAC0AgAhAgMAAKYDACDTAQAAzAIAIAsDAAClAgAgBwAAswIAIKgBAACyAgAwqQEAAB8AEKoBAACyAgAwqwEBAAAAAbcBQACkAgAhyQEBAKECACHRAQEAoQIAIdIBAQChAgAh0wFAALQCACEDAAAAHwAgAQAAIAAwAgAAIQAgAQAAAAMAIAEAAAAMACABAAAAEAAgAQAAABYAIAEAAAAfACABAAAAAQAgFQcAAKwCACAIAACtAgAgCgAArgIAIAsAAK8CACAOAACwAgAgDwAAsQIAIKgBAACqAgAwqQEAACkAEKoBAACqAgAwqwEBAKECACGwAQEAoQIAIbEBAQCjAgAhtwFAAKQCACG4AUAApAIAIeMBAQCjAgAh5AEgAKsCACHlAQEAowIAIeYBAQCjAgAh5wEBAKMCACHoAQEAowIAIekBAgCiAgAhDAcAAPoDACAIAAD7AwAgCgAA_AMAIAsAAP0DACAOAAD-AwAgDwAA_wMAILEBAADMAgAg4wEAAMwCACDlAQAAzAIAIOYBAADMAgAg5wEAAMwCACDoAQAAzAIAIAMAAAApACABAAAqADACAAABACADAAAAKQAgAQAAKgAwAgAAAQAgAwAAACkAIAEAACoAMAIAAAEAIBIHAAD0AwAgCAAA9QMAIAoAAPYDACALAAD3AwAgDgAA-AMAIA8AAPkDACCrAQEAAAABsAEBAAAAAbEBAQAAAAG3AUAAAAABuAFAAAAAAeMBAQAAAAHkASAAAAAB5QEBAAAAAeYBAQAAAAHnAQEAAAAB6AEBAAAAAekBAgAAAAEBFQAALgAgDKsBAQAAAAGwAQEAAAABsQEBAAAAAbcBQAAAAAG4AUAAAAAB4wEBAAAAAeQBIAAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QECAAAAAQEVAAAwADABFQAAMAAwEgcAAK0DACAIAACuAwAgCgAArwMAIAsAALADACAOAACxAwAgDwAAsgMAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIQIAAAABACAVAAAzACAMqwEBANACACGwAQEA0AIAIbEBAQDSAgAhtwFAANQCACG4AUAA1AIAIeMBAQDSAgAh5AEgAKwDACHlAQEA0gIAIeYBAQDSAgAh5wEBANICACHoAQEA0gIAIekBAgDoAgAhAgAAACkAIBUAADUAIAIAAAApACAVAAA1ACADAAAAAQAgHAAALgAgHQAAMwAgAQAAAAEAIAEAAAApACALBgAApwMAICIAAKgDACAjAACrAwAgJAAAqgMAICUAAKkDACCxAQAAzAIAIOMBAADMAgAg5QEAAMwCACDmAQAAzAIAIOcBAADMAgAg6AEAAMwCACAPqAEAAKYCADCpAQAAPAAQqgEAAKYCADCrAQEA8gEAIbABAQDyAQAhsQEBAPQBACG3AUAA-AEAIbgBQAD4AQAh4wEBAPQBACHkASAApwIAIeUBAQD0AQAh5gEBAPQBACHnAQEA9AEAIegBAQD0AQAh6QECAJACACEDAAAAKQAgAQAAOwAwIQAAPAAgAwAAACkAIAEAACoAMAIAAAEAIA4DAAClAgAgqAEAAKACADCpAQAAFAAQqgEAAKACADCrAQEAAAABsQEBAKMCACG3AUAApAIAIbgBQACkAgAhyQEBAAAAAd4BAQChAgAh3wEBAKECACHgAQIAogIAIeEBAgCiAgAh4gEBAKECACEBAAAAPwAgAQAAAD8AIAIDAACmAwAgsQEAAMwCACADAAAAFAAgAQAAQgAwAgAAPwAgAwAAABQAIAEAAEIAMAIAAD8AIAMAAAAUACABAABCADACAAA_ACALAwAApQMAIKsBAQAAAAGxAQEAAAABtwFAAAAAAbgBQAAAAAHJAQEAAAAB3gEBAAAAAd8BAQAAAAHgAQIAAAAB4QECAAAAAeIBAQAAAAEBFQAARgAgCqsBAQAAAAGxAQEAAAABtwFAAAAAAbgBQAAAAAHJAQEAAAAB3gEBAAAAAd8BAQAAAAHgAQIAAAAB4QECAAAAAeIBAQAAAAEBFQAASAAwARUAAEgAMAsDAACkAwAgqwEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHJAQEA0AIAId4BAQDQAgAh3wEBANACACHgAQIA6AIAIeEBAgDoAgAh4gEBANACACECAAAAPwAgFQAASwAgCqsBAQDQAgAhsQEBANICACG3AUAA1AIAIbgBQADUAgAhyQEBANACACHeAQEA0AIAId8BAQDQAgAh4AECAOgCACHhAQIA6AIAIeIBAQDQAgAhAgAAABQAIBUAAE0AIAIAAAAUACAVAABNACADAAAAPwAgHAAARgAgHQAASwAgAQAAAD8AIAEAAAAUACAGBgAAnwMAICIAAKADACAjAACjAwAgJAAAogMAICUAAKEDACCxAQAAzAIAIA2oAQAAnwIAMKkBAABUABCqAQAAnwIAMKsBAQDyAQAhsQEBAPQBACG3AUAA-AEAIbgBQAD4AQAhyQEBAPIBACHeAQEA8gEAId8BAQDyAQAh4AECAJACACHhAQIAkAIAIeIBAQDyAQAhAwAAABQAIAEAAFMAMCEAAFQAIAMAAAAUACABAABCADACAAA_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_AQEAAAABwAEBAIECACHGAQEAAAABxwEBAAAAAcgBAQAAAAEKBgAA-gEAICQAAIACACAlAACAAgAguQGAAAAAAcABgAAAAAHBAQEAAAABwgEBAAAAAcMBAQAAAAHEAYAAAAABxQGAAAAAAQoGAAD9AQAgJAAA_wEAICUAAP8BACC5AYAAAAABwAGAAAAAAcEBAQAAAAHCAQEAAAABwwEBAAAAAcQBgAAAAAHFAYAAAAABCwYAAP0BACAkAAD-AQAgJQAA_gEAILkBQAAAAAG6AUAAAAAFuwFAAAAABbwBQAAAAAG9AUAAAAABvgFAAAAAAb8BQAAAAAHAAUAA_AEAIQsGAAD6AQAgJAAA-wEAICUAAPsBACC5AUAAAAABugFAAAAABLsBQAAAAAS8AUAAAAABvQFAAAAAAb4BQAAAAAG_AUAAAAABwAFAAPkBACELBgAA-gEAICQAAPsBACAlAAD7AQAguQFAAAAAAboBQAAAAAS7AUAAAAAEvAFAAAAAAb0BQAAAAAG-AUAAAAABvwFAAAAAAcABQAD5AQAhCLkBAgAAAAG6AQIAAAAEuwECAAAABLwBAgAAAAG9AQIAAAABvgECAAAAAb8BAgAAAAHAAQIA-gEAIQi5AUAAAAABugFAAAAABLsBQAAAAAS8AUAAAAABvQFAAAAAAb4BQAAAAAG_AUAAAAABwAFAAPsBACELBgAA_QEAICQAAP4BACAlAAD-AQAguQFAAAAAAboBQAAAAAW7AUAAAAAFvAFAAAAAAb0BQAAAAAG-AUAAAAABvwFAAAAAAcABQAD8AQAhCLkBAgAAAAG6AQIAAAAFuwECAAAABbwBAgAAAAG9AQIAAAABvgECAAAAAb8BAgAAAAHAAQIA_QEAIQi5AUAAAAABugFAAAAABbsBQAAAAAW8AUAAAAABvQFAAAAAAb4BQAAAAAG_AUAAAAABwAFAAP4BACEHuQGAAAAAAcABgAAAAAHBAQEAAAABwgEBAAAAAcMBAQAAAAHEAYAAAAABxQGAAAAAAQe5AYAAAAABwAGAAAAAAcEBAQAAAAHCAQEAAAABwwEBAAAAAcQBgAAAAAHFAYAAAAABDgYAAP0BACAkAACCAgAgJQAAggIAILkBAQAAAAG6AQEAAAAFuwEBAAAABbwBAQAAAAG9AQEAAAABvgEBAAAAAb8BAQAAAAHAAQEAgQIAIcYBAQAAAAHHAQEAAAAByAEBAAAAAQu5AQEAAAABugEBAAAABbsBAQAAAAW8AQEAAAABvQEBAAAAAb4BAQAAAAG_AQEAAAABwAEBAIICACHGAQEAAAABxwEBAAAAAcgBAQAAAAEHBgAA-gEAICQAAIQCACAlAACEAgAguQEAAACvAQK6AQAAAK8BCLsBAAAArwEIwAEAAIMCrwEiBLkBAAAArwECugEAAACvAQi7AQAAAK8BCMABAACEAq8BIg4GAAD6AQAgJAAAhgIAICUAAIYCACC5AQEAAAABugEBAAAABLsBAQAAAAS8AQEAAAABvQEBAAAAAb4BAQAAAAG_AQEAAAABwAEBAIUCACHGAQEAAAABxwEBAAAAAcgBAQAAAAELuQEBAAAAAboBAQAAAAS7AQEAAAAEvAEBAAAAAb0BAQAAAAG-AQEAAAABvwEBAAAAAcABAQCGAgAhxgEBAAAAAccBAQAAAAHIAQEAAAABDagBAACHAgAwqQEAANgBABCqAQAAhwIAMKsBAQDyAQAhrwEAAIkCzgEitwFAAPgBACG4AUAA-AEAIckBAQDyAQAhygEBAPIBACHMAQAAiALMASLOAQAA9QEAIM8BAAD2AQAg0AFAAPcBACEHBgAA-gEAICQAAI0CACAlAACNAgAguQEAAADMAQK6AQAAAMwBCLsBAAAAzAEIwAEAAIwCzAEiBwYAAPoBACAkAACLAgAgJQAAiwIAILkBAAAAzgECugEAAADOAQi7AQAAAM4BCMABAACKAs4BIgcGAAD6AQAgJAAAiwIAICUAAIsCACC5AQAAAM4BAroBAAAAzgEIuwEAAADOAQjAAQAAigLOASIEuQEAAADOAQK6AQAAAM4BCLsBAAAAzgEIwAEAAIsCzgEiBwYAAPoBACAkAACNAgAgJQAAjQIAILkBAAAAzAECugEAAADMAQi7AQAAAMwBCMABAACMAswBIgS5AQAAAMwBAroBAAAAzAEIuwEAAADMAQjAAQAAjQLMASIKBwAA9QEAIKgBAACOAgAwqQEAAMIBABCqAQAAjgIAMKsBAQDyAQAhtwFAAPgBACHJAQEA8gEAIdEBAQDyAQAh0gEBAPIBACHTAUAA9wEAIQkCAgCQAgAhqAEAAI8CADCpAQAArAEAEKoBAACPAgAwqwEBAPIBACG3AUAA-AEAIcwBAQDyAQAhzgEAAPUBACDUAQEA8gEAIQ0GAAD6AQAgIgAAkgIAICMAAPoBACAkAAD6AQAgJQAA-gEAILkBAgAAAAG6AQIAAAAEuwECAAAABLwBAgAAAAG9AQIAAAABvgECAAAAAb8BAgAAAAHAAQIAkQIAIQ0GAAD6AQAgIgAAkgIAICMAAPoBACAkAAD6AQAgJQAA-gEAILkBAgAAAAG6AQIAAAAEuwECAAAABLwBAgAAAAG9AQIAAAABvgECAAAAAb8BAgAAAAHAAQIAkQIAIQi5AQgAAAABugEIAAAABLsBCAAAAAS8AQgAAAABvQEIAAAAAb4BCAAAAAG_AQgAAAABwAEIAJICACEOqAEAAJMCADCpAQAAlgEAEKoBAACTAgAwqwEBAPIBACGvAQAAlALXASK0AQEA9AEAIbUBQAD3AQAhtgFAAPcBACG3AUAA-AEAIbgBQAD4AQAhyQEBAPIBACHVAQEA8gEAIdcBAgCQAgAh2AECAJUCACEHBgAA-gEAICQAAJkCACAlAACZAgAguQEAAADXAQK6AQAAANcBCLsBAAAA1wEIwAEAAJgC1wEiDQYAAP0BACAiAACXAgAgIwAA_QEAICQAAP0BACAlAAD9AQAguQECAAAAAboBAgAAAAW7AQIAAAAFvAECAAAAAb0BAgAAAAG-AQIAAAABvwECAAAAAcABAgCWAgAhDQYAAP0BACAiAACXAgAgIwAA_QEAICQAAP0BACAlAAD9AQAguQECAAAAAboBAgAAAAW7AQIAAAAFvAECAAAAAb0BAgAAAAG-AQIAAAABvwECAAAAAcABAgCWAgAhCLkBCAAAAAG6AQgAAAAFuwEIAAAABbwBCAAAAAG9AQgAAAABvgEIAAAAAb8BCAAAAAHAAQgAlwIAIQcGAAD6AQAgJAAAmQIAICUAAJkCACC5AQAAANcBAroBAAAA1wEIuwEAAADXAQjAAQAAmALXASIEuQEAAADXAQK6AQAAANcBCLsBAAAA1wEIwAEAAJkC1wEiCKgBAACaAgAwqQEAAIABABCqAQAAmgIAMKsBAQDyAQAhtwFAAPgBACHOAQAA9QEAINkBAQDyAQAh2gECAJACACEMqAEAAJsCADCpAQAAagAQqgEAAJsCADCrAQEA8gEAIbEBAQD0AQAhtwFAAPgBACG4AUAA-AEAIckBAQDyAQAhzgEAAPUBACDZAQEA8gEAIdwBAACcAtwBIt0BAgCQAgAhBwYAAPoBACAkAACeAgAgJQAAngIAILkBAAAA3AECugEAAADcAQi7AQAAANwBCMABAACdAtwBIgcGAAD6AQAgJAAAngIAICUAAJ4CACC5AQAAANwBAroBAAAA3AEIuwEAAADcAQjAAQAAnQLcASIEuQEAAADcAQK6AQAAANwBCLsBAAAA3AEIwAEAAJ4C3AEiDagBAACfAgAwqQEAAFQAEKoBAACfAgAwqwEBAPIBACGxAQEA9AEAIbcBQAD4AQAhuAFAAPgBACHJAQEA8gEAId4BAQDyAQAh3wEBAPIBACHgAQIAkAIAIeEBAgCQAgAh4gEBAPIBACEOAwAApQIAIKgBAACgAgAwqQEAABQAEKoBAACgAgAwqwEBAKECACGxAQEAowIAIbcBQACkAgAhuAFAAKQCACHJAQEAoQIAId4BAQChAgAh3wEBAKECACHgAQIAogIAIeEBAgCiAgAh4gEBAKECACELuQEBAAAAAboBAQAAAAS7AQEAAAAEvAEBAAAAAb0BAQAAAAG-AQEAAAABvwEBAAAAAcABAQCGAgAhxgEBAAAAAccBAQAAAAHIAQEAAAABCLkBAgAAAAG6AQIAAAAEuwECAAAABLwBAgAAAAG9AQIAAAABvgECAAAAAb8BAgAAAAHAAQIA-gEAIQu5AQEAAAABugEBAAAABbsBAQAAAAW8AQEAAAABvQEBAAAAAb4BAQAAAAG_AQEAAAABwAEBAIICACHGAQEAAAABxwEBAAAAAcgBAQAAAAEIuQFAAAAAAboBQAAAAAS7AUAAAAAEvAFAAAAAAb0BQAAAAAG-AUAAAAABvwFAAAAAAcABQAD7AQAhFwcAAKwCACAIAACtAgAgCgAArgIAIAsAAK8CACAOAACwAgAgDwAAsQIAIKgBAACqAgAwqQEAACkAEKoBAACqAgAwqwEBAKECACGwAQEAoQIAIbEBAQCjAgAhtwFAAKQCACG4AUAApAIAIeMBAQCjAgAh5AEgAKsCACHlAQEAowIAIeYBAQCjAgAh5wEBAKMCACHoAQEAowIAIekBAgCiAgAh8wEAACkAIPQBAAApACAPqAEAAKYCADCpAQAAPAAQqgEAAKYCADCrAQEA8gEAIbABAQDyAQAhsQEBAPQBACG3AUAA-AEAIbgBQAD4AQAh4wEBAPQBACHkASAApwIAIeUBAQD0AQAh5gEBAPQBACHnAQEA9AEAIegBAQD0AQAh6QECAJACACEFBgAA-gEAICQAAKkCACAlAACpAgAguQEgAAAAAcABIACoAgAhBQYAAPoBACAkAACpAgAgJQAAqQIAILkBIAAAAAHAASAAqAIAIQK5ASAAAAABwAEgAKkCACEVBwAArAIAIAgAAK0CACAKAACuAgAgCwAArwIAIA4AALACACAPAACxAgAgqAEAAKoCADCpAQAAKQAQqgEAAKoCADCrAQEAoQIAIbABAQChAgAhsQEBAKMCACG3AUAApAIAIbgBQACkAgAh4wEBAKMCACHkASAAqwIAIeUBAQCjAgAh5gEBAKMCACHnAQEAowIAIegBAQCjAgAh6QECAKICACECuQEgAAAAAcABIACpAgAhA-oBAAADACDrAQAAAwAg7AEAAAMAIAPqAQAADAAg6wEAAAwAIOwBAAAMACAD6gEAABAAIOsBAAAQACDsAQAAEAAgEAMAAKUCACCoAQAAoAIAMKkBAAAUABCqAQAAoAIAMKsBAQChAgAhsQEBAKMCACG3AUAApAIAIbgBQACkAgAhyQEBAKECACHeAQEAoQIAId8BAQChAgAh4AECAKICACHhAQIAogIAIeIBAQChAgAh8wEAABQAIPQBAAAUACAD6gEAABYAIOsBAAAWACDsAQAAFgAgA-oBAAAfACDrAQAAHwAg7AEAAB8AIAsDAAClAgAgBwAAswIAIKgBAACyAgAwqQEAAB8AEKoBAACyAgAwqwEBAKECACG3AUAApAIAIckBAQChAgAh0QEBAKECACHSAQEAoQIAIdMBQAC0AgAhB7kBgAAAAAHAAYAAAAABwQEBAAAAAcIBAQAAAAHDAQEAAAABxAGAAAAAAcUBgAAAAAEIuQFAAAAAAboBQAAAAAW7AUAAAAAFvAFAAAAAAb0BQAAAAAG-AUAAAAABvwFAAAAAAcABQAD-AQAhAgICAAAAAdQBAQAAAAEKAgIAogIAIQwAALcCACCoAQAAtgIAMKkBAAAaABCqAQAAtgIAMKsBAQChAgAhtwFAAKQCACHMAQEAoQIAIc4BAACzAgAg1AEBAKECACESAwAApQIAIA0AALwCACCoAQAAuQIAMKkBAAAWABCqAQAAuQIAMKsBAQChAgAhrwEAALoC1wEitAEBAKMCACG1AUAAtAIAIbYBQAC0AgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAh1QEBAKECACHXAQIAogIAIdgBAgC7AgAh8wEAABYAIPQBAAAWACACyQEBAAAAAdUBAQAAAAEQAwAApQIAIA0AALwCACCoAQAAuQIAMKkBAAAWABCqAQAAuQIAMKsBAQChAgAhrwEAALoC1wEitAEBAKMCACG1AUAAtAIAIbYBQAC0AgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAh1QEBAKECACHXAQIAogIAIdgBAgC7AgAhBLkBAAAA1wECugEAAADXAQi7AQAAANcBCMABAACZAtcBIgi5AQIAAAABugECAAAABbsBAgAAAAW8AQIAAAABvQECAAAAAb4BAgAAAAG_AQIAAAABwAECAP0BACED6gEAABoAIOsBAAAaACDsAQAAGgAgEQkAAKUCACCoAQAAvQIAMKkBAAAQABCqAQAAvQIAMKsBAQChAgAhrAEBAKECACGtAQEAoQIAIa8BAAC-Aq8BIrABAQChAgAhsQEBAKMCACGyAQAAswIAILMBAAC_AgAgtAEBAKMCACG1AUAAtAIAIbYBQAC0AgAhtwFAAKQCACG4AUAApAIAIQS5AQAAAK8BAroBAAAArwEIuwEAAACvAQjAAQAAhAKvASIHuQGAAAAAAcABgAAAAAHBAQEAAAABwgEBAAAAAcMBAQAAAAHEAYAAAAABxQGAAAAAAQLJAQEAAAABygEBAAAAAQ4DAAClAgAgqAEAAMECADCpAQAADAAQqgEAAMECADCrAQEAoQIAIa8BAADDAs4BIrcBQACkAgAhuAFAAKQCACHJAQEAoQIAIcoBAQChAgAhzAEAAMICzAEizgEAALMCACDPAQAAvwIAINABQAC0AgAhBLkBAAAAzAECugEAAADMAQi7AQAAAMwBCMABAACNAswBIgS5AQAAAM4BAroBAAAAzgEIuwEAAADOAQjAAQAAiwLOASIC2QEBAAAAAdoBAgAAAAEJBAAAxgIAIKgBAADFAgAwqQEAAAcAEKoBAADFAgAwqwEBAKECACG3AUAApAIAIc4BAACzAgAg2QEBAKECACHaAQIAogIAIRADAAClAgAgBQAAywIAIKgBAADJAgAwqQEAAAMAEKoBAADJAgAwqwEBAKECACGxAQEAowIAIbcBQACkAgAhuAFAAKQCACHJAQEAoQIAIc4BAACzAgAg2QEBAKECACHcAQAAygLcASLdAQIAogIAIfMBAAADACD0AQAAAwAgAskBAQAAAAHZAQEAAAABAskBAQAAAAHdAQIAAAABDgMAAKUCACAFAADLAgAgqAEAAMkCADCpAQAAAwAQqgEAAMkCADCrAQEAoQIAIbEBAQCjAgAhtwFAAKQCACG4AUAApAIAIckBAQChAgAhzgEAALMCACDZAQEAoQIAIdwBAADKAtwBIt0BAgCiAgAhBLkBAAAA3AECugEAAADcAQi7AQAAANwBCMABAACeAtwBIgPqAQAABwAg6wEAAAcAIOwBAAAHACAAAAAAAfgBAQAAAAEB-AEAAACvAQIB-AEBAAAAAQH4AUAAAAABAfgBQAAAAAEFHAAArgQAIB0AALEEACD1AQAArwQAIPYBAACwBAAg-wEAAAEAIAMcAACuBAAg9QEAAK8EACD7AQAAAQAgAAAAAfgBAAAAzAECAfgBAAAAzgECBRwAAKkEACAdAACsBAAg9QEAAKoEACD2AQAAqwQAIPsBAAABACADHAAAqQQAIPUBAACqBAAg-wEAAAEAIAAAAAUcAACkBAAgHQAApwQAIPUBAAClBAAg9gEAAKYEACD7AQAAAQAgAxwAAKQEACD1AQAApQQAIPsBAAABACAAAAAAAAX4AQIAAAAB_gECAAAAAf8BAgAAAAGAAgIAAAABgQICAAAAAQUcAACfBAAgHQAAogQAIPUBAACgBAAg9gEAAKEEACD7AQAAGAAgAxwAAJ8EACD1AQAAoAQAIPsBAAAYACAAAAAAAAH4AQAAANcBAgX4AQIAAAAB_gECAAAAAf8BAgAAAAGAAgIAAAABgQICAAAAAQUcAACZBAAgHQAAnQQAIPUBAACaBAAg9gEAAJwEACD7AQAAAQAgCxwAAPQCADAdAAD5AgAw9QEAAPUCADD2AQAA9gIAMPcBAAD3AgAg-AEAAPgCADD5AQAA-AIAMPoBAAD4AgAw-wEAAPgCADD8AQAA-gIAMP0BAAD7AgAwBQICAAAAAasBAQAAAAG3AUAAAAABzAEBAAAAAc4BgAAAAAECAAAAHAAgHAAA_wIAIAMAAAAcACAcAAD_AgAgHQAA_gIAIAEVAACbBAAwCwICAKICACEMAAC3AgAgqAEAALYCADCpAQAAGgAQqgEAALYCADCrAQEAAAABtwFAAKQCACHMAQEAoQIAIc4BAACzAgAg1AEBAKECACHtAQAAtQIAIAIAAAAcACAVAAD-AgAgAgAAAPwCACAVAAD9AgAgCQICAKICACGoAQAA-wIAMKkBAAD8AgAQqgEAAPsCADCrAQEAoQIAIbcBQACkAgAhzAEBAKECACHOAQAAswIAINQBAQChAgAhCQICAKICACGoAQAA-wIAMKkBAAD8AgAQqgEAAPsCADCrAQEAoQIAIbcBQACkAgAhzAEBAKECACHOAQAAswIAINQBAQChAgAhBQICAOgCACGrAQEA0AIAIbcBQADUAgAhzAEBANACACHOAYAAAAABBQICAOgCACGrAQEA0AIAIbcBQADUAgAhzAEBANACACHOAYAAAAABBQICAAAAAasBAQAAAAG3AUAAAAABzAEBAAAAAc4BgAAAAAEDHAAAmQQAIPUBAACaBAAg-wEAAAEAIAQcAAD0AgAw9QEAAPUCADD3AQAA9wIAIPsBAAD4AgAwAAAAAAAFHAAAlAQAIB0AAJcEACD1AQAAlQQAIPYBAACWBAAg-wEAAAUAIAMcAACUBAAg9QEAAJUEACD7AQAABQAgAAAAAAAB-AEAAADcAQIFHAAAjgQAIB0AAJIEACD1AQAAjwQAIPYBAACRBAAg-wEAAAEAIAscAACRAwAwHQAAlgMAMPUBAACSAwAw9gEAAJMDADD3AQAAlAMAIPgBAACVAwAw-QEAAJUDADD6AQAAlQMAMPsBAACVAwAw_AEAAJcDADD9AQAAmAMAMASrAQEAAAABtwFAAAAAAc4BgAAAAAHaAQIAAAABAgAAAAkAIBwAAJwDACADAAAACQAgHAAAnAMAIB0AAJsDACABFQAAkAQAMAoEAADGAgAgqAEAAMUCADCpAQAABwAQqgEAAMUCADCrAQEAAAABtwFAAKQCACHOAQAAswIAINkBAQChAgAh2gECAKICACHwAQAAxAIAIAIAAAAJACAVAACbAwAgAgAAAJkDACAVAACaAwAgCKgBAACYAwAwqQEAAJkDABCqAQAAmAMAMKsBAQChAgAhtwFAAKQCACHOAQAAswIAINkBAQChAgAh2gECAKICACEIqAEAAJgDADCpAQAAmQMAEKoBAACYAwAwqwEBAKECACG3AUAApAIAIc4BAACzAgAg2QEBAKECACHaAQIAogIAIQSrAQEA0AIAIbcBQADUAgAhzgGAAAAAAdoBAgDoAgAhBKsBAQDQAgAhtwFAANQCACHOAYAAAAAB2gECAOgCACEEqwEBAAAAAbcBQAAAAAHOAYAAAAAB2gECAAAAAQMcAACOBAAg9QEAAI8EACD7AQAAAQAgBBwAAJEDADD1AQAAkgMAMPcBAACUAwAg-wEAAJUDADAAAAAAAAUcAACJBAAgHQAAjAQAIPUBAACKBAAg9gEAAIsEACD7AQAAAQAgAxwAAIkEACD1AQAAigQAIPsBAAABACAMBwAA-gMAIAgAAPsDACAKAAD8AwAgCwAA_QMAIA4AAP4DACAPAAD_AwAgsQEAAMwCACDjAQAAzAIAIOUBAADMAgAg5gEAAMwCACDnAQAAzAIAIOgBAADMAgAgAAAAAAAB-AEgAAAAAQscAADoAwAwHQAA7QMAMPUBAADpAwAw9gEAAOoDADD3AQAA6wMAIPgBAADsAwAw-QEAAOwDADD6AQAA7AMAMPsBAADsAwAw_AEAAO4DADD9AQAA7wMAMAscAADcAwAwHQAA4QMAMPUBAADdAwAw9gEAAN4DADD3AQAA3wMAIPgBAADgAwAw-QEAAOADADD6AQAA4AMAMPsBAADgAwAw_AEAAOIDADD9AQAA4wMAMAscAADQAwAwHQAA1QMAMPUBAADRAwAw9gEAANIDADD3AQAA0wMAIPgBAADUAwAw-QEAANQDADD6AQAA1AMAMPsBAADUAwAw_AEAANYDADD9AQAA1wMAMAccAADLAwAgHQAAzgMAIPUBAADMAwAg9gEAAM0DACD5AQAAFAAg-gEAABQAIPsBAAA_ACALHAAAvwMAMB0AAMQDADD1AQAAwAMAMPYBAADBAwAw9wEAAMIDACD4AQAAwwMAMPkBAADDAwAw-gEAAMMDADD7AQAAwwMAMPwBAADFAwAw_QEAAMYDADALHAAAswMAMB0AALgDADD1AQAAtAMAMPYBAAC1AwAw9wEAALYDACD4AQAAtwMAMPkBAAC3AwAw-gEAALcDADD7AQAAtwMAMPwBAAC5AwAw_QEAALoDADAGB4AAAAABqwEBAAAAAbcBQAAAAAHRAQEAAAAB0gEBAAAAAdMBQAAAAAECAAAAIQAgHAAAvgMAIAMAAAAhACAcAAC-AwAgHQAAvQMAIAEVAACIBAAwCwMAAKUCACAHAACzAgAgqAEAALICADCpAQAAHwAQqgEAALICADCrAQEAAAABtwFAAKQCACHJAQEAoQIAIdEBAQChAgAh0gEBAKECACHTAUAAtAIAIQIAAAAhACAVAAC9AwAgAgAAALsDACAVAAC8AwAgCgcAALMCACCoAQAAugMAMKkBAAC7AwAQqgEAALoDADCrAQEAoQIAIbcBQACkAgAhyQEBAKECACHRAQEAoQIAIdIBAQChAgAh0wFAALQCACEKBwAAswIAIKgBAAC6AwAwqQEAALsDABCqAQAAugMAMKsBAQChAgAhtwFAAKQCACHJAQEAoQIAIdEBAQChAgAh0gEBAKECACHTAUAAtAIAIQYHgAAAAAGrAQEA0AIAIbcBQADUAgAh0QEBANACACHSAQEA0AIAIdMBQADTAgAhBgeAAAAAAasBAQDQAgAhtwFAANQCACHRAQEA0AIAIdIBAQDQAgAh0wFAANMCACEGB4AAAAABqwEBAAAAAbcBQAAAAAHRAQEAAAAB0gEBAAAAAdMBQAAAAAELDQAAgQMAIKsBAQAAAAGvAQAAANcBArQBAQAAAAG1AUAAAAABtgFAAAAAAbcBQAAAAAG4AUAAAAAB1QEBAAAAAdcBAgAAAAHYAQIAAAABAgAAABgAIBwAAMoDACADAAAAGAAgHAAAygMAIB0AAMkDACABFQAAhwQAMBEDAAClAgAgDQAAvAIAIKgBAAC5AgAwqQEAABYAEKoBAAC5AgAwqwEBAAAAAa8BAAC6AtcBIrQBAQCjAgAhtQFAALQCACG2AUAAtAIAIbcBQACkAgAhuAFAAKQCACHJAQEAoQIAIdUBAQChAgAh1wECAKICACHYAQIAuwIAIe4BAAC4AgAgAgAAABgAIBUAAMkDACACAAAAxwMAIBUAAMgDACAOqAEAAMYDADCpAQAAxwMAEKoBAADGAwAwqwEBAKECACGvAQAAugLXASK0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhyQEBAKECACHVAQEAoQIAIdcBAgCiAgAh2AECALsCACEOqAEAAMYDADCpAQAAxwMAEKoBAADGAwAwqwEBAKECACGvAQAAugLXASK0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhyQEBAKECACHVAQEAoQIAIdcBAgCiAgAh2AECALsCACEKqwEBANACACGvAQAA8ALXASK0AQEA0gIAIbUBQADTAgAhtgFAANMCACG3AUAA1AIAIbgBQADUAgAh1QEBANACACHXAQIA6AIAIdgBAgDxAgAhCw0AAPMCACCrAQEA0AIAIa8BAADwAtcBIrQBAQDSAgAhtQFAANMCACG2AUAA0wIAIbcBQADUAgAhuAFAANQCACHVAQEA0AIAIdcBAgDoAgAh2AECAPECACELDQAAgQMAIKsBAQAAAAGvAQAAANcBArQBAQAAAAG1AUAAAAABtgFAAAAAAbcBQAAAAAG4AUAAAAAB1QEBAAAAAdcBAgAAAAHYAQIAAAABCasBAQAAAAGxAQEAAAABtwFAAAAAAbgBQAAAAAHeAQEAAAAB3wEBAAAAAeABAgAAAAHhAQIAAAAB4gEBAAAAAQIAAAA_ACAcAADLAwAgAwAAABQAIBwAAMsDACAdAADPAwAgCwAAABQAIBUAAM8DACCrAQEA0AIAIbEBAQDSAgAhtwFAANQCACG4AUAA1AIAId4BAQDQAgAh3wEBANACACHgAQIA6AIAIeEBAgDoAgAh4gEBANACACEJqwEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHeAQEA0AIAId8BAQDQAgAh4AECAOgCACHhAQIA6AIAIeIBAQDQAgAhDKsBAQAAAAGtAQEAAAABrwEAAACvAQKwAQEAAAABsQEBAAAAAbIBgAAAAAGzAYAAAAABtAEBAAAAAbUBQAAAAAG2AUAAAAABtwFAAAAAAbgBQAAAAAECAAAAEgAgHAAA2wMAIAMAAAASACAcAADbAwAgHQAA2gMAIAEVAACGBAAwEQkAAKUCACCoAQAAvQIAMKkBAAAQABCqAQAAvQIAMKsBAQAAAAGsAQEAoQIAIa0BAQChAgAhrwEAAL4CrwEisAEBAKECACGxAQEAowIAIbIBAACzAgAgswEAAL8CACC0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhAgAAABIAIBUAANoDACACAAAA2AMAIBUAANkDACAQqAEAANcDADCpAQAA2AMAEKoBAADXAwAwqwEBAKECACGsAQEAoQIAIa0BAQChAgAhrwEAAL4CrwEisAEBAKECACGxAQEAowIAIbIBAACzAgAgswEAAL8CACC0AQEAowIAIbUBQAC0AgAhtgFAALQCACG3AUAApAIAIbgBQACkAgAhEKgBAADXAwAwqQEAANgDABCqAQAA1wMAMKsBAQChAgAhrAEBAKECACGtAQEAoQIAIa8BAAC-Aq8BIrABAQChAgAhsQEBAKMCACGyAQAAswIAILMBAAC_AgAgtAEBAKMCACG1AUAAtAIAIbYBQAC0AgAhtwFAAKQCACG4AUAApAIAIQyrAQEA0AIAIa0BAQDQAgAhrwEAANECrwEisAEBANACACGxAQEA0gIAIbIBgAAAAAGzAYAAAAABtAEBANICACG1AUAA0wIAIbYBQADTAgAhtwFAANQCACG4AUAA1AIAIQyrAQEA0AIAIa0BAQDQAgAhrwEAANECrwEisAEBANACACGxAQEA0gIAIbIBgAAAAAGzAYAAAAABtAEBANICACG1AUAA0wIAIbYBQADTAgAhtwFAANQCACG4AUAA1AIAIQyrAQEAAAABrQEBAAAAAa8BAAAArwECsAEBAAAAAbEBAQAAAAGyAYAAAAABswGAAAAAAbQBAQAAAAG1AUAAAAABtgFAAAAAAbcBQAAAAAG4AUAAAAABCasBAQAAAAGvAQAAAM4BArcBQAAAAAG4AUAAAAABygEBAAAAAcwBAAAAzAECzgGAAAAAAc8BgAAAAAHQAUAAAAABAgAAAA4AIBwAAOcDACADAAAADgAgHAAA5wMAIB0AAOYDACABFQAAhQQAMA8DAAClAgAgqAEAAMECADCpAQAADAAQqgEAAMECADCrAQEAAAABrwEAAMMCzgEitwFAAKQCACG4AUAApAIAIckBAQChAgAhygEBAKECACHMAQAAwgLMASLOAQAAswIAIM8BAAC_AgAg0AFAALQCACHvAQAAwAIAIAIAAAAOACAVAADmAwAgAgAAAOQDACAVAADlAwAgDagBAADjAwAwqQEAAOQDABCqAQAA4wMAMKsBAQChAgAhrwEAAMMCzgEitwFAAKQCACG4AUAApAIAIckBAQChAgAhygEBAKECACHMAQAAwgLMASLOAQAAswIAIM8BAAC_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-AMAIKsBAQAAAAGwAQEAAAABsQEBAAAAAbcBQAAAAAG4AUAAAAAB4wEBAAAAAeQBIAAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QECAAAAAQIAAAABACAcAACkBAAgAwAAACkAIBwAAKQEACAdAACoBAAgEwAAACkAIAcAAK0DACAIAACuAwAgCgAArwMAIAsAALADACAOAACxAwAgFQAAqAQAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIREHAACtAwAgCAAArgMAIAoAAK8DACALAACwAwAgDgAAsQMAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIREHAAD0AwAgCgAA9gMAIAsAAPcDACAOAAD4AwAgDwAA-QMAIKsBAQAAAAGwAQEAAAABsQEBAAAAAbcBQAAAAAG4AUAAAAAB4wEBAAAAAeQBIAAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QECAAAAAQIAAAABACAcAACpBAAgAwAAACkAIBwAAKkEACAdAACtBAAgEwAAACkAIAcAAK0DACAKAACvAwAgCwAAsAMAIA4AALEDACAPAACyAwAgFQAArQQAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIREHAACtAwAgCgAArwMAIAsAALADACAOAACxAwAgDwAAsgMAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIREHAAD0AwAgCAAA9QMAIAsAAPcDACAOAAD4AwAgDwAA-QMAIKsBAQAAAAGwAQEAAAABsQEBAAAAAbcBQAAAAAG4AUAAAAAB4wEBAAAAAeQBIAAAAAHlAQEAAAAB5gEBAAAAAecBAQAAAAHoAQEAAAAB6QECAAAAAQIAAAABACAcAACuBAAgAwAAACkAIBwAAK4EACAdAACyBAAgEwAAACkAIAcAAK0DACAIAACuAwAgCwAAsAMAIA4AALEDACAPAACyAwAgFQAAsgQAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIREHAACtAwAgCAAArgMAIAsAALADACAOAACxAwAgDwAAsgMAIKsBAQDQAgAhsAEBANACACGxAQEA0gIAIbcBQADUAgAhuAFAANQCACHjAQEA0gIAIeQBIACsAwAh5QEBANICACHmAQEA0gIAIecBAQDSAgAh6AEBANICACHpAQIA6AIAIQcGAAwHBgIIDwUKEwYLFQcOGQgPIgsDAwABBQoDBgAEAQQAAgEFCwABAwABAQkAAQEDAAEDAwABBgAKDR0JAQwACAENHgABAwABBQcjAAgkAAolAA4mAA8nAAAAAAUGABEiABIjABMkABQlABUAAAAAAAUGABEiABIjABMkABQlABUBAwABAQMAAQUGABoiABsjABwkAB0lAB4AAAAAAAUGABoiABsjABwkAB0lAB4BAwABAQMAAQUGACMiACQjACUkACYlACcAAAAAAAUGACMiACQjACUkACYlACcBBAACAQQAAgUGACwiAC0jAC4kAC8lADAAAAAAAAUGACwiAC0jAC4kAC8lADABAwABAQMAAQUGADUiADYjADckADglADkAAAAAAAUGADUiADYjADckADglADkBDAAIAQwACAUGAD4iAD8jAEAkAEElAEIAAAAAAAUGAD4iAD8jAEAkAEElAEIBAwABAQMAAQMGAEckAEglAEkAAAADBgBHJABIJQBJAQMAAQEDAAEDBgBOJABPJQBQAAAAAwYATiQATyUAUAEJAAEBCQABAwYAVSQAViUAVwAAAAMGAFUkAFYlAFcQAgERKAESKwETLAEULQEWLwEXMQ0YMg4ZNAEaNg0bNw8eOAEfOQEgOg0mPRAnPhYoQAcpQQcqQwcrRAcsRQctRwcuSQ0vShcwTAcxTg0yTxgzUAc0UQc1Ug02VRk3Vh84VwI5WAI6WQI7WgI8WwI9XQI-Xw0_YCBAYgJBZA1CZSFDZgJEZwJFaA1GayJHbChIbQNJbgNKbwNLcANMcQNNcwNOdQ1PdilQeANReg1SeypTfANUfQNVfg1WgQErV4IBMViDAQhZhAEIWoUBCFuGAQhchwEIXYkBCF6LAQ1fjAEyYI4BCGGQAQ1ikQEzY5IBCGSTAQhllAENZpcBNGeYATpomQEJaZoBCWqbAQlrnAEJbJ0BCW2fAQluoQENb6IBO3CkAQlxpgENcqcBPHOoAQl0qQEJdaoBDXatAT13rgFDeK8BC3mwAQt6sQELe7IBC3yzAQt9tQELfrcBDX-4AUSAAboBC4EBvAENggG9AUWDAb4BC4QBvwELhQHAAQ2GAcMBRocBxAFKiAHFAQWJAcYBBYoBxwEFiwHIAQWMAckBBY0BywEFjgHNAQ2PAc4BS5AB0AEFkQHSAQ2SAdMBTJMB1AEFlAHVAQWVAdYBDZYB2QFNlwHaAVGYAdsBBpkB3AEGmgHdAQabAd4BBpwB3wEGnQHhAQaeAeMBDZ8B5AFSoAHmAQahAegBDaIB6QFTowHqAQakAesBBqUB7AENpgHvAVSnAfABWA"
|
|
@@ -10615,8 +10798,8 @@ var init_prismaNamespace = __esm(() => {
|
|
|
10615
10798
|
Decimal2 = runtime18.Decimal;
|
|
10616
10799
|
getExtensionContext = runtime18.Extensions.getExtensionContext;
|
|
10617
10800
|
prismaVersion = {
|
|
10618
|
-
client: "7.
|
|
10619
|
-
engine: "
|
|
10801
|
+
client: "7.10.0",
|
|
10802
|
+
engine: "0edf323efd1d98336f3f0a68684b56f689b900d3"
|
|
10620
10803
|
};
|
|
10621
10804
|
NullTypes2 = {
|
|
10622
10805
|
DbNull: runtime18.NullTypes.DbNull,
|
|
@@ -12970,7 +13153,7 @@ var init_sse_heartbeat = __esm(() => {
|
|
|
12970
13153
|
});
|
|
12971
13154
|
|
|
12972
13155
|
// apps/server/src/lib/openrouter-models.ts
|
|
12973
|
-
import { existsSync as
|
|
13156
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync7, writeFileSync as writeFileSync3 } from "fs";
|
|
12974
13157
|
import path20 from "path";
|
|
12975
13158
|
import { z as z39 } from "zod";
|
|
12976
13159
|
function getCacheFilePath() {
|
|
@@ -12979,10 +13162,10 @@ function getCacheFilePath() {
|
|
|
12979
13162
|
function readCache() {
|
|
12980
13163
|
try {
|
|
12981
13164
|
const cachePath = getCacheFilePath();
|
|
12982
|
-
if (!
|
|
13165
|
+
if (!existsSync7(cachePath)) {
|
|
12983
13166
|
return null;
|
|
12984
13167
|
}
|
|
12985
|
-
return modelsCacheSchema.parse(JSON.parse(
|
|
13168
|
+
return modelsCacheSchema.parse(JSON.parse(readFileSync7(cachePath, "utf8")));
|
|
12986
13169
|
} catch {
|
|
12987
13170
|
return null;
|
|
12988
13171
|
}
|
|
@@ -13029,14 +13212,14 @@ function summarizeRawModel(raw3) {
|
|
|
13029
13212
|
};
|
|
13030
13213
|
}
|
|
13031
13214
|
async function fetchModelsFromApi() {
|
|
13032
|
-
const response = await
|
|
13215
|
+
const response = await networkFetch(openRouterModelsUrl, {
|
|
13033
13216
|
signal: AbortSignal.timeout(fetchTimeoutMs)
|
|
13034
13217
|
});
|
|
13035
13218
|
if (!response.ok) {
|
|
13036
13219
|
throw new Error(`OpenRouter models API returned HTTP ${response.status}.`);
|
|
13037
13220
|
}
|
|
13038
|
-
const payload = await response.json();
|
|
13039
|
-
const models =
|
|
13221
|
+
const payload = z39.object({ data: z39.array(z39.unknown()) }).parse(await response.json());
|
|
13222
|
+
const models = payload.data.map(summarizeRawModel).filter((model) => model !== null);
|
|
13040
13223
|
if (models.length === 0) {
|
|
13041
13224
|
throw new Error("OpenRouter models API returned no models.");
|
|
13042
13225
|
}
|
|
@@ -13097,6 +13280,7 @@ function toCapabilityPricing(pricing) {
|
|
|
13097
13280
|
var logger5, openRouterModelsUrl = "https://openrouter.ai/api/v1/models", cacheTtlMs, fetchTimeoutMs = 15000, openRouterModelSummarySchema, modelsCacheSchema;
|
|
13098
13281
|
var init_openrouter_models = __esm(() => {
|
|
13099
13282
|
init_src();
|
|
13283
|
+
init_network_fetch();
|
|
13100
13284
|
logger5 = createLogger("openrouter-models");
|
|
13101
13285
|
cacheTtlMs = 24 * 60 * 60 * 1000;
|
|
13102
13286
|
openRouterModelSummarySchema = z39.object({
|
|
@@ -13145,7 +13329,7 @@ function createIdleTimeoutFetch({
|
|
|
13145
13329
|
}
|
|
13146
13330
|
const idleTimeoutFetch = async (input, init) => {
|
|
13147
13331
|
const controller = new AbortController;
|
|
13148
|
-
const callerSignal = init?.signal ?? undefined;
|
|
13332
|
+
const callerSignal = init?.signal ?? (input instanceof Request ? input.signal : undefined);
|
|
13149
13333
|
const forwardCallerAbort = () => controller.abort(callerSignal?.reason);
|
|
13150
13334
|
if (callerSignal) {
|
|
13151
13335
|
if (callerSignal.aborted) {
|
|
@@ -13169,13 +13353,16 @@ function createIdleTimeoutFetch({
|
|
|
13169
13353
|
let response;
|
|
13170
13354
|
try {
|
|
13171
13355
|
response = await fetchImpl(input, { ...init, signal: controller.signal });
|
|
13356
|
+
} catch (error) {
|
|
13357
|
+
callerSignal?.removeEventListener("abort", forwardCallerAbort);
|
|
13358
|
+
throw controller.signal.aborted ? controller.signal.reason : error;
|
|
13172
13359
|
} finally {
|
|
13173
13360
|
if (headersTimer) {
|
|
13174
13361
|
clearTimeout(headersTimer);
|
|
13175
13362
|
}
|
|
13176
13363
|
}
|
|
13177
13364
|
const body = response.body;
|
|
13178
|
-
if (
|
|
13365
|
+
if (!body) {
|
|
13179
13366
|
if (callerSignal) {
|
|
13180
13367
|
callerSignal.removeEventListener("abort", forwardCallerAbort);
|
|
13181
13368
|
}
|
|
@@ -13191,16 +13378,30 @@ function createIdleTimeoutFetch({
|
|
|
13191
13378
|
callerSignal.removeEventListener("abort", forwardCallerAbort);
|
|
13192
13379
|
}
|
|
13193
13380
|
};
|
|
13381
|
+
const reader = body.getReader();
|
|
13194
13382
|
let rearm = () => {};
|
|
13195
|
-
|
|
13383
|
+
let onAbort = () => {};
|
|
13384
|
+
const cleanup = () => {
|
|
13385
|
+
stopIdleTimer();
|
|
13386
|
+
controller.signal.removeEventListener("abort", onAbort);
|
|
13387
|
+
};
|
|
13388
|
+
const stream = new ReadableStream({
|
|
13196
13389
|
start(streamController) {
|
|
13390
|
+
onAbort = () => {
|
|
13391
|
+
cleanup();
|
|
13392
|
+
streamController.error(controller.signal.reason);
|
|
13393
|
+
reader.cancel(controller.signal.reason).catch(() => {});
|
|
13394
|
+
};
|
|
13395
|
+
controller.signal.addEventListener("abort", onAbort, { once: true });
|
|
13396
|
+
if (controller.signal.aborted) {
|
|
13397
|
+
onAbort();
|
|
13398
|
+
return;
|
|
13399
|
+
}
|
|
13197
13400
|
const arm = () => {
|
|
13401
|
+
if (idleTimeoutMs <= 0)
|
|
13402
|
+
return;
|
|
13198
13403
|
idleTimer = setTimeout(() => {
|
|
13199
13404
|
const error = new HttpIdleTimeoutError(`Provider stream timed out: no bytes received for ${idleTimeoutMs}ms`);
|
|
13200
|
-
stopIdleTimer();
|
|
13201
|
-
try {
|
|
13202
|
-
streamController.error(error);
|
|
13203
|
-
} catch {}
|
|
13204
13405
|
abortWithTimeout(error);
|
|
13205
13406
|
}, idleTimeoutMs);
|
|
13206
13407
|
};
|
|
@@ -13212,15 +13413,30 @@ function createIdleTimeoutFetch({
|
|
|
13212
13413
|
arm();
|
|
13213
13414
|
};
|
|
13214
13415
|
},
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13416
|
+
async pull(streamController) {
|
|
13417
|
+
try {
|
|
13418
|
+
const result = await reader.read();
|
|
13419
|
+
if (controller.signal.aborted)
|
|
13420
|
+
return;
|
|
13421
|
+
if (result.done) {
|
|
13422
|
+
cleanup();
|
|
13423
|
+
streamController.close();
|
|
13424
|
+
} else {
|
|
13425
|
+
rearm();
|
|
13426
|
+
streamController.enqueue(result.value);
|
|
13427
|
+
}
|
|
13428
|
+
} catch (error) {
|
|
13429
|
+
cleanup();
|
|
13430
|
+
streamController.error(error);
|
|
13431
|
+
}
|
|
13218
13432
|
},
|
|
13219
|
-
|
|
13220
|
-
|
|
13433
|
+
async cancel(reason) {
|
|
13434
|
+
cleanup();
|
|
13435
|
+
controller.abort(reason);
|
|
13436
|
+
await reader.cancel(reason);
|
|
13221
13437
|
}
|
|
13222
13438
|
});
|
|
13223
|
-
return new Response(
|
|
13439
|
+
return new Response(stream, {
|
|
13224
13440
|
status: response.status,
|
|
13225
13441
|
statusText: response.statusText,
|
|
13226
13442
|
headers: response.headers
|
|
@@ -13438,9 +13654,7 @@ function resolveOpenAITransportModel({
|
|
|
13438
13654
|
needsToolCallDiscipline: true,
|
|
13439
13655
|
providerOptions: isOpenRouter ? getOpenRouterProviderOptions(configuredModel) : undefined,
|
|
13440
13656
|
contextWindow: capabilities?.contextLength ?? getModelContextWindow(config6.provider, configuredModel),
|
|
13441
|
-
missingCredentialHints: apiKey ? [] : isOpenCodeZen ? ["Set OPENCODE_API_KEY to call OpenCode Zen models."] : isOpenRouter ? ["Set OPENROUTER_API_KEY to call OpenRouter models."] : [
|
|
13442
|
-
"Set LIGHTCODE_OPENAI_COMPATIBLE_API_KEY or OPENAI_API_KEY if your OpenAI-compatible endpoint requires authentication."
|
|
13443
|
-
],
|
|
13657
|
+
missingCredentialHints: apiKey ? [] : isOpenCodeZen ? ["Set OPENCODE_API_KEY to call OpenCode Zen models."] : isOpenRouter ? ["Set OPENROUTER_API_KEY to call OpenRouter models."] : [],
|
|
13444
13658
|
maxCompletionTokens: capabilities?.maxCompletionTokens ?? null,
|
|
13445
13659
|
supportsPromptCaching: isOpenRouter && isOpenRouterAnthropicFamilyModel(configuredModel),
|
|
13446
13660
|
pricing: resolveCapabilityPricing(capabilities, isOpenRouter && isOpenRouterAnthropicFamilyModel(configuredModel) ? 0.1 : null),
|
|
@@ -13506,9 +13720,10 @@ function createConfigStatus({
|
|
|
13506
13720
|
}
|
|
13507
13721
|
var providerFetch, anthropicModelAliases, opencodeZenDefaultBaseUrl = "https://opencode.ai/zen/v1", openRouterDefaultBaseUrl = "https://openrouter.ai/api/v1";
|
|
13508
13722
|
var init_provider_registry = __esm(() => {
|
|
13723
|
+
init_network_fetch();
|
|
13509
13724
|
init_src2();
|
|
13510
13725
|
init_idle_timeout_fetch();
|
|
13511
|
-
providerFetch = createIdleTimeoutFetch(resolveIdleTimeoutsFromEnv());
|
|
13726
|
+
providerFetch = createIdleTimeoutFetch({ ...resolveIdleTimeoutsFromEnv(), fetchImpl: networkFetch });
|
|
13512
13727
|
anthropicModelAliases = {
|
|
13513
13728
|
haiku: "claude-haiku-4-5",
|
|
13514
13729
|
sonnet: "claude-sonnet-4-6",
|
|
@@ -13968,13 +14183,11 @@ function formatAvailableSkills(skills) {
|
|
|
13968
14183
|
if (skills.length === 0) {
|
|
13969
14184
|
return "";
|
|
13970
14185
|
}
|
|
13971
|
-
const shown = skills
|
|
13972
|
-
const lines = shown.map((skill) => `- ${skill.name}${skill.description ? `: ${skill.description}` : ""}`);
|
|
13973
|
-
const more = skills.length > shown.length ? `
|
|
13974
|
-
\u2026 and ${skills.length - shown.length} more` : "";
|
|
14186
|
+
const shown = skills;
|
|
14187
|
+
const lines = shown.map((skill) => `- ${skill.name}${skill.description ? `: ${skill.description.replace(/\s+/g, " ").slice(0, 300)}` : ""}`);
|
|
13975
14188
|
return `Available skills (load by name with the skill tool):
|
|
13976
14189
|
${lines.join(`
|
|
13977
|
-
`)}
|
|
14190
|
+
`)}`;
|
|
13978
14191
|
}
|
|
13979
14192
|
function buildAvailableSkills(cwd) {
|
|
13980
14193
|
try {
|
|
@@ -14166,7 +14379,7 @@ ${skills}` : "",
|
|
|
14166
14379
|
].join(`
|
|
14167
14380
|
`);
|
|
14168
14381
|
}
|
|
14169
|
-
var logger7, projectInstructionNames, maxListedEntries = 40,
|
|
14382
|
+
var logger7, projectInstructionNames, maxListedEntries = 40, maxInstructionChars = 6000, maxNestedInstructionChars = 6000, maxNestedInstructionFileChars = 1600, maxBlockChars = 18000, instructionEpochSchema, instructionEpochStateSchema, gitSummaryCacheTtlMs = 5000, gitSummaryCache;
|
|
14170
14383
|
var init_workspace_context = __esm(() => {
|
|
14171
14384
|
init_runtime17();
|
|
14172
14385
|
init_src2();
|
|
@@ -16247,7 +16460,7 @@ var init_extension_runtime = __esm(() => {
|
|
|
16247
16460
|
});
|
|
16248
16461
|
|
|
16249
16462
|
// apps/server/src/routes/diagnostics-routes.ts
|
|
16250
|
-
import { existsSync as
|
|
16463
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4 } from "fs";
|
|
16251
16464
|
import path22 from "path";
|
|
16252
16465
|
import { Hono as Hono3 } from "hono";
|
|
16253
16466
|
function combineStatuses(statuses) {
|
|
@@ -16388,8 +16601,8 @@ function checkWorkspace() {
|
|
|
16388
16601
|
return {
|
|
16389
16602
|
id: "workspace",
|
|
16390
16603
|
label: "Workspace",
|
|
16391
|
-
status:
|
|
16392
|
-
summary:
|
|
16604
|
+
status: existsSync8(cwd) ? "ok" : "error",
|
|
16605
|
+
summary: existsSync8(cwd) ? `Workspace is accessible: ${cwd}` : `Workspace is missing: ${cwd}`,
|
|
16393
16606
|
details: []
|
|
16394
16607
|
};
|
|
16395
16608
|
}
|
|
@@ -16529,7 +16742,7 @@ async function buildConnectivityPayload() {
|
|
|
16529
16742
|
httpsProxy: Boolean(Bun.env.HTTPS_PROXY ?? Bun.env.https_proxy),
|
|
16530
16743
|
httpProxy: Boolean(Bun.env.HTTP_PROXY ?? Bun.env.http_proxy),
|
|
16531
16744
|
noProxy: Boolean(Bun.env.NO_PROXY ?? Bun.env.no_proxy),
|
|
16532
|
-
extraCaCerts: Boolean(Bun.env.NODE_EXTRA_CA_CERTS)
|
|
16745
|
+
extraCaCerts: Boolean(Bun.env.NODE_EXTRA_CA_CERTS || Bun.env.LIGHTCODE_CA_CERTS || Bun.env.SSL_CERT_FILE)
|
|
16533
16746
|
};
|
|
16534
16747
|
if (!baseUrl) {
|
|
16535
16748
|
return {
|
|
@@ -16546,7 +16759,7 @@ async function buildConnectivityPayload() {
|
|
|
16546
16759
|
const target = new URL("models", baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
16547
16760
|
const startedAt = performance.now();
|
|
16548
16761
|
try {
|
|
16549
|
-
const response = await
|
|
16762
|
+
const response = await networkFetch(target, {
|
|
16550
16763
|
signal: AbortSignal.timeout(connectivityProbeTimeoutMs)
|
|
16551
16764
|
});
|
|
16552
16765
|
return {
|
|
@@ -16601,6 +16814,7 @@ async function buildLogsTailPayload(requestedLines) {
|
|
|
16601
16814
|
}
|
|
16602
16815
|
var connectivityProbeTimeoutMs = 1e4, maxLogTailLines = 1000, diagnosticsRoutes;
|
|
16603
16816
|
var init_diagnostics_routes = __esm(() => {
|
|
16817
|
+
init_network_fetch();
|
|
16604
16818
|
init_src2();
|
|
16605
16819
|
init_src();
|
|
16606
16820
|
init_chat_store();
|
|
@@ -16689,7 +16903,7 @@ var init_root_routes = __esm(() => {
|
|
|
16689
16903
|
});
|
|
16690
16904
|
|
|
16691
16905
|
// apps/server/src/routes/web-routes.ts
|
|
16692
|
-
import { lstatSync as lstatSync3, realpathSync as
|
|
16906
|
+
import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "fs";
|
|
16693
16907
|
import { lstat as lstat4, realpath as realpath4 } from "fs/promises";
|
|
16694
16908
|
import path23 from "path";
|
|
16695
16909
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -16708,7 +16922,7 @@ function resolveWebAssetsRoot() {
|
|
|
16708
16922
|
try {
|
|
16709
16923
|
const metadata = lstatSync3(candidate);
|
|
16710
16924
|
if (metadata.isDirectory() && !metadata.isSymbolicLink()) {
|
|
16711
|
-
return
|
|
16925
|
+
return realpathSync3(candidate);
|
|
16712
16926
|
}
|
|
16713
16927
|
} catch {}
|
|
16714
16928
|
}
|
|
@@ -16799,6 +17013,320 @@ var init_web_routes = __esm(() => {
|
|
|
16799
17013
|
}).get("/app/*", serveWebAsset);
|
|
16800
17014
|
});
|
|
16801
17015
|
|
|
17016
|
+
// apps/server/src/lib/native-directory-picker.ts
|
|
17017
|
+
import path24 from "path";
|
|
17018
|
+
import { accessSync, constants as fsConstants2 } from "fs";
|
|
17019
|
+
import { homedir as homedir4 } from "os";
|
|
17020
|
+
async function readBoundedStream(stream, maximumBytes) {
|
|
17021
|
+
const reader = stream.getReader();
|
|
17022
|
+
const chunks = [];
|
|
17023
|
+
let totalBytes = 0;
|
|
17024
|
+
try {
|
|
17025
|
+
while (true) {
|
|
17026
|
+
const { done, value } = await reader.read();
|
|
17027
|
+
if (done)
|
|
17028
|
+
break;
|
|
17029
|
+
totalBytes += value.byteLength;
|
|
17030
|
+
if (totalBytes > maximumBytes) {
|
|
17031
|
+
throw new PickerOutputTooLargeError;
|
|
17032
|
+
}
|
|
17033
|
+
chunks.push(value);
|
|
17034
|
+
}
|
|
17035
|
+
} finally {
|
|
17036
|
+
reader.releaseLock();
|
|
17037
|
+
}
|
|
17038
|
+
const output = new Uint8Array(totalBytes);
|
|
17039
|
+
let offset = 0;
|
|
17040
|
+
for (const chunk of chunks) {
|
|
17041
|
+
output.set(chunk, offset);
|
|
17042
|
+
offset += chunk.byteLength;
|
|
17043
|
+
}
|
|
17044
|
+
return new TextDecoder().decode(output);
|
|
17045
|
+
}
|
|
17046
|
+
function stripToolLineEnding(value) {
|
|
17047
|
+
return value.endsWith(`\r
|
|
17048
|
+
`) ? value.slice(0, -2) : value.endsWith(`
|
|
17049
|
+
`) ? value.slice(0, -1) : value;
|
|
17050
|
+
}
|
|
17051
|
+
function assertPickerPath(value, pathApi) {
|
|
17052
|
+
const windowsRoot = pathApi === path24.win32 ? path24.win32.parse(value).root : null;
|
|
17053
|
+
const isFullyQualifiedWindowsPath = windowsRoot === null || /^[A-Za-z]:[\\/]$/.test(windowsRoot) || /^\\\\(?![?.][\\/])[^\\/]+[\\/][^\\/]+[\\/]$/.test(windowsRoot);
|
|
17054
|
+
if (value.length === 0 || value.length > 4096 || value.includes("\x00") || !pathApi.isAbsolute(value) || !isFullyQualifiedWindowsPath) {
|
|
17055
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The system folder picker returned an invalid folder.");
|
|
17056
|
+
}
|
|
17057
|
+
return value;
|
|
17058
|
+
}
|
|
17059
|
+
function parseWindowsResult(result) {
|
|
17060
|
+
const output = stripToolLineEnding(result.stdout);
|
|
17061
|
+
if (result.exitCode !== 0) {
|
|
17062
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The Windows folder picker could not be opened.");
|
|
17063
|
+
}
|
|
17064
|
+
if (output === "cancelled")
|
|
17065
|
+
return { outcome: "cancelled" };
|
|
17066
|
+
if (!output.startsWith("selected:")) {
|
|
17067
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The Windows folder picker returned an invalid response.");
|
|
17068
|
+
}
|
|
17069
|
+
const encoded = output.slice("selected:".length);
|
|
17070
|
+
if (!encoded || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded)) {
|
|
17071
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The Windows folder picker returned an invalid response.");
|
|
17072
|
+
}
|
|
17073
|
+
try {
|
|
17074
|
+
const directory = new TextDecoder("utf-8", { fatal: true }).decode(Buffer.from(encoded, "base64"));
|
|
17075
|
+
if (Buffer.from(directory, "utf8").toString("base64").replace(/=+$/, "") !== encoded.replace(/=+$/, "")) {
|
|
17076
|
+
throw new Error("invalid base64");
|
|
17077
|
+
}
|
|
17078
|
+
return {
|
|
17079
|
+
outcome: "selected",
|
|
17080
|
+
directory: assertPickerPath(directory, path24.win32)
|
|
17081
|
+
};
|
|
17082
|
+
} catch (error) {
|
|
17083
|
+
if (error instanceof NativeDirectoryPickerError)
|
|
17084
|
+
throw error;
|
|
17085
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The Windows folder picker returned an invalid response.");
|
|
17086
|
+
}
|
|
17087
|
+
}
|
|
17088
|
+
function parseMacosResult(result) {
|
|
17089
|
+
if (result.exitCode !== 0) {
|
|
17090
|
+
if (/\(-128\)|user canceled/i.test(result.stderr)) {
|
|
17091
|
+
return { outcome: "cancelled" };
|
|
17092
|
+
}
|
|
17093
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The macOS folder picker could not be opened.");
|
|
17094
|
+
}
|
|
17095
|
+
return {
|
|
17096
|
+
outcome: "selected",
|
|
17097
|
+
directory: assertPickerPath(stripToolLineEnding(result.stdout), path24.posix)
|
|
17098
|
+
};
|
|
17099
|
+
}
|
|
17100
|
+
function parseLinuxResult(result) {
|
|
17101
|
+
if (result.exitCode === 1)
|
|
17102
|
+
return { outcome: "cancelled" };
|
|
17103
|
+
if (result.exitCode !== 0) {
|
|
17104
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The Linux folder picker could not be opened.");
|
|
17105
|
+
}
|
|
17106
|
+
return {
|
|
17107
|
+
outcome: "selected",
|
|
17108
|
+
directory: assertPickerPath(stripToolLineEnding(result.stdout), path24.posix)
|
|
17109
|
+
};
|
|
17110
|
+
}
|
|
17111
|
+
function resolvePickerCommand({
|
|
17112
|
+
platform: platform4,
|
|
17113
|
+
environment,
|
|
17114
|
+
which
|
|
17115
|
+
}) {
|
|
17116
|
+
if (platform4 === "win32") {
|
|
17117
|
+
const configuredRoot = environment.SystemRoot?.trim();
|
|
17118
|
+
const systemRoot = configuredRoot && path24.win32.isAbsolute(configuredRoot) ? configuredRoot : "C:\\Windows";
|
|
17119
|
+
const candidate = path24.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
17120
|
+
const executable = which(candidate);
|
|
17121
|
+
if (!executable || !path24.win32.isAbsolute(executable))
|
|
17122
|
+
return null;
|
|
17123
|
+
return {
|
|
17124
|
+
kind: "windows",
|
|
17125
|
+
argv: [
|
|
17126
|
+
executable,
|
|
17127
|
+
"-NoLogo",
|
|
17128
|
+
"-NoProfile",
|
|
17129
|
+
"-NonInteractive",
|
|
17130
|
+
"-STA",
|
|
17131
|
+
"-EncodedCommand",
|
|
17132
|
+
Buffer.from(windowsPickerScript, "utf16le").toString("base64")
|
|
17133
|
+
]
|
|
17134
|
+
};
|
|
17135
|
+
}
|
|
17136
|
+
if (platform4 === "darwin") {
|
|
17137
|
+
const executable = which("/usr/bin/osascript");
|
|
17138
|
+
if (!executable || !path24.posix.isAbsolute(executable))
|
|
17139
|
+
return null;
|
|
17140
|
+
return {
|
|
17141
|
+
kind: "macos",
|
|
17142
|
+
argv: [executable, "-e", macosPickerScript]
|
|
17143
|
+
};
|
|
17144
|
+
}
|
|
17145
|
+
if (platform4 === "linux") {
|
|
17146
|
+
if (!environment.DISPLAY?.trim() && !environment.WAYLAND_DISPLAY?.trim()) {
|
|
17147
|
+
return null;
|
|
17148
|
+
}
|
|
17149
|
+
const desktop = environment.XDG_CURRENT_DESKTOP?.toLowerCase() ?? "";
|
|
17150
|
+
const candidates = desktop.includes("kde") ? ["kdialog", "zenity"] : ["zenity", "kdialog"];
|
|
17151
|
+
for (const command of candidates) {
|
|
17152
|
+
let executable = null;
|
|
17153
|
+
for (const directory of trustedLinuxExecutableDirectories) {
|
|
17154
|
+
const candidate = path24.posix.join(directory, command);
|
|
17155
|
+
const resolved = which(candidate);
|
|
17156
|
+
if (resolved === candidate) {
|
|
17157
|
+
executable = resolved;
|
|
17158
|
+
break;
|
|
17159
|
+
}
|
|
17160
|
+
}
|
|
17161
|
+
if (!executable)
|
|
17162
|
+
continue;
|
|
17163
|
+
if (command === "zenity") {
|
|
17164
|
+
return {
|
|
17165
|
+
kind: "zenity",
|
|
17166
|
+
argv: [
|
|
17167
|
+
executable,
|
|
17168
|
+
"--file-selection",
|
|
17169
|
+
"--directory",
|
|
17170
|
+
"--title=Choose a project folder"
|
|
17171
|
+
]
|
|
17172
|
+
};
|
|
17173
|
+
}
|
|
17174
|
+
return {
|
|
17175
|
+
kind: "kdialog",
|
|
17176
|
+
argv: [
|
|
17177
|
+
executable,
|
|
17178
|
+
"--title",
|
|
17179
|
+
"Choose a project folder",
|
|
17180
|
+
"--getexistingdirectory",
|
|
17181
|
+
path24.posix.isAbsolute(homedir4()) ? homedir4() : "/"
|
|
17182
|
+
]
|
|
17183
|
+
};
|
|
17184
|
+
}
|
|
17185
|
+
}
|
|
17186
|
+
return null;
|
|
17187
|
+
}
|
|
17188
|
+
function createNativeDirectoryPicker(options = {}) {
|
|
17189
|
+
const platform4 = options.platform ?? process.platform;
|
|
17190
|
+
const environment = options.environment ?? Bun.env;
|
|
17191
|
+
const which = options.which ?? ((candidate) => {
|
|
17192
|
+
try {
|
|
17193
|
+
accessSync(candidate, fsConstants2.X_OK);
|
|
17194
|
+
return candidate;
|
|
17195
|
+
} catch {
|
|
17196
|
+
return null;
|
|
17197
|
+
}
|
|
17198
|
+
});
|
|
17199
|
+
const runProcess = options.runProcess ?? runNativePickerProcess;
|
|
17200
|
+
let active = false;
|
|
17201
|
+
return {
|
|
17202
|
+
async pick(signal) {
|
|
17203
|
+
if (active) {
|
|
17204
|
+
throw new NativeDirectoryPickerError("native_picker_busy", "A folder picker is already open.");
|
|
17205
|
+
}
|
|
17206
|
+
if (signal?.aborted)
|
|
17207
|
+
return { outcome: "cancelled" };
|
|
17208
|
+
const command = resolvePickerCommand({ platform: platform4, environment, which });
|
|
17209
|
+
if (!command) {
|
|
17210
|
+
throw new NativeDirectoryPickerError("native_picker_unavailable", "No supported system folder picker is available.");
|
|
17211
|
+
}
|
|
17212
|
+
active = true;
|
|
17213
|
+
try {
|
|
17214
|
+
const result = await runProcess(command.argv, signal);
|
|
17215
|
+
if (signal?.aborted)
|
|
17216
|
+
return { outcome: "cancelled" };
|
|
17217
|
+
if (command.kind === "windows")
|
|
17218
|
+
return parseWindowsResult(result);
|
|
17219
|
+
if (command.kind === "macos")
|
|
17220
|
+
return parseMacosResult(result);
|
|
17221
|
+
return parseLinuxResult(result);
|
|
17222
|
+
} catch (error) {
|
|
17223
|
+
if (error instanceof NativeDirectoryPickerError)
|
|
17224
|
+
throw error;
|
|
17225
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The system folder picker could not be opened.");
|
|
17226
|
+
} finally {
|
|
17227
|
+
active = false;
|
|
17228
|
+
}
|
|
17229
|
+
}
|
|
17230
|
+
};
|
|
17231
|
+
}
|
|
17232
|
+
var maximumPickerOutputBytes, NativeDirectoryPickerError, trustedLinuxExecutableDirectories, PickerOutputTooLargeError, runNativePickerProcess = async (command, signal) => {
|
|
17233
|
+
if (signal?.aborted) {
|
|
17234
|
+
return { exitCode: 1, stdout: "", stderr: "" };
|
|
17235
|
+
}
|
|
17236
|
+
const child = Bun.spawn([...command], {
|
|
17237
|
+
stdin: "ignore",
|
|
17238
|
+
stdout: "pipe",
|
|
17239
|
+
stderr: "pipe",
|
|
17240
|
+
windowsHide: true
|
|
17241
|
+
});
|
|
17242
|
+
let aborted = false;
|
|
17243
|
+
const abort = () => {
|
|
17244
|
+
aborted = true;
|
|
17245
|
+
try {
|
|
17246
|
+
child.kill();
|
|
17247
|
+
} catch {}
|
|
17248
|
+
};
|
|
17249
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
17250
|
+
if (signal?.aborted)
|
|
17251
|
+
abort();
|
|
17252
|
+
try {
|
|
17253
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
17254
|
+
readBoundedStream(child.stdout, maximumPickerOutputBytes),
|
|
17255
|
+
readBoundedStream(child.stderr, maximumPickerOutputBytes),
|
|
17256
|
+
child.exited
|
|
17257
|
+
]);
|
|
17258
|
+
return {
|
|
17259
|
+
exitCode: aborted ? 1 : exitCode,
|
|
17260
|
+
stdout: aborted ? "" : stdout,
|
|
17261
|
+
stderr: aborted ? "" : stderr
|
|
17262
|
+
};
|
|
17263
|
+
} catch (error) {
|
|
17264
|
+
abort();
|
|
17265
|
+
if (error instanceof PickerOutputTooLargeError) {
|
|
17266
|
+
throw new NativeDirectoryPickerError("native_picker_failed", "The system folder picker returned an invalid response.");
|
|
17267
|
+
}
|
|
17268
|
+
throw error;
|
|
17269
|
+
} finally {
|
|
17270
|
+
signal?.removeEventListener("abort", abort);
|
|
17271
|
+
}
|
|
17272
|
+
}, windowsPickerScript, macosPickerScript;
|
|
17273
|
+
var init_native_directory_picker = __esm(() => {
|
|
17274
|
+
maximumPickerOutputBytes = 16 * 1024;
|
|
17275
|
+
NativeDirectoryPickerError = class NativeDirectoryPickerError extends Error {
|
|
17276
|
+
code;
|
|
17277
|
+
constructor(code, message) {
|
|
17278
|
+
super(message);
|
|
17279
|
+
this.code = code;
|
|
17280
|
+
this.name = "NativeDirectoryPickerError";
|
|
17281
|
+
}
|
|
17282
|
+
};
|
|
17283
|
+
trustedLinuxExecutableDirectories = [
|
|
17284
|
+
"/usr/bin",
|
|
17285
|
+
"/bin",
|
|
17286
|
+
"/run/current-system/sw/bin"
|
|
17287
|
+
];
|
|
17288
|
+
PickerOutputTooLargeError = class PickerOutputTooLargeError extends Error {
|
|
17289
|
+
};
|
|
17290
|
+
windowsPickerScript = String.raw`
|
|
17291
|
+
$ErrorActionPreference = 'Stop'
|
|
17292
|
+
[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false)
|
|
17293
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
17294
|
+
$dialog = New-Object System.Windows.Forms.FolderBrowserDialog
|
|
17295
|
+
$dialog.Description = 'Choose a project folder'
|
|
17296
|
+
$dialog.ShowNewFolderButton = $true
|
|
17297
|
+
$dialog.AutoUpgradeEnabled = $true
|
|
17298
|
+
$owner = New-Object System.Windows.Forms.Form
|
|
17299
|
+
$owner.TopMost = $true
|
|
17300
|
+
$owner.ShowInTaskbar = $false
|
|
17301
|
+
$owner.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
|
|
17302
|
+
$owner.Location = New-Object System.Drawing.Point(-32000, -32000)
|
|
17303
|
+
$owner.Size = New-Object System.Drawing.Size(1, 1)
|
|
17304
|
+
$owner.Opacity = 0
|
|
17305
|
+
try {
|
|
17306
|
+
$owner.Show()
|
|
17307
|
+
$owner.Activate()
|
|
17308
|
+
$result = $dialog.ShowDialog($owner)
|
|
17309
|
+
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
|
|
17310
|
+
$bytes = [Text.Encoding]::UTF8.GetBytes($dialog.SelectedPath)
|
|
17311
|
+
[Console]::Out.Write('selected:' + [Convert]::ToBase64String($bytes))
|
|
17312
|
+
} else {
|
|
17313
|
+
[Console]::Out.Write('cancelled')
|
|
17314
|
+
}
|
|
17315
|
+
} finally {
|
|
17316
|
+
$dialog.Dispose()
|
|
17317
|
+
$owner.Dispose()
|
|
17318
|
+
}
|
|
17319
|
+
`;
|
|
17320
|
+
macosPickerScript = String.raw`
|
|
17321
|
+
try
|
|
17322
|
+
set chosenFolder to choose folder with prompt "Choose a project folder"
|
|
17323
|
+
return POSIX path of chosenFolder
|
|
17324
|
+
on error number -128
|
|
17325
|
+
error number -128
|
|
17326
|
+
end try
|
|
17327
|
+
`;
|
|
17328
|
+
});
|
|
17329
|
+
|
|
16802
17330
|
// apps/server/src/routes/workspace-routes.ts
|
|
16803
17331
|
import { zValidator as zValidator3 } from "@hono/zod-validator";
|
|
16804
17332
|
import {
|
|
@@ -16807,12 +17335,17 @@ import {
|
|
|
16807
17335
|
randomBytes,
|
|
16808
17336
|
timingSafeEqual as timingSafeEqual2
|
|
16809
17337
|
} from "crypto";
|
|
16810
|
-
import { constants as
|
|
16811
|
-
import { homedir as
|
|
16812
|
-
import
|
|
17338
|
+
import { constants as fsConstants3, promises as fs8 } from "fs";
|
|
17339
|
+
import { homedir as homedir5 } from "os";
|
|
17340
|
+
import path25 from "path";
|
|
16813
17341
|
import { Hono as Hono7 } from "hono";
|
|
16814
17342
|
function pathImplementation(platform4) {
|
|
16815
|
-
return platform4 === "win32" ?
|
|
17343
|
+
return platform4 === "win32" ? path25.win32 : path25.posix;
|
|
17344
|
+
}
|
|
17345
|
+
function isFilesystemRootPath(candidate, platform4 = process.platform) {
|
|
17346
|
+
const pathApi = pathImplementation(platform4);
|
|
17347
|
+
const normalized = pathApi.normalize(candidate);
|
|
17348
|
+
return normalized === pathApi.parse(normalized).root;
|
|
16816
17349
|
}
|
|
16817
17350
|
function normalizeKnownFolderCandidate(candidate, platform4) {
|
|
16818
17351
|
if (candidate.includes("\x00")) {
|
|
@@ -16823,7 +17356,7 @@ function normalizeKnownFolderCandidate(candidate, platform4) {
|
|
|
16823
17356
|
return null;
|
|
16824
17357
|
}
|
|
16825
17358
|
const normalized = pathApi.normalize(candidate);
|
|
16826
|
-
if (normalized
|
|
17359
|
+
if (isFilesystemRootPath(normalized, platform4)) {
|
|
16827
17360
|
return null;
|
|
16828
17361
|
}
|
|
16829
17362
|
return normalized;
|
|
@@ -16841,10 +17374,10 @@ async function probeDirectory(candidate) {
|
|
|
16841
17374
|
}
|
|
16842
17375
|
}
|
|
16843
17376
|
async function readSmallUserDirsConfiguration(filePath) {
|
|
16844
|
-
const noFollowFlag = typeof
|
|
17377
|
+
const noFollowFlag = typeof fsConstants3.O_NOFOLLOW === "number" ? fsConstants3.O_NOFOLLOW : 0;
|
|
16845
17378
|
let handle;
|
|
16846
17379
|
try {
|
|
16847
|
-
handle = await fs8.open(filePath,
|
|
17380
|
+
handle = await fs8.open(filePath, fsConstants3.O_RDONLY | noFollowFlag);
|
|
16848
17381
|
const metadata = await handle.stat();
|
|
16849
17382
|
if (!metadata.isFile() || metadata.size <= 0 || metadata.size > maximumUserDirsConfigurationBytes) {
|
|
16850
17383
|
return null;
|
|
@@ -16865,8 +17398,8 @@ async function resolveWindowsKnownFolder(environment, folder) {
|
|
|
16865
17398
|
if (!windowsRoot) {
|
|
16866
17399
|
return null;
|
|
16867
17400
|
}
|
|
16868
|
-
const systemDirectory =
|
|
16869
|
-
const executable =
|
|
17401
|
+
const systemDirectory = path25.win32.join(windowsRoot, "System32");
|
|
17402
|
+
const executable = path25.win32.join(systemDirectory, "WindowsPowerShell", "v1.0", "powershell.exe");
|
|
16870
17403
|
const folderExpression = folder === "desktop" ? "[Environment]::GetFolderPath([Environment+SpecialFolder]::DesktopDirectory)" : folder === "documents" ? "[Environment]::GetFolderPath([Environment+SpecialFolder]::MyDocuments)" : "[Environment]::ExpandEnvironmentVariables([string](Get-ItemProperty -LiteralPath 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders' -Name '{374DE290-123F-4565-9164-39C4925E467B}' -ErrorAction Stop).'{374DE290-123F-4565-9164-39C4925E467B}')";
|
|
16871
17404
|
const child = Bun.spawn([
|
|
16872
17405
|
executable,
|
|
@@ -16925,15 +17458,15 @@ function parseXdgUserDirectory(contents, homeDirectory, variableName) {
|
|
|
16925
17458
|
return null;
|
|
16926
17459
|
}
|
|
16927
17460
|
if (configured.startsWith("$HOME/")) {
|
|
16928
|
-
return
|
|
17461
|
+
return path25.posix.resolve(homeDirectory, configured.slice(6));
|
|
16929
17462
|
}
|
|
16930
17463
|
if (configured.startsWith("${HOME}/")) {
|
|
16931
|
-
return
|
|
17464
|
+
return path25.posix.resolve(homeDirectory, configured.slice(8));
|
|
16932
17465
|
}
|
|
16933
17466
|
if (configured.includes("$")) {
|
|
16934
17467
|
return null;
|
|
16935
17468
|
}
|
|
16936
|
-
return
|
|
17469
|
+
return path25.posix.isAbsolute(configured) ? path25.posix.normalize(configured) : null;
|
|
16937
17470
|
}
|
|
16938
17471
|
return null;
|
|
16939
17472
|
}
|
|
@@ -16963,7 +17496,7 @@ async function resolveDesktopDirectoryPath(options = {}) {
|
|
|
16963
17496
|
const platform4 = options.platform ?? process.platform;
|
|
16964
17497
|
const pathApi = pathImplementation(platform4);
|
|
16965
17498
|
const environment = options.environment ?? Bun.env;
|
|
16966
|
-
const homeDirectory = pathApi.normalize(options.homeDirectory ??
|
|
17499
|
+
const homeDirectory = pathApi.normalize(options.homeDirectory ?? homedir5());
|
|
16967
17500
|
const explicit = environment.LIGHTCODE_DESKTOP_PATH?.trim();
|
|
16968
17501
|
if (explicit) {
|
|
16969
17502
|
const normalized = normalizeKnownFolderCandidate(explicit, platform4);
|
|
@@ -16987,17 +17520,17 @@ async function resolveDesktopDirectoryPath(options = {}) {
|
|
|
16987
17520
|
return [];
|
|
16988
17521
|
}
|
|
16989
17522
|
return [
|
|
16990
|
-
index === 0 ? trimmed :
|
|
17523
|
+
index === 0 ? trimmed : path25.win32.join(trimmed, "Desktop")
|
|
16991
17524
|
];
|
|
16992
17525
|
});
|
|
16993
|
-
candidates.push(
|
|
16994
|
-
return await firstUsableKnownFolder(candidates, platform4, probe) ??
|
|
17526
|
+
candidates.push(path25.win32.join(userProfile, "Desktop"));
|
|
17527
|
+
return await firstUsableKnownFolder(candidates, platform4, probe) ?? path25.win32.join(homeDirectory, "Desktop");
|
|
16995
17528
|
}
|
|
16996
17529
|
if (platform4 === "linux") {
|
|
16997
17530
|
const configHome = environment.XDG_CONFIG_HOME?.trim();
|
|
16998
|
-
const safeConfigHome = configHome &&
|
|
17531
|
+
const safeConfigHome = configHome && path25.posix.isAbsolute(configHome) ? path25.posix.normalize(configHome) : path25.posix.join(homeDirectory, ".config");
|
|
16999
17532
|
const readConfiguration = options.readUserDirsConfiguration ?? readSmallUserDirsConfiguration;
|
|
17000
|
-
const contents = await readConfiguration(
|
|
17533
|
+
const contents = await readConfiguration(path25.posix.join(safeConfigHome, "user-dirs.dirs"));
|
|
17001
17534
|
const configured = contents ? parseXdgUserDirectory(contents, homeDirectory, "XDG_DESKTOP_DIR") : null;
|
|
17002
17535
|
if (configured) {
|
|
17003
17536
|
const selected = await firstUsableKnownFolder([configured], platform4, probe);
|
|
@@ -17012,7 +17545,7 @@ async function resolveUserDirectoryPath(folder, options) {
|
|
|
17012
17545
|
const platform4 = options.platform ?? process.platform;
|
|
17013
17546
|
const pathApi = pathImplementation(platform4);
|
|
17014
17547
|
const environment = options.environment ?? Bun.env;
|
|
17015
|
-
const homeDirectory = pathApi.normalize(options.homeDirectory ??
|
|
17548
|
+
const homeDirectory = pathApi.normalize(options.homeDirectory ?? homedir5());
|
|
17016
17549
|
const displayName = folder === "documents" ? "Documents" : "Downloads";
|
|
17017
17550
|
const overrideName = folder === "documents" ? "LIGHTCODE_DOCUMENTS_PATH" : "LIGHTCODE_DOWNLOADS_PATH";
|
|
17018
17551
|
const explicit = environment[overrideName]?.trim();
|
|
@@ -17034,17 +17567,17 @@ async function resolveUserDirectoryPath(folder, options) {
|
|
|
17034
17567
|
];
|
|
17035
17568
|
const candidates = [
|
|
17036
17569
|
knownFolder,
|
|
17037
|
-
...cloudRoots.map((root) => root?.trim() ?
|
|
17038
|
-
|
|
17039
|
-
|
|
17570
|
+
...cloudRoots.map((root) => root?.trim() ? path25.win32.join(root.trim(), displayName) : null),
|
|
17571
|
+
path25.win32.join(userProfile, displayName),
|
|
17572
|
+
path25.win32.join(homeDirectory, displayName)
|
|
17040
17573
|
];
|
|
17041
|
-
return await firstUsableKnownFolder(candidates, platform4, probe) ??
|
|
17574
|
+
return await firstUsableKnownFolder(candidates, platform4, probe) ?? path25.win32.join(homeDirectory, displayName);
|
|
17042
17575
|
}
|
|
17043
17576
|
if (platform4 === "linux") {
|
|
17044
17577
|
const configHome = environment.XDG_CONFIG_HOME?.trim();
|
|
17045
|
-
const safeConfigHome = configHome &&
|
|
17578
|
+
const safeConfigHome = configHome && path25.posix.isAbsolute(configHome) ? path25.posix.normalize(configHome) : path25.posix.join(homeDirectory, ".config");
|
|
17046
17579
|
const readConfiguration = options.readUserDirsConfiguration ?? readSmallUserDirsConfiguration;
|
|
17047
|
-
const contents = await readConfiguration(
|
|
17580
|
+
const contents = await readConfiguration(path25.posix.join(safeConfigHome, "user-dirs.dirs"));
|
|
17048
17581
|
const configured = contents ? parseXdgUserDirectory(contents, homeDirectory, folder === "documents" ? "XDG_DOCUMENTS_DIR" : "XDG_DOWNLOAD_DIR") : null;
|
|
17049
17582
|
const selected = await firstUsableKnownFolder([configured], platform4, probe);
|
|
17050
17583
|
if (selected) {
|
|
@@ -17063,7 +17596,7 @@ async function resolveProjectsDirectoryPath(options = {}) {
|
|
|
17063
17596
|
const platform4 = options.platform ?? process.platform;
|
|
17064
17597
|
const pathApi = pathImplementation(platform4);
|
|
17065
17598
|
const environment = options.environment ?? Bun.env;
|
|
17066
|
-
const homeDirectory = pathApi.normalize(options.homeDirectory ??
|
|
17599
|
+
const homeDirectory = pathApi.normalize(options.homeDirectory ?? homedir5());
|
|
17067
17600
|
const explicit = environment.LIGHTCODE_PROJECTS_PATH?.trim();
|
|
17068
17601
|
if (explicit) {
|
|
17069
17602
|
const normalized = normalizeKnownFolderCandidate(explicit, platform4);
|
|
@@ -17114,11 +17647,23 @@ function mapFilesystemError(error) {
|
|
|
17114
17647
|
}
|
|
17115
17648
|
return new WorkspaceRouteError("workspace_unavailable", "Unable to access the selected workspace.", 500, true);
|
|
17116
17649
|
}
|
|
17650
|
+
function mapNativePickerError(error) {
|
|
17651
|
+
if (!(error instanceof NativeDirectoryPickerError)) {
|
|
17652
|
+
return new WorkspaceRouteError("native_picker_failed", "The system folder picker could not be opened.", 500, true);
|
|
17653
|
+
}
|
|
17654
|
+
if (error.code === "native_picker_busy") {
|
|
17655
|
+
return new WorkspaceRouteError(error.code, "A folder picker is already open.", 409, true);
|
|
17656
|
+
}
|
|
17657
|
+
if (error.code === "native_picker_unavailable") {
|
|
17658
|
+
return new WorkspaceRouteError(error.code, "No supported system folder picker is available.", 503, false);
|
|
17659
|
+
}
|
|
17660
|
+
return new WorkspaceRouteError(error.code, "The system folder picker could not be opened.", 500, true);
|
|
17661
|
+
}
|
|
17117
17662
|
function workspaceErrorResponse(c, error) {
|
|
17118
17663
|
const mapped = error instanceof WorkspaceRouteError ? error : mapFilesystemError(error);
|
|
17119
17664
|
if (mapped.status === 500) {
|
|
17120
17665
|
logger13.error("workspace_request_failed", {
|
|
17121
|
-
error: getErrorMessage(
|
|
17666
|
+
error: getErrorMessage(mapped)
|
|
17122
17667
|
});
|
|
17123
17668
|
}
|
|
17124
17669
|
return c.json({
|
|
@@ -17144,13 +17689,13 @@ function identitiesMatch(left, right) {
|
|
|
17144
17689
|
return left.device === right.device && left.inode === right.inode;
|
|
17145
17690
|
}
|
|
17146
17691
|
function isContainedPath2(root, candidate) {
|
|
17147
|
-
const relative =
|
|
17148
|
-
return relative === "" || relative !== ".." && !relative.startsWith(`..${
|
|
17692
|
+
const relative = path25.relative(root, candidate);
|
|
17693
|
+
return relative === "" || relative !== ".." && !relative.startsWith(`..${path25.sep}`) && !path25.isAbsolute(relative);
|
|
17149
17694
|
}
|
|
17150
17695
|
async function resolveKnownDirectory(directory) {
|
|
17151
17696
|
try {
|
|
17152
|
-
const root = await fs8.realpath(
|
|
17153
|
-
if (
|
|
17697
|
+
const root = await fs8.realpath(path25.resolve(directory));
|
|
17698
|
+
if (isFilesystemRootPath(root)) {
|
|
17154
17699
|
throw new WorkspaceRouteError("workspace_unavailable", "A filesystem root cannot be opened as a workspace location.", 500, false);
|
|
17155
17700
|
}
|
|
17156
17701
|
const stats = await fs8.stat(root, { bigint: true });
|
|
@@ -17199,7 +17744,7 @@ async function symlinkFailure(root, candidate, locationName) {
|
|
|
17199
17744
|
async function resolveDirectoryFromSegments(root, segments, locationName) {
|
|
17200
17745
|
let current = root;
|
|
17201
17746
|
for (const segment of segments) {
|
|
17202
|
-
const candidate =
|
|
17747
|
+
const candidate = path25.join(current, segment);
|
|
17203
17748
|
if (!isContainedPath2(root, candidate)) {
|
|
17204
17749
|
throw new WorkspaceRouteError("workspace_symlink_escape", `The requested path is outside the allowed ${locationName} location.`, 403, false);
|
|
17205
17750
|
}
|
|
@@ -17302,7 +17847,7 @@ function decodeCursor(secret, cursor, binding) {
|
|
|
17302
17847
|
}
|
|
17303
17848
|
}
|
|
17304
17849
|
async function describeEntry(root, directory, name) {
|
|
17305
|
-
const candidate =
|
|
17850
|
+
const candidate = path25.join(directory, name);
|
|
17306
17851
|
try {
|
|
17307
17852
|
const stats = await fs8.lstat(candidate);
|
|
17308
17853
|
if (stats.isSymbolicLink()) {
|
|
@@ -17326,7 +17871,7 @@ async function describeEntry(root, directory, name) {
|
|
|
17326
17871
|
}
|
|
17327
17872
|
}
|
|
17328
17873
|
const kind = stats.isDirectory() ? "directory" : stats.isFile() ? "file" : "other";
|
|
17329
|
-
const requiredAccess = stats.isDirectory() ?
|
|
17874
|
+
const requiredAccess = stats.isDirectory() ? fsConstants3.R_OK | fsConstants3.X_OK : fsConstants3.R_OK;
|
|
17330
17875
|
const readable = await fs8.access(candidate, requiredAccess).then(() => true).catch(() => false);
|
|
17331
17876
|
return {
|
|
17332
17877
|
name,
|
|
@@ -17382,7 +17927,7 @@ function createWorkspaceRoutes(options = {}) {
|
|
|
17382
17927
|
return normalized;
|
|
17383
17928
|
} : () => resolveDesktopDirectoryPath());
|
|
17384
17929
|
const desktopPathLabel = options.desktopPathLabel ?? "Desktop";
|
|
17385
|
-
const defaultHomePath = async () =>
|
|
17930
|
+
const defaultHomePath = async () => homedir5();
|
|
17386
17931
|
const defaultDocumentsPath = () => resolveDocumentsDirectoryPath();
|
|
17387
17932
|
const defaultDownloadsPath = () => resolveDownloadsDirectoryPath();
|
|
17388
17933
|
const definitions = [
|
|
@@ -17424,6 +17969,8 @@ function createWorkspaceRoutes(options = {}) {
|
|
|
17424
17969
|
];
|
|
17425
17970
|
const definitionsById = new Map(definitions.map((definition) => [definition.id, definition]));
|
|
17426
17971
|
const createSession = options.createSession ?? createChatSession;
|
|
17972
|
+
const nativeDirectoryPicker = options.nativeDirectoryPicker ?? createNativeDirectoryPicker();
|
|
17973
|
+
const authorizeNativePickerRequest = options.authorizeNativePickerRequest ?? isAuthenticatedWebRequest;
|
|
17427
17974
|
const cursorSecret = randomBytes(32);
|
|
17428
17975
|
const browserCapabilities = new Map;
|
|
17429
17976
|
const workspaceGrants = new Map;
|
|
@@ -17442,7 +17989,70 @@ function createWorkspaceRoutes(options = {}) {
|
|
|
17442
17989
|
}
|
|
17443
17990
|
return grant;
|
|
17444
17991
|
};
|
|
17445
|
-
|
|
17992
|
+
const storeWorkspaceGrant = async ({
|
|
17993
|
+
root,
|
|
17994
|
+
identity,
|
|
17995
|
+
name,
|
|
17996
|
+
pathLabel
|
|
17997
|
+
}) => {
|
|
17998
|
+
await fs8.access(root, fsConstants3.R_OK | fsConstants3.X_OK);
|
|
17999
|
+
const createdAt = new Date(now()).toISOString();
|
|
18000
|
+
const id = crypto.randomUUID();
|
|
18001
|
+
const grant = {
|
|
18002
|
+
id,
|
|
18003
|
+
name,
|
|
18004
|
+
pathLabel,
|
|
18005
|
+
createdAt,
|
|
18006
|
+
root,
|
|
18007
|
+
identity
|
|
18008
|
+
};
|
|
18009
|
+
workspaceGrants.set(id, grant);
|
|
18010
|
+
trimOldestEntries(workspaceGrants, maximumWorkspaceGrants);
|
|
18011
|
+
try {
|
|
18012
|
+
await assertRootIdentity(grant);
|
|
18013
|
+
} catch (error) {
|
|
18014
|
+
workspaceGrants.delete(id);
|
|
18015
|
+
throw error;
|
|
18016
|
+
}
|
|
18017
|
+
return workspaceGrantSchema.parse({ id, name, pathLabel, createdAt });
|
|
18018
|
+
};
|
|
18019
|
+
return new Hono7().post("/picker/open", zValidator3("json", workspaceNativePickerRequestSchema, (result, c) => {
|
|
18020
|
+
if (!result.success) {
|
|
18021
|
+
return invalidRequestResponse(c);
|
|
18022
|
+
}
|
|
18023
|
+
}), async (c) => {
|
|
18024
|
+
if (!authorizeNativePickerRequest(c.req.raw)) {
|
|
18025
|
+
return c.json({
|
|
18026
|
+
error: "The system folder picker is available only to an authenticated Lightcode web session.",
|
|
18027
|
+
code: "web_browser_required"
|
|
18028
|
+
}, 403);
|
|
18029
|
+
}
|
|
18030
|
+
try {
|
|
18031
|
+
let picked;
|
|
18032
|
+
try {
|
|
18033
|
+
picked = await nativeDirectoryPicker.pick(c.req.raw.signal);
|
|
18034
|
+
} catch (error) {
|
|
18035
|
+
throw mapNativePickerError(error);
|
|
18036
|
+
}
|
|
18037
|
+
if (picked.outcome === "cancelled") {
|
|
18038
|
+
return c.json(workspaceNativePickerResponseSchema.parse({
|
|
18039
|
+
outcome: "cancelled"
|
|
18040
|
+
}), 200);
|
|
18041
|
+
}
|
|
18042
|
+
const directory = await resolveKnownDirectory(picked.directory);
|
|
18043
|
+
const workspace = await storeWorkspaceGrant({
|
|
18044
|
+
...directory,
|
|
18045
|
+
name: path25.basename(directory.root),
|
|
18046
|
+
pathLabel: directory.root
|
|
18047
|
+
});
|
|
18048
|
+
return c.json(workspaceNativePickerResponseSchema.parse({
|
|
18049
|
+
outcome: "selected",
|
|
18050
|
+
workspace
|
|
18051
|
+
}), 201);
|
|
18052
|
+
} catch (error) {
|
|
18053
|
+
return workspaceErrorResponse(c, error);
|
|
18054
|
+
}
|
|
18055
|
+
}).get("/locations", (c) => c.json(workspaceLocationsResponseSchema.parse({
|
|
17446
18056
|
locations: definitions.map((definition) => knownLocation(definition, "unprobed"))
|
|
17447
18057
|
}))).post("/browser/open", zValidator3("json", workspaceBrowserOpenRequestSchema, (result, c) => {
|
|
17448
18058
|
if (!result.success) {
|
|
@@ -17578,37 +18188,19 @@ function createWorkspaceRoutes(options = {}) {
|
|
|
17578
18188
|
operation: "select",
|
|
17579
18189
|
directory: directory.path
|
|
17580
18190
|
});
|
|
17581
|
-
await fs8.access(directory.path, fsConstants2.R_OK | fsConstants2.X_OK);
|
|
17582
|
-
const createdAt = new Date(now()).toISOString();
|
|
17583
|
-
const id = crypto.randomUUID();
|
|
17584
18191
|
const name = segments.at(-1) ?? capability2.rootName;
|
|
17585
18192
|
const pathLabel = [
|
|
17586
18193
|
capability2.location.pathLabel,
|
|
17587
18194
|
...segments
|
|
17588
18195
|
].join("/");
|
|
17589
|
-
const
|
|
17590
|
-
id,
|
|
17591
|
-
name,
|
|
17592
|
-
pathLabel,
|
|
17593
|
-
createdAt,
|
|
18196
|
+
const workspace = await storeWorkspaceGrant({
|
|
17594
18197
|
root: directory.path,
|
|
17595
|
-
identity: directory.identity
|
|
17596
|
-
|
|
17597
|
-
|
|
17598
|
-
|
|
17599
|
-
try {
|
|
17600
|
-
await assertRootIdentity(grant);
|
|
17601
|
-
} catch (error) {
|
|
17602
|
-
workspaceGrants.delete(id);
|
|
17603
|
-
throw error;
|
|
17604
|
-
}
|
|
18198
|
+
identity: directory.identity,
|
|
18199
|
+
name,
|
|
18200
|
+
pathLabel
|
|
18201
|
+
});
|
|
17605
18202
|
return c.json(workspaceBrowserSelectResponseSchema.parse({
|
|
17606
|
-
workspace
|
|
17607
|
-
id,
|
|
17608
|
-
name,
|
|
17609
|
-
pathLabel,
|
|
17610
|
-
createdAt
|
|
17611
|
-
})
|
|
18203
|
+
workspace
|
|
17612
18204
|
}), 201);
|
|
17613
18205
|
} catch (error) {
|
|
17614
18206
|
return workspaceErrorResponse(c, error);
|
|
@@ -17646,6 +18238,8 @@ var init_workspace_routes = __esm(() => {
|
|
|
17646
18238
|
init_src();
|
|
17647
18239
|
init_chat_store();
|
|
17648
18240
|
init_runtime_config();
|
|
18241
|
+
init_native_directory_picker();
|
|
18242
|
+
init_web_auth();
|
|
17649
18243
|
logger13 = createLogger("workspace-routes");
|
|
17650
18244
|
defaultBrowserCapabilityTtlMs = 10 * 60 * 1000;
|
|
17651
18245
|
maximumUserDirsConfigurationBytes = 16 * 1024;
|