Files
cobble/src/data/app-data.ts
T
tbenandClaude Opus 5.5 f13fa863c5 Trim page props and page the conversation's messages
Bot and workspace lists in page props leave out instructions, memory and
workspace context, and carry the last message as a short preview. The
header avatar's edit form loads the bot's instructions when it opens.
The conversation renders its latest 30 messages and loads older ones as
the thread scrolls to its top.

Also: the composer shows a placeholder until its editor loads, and
`bun start` no longer builds first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 20:09:01 +01:00

427 lines
15 KiB
TypeScript

import { SiteData } from "./site-data";
export const AppData = {
HashCost: 12,
/**
* Shared with twui's `ColorSchemeSelector`, so it must stay `theme`.
*/
ThemeStorageKey: "theme",
/**
* How many of a build's files the loading page downloads at once.
*/
PrecacheConcurrency: 6,
/**
* How many more times the loading page downloads files it finds
* missing from the cache after a pass, before it gives up on them.
*/
PrecacheVerifyPasses: 2,
/**
* How long the loading page waits for a new service worker to take
* over before it reloads into the app anyway.
*/
PrecacheWorkerWaitMs: 10_000,
/**
* The loading page gives up and lets the app run from the network
* when no new file lands for this long.
*/
PrecacheStallMs: 30_000,
/**
* Prefix of the composer's unsent drafts in `localStorage`, one per
* bot and workspace.
*/
ComposerDraftStorageKey: `${SiteData["SiteSlug"]}_composer_draft`,
/**
* Prefix of the chat header's model data in `localStorage`: one catalog
* per user, and one small setting per bot and workspace.
* `HarnessCatalogCacheMs` is how long the catalog is shown before it is
* fetched again, `HarnessOverviewCacheMs` the setting.
*/
HarnessCacheStorageKey: `${SiteData["SiteSlug"]}_harness_cache`,
HarnessCatalogCacheMs: 60 * 60 * 1000,
/**
* The per-conversation key an older version wrote. Removed on logout
* and by `clearHarnessCache`.
*/
LegacyHarnessOverviewStorageKey: `${SiteData["SiteSlug"]}_harness_overview`,
HarnessOverviewCacheMs: 10 * 60 * 1000,
ServerHealthMessage: "Server Running Well",
/**
* Where a device downloads the local CA that signed the app's
* certificate, so it can trust it (`serveLocalCa`): the certificate
* and an iOS/macOS profile that installs it, and the names they
* download as. Only served with TLS and `TLS_CA_FILE`.
*/
TlsCaPath: "/ca.crt",
TlsCaFilename: `${SiteData["SiteSlug"]}-ca.crt`,
TlsCaProfilePath: "/ca.mobileconfig",
TlsCaProfileFilename: `${SiteData["SiteSlug"]}-ca.mobileconfig`,
AuthKeyCookieName: `${SiteData["SiteSlug"]}_auth_key`,
AuthCSRFCookieName: `${SiteData["SiteSlug"]}_auth_csrf`,
/**
* The build this browser has been through the loading page for
* (`handlePrecacheGate`). Set by the page itself, so not `HttpOnly`;
* it holds nothing private.
*/
BuildCookieName: `${SiteData["SiteSlug"]}_build`,
BuildCookieMaxAgeSeconds: 365 * 24 * 60 * 60,
AuthExpiryDays: 60,
APICrudBasePath: "/api/admin/crud",
ForcePrivateHeaderKey: `x-${SiteData["SiteSlug"]}-force-private`,
ForcePublicHeaderKey: `x-${SiteData["SiteSlug"]}-force-public`,
DefaultQueryLimit: 40,
MainImageSize: 500,
MaxImageWidth: 1500,
ImageThumbnailSize: 150,
ImageQuality: 85,
ImageThumbnailQuality: 70,
PaystackEndpoint: "https://api.paystack.co",
ContactFormLimit: 5,
RateLimitWindowMinutes: 15,
UsernameRegex: /^[a-z0-9._-]{3,32}$/,
PasswordMinLength: 8,
PasswordMaxLength: 128,
PasswordAttemptLimit: 10,
/**
* Docker network shared by the app and every computer. The app makes
* sure it exists on startup and before it creates a container, and
* joins it when it runs in docker.
*/
DockerNetworkName: SiteData["SiteSlug"],
/**
* Port the AIO sandbox listens on inside its container.
*/
ComputerPort: 8080,
/**
* Every computer the app creates runs this image, named
* `<ComputerContainerPrefix>-<computer id>` on `DockerNetworkName`.
*/
ComputerImage: "ghcr.io/agent-infra/sandbox:latest",
ComputerContainerPrefix: `${SiteData["SiteSlug"]}-computer`,
/**
* A computer's home directory (`ComputerHomeDir` in its container) is
* kept at `DATA_DIR/<ComputerDataDir>/<id>`, owned by the sandbox's
* user. It stays when the computer is deleted.
*/
ComputerDataDir: "computers",
ComputerHomeDir: "/home/gem",
ComputerUserUid: 1000,
ComputerUserGid: 1000,
/**
* Resources a new computer's container gets, saved on the computer
* (`cpus`, `memory_mb`) when it is created.
*/
ComputerDefaultCpus: 1,
ComputerDefaultMemoryMb: 2048,
ComputerMinCpus: 0.25,
ComputerMaxCpus: 64,
ComputerMinMemoryMb: 512,
/**
* Docker's health check on every computer container: the sandbox's API
* on `ComputerPort` and its browser answer. A new computer stays
* `creating` until it passes, for at most `ComputerHealthyTimeoutMs`,
* checked every `ComputerHealthPollMs`.
*/
ComputerHealthcheck: {
IntervalSeconds: 5,
TimeoutSeconds: 5,
StartPeriodSeconds: 120,
Retries: 3,
},
ComputerHealthyTimeoutMs: 5 * 60 * 1000,
ComputerHealthPollMs: 2000,
/**
* How long docker gives a computer's container to stop before it is
* killed, when it is removed or recreated.
*/
ComputerStopTimeoutSeconds: 10,
/**
* A computer is reached at its hostname, else its IP address. Each
* address gets this long to answer, and the one that did is reused
* for `ComputerAddressCacheMs`.
*/
ComputerReachTimeoutMs: 2000,
ComputerAddressCacheMs: 60 * 1000,
/**
* Per computer container.
*/
ComputerShmBytes: 2 * 1024 * 1024 * 1024,
/**
* The docker engine API, reached over its unix socket.
*/
DockerSocketPath: "/var/run/docker.sock",
/**
* Cap on a bot's `system_prompt` and `memory`, and on a workspace's
* `system_prompt`, so self-updates can't grow a prompt without bound.
*/
PromptMaxLength: 20000,
/**
* `bots_queue` (bun-sqlite `isQueue`). A job that hasn't sent an update
* within the lock timeout is presumed lost and goes back to the queue,
* so long computer jobs must call `updateBotJob` more often than this.
*/
BotQueueMaxAttempts: 3,
BotQueueLockTimeoutMs: 10 * 60 * 1000,
BotQueueBackoffMs: 30 * 1000,
/**
* One attempt of a job (one model run or task, tools included) gives up
* after this long and counts as a failed try, so a call that hangs
* without ever answering can't hold the job, its computer or the
* conversation forever. The lock is outlived by the heartbeat, so this
* is the only thing that stops a live but stuck run.
*/
BotJobAttemptTimeoutMs: 60 * 60 * 1000,
/**
* A failed scheduled run is tried again after this, doubling each time
* (`scheduledRunRetryAt`), so a short outage doesn't sink the run.
*/
ScheduledRunRetryMs: 5 * 60 * 1000,
/**
* The queue handler's lock name. Stable across restarts, so on startup
* it can release the jobs it was running when the process stopped.
*/
BotQueueWorker: "main",
BotQueuePollMs: 3000,
/**
* Tasks run at once. Tasks on the same computer always run one at a time.
*/
BotQueueConcurrency: 3,
/**
* Chat replies run at once, on their own slots so they never wait
* behind long tasks. One per bot at a time.
*/
BotQueueReplyConcurrency: 3,
/**
* Finished jobs are deleted after this many days.
*/
BotQueueRetentionDays: 30,
/**
* A bot's schedules (`cron_jobs`): how many it can have, and the
* shortest gap between two runs, so a schedule can't flood the queue.
*/
CronJobMaxPerBot: 20,
CronJobMinIntervalMs: 5 * 60 * 1000,
/**
* Due schedules queued per tick of the `run-cron-jobs` cron.
*/
CronJobBatchSize: 50,
/**
* Automatic model picks (`rankAutoModels`). A free model from outside
* `AutoModelVendorPreference` must have at least this much context, and
* this intelligence index or, unscored, this many billion parameters.
*/
HarnessAutoMinContext: 32000,
HarnessAutoMinScore: 12,
HarnessAutoMinSizeB: 20,
/**
* Models tried per harness call before giving up (pinned plus
* automatic fallbacks).
*/
HarnessMaxCandidates: 5,
HarnessRequestTimeoutMs: 3 * 60 * 1000,
/**
* One tool call gives up after this long, whatever the tool is (bot
* tools, MCP servers, computers, custom tools), so a tool that ignores
* its own limits can't stall the run. Its result comes back as an error
* the model can work around.
*/
HarnessToolTimeoutMs: 10 * 60 * 1000,
/**
* A model that rate limits or fails is skipped for this long, unless
* the provider says when to come back (capped at the max).
*/
HarnessCooldownMs: 60 * 1000,
HarnessMaxCooldownMs: 24 * 60 * 60 * 1000,
/**
* Model turns in one text run before it must stop and report.
*/
HarnessMaxToolSteps: 30,
/**
* Longest tool result handed back to the model.
*/
HarnessToolResultMaxChars: 20000,
/**
* Upload cap for audio sent to transcription.
*/
HarnessMaxAudioBytes: 25 * 1024 * 1024,
/**
* Connecting to an MCP server (a computer) gives up after this long.
*/
McpConnectTimeoutMs: 15 * 1000,
/**
* One MCP tool call gives up after this long without progress.
*/
McpToolTimeoutMs: 5 * 60 * 1000,
/**
* MCP servers set up in Settings, under MCPs: a stdio server runs in
* `DATA_DIR/<McpDataDir>/<id>` (its setup installs there, so it
* survives updates), its setup command may take `McpSetupTimeoutMs`,
* and it's stopped after `McpStdioIdleMs` without a call.
*/
McpDataDir: "mcp",
McpSetupTimeoutMs: 10 * 60 * 1000,
McpStdioIdleMs: 10 * 60 * 1000,
/**
* A custom tool (Settings, under Tools) gives up after its own timeout,
* `CustomToolDefaultTimeoutMs` when it has none, never past
* `CustomToolMaxTimeoutMs`.
*/
CustomToolDefaultTimeoutMs: 60 * 1000,
CustomToolMaxTimeoutMs: 10 * 60 * 1000,
/**
* `search_computers`: how long the command may run on each computer,
* and how much of each computer's output the bot reads.
*/
ComputerSearchTimeoutMs: 30 * 1000,
ComputerSearchMaxOutputChars: 4000,
/**
* How many of a job's latest steps (`bots_queue_updates`) the
* working-on panel shows.
*/
BotJobUpdatesShown: 12,
/**
* How often each server process reads new bot messages, job steps and
* bot changes from the database for its own sockets (`liveRelay`).
*/
LiveRelayPollMs: 1500,
/**
* While a reply is due in the open conversation, how often the page
* checks for new messages itself, in case a live push was missed (the
* socket was down) and the thinking row would otherwise stay up.
*/
BotReplyCatchUpMs: 5000,
/**
* How many of a session's latest messages that check reads.
*/
BotReplyCatchUpMessages: 20,
/**
* How much of the conversation a bot sees when it replies.
*/
BotReplyHistoryMessages: 40,
/**
* How many of a session's latest messages the conversation page
* renders with; older ones load as the thread is scrolled up.
*/
ConversationFirstMessages: 30,
/**
* How many older messages each scroll to the top of the thread loads.
*/
ConversationOlderMessages: 30,
/**
* How much of a bot's last message the rail's lists carry, as plain
* text (`messagePreview`): a row shows one line of it.
*/
RailPreviewMaxChars: 160,
/**
* A session with this many messages is closed when the user writes
* again, and the message starts the next one (carrying a summary).
*/
BotSessionMaxMessages: 120,
/**
* How much of a closed session the bot reads to summarize it, and how
* long the summary may be.
*/
BotSessionSummaryMessages: 80,
BotSessionSummaryMaxChars: 4000,
/**
* The first messages of a session the bot reads to name and summarize
* it once the first reply is in, and how long its title may be.
*/
BotSessionNameMessages: 4,
BotSessionTitleMaxChars: 80,
/**
* Sessions listed per page in a conversation's sessions modal.
*/
BotSessionsPageSize: 30,
/**
* Worker bots the rail lists, most recently active first, before
* "See all bots".
*/
RailRecentBots: 5,
/**
* Workspaces the rail lists, most recently active first, before
* "See all workspaces".
*/
RailRecentWorkspaces: 5,
/**
* Stones shown beside "See all bots" and "See all workspaces".
*/
RailSeeAllStones: 3,
/**
* Recent sessions the rail lists under the open bot, before "All
* sessions".
*/
RailRecentSessions: 5,
/**
* Recent sessions a workspace's dashboard shows.
*/
WorkspaceActivityItems: 6,
/**
* Tool turns a chat reply may take. Long work goes to a task instead.
*/
BotReplyMaxToolSteps: 8,
/**
* Chat attachments: per file, per message, and how much of a
* document's text a reply reads.
*/
BotAttachmentMaxBytes: 20 * 1024 * 1024,
BotAttachmentMaxFiles: 6,
BotAttachmentMaxTextChars: 20000,
/**
* Only this many of the latest messages with files hand the files
* themselves to a reply; older ones are named.
*/
BotReplyAttachmentMessages: 4,
/**
* Longest dictation the composer records before it stops on its own.
*/
ComposerVoiceMaxMs: 5 * 60 * 1000,
/**
* Most bots or workspaces the composer's mention menu lists at once.
*/
ComposerMentionMaxItems: 6,
/**
* Most of a bot message read aloud; the rest is cut.
*/
SpeechMaxChars: 4000,
/**
* What a speech model reads when a voice is tried in the model settings.
*/
VoicePreviewText: "Hi there. This is how I'll sound when I read my replies aloud.",
/**
* Largest picture a bot or a workspace can have.
*/
ProfileImageMaxBytes: 5 * 1024 * 1024,
/**
* A user with an open socket seen this recently gets no push: they
* are already looking at the app.
*/
PushPresenceWindowMs: 45_000,
/**
* A notification's body is one line, cut here.
*/
PushBodyMaxChars: 140,
/**
* How long a push service may hold a notification for a device that
* is offline.
*/
PushTtlSeconds: 60 * 60,
/**
* Responses smaller than this go out uncompressed: the encoding
* costs more than it saves.
*/
CompressMinBytes: 1024,
/**
* Brotli quality for page scripts and styles, compressed once per
* file and kept in memory (`compressResponse`). 11 is about 25 times
* slower for 10% less; 5 is close to 9's size at half the time.
*/
CompressBrotliQuality: 5,
/**
* How many compressed page scripts and styles, and how many bytes of
* them, stay in memory. A rebuild names its files anew, so the oldest
* go first.
*/
CompressCacheMaxFiles: 600,
CompressCacheMaxBytes: 32 * 1024 * 1024,
} as const;