Files
cobble/src/data/app-data.ts
T
tbenandClaude Opus 5.5 6c1399f88f Keep composer drafts across reloads and preview attached images
The composer's unsent text and uploaded files are kept in localStorage
per bot and workspace until sent. Picked images show a small preview in
place of their icon.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 14:18:13 +01:00

253 lines
8.3 KiB
TypeScript

import { SiteData } from "./site-data";
export const AppData = {
HashCost: 12,
/**
* Shared with twui's `ColorSchemeSelector`, so it must stay `theme`.
*/
ThemeStorageKey: "theme",
/**
* Prefix of the composer's unsent drafts in `localStorage`, one per
* bot and workspace.
*/
ComposerDraftStorageKey: `${SiteData["SiteSlug"]}_composer_draft`,
ServerHealthMessage: "Server Running Well",
AuthKeyCookieName: `${SiteData["SiteSlug"]}_auth_key`,
AuthCSRFCookieName: `${SiteData["SiteSlug"]}_auth_csrf`,
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,
/**
* 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,
/**
* 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,
/**
* `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,
/**
* How much of the conversation a bot sees when it replies.
*/
BotReplyHistoryMessages: 40,
/**
* 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,
/**
* 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: 8,
/**
* Stones shown beside "See all bots".
*/
RailSeeAllStones: 4,
/**
* 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,
/**
* Largest picture a bot or a workspace can have.
*/
ProfileImageMaxBytes: 5 * 1024 * 1024,
} as const;