offsite 0.0.73 → 0.0.75
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/apps/client/dist/assets/{XIcon-DL0NnGXV.js → XIcon-B7qo7ktZ.js} +1 -1
- package/apps/client/dist/assets/{context-menu-BfvCZuoZ.js → context-menu-DtDt9J-Y.js} +3 -3
- package/apps/client/dist/assets/{diff-panel-CLdhUPhz.js → diff-panel-CV6uu6yW.js} +1 -1
- package/apps/client/dist/assets/{editor-dialog-B0L0Qv3X.js → editor-dialog-Ba0-LsB-.js} +1 -1
- package/apps/client/dist/assets/{image-viewer-da331qFf.js → image-viewer-BSrwc-Uw.js} +1 -1
- package/apps/client/dist/assets/index-BBQhJD8u.js +72 -0
- package/apps/client/dist/assets/index-BSXRfufh.css +2 -0
- package/apps/client/dist/assets/{preview-dialog-f6zcwrYq.js → preview-dialog-BXE1icd3.js} +1 -1
- package/apps/client/dist/assets/{video-viewer-BYejPn-Z.js → video-viewer-BgTM-Xa8.js} +1 -1
- package/apps/client/dist/index.html +6 -6
- package/apps/client/dist/manifest.webmanifest +1 -1
- package/apps/client/dist/sw.js +1 -1
- package/apps/server/dist/main.mjs +239 -72
- package/apps/server/dist/main.mjs.map +1 -1
- package/package.json +1 -1
- package/apps/client/dist/assets/index-DXGWYNwY.css +0 -2
- package/apps/client/dist/assets/index-_IWPtK9J.js +0 -73
|
@@ -3147,6 +3147,31 @@ function checkInProject(root, full, file) {
|
|
|
3147
3147
|
const relative = path.relative(root, full);
|
|
3148
3148
|
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) throw new Error(`${file} is outside the project`);
|
|
3149
3149
|
}
|
|
3150
|
+
function serveMedia(token, request, response) {
|
|
3151
|
+
if (request.method !== "GET") {
|
|
3152
|
+
response.statusCode = 405;
|
|
3153
|
+
response.end("use GET");
|
|
3154
|
+
return;
|
|
3155
|
+
}
|
|
3156
|
+
const link = findMediaLink(token);
|
|
3157
|
+
if (link === null) {
|
|
3158
|
+
response.statusCode = 404;
|
|
3159
|
+
response.end("This media link expired");
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
const stats = statSync(link.file, { throwIfNoEntry: false });
|
|
3163
|
+
if (stats === void 0 || !stats.isFile()) {
|
|
3164
|
+
response.statusCode = 404;
|
|
3165
|
+
response.end("not found");
|
|
3166
|
+
return;
|
|
3167
|
+
}
|
|
3168
|
+
response.setHeader("access-control-allow-origin", "*");
|
|
3169
|
+
response.setHeader("content-type", link.mediaType);
|
|
3170
|
+
response.setHeader("cache-control", "private, max-age=3600");
|
|
3171
|
+
response.setHeader("content-security-policy", "sandbox");
|
|
3172
|
+
response.setHeader("x-content-type-options", "nosniff");
|
|
3173
|
+
streamFile(link.file, stats.size, request, response);
|
|
3174
|
+
}
|
|
3150
3175
|
// src/services/generate-text.ts
|
|
3151
3176
|
async function generateText(setting, cwd, instructions, prompt) {
|
|
3152
3177
|
const settings = readConfig()[setting];
|
|
@@ -7599,58 +7624,139 @@ function send(connection, event) {
|
|
|
7599
7624
|
event
|
|
7600
7625
|
});
|
|
7601
7626
|
}
|
|
7627
|
+
// ../core/src/app-icons.ts
|
|
7628
|
+
const appIcons = [
|
|
7629
|
+
{
|
|
7630
|
+
id: "original",
|
|
7631
|
+
name: "Original",
|
|
7632
|
+
scale: 1,
|
|
7633
|
+
tile: null
|
|
7634
|
+
},
|
|
7635
|
+
{
|
|
7636
|
+
id: "small",
|
|
7637
|
+
name: "Small",
|
|
7638
|
+
scale: .7,
|
|
7639
|
+
tile: null
|
|
7640
|
+
},
|
|
7641
|
+
{
|
|
7642
|
+
id: "dark",
|
|
7643
|
+
name: "Dark",
|
|
7644
|
+
scale: .7,
|
|
7645
|
+
tile: {
|
|
7646
|
+
color: "#0a0a0a",
|
|
7647
|
+
shape: "rounded"
|
|
7648
|
+
}
|
|
7649
|
+
},
|
|
7650
|
+
{
|
|
7651
|
+
id: "light",
|
|
7652
|
+
name: "Light",
|
|
7653
|
+
scale: .7,
|
|
7654
|
+
tile: {
|
|
7655
|
+
color: "#ffffff",
|
|
7656
|
+
shape: "rounded"
|
|
7657
|
+
}
|
|
7658
|
+
},
|
|
7659
|
+
{
|
|
7660
|
+
id: "dark-circle",
|
|
7661
|
+
name: "Dark circle",
|
|
7662
|
+
scale: .62,
|
|
7663
|
+
tile: {
|
|
7664
|
+
color: "#0a0a0a",
|
|
7665
|
+
shape: "circle"
|
|
7666
|
+
}
|
|
7667
|
+
},
|
|
7668
|
+
{
|
|
7669
|
+
id: "light-circle",
|
|
7670
|
+
name: "Light circle",
|
|
7671
|
+
scale: .62,
|
|
7672
|
+
tile: {
|
|
7673
|
+
color: "#ffffff",
|
|
7674
|
+
shape: "circle"
|
|
7675
|
+
}
|
|
7676
|
+
},
|
|
7677
|
+
{
|
|
7678
|
+
id: "dark-square",
|
|
7679
|
+
name: "Dark square",
|
|
7680
|
+
scale: .7,
|
|
7681
|
+
tile: {
|
|
7682
|
+
color: "#0a0a0a",
|
|
7683
|
+
shape: "square"
|
|
7684
|
+
}
|
|
7685
|
+
},
|
|
7686
|
+
{
|
|
7687
|
+
id: "light-square",
|
|
7688
|
+
name: "Light square",
|
|
7689
|
+
scale: .7,
|
|
7690
|
+
tile: {
|
|
7691
|
+
color: "#ffffff",
|
|
7692
|
+
shape: "square"
|
|
7693
|
+
}
|
|
7694
|
+
}
|
|
7695
|
+
];
|
|
7602
7696
|
// src/storage/state.ts
|
|
7603
|
-
const stateSchema = z.strictObject({
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7697
|
+
const stateSchema = z.strictObject({
|
|
7698
|
+
composer: z.strictObject({
|
|
7699
|
+
provider: z.enum([
|
|
7700
|
+
"claude",
|
|
7701
|
+
"codex",
|
|
7702
|
+
"opencode"
|
|
7703
|
+
]).default("claude"),
|
|
7704
|
+
claude: z.strictObject({
|
|
7705
|
+
accountId: z.string().nullable().default(null),
|
|
7706
|
+
model: z.string().nullable().default(null),
|
|
7707
|
+
effort: z.enum([
|
|
7708
|
+
"low",
|
|
7709
|
+
"medium",
|
|
7710
|
+
"high",
|
|
7711
|
+
"xhigh",
|
|
7712
|
+
"max"
|
|
7713
|
+
]).nullable().default(null),
|
|
7714
|
+
mode: z.enum([
|
|
7715
|
+
"default",
|
|
7716
|
+
"acceptEdits",
|
|
7717
|
+
"bypassPermissions",
|
|
7718
|
+
"plan",
|
|
7719
|
+
"dontAsk",
|
|
7720
|
+
"auto"
|
|
7721
|
+
]).nullable().default("bypassPermissions"),
|
|
7722
|
+
plan: z.boolean().default(false)
|
|
7723
|
+
}).prefault({}),
|
|
7724
|
+
codex: z.strictObject({
|
|
7725
|
+
accountId: z.string().nullable().default(null),
|
|
7726
|
+
model: z.string().nullable().default(null),
|
|
7727
|
+
effort: z.string().nullable().default(null),
|
|
7728
|
+
mode: z.enum([
|
|
7729
|
+
"read-only",
|
|
7730
|
+
"auto",
|
|
7731
|
+
"full-access"
|
|
7732
|
+
]).nullable().default("auto"),
|
|
7733
|
+
plan: z.boolean().default(false)
|
|
7734
|
+
}).prefault({}),
|
|
7735
|
+
opencode: z.strictObject({
|
|
7736
|
+
accountId: z.null().default(null),
|
|
7737
|
+
model: z.string().nullable().default(null),
|
|
7738
|
+
effort: z.string().nullable().default(null),
|
|
7739
|
+
mode: z.string().nullable().default(null),
|
|
7740
|
+
plan: z.boolean().default(false)
|
|
7741
|
+
}).prefault({})
|
|
7639
7742
|
}).prefault({}),
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
model: z.string().nullable().default(null),
|
|
7643
|
-
effort: z.string().nullable().default(null),
|
|
7644
|
-
mode: z.string().nullable().default(null),
|
|
7645
|
-
plan: z.boolean().default(false)
|
|
7646
|
-
}).prefault({})
|
|
7647
|
-
}).prefault({}) });
|
|
7743
|
+
appIcon: z.custom((value) => appIcons.some((icon) => icon.id === value)).default("original")
|
|
7744
|
+
});
|
|
7648
7745
|
const defaults = stateSchema.parse({});
|
|
7746
|
+
function readState() {
|
|
7747
|
+
return readSettings("state.json", stateSchema, defaults);
|
|
7748
|
+
}
|
|
7649
7749
|
function readComposer() {
|
|
7650
|
-
return
|
|
7750
|
+
return readState().composer;
|
|
7751
|
+
}
|
|
7752
|
+
function readAppIcon() {
|
|
7753
|
+
return readState().appIcon;
|
|
7651
7754
|
}
|
|
7652
7755
|
function saveComposer(value) {
|
|
7653
|
-
const result = stateSchema.safeParse({
|
|
7756
|
+
const result = stateSchema.safeParse({
|
|
7757
|
+
...readState(),
|
|
7758
|
+
composer: value
|
|
7759
|
+
});
|
|
7654
7760
|
if (!result.success) throw new Error(z.prettifyError(result.error));
|
|
7655
7761
|
writeJson("state.json", result.data);
|
|
7656
7762
|
broadcast({
|
|
@@ -7659,6 +7765,19 @@ function saveComposer(value) {
|
|
|
7659
7765
|
});
|
|
7660
7766
|
return result.data.composer;
|
|
7661
7767
|
}
|
|
7768
|
+
function saveAppIcon(value) {
|
|
7769
|
+
const result = stateSchema.safeParse({
|
|
7770
|
+
...readState(),
|
|
7771
|
+
appIcon: value
|
|
7772
|
+
});
|
|
7773
|
+
if (!result.success) throw new Error(z.prettifyError(result.error));
|
|
7774
|
+
writeJson("state.json", result.data);
|
|
7775
|
+
broadcast({
|
|
7776
|
+
type: "appIcon",
|
|
7777
|
+
appIcon: result.data.appIcon
|
|
7778
|
+
});
|
|
7779
|
+
return result.data.appIcon;
|
|
7780
|
+
}
|
|
7662
7781
|
// src/api/socket.ts
|
|
7663
7782
|
const handlers = {
|
|
7664
7783
|
ping: () => null,
|
|
@@ -7672,12 +7791,14 @@ const handlers = {
|
|
|
7672
7791
|
sessions: sessions(),
|
|
7673
7792
|
providers: providerStatuses(),
|
|
7674
7793
|
activity: activity(),
|
|
7675
|
-
terminals: terminalTabs()
|
|
7794
|
+
terminals: terminalTabs(),
|
|
7795
|
+
appIcon: readAppIcon()
|
|
7676
7796
|
};
|
|
7677
7797
|
},
|
|
7678
7798
|
"config.get": () => configInfo(),
|
|
7679
7799
|
"composer.get": () => readComposer(),
|
|
7680
7800
|
"composer.save": (params) => saveComposer(params),
|
|
7801
|
+
"appIcon.save": (params) => saveAppIcon(params),
|
|
7681
7802
|
"config.save": async (params) => {
|
|
7682
7803
|
const before = readConfig();
|
|
7683
7804
|
const saved = saveConfig(params);
|
|
@@ -9094,6 +9215,71 @@ function fail(response, status, message) {
|
|
|
9094
9215
|
response.setHeader("content-type", "text/plain; charset=utf-8");
|
|
9095
9216
|
response.end(message);
|
|
9096
9217
|
}
|
|
9218
|
+
// src/services/app-icon.ts
|
|
9219
|
+
const pngs = /* @__PURE__ */ new Map([
|
|
9220
|
+
["icon-192.png", {
|
|
9221
|
+
size: 192,
|
|
9222
|
+
maskable: false
|
|
9223
|
+
}],
|
|
9224
|
+
["icon-512.png", {
|
|
9225
|
+
size: 512,
|
|
9226
|
+
maskable: false
|
|
9227
|
+
}],
|
|
9228
|
+
["icon-maskable-512.png", {
|
|
9229
|
+
size: 512,
|
|
9230
|
+
maskable: true
|
|
9231
|
+
}]
|
|
9232
|
+
]);
|
|
9233
|
+
async function serveAppIcon(publicDir, pathname, response) {
|
|
9234
|
+
const logoPath = path.join(publicDir, "icon.svg");
|
|
9235
|
+
if (!existsSync(logoPath)) {
|
|
9236
|
+
response.statusCode = 404;
|
|
9237
|
+
response.end("web app not built; run pnpm build");
|
|
9238
|
+
return;
|
|
9239
|
+
}
|
|
9240
|
+
try {
|
|
9241
|
+
const icon = await renderAppIcon(readFileSync(logoPath, "utf8"), pathname.slice(14));
|
|
9242
|
+
if (icon === null) {
|
|
9243
|
+
response.statusCode = 404;
|
|
9244
|
+
response.end("not found");
|
|
9245
|
+
return;
|
|
9246
|
+
}
|
|
9247
|
+
response.setHeader("content-type", icon.type);
|
|
9248
|
+
response.setHeader("cache-control", "no-cache");
|
|
9249
|
+
response.end(icon.body);
|
|
9250
|
+
} catch (error) {
|
|
9251
|
+
console.warn(`could not serve the app icon: ${error}`);
|
|
9252
|
+
response.statusCode = 500;
|
|
9253
|
+
response.end("could not render the app icon");
|
|
9254
|
+
}
|
|
9255
|
+
}
|
|
9256
|
+
async function renderAppIcon(logo, file) {
|
|
9257
|
+
if (file === "icon.svg") return {
|
|
9258
|
+
type: "image/svg+xml",
|
|
9259
|
+
body: iconSvg(logo, false)
|
|
9260
|
+
};
|
|
9261
|
+
const png = pngs.get(file);
|
|
9262
|
+
if (png === void 0) return null;
|
|
9263
|
+
return {
|
|
9264
|
+
type: "image/png",
|
|
9265
|
+
body: await sharp(Buffer.from(iconSvg(logo, png.maskable))).resize(png.size, png.size).png().toBuffer()
|
|
9266
|
+
};
|
|
9267
|
+
}
|
|
9268
|
+
function iconSvg(logo, maskable) {
|
|
9269
|
+
const id = readAppIcon();
|
|
9270
|
+
const icon = appIcons.find((item) => item.id === id);
|
|
9271
|
+
if (icon === void 0) throw new Error(`unknown app icon ${id}`);
|
|
9272
|
+
const size = 512 * (maskable ? .72 : icon.scale);
|
|
9273
|
+
const offset = (512 - size) / 2;
|
|
9274
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">${tile(icon, maskable)}${logo.replace("<svg ", `<svg x="${offset}" y="${offset}" width="${size}" height="${size}" `)}</svg>`;
|
|
9275
|
+
}
|
|
9276
|
+
function tile(icon, maskable) {
|
|
9277
|
+
if (icon.tile === null) return "";
|
|
9278
|
+
if (maskable || icon.tile.shape === "square") return `<rect width="512" height="512" fill="${icon.tile.color}"/>`;
|
|
9279
|
+
if (icon.tile.shape === "rounded") return `<rect width="512" height="512" rx="112.64" fill="${icon.tile.color}"/>`;
|
|
9280
|
+
if (icon.tile.shape === "circle") return `<circle cx="256" cy="256" r="256" fill="${icon.tile.color}"/>`;
|
|
9281
|
+
throw new Error(`unknown tile shape for ${icon.id}`);
|
|
9282
|
+
}
|
|
9097
9283
|
// src/main.ts
|
|
9098
9284
|
const UNPAIR_CHECK = 5e3;
|
|
9099
9285
|
const TICKET_LIFETIME = 6e4;
|
|
@@ -9194,6 +9380,10 @@ function answerRequest(request, response) {
|
|
|
9194
9380
|
answerOpen(request, response);
|
|
9195
9381
|
return;
|
|
9196
9382
|
}
|
|
9383
|
+
if (url.pathname.startsWith("/api/app-icon/")) {
|
|
9384
|
+
serveAppIcon(publicDir, url.pathname, response);
|
|
9385
|
+
return;
|
|
9386
|
+
}
|
|
9197
9387
|
if (url.pathname.startsWith("/api/")) {
|
|
9198
9388
|
answerApi(url.pathname, request, response);
|
|
9199
9389
|
return;
|
|
@@ -9303,31 +9493,6 @@ function answerApi(pathname, request, response) {
|
|
|
9303
9493
|
response.statusCode = 404;
|
|
9304
9494
|
response.end("not found");
|
|
9305
9495
|
}
|
|
9306
|
-
function serveMedia(token, request, response) {
|
|
9307
|
-
if (request.method !== "GET") {
|
|
9308
|
-
response.statusCode = 405;
|
|
9309
|
-
response.end("use GET");
|
|
9310
|
-
return;
|
|
9311
|
-
}
|
|
9312
|
-
const link = findMediaLink(token);
|
|
9313
|
-
if (link === null) {
|
|
9314
|
-
response.statusCode = 404;
|
|
9315
|
-
response.end("This media link expired");
|
|
9316
|
-
return;
|
|
9317
|
-
}
|
|
9318
|
-
const stats = statSync(link.file, { throwIfNoEntry: false });
|
|
9319
|
-
if (stats === void 0 || !stats.isFile()) {
|
|
9320
|
-
response.statusCode = 404;
|
|
9321
|
-
response.end("not found");
|
|
9322
|
-
return;
|
|
9323
|
-
}
|
|
9324
|
-
response.setHeader("access-control-allow-origin", "*");
|
|
9325
|
-
response.setHeader("content-type", link.mediaType);
|
|
9326
|
-
response.setHeader("cache-control", "private, max-age=3600");
|
|
9327
|
-
response.setHeader("content-security-policy", "sandbox");
|
|
9328
|
-
response.setHeader("x-content-type-options", "nosniff");
|
|
9329
|
-
streamFile(link.file, stats.size, request, response);
|
|
9330
|
-
}
|
|
9331
9496
|
function serveBrowse(pathname, request, response) {
|
|
9332
9497
|
if (request.method !== "GET") {
|
|
9333
9498
|
response.statusCode = 405;
|
|
@@ -9464,6 +9629,7 @@ function serveFile(pathname, request, response) {
|
|
|
9464
9629
|
}
|
|
9465
9630
|
response.setHeader("content-type", contentTypes[path.extname(file)] ?? "application/octet-stream");
|
|
9466
9631
|
if (path.basename(file) === "index.html") {
|
|
9632
|
+
response.setHeader("cache-control", "no-cache");
|
|
9467
9633
|
let page = readFileSync(file, "utf8");
|
|
9468
9634
|
if (!args.pwa) page = page.replace(/<link rel="manifest"[^>]*>/, "");
|
|
9469
9635
|
if (args.connect !== null) page = page.replace("</head>", `<meta name="offsite-connect" content="${args.connect.join(" ")}"></head>`);
|
|
@@ -9471,6 +9637,7 @@ function serveFile(pathname, request, response) {
|
|
|
9471
9637
|
return;
|
|
9472
9638
|
}
|
|
9473
9639
|
if (file === requested && pathname.startsWith("/assets/")) response.setHeader("cache-control", "public, max-age=31536000, immutable");
|
|
9640
|
+
if (pathname === "/sw.js") response.setHeader("cache-control", "no-cache");
|
|
9474
9641
|
if (compressible.has(path.extname(file))) {
|
|
9475
9642
|
response.setHeader("vary", "accept-encoding");
|
|
9476
9643
|
if (/\bgzip\b/.test(request.headers["accept-encoding"] ?? "")) {
|