Skip to content

Commit 41f2478

Browse files
committed
chore: refresh dist and vendor bundles
1 parent b3807f3 commit 41f2478

File tree

15 files changed

+596
-106
lines changed

15 files changed

+596
-106
lines changed

runtime/generated/dist/agent-control/handlers/login.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ function getAuthStorage(session, modelRegistry) {
8383
function getModelRegistry(session, modelRegistry) {
8484
return (session.modelRegistry ?? modelRegistry);
8585
}
86+
function refreshModelRegistry(registry) {
87+
registry.refresh?.();
88+
}
8689
function getProviderStatuses(authStorage) {
8790
return PROVIDER_DEFS.map((def) => {
8891
const cred = authStorage.get(def.id);
@@ -440,6 +443,7 @@ async function handleStep2(session, authStorage, modelRegistry, registry, data)
440443
backupFile(getAuthJsonPath());
441444
authStorage.set(providerId, { type: "api_key", key: apiKey });
442445
authStorage.reload();
446+
refreshModelRegistry(registry);
443447
// Show Card 3 with models for this provider, or activate directly when only one exists.
444448
return await showCard3OrComplete(session, modelRegistry, def, providerId, name, registry);
445449
}
@@ -454,6 +458,7 @@ async function handleStep2(session, authStorage, modelRegistry, registry, data)
454458
}
455459
}
456460
authStorage.reload();
461+
refreshModelRegistry(registry);
457462
const cred = authStorage.get(providerId);
458463
if (cred?.type === "oauth") {
459464
return await showCard3OrComplete(session, modelRegistry, def, providerId, name, registry);
@@ -494,6 +499,7 @@ async function handleStep2(session, authStorage, modelRegistry, registry, data)
494499
authStorage.set(providerId, undefined);
495500
authStorage.reload();
496501
}
502+
refreshModelRegistry(registry);
497503
if (def?.isCustom) {
498504
const modelsJson = readJsonFile(getModelsJsonPath());
499505
if (modelsJson.providers?.[providerId]) {

runtime/generated/dist/agent-pool/runtime-facade.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class AgentRuntimeFacade {
3232
async getAvailableModels(chatJid) {
3333
const session = await this.options.getOrCreate(chatJid);
3434
const registry = session.modelRegistry ?? this.options.modelRegistry;
35+
registry.refresh();
3536
const available = registry.getAvailable();
3637
const models = available.map((model) => `${model.provider}/${model.id}`);
3738
const currentModel = session.model ? `${session.model.provider}/${session.model.id}` : null;

runtime/generated/dist/agent-pool/session.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const OPTIONAL_EXTENSIONS = [
3636
{ path: resolve(EXTENSIONS_DIR, "browser", "cdp-browser", "index.ts") },
3737
{ path: resolve(EXTENSIONS_DIR, "platform", "windows", "win-ui", "index.ts") },
3838
{ path: resolve(EXTENSIONS_DIR, "viewers", "office-viewer", "index.ts") },
39+
{ path: resolve(EXTENSIONS_DIR, "integrations", "office-tools", "index.ts") },
3940
{ path: resolve(EXTENSIONS_DIR, "viewers", "drawio-editor", "index.ts") },
4041
];
4142
/** Walk up from startDir looking for a node_modules that contains @mariozechner/pi-ai. */

runtime/generated/dist/channels/web/handlers/agent.js

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -709,18 +709,25 @@ export async function processChat(channel, chatJid, agentId, threadRootId) {
709709
const hasActiveClients = channel.sse.clients.size > 0;
710710
// Keep interactive web turns bounded so stalled sessions still reach a
711711
// terminal state, but do not clamp them too aggressively. A 5 minute cap
712-
// proved too short for legitimate long-running tool workflows, and 15
713-
// minutes has still been a little tight for some real sessions, so allow up
714-
// to 20 minutes here while still respecting any lower global timeout.
712+
// proved too short for legitimate long-running tool workflows, 20 minutes
713+
// has still been too tight for some real sessions, so allow up to 40
714+
// minutes here while still respecting any lower global timeout.
715715
const agentRuntimeConfig = getAgentRuntimeConfig();
716-
const INTERACTIVE_WEB_TIMEOUT_MS = Math.min(agentRuntimeConfig.timeoutMs, 20 * 60 * 1000);
716+
const INTERACTIVE_WEB_TIMEOUT_MS = Math.min(agentRuntimeConfig.timeoutMs, 40 * 60 * 1000);
717717
const timeoutMs = hasActiveClients
718718
? INTERACTIVE_WEB_TIMEOUT_MS
719719
: (agentRuntimeConfig.backgroundTimeoutMs > 0 ? agentRuntimeConfig.backgroundTimeoutMs : agentRuntimeConfig.timeoutMs);
720720
let turnCount = 0;
721721
let hadIntermediateOutput = false;
722722
let persistedIntermediateOutput = false;
723723
let intermediatePersistFailed = false;
724+
const isCompactionIntentActive = () => {
725+
const status = channel.getAgentStatus(chatJid);
726+
if (!status || typeof status !== "object")
727+
return false;
728+
const intentKey = status.intent_key ?? status.intentKey;
729+
return status.type === "intent" && intentKey === "compaction";
730+
};
724731
const publishDraftFallback = (reason) => {
725732
// Draft fallback should publish the currently visible draft for whichever
726733
// turn failed to finalize, even if earlier turns in the same session were
@@ -731,11 +738,14 @@ export async function processChat(channel, chatJid, agentId, threadRootId) {
731738
const draftText = typeof draft?.text === "string" ? draft.text.trim() : "";
732739
if (!draftText)
733740
return false;
741+
const compactionNote = isCompactionIntentActive()
742+
? "\n\nℹ️ Context compaction was in progress."
743+
: "";
734744
const suffix = reason === "timeout"
735-
? "\n\n⚠️ Response timed out before finalization."
745+
? `\n\n⚠️ Response timed out before finalization.${compactionNote}`
736746
: reason === "error"
737-
? "\n\n⚠️ Response ended with an error before finalization."
738-
: "";
747+
? `\n\n⚠️ Response ended with an error before finalization.${compactionNote}`
748+
: compactionNote;
739749
return storeAgentTurn(channel, emitter, {
740750
chatJid,
741751
text: `${draftText}${suffix}`,

runtime/generated/dist/channels/web/handlers/workspace.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ export function handleWorkspaceDelete(req) {
7777
*/
7878
export function handleWorkspaceRaw(req) {
7979
const url = new URL(req.url);
80-
const result = workspaceService.getRaw(url.searchParams.get("path"));
80+
const download = url.searchParams.get("download") === "1" || url.searchParams.get("download") === "true";
81+
const result = workspaceService.getRaw(url.searchParams.get("path"), download);
8182
if (result.status !== 200) {
8283
return new Response(result.body, {
8384
status: result.status,
@@ -91,11 +92,13 @@ export function handleWorkspaceRaw(req) {
9192
const file = result.body;
9293
const filePath = result.filePath || null;
9394
const fileSize = typeof result.size === "number" ? result.size : (typeof file?.size === "number" ? file.size : 0);
95+
const downloadFilename = String(result.filename || "download").replace(/["\\]/g, "_");
9496
const baseHeaders = {
9597
"Content-Type": contentType,
9698
"Accept-Ranges": "bytes",
9799
"X-Frame-Options": "SAMEORIGIN",
98100
"Content-Security-Policy": "default-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'",
101+
...(result.download ? { "Content-Disposition": `attachment; filename="${downloadFilename}"` } : {}),
99102
};
100103
const readRangeChunk = (start, chunkSize) => {
101104
if (!filePath || chunkSize <= 0)

runtime/generated/dist/channels/web/runtime/queued-followup-lifecycle-service.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ function toDeferredQueuedFollowupRecord(item) {
3434
}
3535
export class QueuedFollowupLifecycleService {
3636
placeholderStore;
37+
nextDeferredRowIdByChat = new Map();
3738
constructor(placeholderStore = new FollowupPlaceholderStore()) {
3839
this.placeholderStore = placeholderStore;
3940
}
@@ -148,7 +149,10 @@ export class QueuedFollowupLifecycleService {
148149
}
149150
allocateDeferredQueuedRowId(chatJid) {
150151
const queued = this.getDeferredQueuedFollowupItems(chatJid);
151-
const minRowId = queued.reduce((min, item) => (item.rowId < min ? item.rowId : min), 0);
152-
return minRowId <= -1 ? minRowId - 1 : -1;
152+
const minQueuedRowId = queued.reduce((min, item) => (item.rowId < min ? item.rowId : min), 0);
153+
const previousSeed = this.nextDeferredRowIdByChat.get(chatJid) ?? 0;
154+
const nextRowId = Math.min(minQueuedRowId - 1, previousSeed - 1, -1);
155+
this.nextDeferredRowIdByChat.set(chatJid, nextRowId);
156+
return nextRowId;
153157
}
154158
}

runtime/generated/dist/channels/web/workspace/file-service.js

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,126 @@
99
import { existsSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "fs";
1010
import { readdir } from "fs/promises";
1111
import path from "path";
12+
import { gunzipSync } from "zlib";
1213
import { Zip, ZipDeflate, ZipPassThrough } from "fflate";
1314
import { createMedia } from "../../../db.js";
1415
import { createLogger } from "../../../utils/logger.js";
1516
import { MAX_ATTACH_BYTES, MAX_EDIT_BYTES, MAX_PREVIEW_BYTES, MAX_UPLOAD_BYTES } from "./constants.js";
1617
import { contentTypeForPath, detectBinary, formatMtime, isImageFile, isTextFile } from "./file-utils.js";
1718
import { isHiddenPath, resolveWorkspacePath, shouldIgnorePath, toRelativePath } from "./paths.js";
1819
const log = createLogger("web.workspace.file-service");
20+
function parseZipEntries(buffer, maxEntries = 200) {
21+
const eocdSignature = 0x06054b50;
22+
const cdSignature = 0x02014b50;
23+
const minEocdSize = 22;
24+
const maxCommentSize = 0xffff;
25+
const searchStart = Math.max(0, buffer.length - (minEocdSize + maxCommentSize));
26+
let eocdOffset = -1;
27+
for (let offset = buffer.length - minEocdSize; offset >= searchStart; offset -= 1) {
28+
if (buffer.readUInt32LE(offset) === eocdSignature) {
29+
eocdOffset = offset;
30+
break;
31+
}
32+
}
33+
if (eocdOffset < 0) {
34+
throw new Error("ZIP end-of-central-directory record not found");
35+
}
36+
const entryCount = buffer.readUInt16LE(eocdOffset + 10);
37+
const centralDirectoryOffset = buffer.readUInt32LE(eocdOffset + 16);
38+
const entries = [];
39+
let offset = centralDirectoryOffset;
40+
let totalEntries = 0;
41+
while (offset + 46 <= buffer.length && totalEntries < entryCount) {
42+
if (buffer.readUInt32LE(offset) !== cdSignature)
43+
break;
44+
const compressedSize = buffer.readUInt32LE(offset + 20);
45+
const uncompressedSize = buffer.readUInt32LE(offset + 24);
46+
const fileNameLength = buffer.readUInt16LE(offset + 28);
47+
const extraLength = buffer.readUInt16LE(offset + 30);
48+
const commentLength = buffer.readUInt16LE(offset + 32);
49+
const externalAttrs = buffer.readUInt32LE(offset + 38);
50+
const nameStart = offset + 46;
51+
const nameEnd = nameStart + fileNameLength;
52+
if (nameEnd > buffer.length)
53+
break;
54+
const name = buffer.toString("utf8", nameStart, nameEnd);
55+
const isDirectory = name.endsWith("/") || ((externalAttrs >>> 16) & 0o170000) === 0o040000;
56+
totalEntries += 1;
57+
if (entries.length < maxEntries) {
58+
entries.push({
59+
name,
60+
compressedSize,
61+
uncompressedSize,
62+
isDirectory,
63+
});
64+
}
65+
offset = nameEnd + extraLength + commentLength;
66+
}
67+
return {
68+
entries,
69+
totalEntries,
70+
truncated: totalEntries > entries.length,
71+
};
72+
}
73+
function isTarGzPath(filePath) {
74+
const lower = filePath.toLowerCase();
75+
return lower.endsWith(".tar.gz") || lower.endsWith(".tgz");
76+
}
77+
function parseTarEntries(buffer, maxEntries = 200) {
78+
const entries = [];
79+
let offset = 0;
80+
let totalEntries = 0;
81+
while (offset + 512 <= buffer.length) {
82+
const header = buffer.subarray(offset, offset + 512);
83+
if (header.every((byte) => byte === 0))
84+
break;
85+
const rawName = header.toString("utf8", 0, 100).replace(/\0.*$/, "");
86+
const rawPrefix = header.toString("utf8", 345, 500).replace(/\0.*$/, "");
87+
const sizeOctal = header.toString("utf8", 124, 136).replace(/\0.*$/, "").trim();
88+
const typeFlag = header.toString("utf8", 156, 157) || "0";
89+
const size = sizeOctal ? parseInt(sizeOctal.replace(/\s/g, ""), 8) || 0 : 0;
90+
const name = rawPrefix ? `${rawPrefix}/${rawName}` : rawName;
91+
const isDirectory = typeFlag === "5" || name.endsWith("/");
92+
if (!name)
93+
break;
94+
totalEntries += 1;
95+
if (entries.length < maxEntries) {
96+
entries.push({
97+
name,
98+
compressedSize: null,
99+
uncompressedSize: size,
100+
isDirectory,
101+
});
102+
}
103+
offset += 512 + Math.ceil(size / 512) * 512;
104+
}
105+
return {
106+
entries,
107+
totalEntries,
108+
truncated: totalEntries > entries.length,
109+
};
110+
}
111+
function formatArchiveListing(label, relPath, stats, parsed) {
112+
const lines = [
113+
`${label}: ${relPath}`,
114+
`Entries: ${parsed.totalEntries}`,
115+
`Archive size: ${stats.size} bytes`,
116+
"",
117+
];
118+
for (const entry of parsed.entries) {
119+
const kind = entry.isDirectory ? "dir " : "file";
120+
const compressionLabel = entry.compressedSize != null && entry.compressedSize !== entry.uncompressedSize
121+
? `, ${entry.compressedSize} B compressed`
122+
: "";
123+
const sizeLabel = entry.isDirectory ? "" : ` (${entry.uncompressedSize} B${compressionLabel})`;
124+
lines.push(`${kind} ${entry.name}${sizeLabel}`);
125+
}
126+
if (parsed.truncated) {
127+
lines.push("");
128+
lines.push(`… showing first ${parsed.entries.length} entries of ${parsed.totalEntries}.`);
129+
}
130+
return lines.join("\n");
131+
}
19132
function normalizeEntryName(raw) {
20133
const name = (raw || "").trim();
21134
if (!name || name === "." || name === "..")
@@ -41,6 +154,7 @@ export class WorkspaceFileService {
41154
const relPath = toRelativePath(targetPath);
42155
const contentType = contentTypeForPath(targetPath);
43156
const isImage = isImageFile(targetPath);
157+
const ext = path.extname(targetPath).toLowerCase();
44158
if (isImage) {
45159
const rawUrl = `/workspace/raw?path=${encodeURIComponent(relPath)}`;
46160
return {
@@ -68,6 +182,39 @@ export class WorkspaceFileService {
68182
return { status: 400, body: { error: "File too large to edit" } };
69183
}
70184
const buffer = readFileSync(targetPath, { encoding: null });
185+
if (!isEditMode && (ext === ".zip" || isTarGzPath(targetPath))) {
186+
try {
187+
const isZip = ext === ".zip";
188+
const parsed = isZip ? parseZipEntries(buffer) : parseTarEntries(gunzipSync(buffer));
189+
return {
190+
status: 200,
191+
body: {
192+
path: relPath,
193+
name: path.basename(targetPath),
194+
kind: "text",
195+
content_type: contentType,
196+
size: stats.size,
197+
mtime: formatMtime(stats),
198+
text: formatArchiveListing(isZip ? "ZIP archive" : "tar.gz archive", relPath, stats, parsed),
199+
truncated: parsed.truncated,
200+
},
201+
};
202+
}
203+
catch {
204+
return {
205+
status: 200,
206+
body: {
207+
path: relPath,
208+
name: path.basename(targetPath),
209+
kind: "binary",
210+
content_type: contentType,
211+
size: stats.size,
212+
mtime: formatMtime(stats),
213+
truncated: false,
214+
},
215+
};
216+
}
217+
}
71218
const slice = buffer.subarray(0, maxBytes);
72219
const truncated = buffer.length > maxBytes;
73220
if (!isTextFile(targetPath) && detectBinary(slice)) {
@@ -113,7 +260,7 @@ export class WorkspaceFileService {
113260
return { status: 500, body: { error: "Failed to read file" } };
114261
}
115262
}
116-
getRaw(pathParam) {
263+
getRaw(pathParam, download = false) {
117264
const targetPath = resolveWorkspacePath(pathParam);
118265
if (!targetPath)
119266
return { status: 400, body: "Invalid path" };
@@ -123,7 +270,15 @@ export class WorkspaceFileService {
123270
return { status: 400, body: "Path is a directory" };
124271
const contentType = contentTypeForPath(targetPath);
125272
const file = Bun.file(targetPath);
126-
return { status: 200, body: file, contentType, filePath: targetPath, size: stats.size };
273+
return {
274+
status: 200,
275+
body: file,
276+
contentType,
277+
filePath: targetPath,
278+
size: stats.size,
279+
filename: path.basename(targetPath),
280+
download,
281+
};
127282
}
128283
catch {
129284
return { status: 404, body: "Not found" };

runtime/generated/dist/channels/web/workspace/file-utils.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export function contentTypeForPath(filePath) {
4545
return "text/tab-separated-values";
4646
case ".pdf":
4747
return "application/pdf";
48+
case ".zip":
49+
return "application/zip";
4850
case ".docx":
4951
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
5052
case ".xlsx":

runtime/generated/dist/channels/web/workspace/service.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export class WorkspaceService {
2020
getFile(pathParam, maxParam, mode) {
2121
return this.fileService.getFile(pathParam, maxParam, mode);
2222
}
23-
getRaw(pathParam) {
24-
return this.fileService.getRaw(pathParam);
23+
getRaw(pathParam, download = false) {
24+
return this.fileService.getRaw(pathParam, download);
2525
}
2626
getGitBranch(pathParam) {
2727
const branch = getWorkspaceGitBranch(pathParam);

runtime/generated/dist/core/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export const AGENT_RUNTIME_CONFIG = Object.freeze({
321321
envConfig.PICLAW_AGENT_TIMEOUT ||
322322
process.env.AGENT_TIMEOUT ||
323323
envConfig.AGENT_TIMEOUT ||
324-
"1800000", 10),
324+
"3600000", 10),
325325
backgroundTimeoutMs: parseInt(process.env.PICLAW_BACKGROUND_AGENT_TIMEOUT ||
326326
envConfig.PICLAW_BACKGROUND_AGENT_TIMEOUT ||
327327
process.env.AGENT_TIMEOUT_BACKGROUND ||

0 commit comments

Comments
 (0)