Add a default-on email confirmation gate that rejects users with
`requires_email_confirmation && !email_confirmed` on all authenticated
routes, returning 403 with `email_confirmation_required`.
Previously this was only enforced client-side via a GUI modal, meaning
direct API calls could bypass the check entirely.
Essential routes are exempted via `allowUnconfirmed: true`:
`/whoami`, `/logout`, `/send-confirm-email`, `/confirm-email`,
`/save_account`, `/get-anticsrf-token`, `/get-gui-token`,
`/session/sync-cookie`, `/auth/revoke-session`,
`/user-protected/delete-own-user`
No impact on temp users (`requires_email_confirmation` is false),
self-hosted deployments without email (flag is never set), or
unauthenticated routes (login, signup, password recovery, OIDC).
Co-authored-by: Claude Opus 4.6 <[email protected]>
- Add XAITTSProvider calling POST /v1/tts with 5 voices (eve, ara, rex,
sal, leo), speech tags, and configurable output format
- Add XAISpeechToTextDriver calling POST /v1/stt with support for
diarization, multichannel, text formatting, and xAI's native URL
param for remote audio files
- Register both providers in TTSDriver and driver index using existing
xAI API key from config
- Update puter.js client to route provider:'xai' for both txt2speech
and speech2txt, including listVoices/listEngines
- Add TypeScript types for new STT options (provider, format, diarize,
multichannel, etc.)
- Update txt2speech.md and speech2txt.md with xAI options and examples
- Add playground examples for both TTS and STT
Cost metering:
TTS: 420 microcents/char ($4.20/1M chars)
STT: 2778 microcents/sec ($0.10/hr)
Introduce a new Gemini TTS provider and wire it through the driver, client, docs, and examples. Adds src/backend/drivers/ai-tts/providers/gemini/GeminiTTSProvider.ts (Google GenAI client usage, PCM->WAV wrapping, metering, model/voice validation) and a costs table in providers/gemini/costs.ts. Registers the provider in TTSDriver, exposes the alias gemini-tts, and prefers it in provider selection. Updates puter-js client to recognize "gemini" provider/engine and route driver calls to gemini-tts. Documentation updated with Gemini options, a usage example, and a playground example HTML file.
* Remove gross retarded legacy tools and docs
* Remove tools scripts
* nuke the bs
* Remove contributor/self-hosting docs, update license
* Remove src/useapi package and update configs
* remove source map files
* Remove wiki submodule
* ok not everything is retarded, for example this one (v86) is cool but has to go for now
* Remove puter-wisp module
* Remove install.md
* Remove twisp submodule
* Remove epoxy-tls submodule
Remove the epoxy-tls submodule and its configuration: delete the gitlink at submodules/epoxy-tls and remove the corresponding entry from .gitmodules.
* Fixing issues with mobile contextMenu in puter env app where user couldn't tap on menu items and there was checkmark in wrong place
* context menu mobile version - handle submenus
* context menu mobile icon placement tweak
* Web Components for Puter SDK UI API
* Rest of the components
* component docs
* Revert file and directory picker changes
* style matching with puter.com and support for custom styling
* item divider style tweak
* Puter JS - Web Components tweaking
* alert default image fix
* context menu mobile style fix
* Fix app iframe height when app is in fullpage mode and has puter-js menubar
* menubar web component tweak
* Action sheet behavior for contextmenu on mobile also in env app
* replace alert icons
* context menu and menubar keyboard navigation, submenu mouse navigation improvements
* package-lock
* Improve submenu mouse hovering
Make the DB update in AppES awaitable so the write completes before proceeding (avoids race conditions). Also add invalidation of the Redis object key for the app UID in AppInformationService to ensure cached entries keyed by uid are cleared after updates.
When the Start button is clicked while the popover is already open,
close it instead of doing nothing. This fixes the toggle behavior
on Android Chrome where the menu stays open on repeated taps.
The `.popover-launcher` removal triggers the UIPopover remove event
handler which automatically cleans up the `has-open-popover` class.
Fixes#1681
* Consistent header with files
* custom order with draggable app icons
* mobile style tweak
* Drag apps to sidebar
* uninstall
* Add desktop switch button to home tab
Drag sidebar apps order
* Display app storage use in Usage tab
* Add context menu options to apps: open in new tab, open in window
* Sidebar apps section with taskbar/dock behavior
* add close button to sidebar app item
* prevent dashboard files items from being selected when dragging
* File contextmenu shows filename
Keep dashboard URL when opening items
* Fixed issue with mobile selecting
* sidebar toggling
* sidebar tooltips
* done!
* Files tab statusbar width fix
* Consistent header with files
* custom order with draggable app icons
* mobile style tweak
* Drag apps to sidebar
* uninstall
* Add desktop switch button to home tab
Drag sidebar apps order
* Display app storage use in Usage tab
* Add context menu options to apps: open in new tab, open in window
* Sidebar apps section with taskbar/dock behavior
* add close button to sidebar app item
* prevent dashboard files items from being selected when dragging
* File contextmenu shows filename
Keep dashboard URL when opening items
* Fixed issue with mobile selecting
* sidebar toggling
* sidebar tooltips
* done!
* Files tab statusbar width fix
* Remove desktop switch button from Home tab
* App uninstall fix
* mobile style tweaks for dashboard sidebar
* Usage tab header fixes
* style tweaks
* Disable Uninstall for certain system apps
* Use app title in uninstall modal
* Remove delete-data option from uninstall modal
* Update dashboard.css
* Update TabApps.js
---------
Co-authored-by: jelveh <[email protected]>
Remove the alpha notice banner and spacer from Peer documentation pages (Peer.md, connect.md, ensureTurnRelays.md, connect.md, serve.md). This updates the docs to stop advertising the Peer API as alpha and cleans up redundant banner markup.
When reload_on_success is set, use '/' as the fallback redirect URL instead of the current page (window.location.href). This prevents redirecting back to the signup page after a successful signup while preserving any explicit options.redirect_url value.
Move @esbuild/linux-x64 from dependencies to optionalDependencies in src/docs/package.json so the platform-specific esbuild binary is treated as optional. Update package-lock.json to reflect that change (adds platform-specific @esbuild entries, marks various packages as peer/optional, bumps @emnapi/wasi-threads to 1.2.1 and removes obsolete @emnapi core/runtime entries).
Do not unconditionally overwrite window.disable_temp_users during GUI init. If window.disable_temp_users is already set, keep it; otherwise fall back to options.disable_temp_users (or false). Added a clarifying comment explaining the behavior.
* Add kv.list() pagination playground example
Create an interactive playground example for kv.list() that
demonstrates cursor-based pagination with sample data (6 items,
2 per page). Also wire the pagination docs example to the playground
by changing the code fence from plain html to html;kv-list.
Fixes#2755
* fix: address review feedback - restore code example, create new pagination playground
* minor refactor
---------
Co-authored-by: Reynaldi Chernando <[email protected]>
* docs(kv): add sorting section with examples to list() API reference
Added sorting section with examples for lexicographic order and zero-padding for numbers.
* docs(kv): add sorting note to list() description
* feat(playground): add kv-list-sort example
* feat(playground): add kv-list-padding.html
* add Sorting examples to kv list on doc/src/examples.js
* docs(kv): add sorting examples to list.md examples section
* Refine copy and code example
* remove extra newline
---------
Co-authored-by: Reynaldi Chernando <[email protected]>
* Map context_length for OpenRouter models
OpenRouter's API returns context_length for each model, but it was not
being mapped to the context field in the model list response. This
caused the context window size to be missing for all OpenRouter models.
Closes#2347
* Add context field to MistralAI and OpenAI model definitions
Addresses reviewer feedback to support the context field in more
providers. All 9 providers now consistently expose context window
sizes via the context field.
- MistralAI: 16 models (context matches known window sizes)
- OpenAI: 27 models (128k for GPT series, 200k for o-series,
1M+ for GPT-4.1 and GPT-5.4)
Bump the .dashboard-sidebar width from 200px to 250px to provide more room for navigation items and improve layout spacing. min-width, background, and border styles remain unchanged.
* Display logged-in banner on homepage
Pass auth_user from the router into PuterHomepageService and show a logged-in banner when a user is present. _default.js now includes auth_user in the svc_puterHomepage.send call. PuterHomepageService.send signature was updated to accept auth_user; the service stores logged_in_user, forwards it to generate_puter_page_html, and injects a styled "Logged in as <username>" banner into the top of the page when available. This surfaces the current user on the GUI and exposes logged_in_user to page generation and addons.
* Include request path and logged in user in GUI params; remove banner
* fix: bad auth_user check for homepage
---------
Co-authored-by: Daniel Salazar <[email protected]>
Prevent a visual flash by hiding the apps grid until all app icons have loaded. Adds revealWhenLoaded($container) which removes the myapps-grid-loading class when images finish (or error). TabApps now caches the .myapps-container lookup and calls revealWhenLoaded after initial render, after search results, and after loading installed apps. CSS changes: add .myapps-grid-loading (opacity:0 + transition) and a small padding-right tweak for the search input.
Fetch both the installedApps and get-launch-apps endpoints in parallel, normalize recommended + recent launch items, and merge them with installed apps while deduplicating by name (launch items are prioritized). Update this._apps and render the combined list. Also simplify the app tile icon styling by removing border-radius and box-shadow for a flatter icon appearance. Error handling for failed loads is preserved.
Add /css/dashboard.css to the GUI asset lists so dashboard styles are served and bundled. Updated src/gui/puter-gui.json and src/gui/src/static-assets.js to include the new stylesheet.
* feat: add Anthropic Messages API compatibility layer
Add a new endpoint at /puterai/anthropic/v1/messages that implements the
Anthropic Messages API wire format, allowing clients using the Anthropic
SDK to point directly at Puter.
- New router translates between Anthropic format and Puter's internal
svcAiChat.complete() pipeline
- Supports non-streaming, SSE streaming (proper Anthropic event sequence),
and tool use round-trips
- Translates system field, tool definitions (input_schema -> parameters),
and tool_result content blocks
- Integration tests covering non-streaming, streaming, tool use,
Anthropic SDK compatibility, and system parameter
Closes#2554
* Fix authentication middleware
---------
Co-authored-by: ProgrammerIn-wonderland <[email protected]>
Prevent creating temporary users on unauthenticated first visits when the current action is the login or signup flow. The initgui else-if was expanded to include explicit checks for action !== 'login' and action !== 'signup', avoiding interference with explicit authentication routes and Turnstile challenges.
Use a single expression to derive the plan key (offering.name or 'free') and pass it to i18n when updating .bento-plan-name. This removes the previous ternary and duplicates, allowing dynamic offering names to be localized consistently.
Add missing English translations for plan tiers (free, basic, professional, business) to src/gui/src/i18n/translations/en.js and perform a minor formatting cleanup near billing messages to ensure keys are available for UI display.
Update TabHome to read the plan name from subscription.offering.name instead of subscription.plan_name. This adapts to the updated subscription object shape while keeping the fallback to the 'pro' translation and the 'free' label when no active subscription exists.
The taskbar uses position:fixed with bottom:5px, which gets hidden
behind the iOS Safari bottom toolbar on devices with home indicators.
Use env(safe-area-inset-bottom) to push the dock above the safe area.
The viewport-fit=cover meta tag is already present in initgui.js.
Fixes#2517
* fix: tighten up cors for socket io
* fix: allow socket io to push to rooms in redis
* fix: various socket io issues to improve cross session stability
Update check for suspended users on change_emeail and user-protected
endpoints. The `change_email` endpoint isn't using the auth middleware
because it infers from the token that was passed - this means it needs
explicit logic to check suspended users; before suspended users were
able to complete a a flow for changing their username if they already
started it before being suspended.
Update user-protected endpoints and configurable_auth so endpoints that
make sensitive account changes do not rely on cached information about a
user.
Introduce a new i18n key `add_to_desktop` with value 'Add to Desktop' to the English translations file. This provides a label for UI actions that add items or apps to the desktop.
* chore: upgrade git-date (used for release notes generator)
* chore: update vitest, vitest plugins, and svgo
* chore: run `npm audit fix`
* chore: run `npm audit --force`
* meta: empty commit to run git tests
* fix: tests gone because of a... syntax error?
I question GitHub's judgement of handling a syntax error in the file
that defines tests to run on PRs by pretending everything is fine and
passing all PRs. That to me seems like the worst possible way to handle
that. I think they should have done it not like that.
When a global ClickHouse client is available, run two parallel ClickHouse queries (JSONEachRow) to fetch per-app open_count and distinct user_count, parse results into Maps (parsing counts as integers). If ClickHouse is not present, fall back to the original MySQL aggregate queries. Apps list still comes from MySQL as before. This enables using ClickHouse for analytics performance while preserving the existing behavior as a fallback.
* fix: only set authToken if present for apps
* fix: keep bootstrap in url for app to do whatever
* fix: tests
* fix: app merging
just cleaning up how merging subdomain and canon apps work, namely, persisting data better and making sure its temp alias are deleted when appropriate
* fix: tests oom
Usage example:
const b = new puter.fs.Batch();
b.move('file_1.txt', '~/Trash');
b.move('file_2.txt', '~/Trash');
await b.end();
Chaining is also supported:
await new puter.fs.Batch()
.move('file_1.txt', '~/Trash')
.move('file_2.txt', '~/Trash')
.end();
This commit provides `move` and `delete` methods for Batch.
* feat: scope index_url uniqueness to hosted domains
Allows duplicate non-hosted origins while enforcing hosted-origin uniqueness and joining new app creation into an existing owner-matching hosted app UUID.
Restricts hosted index_url joins to unowned conflict apps, persists old-to-canonical app UID aliases in kvstore via sudo, and resolves aliases on read with parallel lookup to minimize latency.
* fix: allow merge for owned origin bootstrap apps
Restores hosted update/create merge when the conflicting app is the same-user auto-created origin bootstrap app while still blocking merges into normal same-owner apps to avoid multi-join behavior.
Adds non-blocking public hosted actor cookie mint/verify flow for non-private apps, sets actor context when available, and includes focused middleware/auth tests for security and performance-sensitive paths.
Adds an extension that presents an unauthenticated page for testing
various actions of Puter when it's under development. This action is
only meant to be used in development and is not loaded by default.
* feat: phase 2 enforce index url ownership and uniqueness
Adds write-time index URL uniqueness checks, expands hosted subdomain ownership enforcement to private hosting domains, and updates AppService tests for duplicate-index behavior.
* test: align app service comp fixtures with index url uniqueness
Updates regression test fixtures that intentionally exercise name conflicts and selection paths to use unique index_url values under the new one-index-per-app constraint.
* fix: exempt placeholder index url from uniqueness checks
Skips index_url uniqueness enforcement for the shared dev-center coming-soon URL in both AppService and AppES, and adds unit/comp regressions to keep one-index-per-app behavior for all other URLs.
Set reload_on_success explicitly when invoking UIWindowLogin so the UI does not trigger a page reload if the GUI is embedded in a popup. Previously the call forwarded a reload_on_success variable; now it uses !window.embedded_in_popup to prevent unwanted reloads in popup embeds.
* Revert "dev(oidc): hide unnecessary div"
This reverts commit 468558f8dc.
* fix(oidc): remove the "You will be asked to..." box properly
Earlier this was removed with a simple `display: none` in CSS to avoid
changing any logic, and the reason for that was OIDC had already gone
through significant testing, re-testing, and bug fixes; it became clear
that changes to the auth flow are fragile and the test surface is very
large. Now unfortunately what seemed like a smart decision to fix a
cosmetic issue with CSS instead of updating logic actually wound up
breaking the change username/password flow for non-OIDC users. This
commit removes this box properly and hopefully does not introduce a
subsequent terrible bug. Why would it? There's absolutely no reason I
can see that it would, but it would seem that nothing is safe, not even
CSS.
* temp: disable LRU cache of homepage for now
This is working fine but we're disabling it temporarily so we can test
specific future changes in isolation without managing two separate
branches.
* fix: put verify password text in the box
There's always something...
LRU cache the output of PuterHomepageService with a cache key based on
metadata that affects the output of the homepage (if an app was
specified, and if so what app was specified).
With this change in place we can afford more time processing this
output, for example to minify the output and reduce outbound bandwidth.
* add configurable GUI bundle
* also support CSS and puterjs custom location
* simplify ternary
* used bundled instead of use_bundled_gui
* Quote the string
* close script tag
* feat: phase 1 canonical app origin resolution
Adds cache-first canonical app uid resolution for origin-based auth flows with oldest-app selection and deterministic fallback, plus regression tests for hosted/non-hosted canonicalization behavior.
* refactor: use kv singleton for origin local cache
Replaces AuthService app-origin local canonicalization Map cache with kvjs singleton keys, applies TTL via EX on writes, and rotates local cache namespace on version bumps to avoid broad clears.
* refactor: target origin cache invalidation
Removes global app-origin cache version bumps and invalidates canonical origin cache entries by affected app index URLs from app.changed payloads. Also emits app and old_app data on update events for targeted invalidation.
* fix: avoid invalid old_app owner field in app change event
Removes owner_user_id access from AppES old_entity event payload because the entity model does not expose that property, fixing AppService comp upsert regression tests.
Convert newline characters in email reason text to <br /> tags and ensure proper escaping. Replaced {{reason}} with {{{nl2br reason}}} in the rejection template and registered an nl2br Handlebars helper that escapes HTML entities, transforms newlines to <br /> and returns a SafeString so line breaks render correctly in emails.
Each of these methods is only being called by get_app_icon_url. By
changing that ternary operator into an `if` block with an early return
we can move the bodies of these functions here. If one of the former
functions ever needs to be used in more than one place, it's easy to
extract it out of here agian - for now though let's not pay the cost of
jumping to another function definition while trying to understand this
code if we're not gaining anything from it.
* style(puterfs): update adherence to linter rules
* fix(puterfs): await queue items for fsentry actions
This will ensure some operations always function as expected in a
sequence, although it may incur some performance costs.
* dev(apps): add configuration to not use app icon subdomain
For some local configurations of Puter, such as using ngrok or a hosting
service that has limited subdomains or limited subdomain depth, the
static hosting subdomain for app icons is difficult to configure and may
not be viable. Since this is only done so an external geo-replicated
cache can be used, and it's always possible for Puter's backend to
generate an app icon, it should be possible to configure Puter's backend
to use icons from a URL hosted on the default subdomain.
Add a configuration parameter to the service "app-icon" called
"no_subdomain" which prevents Puter's backend from sending puter-icons
subdomain URLs or redirecting to them.
Also perform some small cleanup changes to make the existing code easier
to understand, including:
- rename `buildAppIconUrl` to `buildAppIconSubdomainUrl` to make it
clear which of the two types of icon URLs are being generated.
- replace `withAppIconUrl` with `get_app_icon_url` so it is possible to
get an icon URL without mutating an app object.
- make the `get_taskbar_items` helper use the same code for getting app
icons as the `get_apps` helper.
* fix(apps): test initializes a service with no config
The request object was not being passed to OIDC signup because it is
called by createUserFromOIDC which doesn't take a request object as a
parameter. It was decided to have `create_user` take the request object
from context if it's not specified rather than change the signature of
createUserFromOIDC.
I decided not to remove it because I really don't want to introduce a
bug right now while everything is finally working smoothly... I'm making
a note to properly clean this up later when it can be more easily tested
in isolation from everything else.
It turns out there are nuances between `puter.ui.authenticateWithPuter`
vs `puter.auth.signIn` - these don't do the same thing. The primary
difference is that `puter.ui.authenticateWithPuter` will display an
override if it's not triggered by a user action, whereas
`puter.auth.signIn` will not. This definitely suggests
`puter.ui.authenticateWithPuter` should be a caller of
`puter.auth.signIn` instead of implementing its own logic for handling
the popup - that makes this part of the code more fagile - but that
refactor is out-of-scope for this bug fix.
* feat: resolve private app hosts by index_url fallback
Adds a private-app lookup fallback for hosted subdomains without associated_app_id by matching owner-scoped index_url candidates built from request host and configured protocol.
* fix: redirect path
* fix: add new domains too
* fix, bootstrap url
* fix: bootstrap url
* fix: auto sign in puter pirvate app
* Fix: When a maximized window gets resized, Puter apps should be resized as well
* Fix maximixed selector to match any window with data-is_maximized (not just apps)
For convenience, switch flow if the user's action doesn't match the
system state when signing up or logging in with Google:
- If the user chooses "signup" but they already have an account, log
them into that account.
- If the user chooses "login" but they do not have an account yet,
create an account where their authenticated email address.
Adds a config flag to disable private app gate enforcement, structured middleware audit logs for private access decisions, and regression coverage for the disabled-gate path.
When a rate-limit scope is not configured, use a default configuration
instead of throwing an error. Display a warning about the unconfigured
rate-limit scope when the default is used.
* fix: disable broadcast for cache invalidation
* fix: remove broadcast for redis events for now
* fix: don't await cache invalidation for grant app permission
Fixes an error introduced in 4b8c46e where the page load is attempted to
be triggered by dispatching the login event, however the listener which
handles loading the page has not yet been registered.
* fix(oidc): OIDC login with puter.js popup auth
Bring login through OpenID Connect to a working state in the puter.js
popup authentication flow. This allows OIDC login to work with
third-party websites and apps.
* fix(oidc): error handling, use const (initgui)
Remove a condition that can be handled by the control flow logic
already implied by a try...catch, which also allows a variable to become
const, and log errors in this catch block.
* doc(oidc): make this comment a little more helpful
* clean(oidc): remove out-of-scope puter.js change
Remove a change that gives explicit overrides of the `defaultGUIOrigin`
paramter precedence over other sources of this value. This was necessary
when testing but might not be the correct fix for this issue.
Await the window.update_auth_data call in initgui.js so subsequent logic (such as popup spinner hiding and timing) runs after authentication data has been updated. This prevents race conditions where later UI code executes before auth state is fully applied.
Read user preference keys (show_hidden_files, language, clock_visible) into local variables with try/catch and sensible defaults, instead of fetching/parsing them inline. This prevents exceptions from missing or malformed KV entries and centralizes parsing for show_hidden_files. Also remove an extra blank line in initgui.js's AJAX complete callback.
Redirect to the login or signup page when there is an error signing in
or creating an account using OIDC, instead of displaying the error on a
new page. Alter the flow in cases where the suggested action is not the
same as the initial action taken by the user (based on the error case).
* fix nano banana pro pricing and resolutions
* move gemini resolution map into models.ts
* require gemini 3 model for specific resolution and price logic
* fix usageamount for mp models
UIItem makes a recursive call when there are multiple matching elements
in the `options.appendTo` argument. When calling recursively, the
`appendTo` property of the `options` object is mutated to a specific
element before the call, which expects that each call to UIItem occurs
synchronously. UIItem was made asynchronous by
9d598f7965
which resulted in a bug causing duplicate item icons in one directory
window instead of one item icon in each directory window after a file
upload when multiple instances of a window at the same directory
location exist.
Resolves#2514
we saw some errors with icons not allowed when being objects, this likely user error, but this adds some validation to at least avoid nulls being flagged wrong
* fix: allow healthcheck from other hosts
* fix: don't await for cache writes
we think some awaiting on redis writes was causing issues, we shouldn't need to await really, so removing now. will have optimistic caching for these
some style changes from a recently changed rule that seems to clash with prior one
Fixed: The gradient and progress bar on the usage details page is not very pleasant and looks inverted
Fixed: The billing card on the billing tab is still light mode
This code was previously lost because I edited `outcomeutil.js` instead
of `outcomeutil.ts`. We're not building into a `dist/` directory and
`tsc` has a most peculiar lack of generating a comment at the top of
output files stating something like "// GENERATED - DO NOT EDIT" as I've
seen from every other code generator or transpiler I've worked with.
This caused the bug with duplicate confirmed emails and "account not
found" during testing on the staging server.
I forgot that our transpile tooling requires manually gitignoring
individual javascript files because we don't actually create a full
generated build of backend.
During development a property named `success` was inverted to a property
named `failed` which resulted in an incorrect accessor reference with a
referring piece of code that wasn't updated. This is type error.
In lieu of knowing exactly what happened (probably more than one thing),
the "Disable 2FA" window was very broken. It was blank, but then after
fixing that all the actions were broken. There wasn't much value in
keeping the implementation though, because it was already inconsistent
with other flows - instead of fixing what was there it made more sense
to re-use the pattern of UIWindowChangeUsername and UIWindowChangeEmail,
creating UIWindowDisable2FA. After testing this, it works much better
(it actaully works), but there is a caching issue unrelated to the UI
implementation.
A component was removed and an html property was passed to
UIComponentWindow. This makes sense because UIWindow accepts an html
property, so rather than update the calling code it made more sense to
update UIComponentWindow to be more intuitive.
This button was useful during manual testing, but the re-authentication
flow for protected endpoints with OIDC users reliably invokes the popup,
so this is no longer necessary. Removing this button reduces clutter on
these screens and might make the flow easier for users to understand.
In implementing OIDC it became necessary to introduce the separation of
"GUI Tokens" and "Session Tokens". This breaks QR login because Puter
does not set the HTTP-only session cookie when logging in with this
flow.
Add a middelware to WebServerService to detect QR Code logins and set
the appropriate HTTP-only session cookie.
Use the openRevalidatePopup function in util/openid.js within
UIWindowChangePassword instead of re-implementing that functionality.
Additionally, normalize some of the code so it is more similar to
UIWindowChangeUsername and UIWindowChangePassword.
There is common functionality between all of the GUI code for actions on
protected endpoints. Update UIWindowChangeEmail and
UIWindowChangeUsername to both use a new utility function called
openRevalidatePopup in util/openid.js.
This file is called `openid.js` instead of `oidc.js` so that it's more
easily recognized by contributors who might be more familiar with the
name of the organization than the name of the standard itself.
After these changes, UIWindowChangePassword and the "disable 2FA" button
in UITabSecurity still need to be updated to use `util/openid.js`
instead of duplicating this functionality.
The justification for following DRY here instead of leaving the
implementation as-is is because these flows are particularly error
prone and will be difficult to maintain without this consistency. Some
subtle bugs I previously wasn't aware of got fixed in the process.
The OIDC re-authentication flow, which replaces password confirmation
for accounts that were created with OIDC and do not have a password, was
previously added to "change username" for manual testing of the
backend-side implementation. Add the re-authentication flow to the
remaining user-protected endpoints, which are:
- change password
- change email
- disable two-factor authentication
When using "change password" on a new account created via OIDC, the
account changes state to a passworded account which causes these flows
to use password confirmation as before instead of re-authentication.
The monthly number of username changes was hardcoded as `2`. Being able
to configure this value makes it easier to test the username change
flow. Hosters of OSS Puter may also find this configuration beneficial.
When users make sensitive changes to their account they are asked to
re-enter their password. This prevents a hijacked session from causing
futher damage.
Users created with the new OIDC flow do not necessarily have a password
set on their account, and they need to also be able to make these
changes. While removal of the password entry requirement for these users
would solve this problem, it would also make their accounts more
vulnerable. To solve this problem while maintaining the same security
standard for OIDC users, we need them to confirm via either 2FA or
re-authentication via OIDC. Since users aren't required to have 2FA, the
re-authentication via OIDC approach is also the minimum viable solution.
This commit adds OIDC re-authentication support for all endpoints under
UserProtectedEndpointsService, and makes updates to the
UIWindowChangeUsername dialog for manual testing.
Currently this implementation fails at the final submission to change
the username because of a separate issue with the correct authentication
token not being set; this is related to the separation of GUI tokens vs
http-only tokens.
This commit is rather monolithic. An attempt to split it up into smaller
changes proved too difficult (as well as frustrating) and I realized it
would absolutely increase the chance of having a broken commit (making
bisects more difficult) unless a lot of testing effort between commits
was performed, which would have very little benefit.
The changes in this commit include:
- Outcome utility used by SignupService for error handling
- SignupService, whichs implements re-usable create_user function
- Signup method in OIDCService
- flow-specific callbacks in OIDC (separates login from signup)
- **SEPARATE SESSION COOKIE AND GUI COOKIE**
- this change "rocks the boat" the most and has the highest likelihood
of causing problems
* Fixed issues where file list wasn't scrollable on mobile device, and tap'n'hold on file opened wrong context menu.
* Fixes text color of selected row
- [x] Fixes path navigation button transitions
- [x] Fixes path navigation button colors
- [x] Hide AppData folder
- [x] Hide hidden files
Fix ESM/CJS interop issue in unit tests with a hack that checks the
class name as a string instead of just doing an `instanceof` check. This
is assuming that the "rewriter must be a PermissionRewriter" error I'm
seeing on GitHub is because there are two different "copies" of
PermissionWriter due to ESM/CJS interop issues. If this is not the case,
then you're not reading this commit message on `main`; if this commit is
on `main` then that's exactly what went down.
Add the ability to request an app's root directory. A permission
rewriter is provided so that apps may refer to a permission when
requesting this access without knowing the path of the app's root
directory.
* Dashboard - Added files tab with basic folder and files listing.
* clearing out some linter errors
* Removed Public folder for now
* Added "modified" column
Subfolder are listed before the files
* Dashboard - files tab: context menu basics
* Dashboard - Files tab: subfolders can be opened. Items can be opened from more-menu or by double clicking on them
* Dashboard - Files tab: use UIContentMenu instead of custom menu for "more menu"
* Dashboard - Files tab: Delete implemented, Trash folder added
* refactored context menu rendering
* Implemented UIItem context menu functionalities
Added path
* Rename files and folders
* Rename fix
* tweaks and fixes
* WIP: Multiple selection, drag and drop, trash folder improvements
* clean
* Files handling improvements
* empty trash fix
* grid view
* grid view improvements
* update icons
context menu for multiple items shows file counts such as: Delete (9)
* Path navifation buttons
* better way to get user's directories
* Added icons for various file types
* Use puter.kv instead of window.user_preferences
* sorting and column resizing
* documentation of the functions
* Style update. Dashboard colors now as CSS variables
* refactored restoring from trash and emptying trash with proper callbacks & refreshing
* select documents folder by default
style tweaking
* Drag to select files and folders
* dark mode
* style tweaks
* removed some dead code..
* Keyboard shortcuts (copied from UIWindow - untested & in progress)
* Add drag-and-drop file upload support to Dashboard
Implement native file drag-and-drop from local filesystem to Dashboard:
- Add dragster handlers for main content area, sidebar folders, and folder rows
- Create uploadFiles() method with progress modal and directory refresh
- Add visual feedback CSS for drop zones (highlight on hover)
- Fix subfolder drop detection to prevent duplicate uploads
- Add callback support to unzipItem/untarItem for directory refresh
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* style tweaks
* Fix cut/paste functionality in Dashboard
The cut operation was storing clipboard items as plain path strings, but
window.move_clipboard_items() looks for .item DOM elements which don't
exist in Dashboard (it uses .row elements). Added a Dashboard-specific
moveClipboardItems() method that calls puter.fs.move() directly with UIDs,
and updated cut to store objects with path and uid like copy does.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Add mobile phone layout optimizations for Dashboard
- Add responsive CSS for screens ≤480px with two-row file list layout
- Wrap item-size and item-modified in item-metadata div for mobile grid
- Hide directories sidebar on mobile (use breadcrumbs for navigation)
- Reorganize header with breadcrumbs on top row, nav buttons below
- Add single-tap to open folders on touch devices
- Fix context menu "Open" action in Dashboard by adding onOpen callback
- Hide column headers on mobile since metadata is shown per-item
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Add CSS variables to Dashboard bento elements for dark mode support
Replace hardcoded color values with CSS custom properties throughout
the bento card components to enable proper dark mode theming. Adds new
variables for icon shadows, fancy headers, gradients, and usage bars
with appropriate values for both light and dark color schemes.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Add spacebar image preview feature to Dashboard Files
Pressing spacebar on a selected image file now shows a full-size preview
popover centered over the files container. Features include:
- Toggle behavior: press spacebar again to close
- Auto-switch: selecting another file updates the preview
- Click outside to dismiss
- Works in both grid and list view
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Add floating action bar for multi-file selection in Dashboard Files
When 2+ files are selected, a floating action bar appears above the footer
with quick access buttons for common operations:
- Download, Cut, Copy, Delete for normal files
- Restore and Delete Permanently for items in Trash
The bar slides up with a smooth animation and disappears when clicking
the background to deselect. Includes mobile-responsive styling with
icon-only buttons on smaller screens.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Add mobile select mode for multi-file selection in Dashboard Files
On mobile devices, users can now tap a select button in the path actions
to enter select mode. In this mode, tapping files toggles their selection
instead of opening them, with checkboxes appearing next to each item.
The floating action bar appears with 1+ selected items (vs 2+ on desktop)
and includes a Done button to exit select mode.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Center empty directory message in Dashboard Files
Replace row-based layout with centered flex positioning for the
"No files in this directory" message, improving visual presentation.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Fixed issue where clicking on files background created blue dot (drag rectangle selection bug)
* Image preview size tweak
* Add URL-based routing to Dashboard with hash fragments
Enable shareable/bookmarkable URLs for Dashboard tabs and file paths.
The URL hash reflects current location (e.g., #files/username/Documents,
#usage, #account). Browser back/forward navigation now works for folder
navigation, and direct URL entry loads the correct tab and path.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* fixing draggable styles
* drag clone fixes
* Add smart column resizing and filename truncation to Dashboard Files
- Add middle-truncation for filenames preserving extensions (e.g., "longfile…name.txt")
- Double-click column resize handles to auto-fit content width
- Reset saved column widths to defaults if they don't fit smaller screens
- Apply truncation to both list and grid views
Co-Authored-By: Claude Opus 4.5 <[email protected]>
* Separated dashboard styles into dashboard.css and loading it dynamically only when navigating to /dashboard
* Files and folders can be dropped over path items in order to move them. This is useful when you want to move items into parent folders.
* Use custom context menu component for item-more menu on mobile devices
* Created callback system to undo_last_action so that dashboard file list would always refresh after undo operation
* gray update
* hovering folder while dragging items opens the folder
* Fixed issue with hover-dropping
* Fixed chained drag-over-folder-and-hover system
* dark mode tweak
* - [x] Right clicking on background of an empty folder doesn't trigger context menu
- [x] Right clicking on path should keep path item active
- [x] Sidebar folder don't have context menu
- [x] Drag item should be opaque so I can see through it
- [x] Transition animation issue when hovering path action buttons
- [x] Double clicking on column resizer: add padding
- [x] Load dashboard.css before loading the page content
- [x] Mobile: opening menu, clicking outside menu should close it
- [x] Mobile: on smaller screen there should be still two columns
- [x] Mobile: file name truncation in grid view doesn't work
* Added missing badges
* WIP has_worker
* display worker icon on the .js files which are workers
* Display worker badge on worker files, hovering badge shows worker URL.
Worker URL added to file properties modal.
* disable "publish as website" from context menu for folders that are already published
* Loading spinner for Files
* tweaks and fixes
* Files clean loading spinner
* Files: worker URL in the properties modal is clickable link
* use custom tooltip to display worker URL
* refactored renderDirectory
* Fix Sidebar folder highlighting
* add Beta badge on Files tab
* Implemeting socket based item updating
* Put newly added items into the position where they would land when list is sorted
* restore from trash refresh fix
* Revert "Revert "Adds worker badge to .js files which have been registered as workers. Hovering badge shows popover with worker URL. File properties modal also shows clickable worker URL. (#2462)""
This reverts commit c2750f2ca1.
* worker in stat
* update puterjs and frontend code to support returnWorkers in stat
* Better way of handling worker info
* Fixed issue where right clicking on background opened two instances of a context menu
* Fixes issue where while renaming a file, double clicking on word opened the file
* fixes issue where while dragging multiple items the top-most item was transparent resulting blurry mess
* when opening a folder, update view instantly
* Improved drag-to-select items
* Added feature where typing selects matching file items
Fixed issue where keyboard listener for file list was active when context menu was open
* Fixed issues with File -> New in context menu
Fixes issue where files-selection-actions menu didn't disappear after deleting items
* Improved drag to select behavior
Improved drag items
Improved worker badge handling
* Cancel zone for dragging items (when spring-loading subfolders)
* context menu's submenu tweak
* Fixed issue where resizing window didn't work (when using "Open in New Window" from context menu)
* Disabled buttons on .files-selection-actions while drag-to-select is happening
* Fixes issue where creating new items using right-clicking re-rendered the directory view
---------
Co-authored-by: Claude Opus 4.5 <[email protected]>
Co-authored-by: ProgrammerIn-wonderland <[email protected]>
Handle upgrade flow when running in the app environment by calling await puter.ui.requestUpgrade() in driverCall_. Added app-specific branches in two places where usage/insufficient-funds were previously handled only for web (which showed a web dialog). This ensures the in-app UI is used for upgrade requests and awaits the result.
Temporarily comment out code in UIWindowPublishWorker that updates item UI after publishing: hiding the lines that show the item website badge, show per-item website-url badges, and set the data-website_url attribute. This prevents the publish worker from automatically modifying those DOM elements/attributes (kept commented for potential rollback or debugging).
* add sandboxing by default in god mode workers
* closes#2481
* Update UIWindowPublishWorker.js
* Add sandbox option to worker publish UI
Add a collapsible 'Advanced' section with a 'Sandboxed' checkbox (checked by default) to UIWindowPublishWorker. On publish the code reads the checkbox state and builds createOptions ({ sandbox: true } or { sandbox: false }) and passes it to puter.workers.create as an argument so workers can be created in sandboxed or non-sandboxed mode. Small UI styling and markup for the details/summary block included.
---------
Co-authored-by: jelveh <[email protected]>
* [PUT-471] feat: estimate and bill input for gemini imgaes :dev:
* [PUT-472] add input/output costs to openai image models too
* npm version bump
* remove second url log
* fix gemini pro image
---------
Co-authored-by: ProgrammerIn-wonderland <[email protected]>
For reasons still unknown, there are circumstances where the permission
scanner denies permission to access tokens that should have been granted
permission. This change de-abstracts/flattens the logic for checking
access tokens so that it is easier to understand and maintain. The newly
implemented code does not suffer from the same issue.
Change default behavior for email confirmation by initializing email_confirmation_required to 0 (not required) instead of 1. Remove the duplicate declaration and clarify the comment; existing logic still overrides this default (sets to 0 for matching pseudo_user/uuid_user and to 1 when event.requires_email_confirmation). Minor whitespace cleanup.
After a successful flow, fetch the user app token for the opener origin, cache the returned app_uid on window.host_app_uid, and post a 'puter.token' message to the opener containing success, msg_id, token, username, and app_uid. If the action is absent or equals 'sign-in', close the popup window. This enables parent windows to receive credentials in popup/embedded auth flows.
It is possible this broke after redis caching was employed because it
broke the expectation that assignments to attributes on cached objects
would remain for future accesses on said objects. This has not been
confirmed as the cause.
This also causes the filename to have the extension `.mjs` instead of
`.js`, as well as an await added in FilesystemAPIService. Luckily
lifecycle events are async so this didn't cause any problems.
I add this change somewhat reluctantly because this _should_ be a
non-functional change. Technically adding the `await` in
FilesystemAPIService makes it possible (albiet incredibly unlikely) for
some subtle bug or change in behavior to be introduced.
This change makes GUI invoke readdir without fetching subdomains, and
then fetch subdomains after. This allows displaying the directory items
sooner and then later populating the icons with glyphs to indicate if
there is an associated subdomain.
This was AI-assisted with manual modifications and bug fixes as
necessary.
This endpoint can be called to get subdomain information after
performing a readdir without fetching subdomains.
This was AI-assisted with modifications and bug fixes as necessary.
This parameter will allow readdir requests to not include subdomain
fetching, which will allow for the later effort of fetching subdomains
for directory listings in the gui with a separate request.
This extensions brings back the dev-socket functionality, which is
really important when testing things like broadcast, alarms, events, etc
; it saves a lot of time if you can invoke a command directly to the
backend.
This is an optional extension that will not be included in production
deployments. This is for development purposes only.
This still needs to be tested. I was going to test this using the `test`
command registered by BroadcastService that exists for this purpose but
`dev.sock` doesn't seem to be working anymore.
Why wasn't `dev.sock` working? Well... we deleted all the code that
makes it work. Why did we delete it? That question isn't a setup for my
next statement; I genuinely do not know. The whole point of dev.sock was
so we could remove the dev console but still maintain support for this
commandline interface that's absolutely needed for testing things that
aren't accesible directly from Puter's GUI.
This tool makes it possible to manually test webhook support in
BroadcastService without running multiple Puter instances. This helps to
verify the functionality without setting up multiple Puter peers
locally.
This commit adds the "receive" side of webhook support for
BroadcastService, which will eventually make broadcasting stateless and
not requiring of persistent connections.
Some specific considerations taken into account include:
- incremental nonce to prevent replay attacks
- request timestamp to prevent nonce-reuse after restarting
- HMAC signature to ensure authorized peer
Known limitations:
- if instances run indefinitely, eventually the nonce value would wrap
around to zero and broadcasts would stop working. It is assumed that
9 quintillion requests in the lifetime of an instance is reasonably
impossible.
It turns out this part of `35461a0` was not necessary to fix this issue,
and the code is still more correct if it falls true when the token's
authorizor has a permission granted.
Range header support was mostly incorrect, which brought to surface
undefined behavior in OnlyOffice which resulted in a request hanging.
This was the cause of the `pdf-editor` app hanging for a while when
opening it with a new file.
When the user clicks Cancel in the authorization window, the code now disables action buttons and replaces the window body with a cancellation UI (header with icon, title, description and a message). Added corresponding English i18n keys (authorization_cancelled, authorization_cancelled_desc, authorization_cancelled_message) to provide localized text for the new cancelled state.
Introduce a new UIWindowAuthMe component that displays a security-focused consent dialog for redirecting to third-party URLs with the user's auth token. Adds related i18n strings and integrates the dialog into initgui, replacing the previous UIAlert confirm flows; when approved (resolves true) the token is appended to the redirect URL and navigation proceeds. Changes: adds src/gui/src/UI/UIWindowAuthMe.js, updates src/gui/src/i18n/translations/en.js, and imports/uses the new dialog in src/gui/src/initgui.js.
Introduce a new UIWindowCopyToken component to display the user's auth token with a copy-to-clipboard button and confirmation message. Integrate the token UI into the account dashboard (TabAccount) by adding an auth token card and click handler to open the window. Add corresponding i18n keys (auth_token, token_copied, copy_token_message, copy_token_description) and import the new window in initgui. Also wire the global action 'copyauth' to show the token dialog and adjust session/login flow so the session list/login windows respect the action (avoid auto-reload when showing the token dialog). Minor UI string cleanup to use i18n('approve') directly.
Replace the plain text response with a styled HTML confirmation page for the local authentication callback. The handler now sets Content-Type to text/html and returns a responsive, animated "Authentication Successful" page (with checkmark graphic and Puter branding) while preserving the existing token extraction from the callback URL's search params.
Read the 'action' value from URL query params and handle a new 'authme' action. When 'authme' is present, prompt the user to approve redirecting to the provided redirectURL; if approved, append the current auth token as a 'token' query parameter and navigate to that URL. The prompt is shown in two places (after auth data is updated and before loading the desktop) to cover different entry flows. Also removed a stray blank line.
There were a couple issues with ACL where access would be denied to app
tokens within access tokens, caused by:
- incorrect recursion: only `false` was considered when in fact the
result from the recursive call is appropriate
- files without a known path are incorrectly handled, which can happen
when iterating over parent directories
* docs: add example for streaming with function calling
* Minor fix and add example to playground
---------
Co-authored-by: Reynaldi Chernando <[email protected]>
WebDAVService catches `/*`, which shouldn't be a problem because it is
on the `dav.` subdomain - however, other middlewares were being invoked
before the subdomain check. Thanks to the `'route'` parameter for the
`next` function we can handle subdomain checks in a more reliable way
* Add ststem info to user options extensions - Add UIWindowSystemInfo, add ui sections for client and server, add basic getClientinfo function
* Fix typo
* Replace accidentally deleted es.js file
* Refactor client information to be consistant with project standard
* Complete Client information in ststem information window
* Remove console logs
* Add basic api functionality for getting server system information
* Structure return data from system server information endpoint | Add copyright to UIWindowSystemInfo
* Add function to format server system api data | Add loading element to server container while waiting for data | Complete System Information
* fix: disallow non admin for backend + move to extensions
---------
Co-authored-by: Daniel Salazar <[email protected]>
This is the effort remaining to bring back URL parameters to drivers
which support them. This fixes the implementation for DNS resolution
resulting in errors for undefined IP addresses when DNS resolution is
successful.
Introduced a resize_window_to_aspect_ratio function and added 'Advanced' menu items to allow resizing the window to 16:9, 4:3, or 9:16 aspect ratios. This enhances user control over window dimensions for specific use cases.
This reverts commit 2139551abf.
It looks like this breaks dev-center because the file associations
aren't properly sent. I will need to investigate this.
This is the first functional migration from ths `es:app` driver to the
`app` driver. Any call to `puter.apps.get` will go through `es:app`
after this change.
* wip: batch fetch get apps for launch apps and recommended apps
* fix: boot issues
* fix: bad refresh app cache
* tmp: remove test for now since can't mock db call
This is the first functional migration from ths `es:app` driver to the
`app` driver. Any call to `puter.apps.get` will go through `es:app`
after this change.
It turned out this error was not coming from `app`, but it was coming
from `app:es` due to a pre-existing issue. Since these tests are meant
to compare the resulting behavior and `app` can handle this case while
`app:es` cannot, the best course of action is to avoid invoking the
issue and only test the intended behavior.
Add tests for all the CRUD operations and related edge cases in `app` to
ensure the behavior is the same as `es:app`. These tests detect 3 issues
across 4 failing tests.
This is comitted separately from the commit for AppService.comp.test.js
that will follow because it interacts with all other test cases. It did
not cause any issue based on what I observed, but I'm still wrapping it
in a separate commit in case we need to revert or change it later.
An "anti-test" (test that should fail) was created to verify that a test
fails when apps are different. This revealed a problem in the original
logic of comparing the database state (UUIDs don't need to be, and will
not be, identical; they need to be excluded from comparison). This
commit contains the new test and fixes the existing test case, which was
passing because this problem caused a false-negative.
The file `context.js` causes problems in unit tests because vitest does
not play nice with CJS, especially when both CJS and ESM are in use such
as in our repository.
Given that it is not feasible to solve the underlying interoperability
issue, I have elected to make `context.js` a singleton in `Symbol.for`.
This worked very well with `helpers.js`.
The `helpers.js` file has two instances when testing with vitest.
Usually this can be solved by creating an "import bridge" file - another
CJS file that imports the desired CJS file and re-exports it so that the
`require` mechanism for caching modules is used instead of the `import`
mechanism for caching modules. Unfortunately in my most recent test
cases this does not work. I do not know why this does not work. However,
without doing a deep-dive into the internals of vitest I can at least
see that the only state in helpers is for providing `services` as a
pseudo-global, so a hack with `Symbol.for` solves everything.
This test was very difficult to get working because of issues
initializing the context under vitest. After a lot of effort and trying
to narrow down the issue in many ways that didn't work, I eventually
found that manually setting the storage and calling run on the
AsyncLocalStorage object got it working. I'm currently unsure if this is
specific to vitest or not. We don't seem to do this in Puter's kernel
but everything works fine in the typical runtime. Maybe this is
side-effect of otel's own use of AsyncLocalStorage.
This is a naive implementation of the `.upsert()` method that simply
calls `.create()` or `.update()` depending on whether or not the app
already exists.
Primarily these tests were AI generated an then checked over for sanity.
These tests are good unit tests to avoid regressions as a result of
changes to this code but are not sufficient to test for regressions
introduced by this new implementation that will replace `es:app`.
Fixes are also included for a couple issues that were found:
- `null` being included in extensions list
- property called `user_owner` instead of `owner`
Most of this implementation matched `.select()` which saved time. The
common behavior can be factored out, but since the purpose of this
refactor is to flatten everything as much as possible I'm going to leave
the duplicated code and make a note to do this later.
The challenging part was `#build_complex_id_where()`, which is the
equivalent to the `fetch_based_on_complex_id_()` method in
EntityStoreService. This allows `uid: app-UUID-OF-APP` and `id: { name:
'editor' }` to both work.
Adds the `icon_size` parameter to the `.select()` method on the new
non-ES/OM implementation.
When adding the necessary `params` parameter to the `.select()`
method, it was noticed that the `predicate` parameter did not have a
default value - potentially causing a regression; a default value was
set for both `params` and `predicate`.
It turns out self-referencing tables add some nuances to what is and
what isn't ambiguous in SQL queries, so getting this right took a little
longer than expected. Following the entire chain doesn't seem to be
possible so a compromise is made by only traversing one level of depth.
(you can the uid of the owner of the app, but not the uid of the owner
app's own owner)
The "flat" implementation of permissions was broken because
revokePermission tried to delete entries by calling `.set` with an
option called "delete". I'm not sure if this has ever existed on the
puter-kvstore interface, so it's weird that it was called like that.
The permission implicator for protected apps was written before changes
to the permission system that affect the conditions under which a user
is allowed to grant and revoke permissions; specifically this is the
`manage:` set of permissions, which now needs to be granted to the owner
of a protected app.
Additionally, the "level" component of the permission is ignored because
the owner of a protected all is implied to have all the permissions
pertaining to that protected app.
Make the home directory (AKA "~") the default CWD for puter.js, making
relative paths work in environments other than app environments (i.e.
gui or worker environments).
Handle a race condition affecting mkdir operations with the
`createMissingParents` option enabled. When creating a directory because
this option was specified, errors because the directory already exists
are likely due to a race condition and should not be propagated to the
client but instead handled by using the directory that's already there.
* Improve UI for App Deployment Options in Dev Center
- Added CSS styling for deployment option cards
- Implemented active state switching between deployment methods with guardrails
- Abstracted saveEditApp for reuse across Deploy and Edit tabs
- Added error handling for invalid URLs in the Deploy tab
* updated mode's description and fixed function's error
* updated by npm install
* Revert "updated by npm install"
This reverts commit 82cd962f62.
* in url mode the deploy button is enabled by default
* Add README for Puter localization and setup
This README provides an overview of Puter, including installation instructions, system requirements, and support information.
* Update README.od.md
---------
Co-authored-by: Nariman Jelveh <[email protected]>
Introduces thumbnail generation for image files during upload operations. Thumbnails are generated client-side if enabled via the `generateThumbnails` option, and are included in file metadata and operation payloads. This enhances file previews and user experience in the file system.
Based on a stack trace from production and manual static analysis, it
appears that a race condition occurs within hashing_stream
intermittently. The conditions that cause this issue might be heavy
backpressure. The source stream emits the 'end' event before
stream.Transform's transform callback has had a chance to process all of
the chunks, which results in an incorrect order in calling methods on
the `typeof crypto.createHash()` object.
It would appear that `source.pipe(stream)` is not able to propagate
errors from Transform because the chain was simply broken and upload
would get stuck (if this was indeed the cause of upload getting stuck,
which seems likely but not conclusive)
There was a configuration parameter for this but it isn't being used and
has the incorrect name in `config.js`. I decided to keep the old check
here anyway because having support to configure a lower size limit could
come in handy.
I set the limit to 2MiB through the following logic:
- largest icon size I've ever heard of is 512px
- 512*512*4 (4 color channels) is 1048576 (1MiB)
- increase to next MiB just to be safe
Deleted the ComplainAboutVersionsService and its registration in SelfHostedModule, as well as cleaned up related service mappings in DriverService. This streamlines the codebase by removing the version complaint feature.
Fixes#2218
The DEV Center was unable to open worker files in the text editor because
it lacked godmode permissions. The file_paths parameter in puter.ui.launchApp
requires the calling app to have godmode=1 in order to work.
Changes:
- Added database migration 0044_dev-center-godmode.sql to set godmode=1
for the dev-center app (uid: app-0b37f054-07d4-4627-8765-11bd23e889d4)
- Updated SqliteDatabaseAccessService.js to include the new migration
This allows DEV Center to successfully pass file paths when launching the
editor app, fixing the issue where clicking on a worker file path resulted
in an empty editor window.
There were two different things here:
- invalid requests have an ambiguous error message
- migration of PuterFSProvider to an extension caused an issue
for shortcut creation in some flows
Closes#2200
Remove a method in hl_mkdir which was determined to not be referred to
anywhere. hl_mkdir was re-tested to verify that this did not cause a
regression.
This error message was ambiguous for mkdir operations where a shortcut
target is specified for hl_mkdir. The message looks like it's referring
to the shortcut target but really it is referring to the parent
directory for the new directory that will be created.
This merits a test because changes to how `puter.site` works in the
future could easily break this redirection, and maintaining this
redirect is important to us.
Redirect the subdomains `""` and `"www"` to a configurable URL, which is
by default `https://developer.puter.com/static-hosting/`.
This is potentially a breaking change for local instances that have a
subdomain called "www". Users hosting their own Puter may want to be
aware of this.
Closes#2214
Removed unnecessary console.log statements from PuterFSProvider.js and WebServerService.js. Increased PENDING_QUERY_TTL to 3 seconds and added a timeout mechanism for coalesced queries in get_app to prevent indefinite waiting.
* Update first-run-issues.md with dnf5 instructions
Add installation instructions for Development Tools on dnf5.
* Fixing the command to install it on Fedora 41+
Introduces a TTL-based pending query cache to the get_app function to prevent duplicate database queries for the same app lookup. This change improves efficiency by coalescing concurrent requests for the same app and ensures only one database query is performed per unique lookup within the TTL window.
This commit adds the DataAccessModule, which is where replacement
"flatter" implementations for what is currently implemented via
EntityStorage/OM will be developed.
This commit also adds AppService, which is where the `crud-q`
implementor for apps will be implemented.
This commit adds the `select()` implementation for AppService. Currently
it is missing many behaviors for parity with the current ES/OM
implementation including:
- coercion of boolean values
- nested objects and their properties
- `icon_size` parameter support
The EntityStorage/OM mechanism for data access is being replaced.
Specifying 'es:app' in puter.js calls will allow the ES/OM mechanism and
its replacement to be tested together to check for regressions. When the
replacement is done, we can change 'es:app' to the new service name.
This is comitted separately because it should not have any functional
changes. Do not skip this in a `git bisect`, but do not revert this when
testing commits for functional changes.
Eliminated the spinner shown when creating a temporary user in popup mode and removed the corresponding hideSpinner call. This streamlines the user experience during account setup.
Adds the necessary configuration and the `npm run bench` script, as well
as the first benchmark to verify everything is working. The first
benchmark is permissionUtils. This is important to benchmark because
permission strings are used often and there is some non-trivial logic
such as escaping of full-colon characters. Other overheads like database
access will be much more significant, but it may be useful to know how
much more significant in quantifiable terms.
It took a long time to figure out why this was happening, but
user-to-app permissions and dev-to-app permissions were being checked in
sequence instead of concurrently. It turns out it was a recursive call
in user-to-app permissions that was blocking. This recursive call was
not actually a dependency of the query for user-to-app permissions; it
was only needed for determining if default user-to-app permissions are
held by the user. This was fixed by simply splitting up these
non-dependent queries into two separate scanners.
* Remove smol utility library and update usage
Deleted the smol utility library from putility, removed its documentation, and refactored code in linux.js to use native string methods instead of smol.split. This simplifies the codebase by eliminating a redundant utility.
* Remove `putility.libs.time` and inline time utilities
* Update imports and time constant usage in core modules
Replaced usage of time.SECOND with a local SECOND constant in ServerHealthService for clarity and removed unused import. Updated all service imports in TestCoreModule to explicitly include the .js extension for compatibility with ES module resolution.
* Remove unused `wrap_text` and `ansi_visible_length` functions
Deleted the wrap_text and ansi_visible_length utility functions from string.js, as they are no longer needed or used in the codebase.
* Remove `format_as_usd` utility and related docs
The format_as_usd function and its documentation have been removed from the codebase and README files. This cleans up unused or deprecated currency formatting utilities.
* Remove osclink utility and update references
The osclink function and its documentation have been removed from putility. All usages in backend modules have been updated to use plain URLs instead of OSC 8 hyperlinks. This simplifies string utilities and avoids terminal-specific formatting.
* Remove PosixError utility module
* Remove NariMethodsFeature and related references
Deleted the NariMethodsFeature module and removed its usage from AdvancedBase and PuterJSFileSystemModule. This simplifies the codebase by eliminating unused or deprecated NARI method support.
* Remove DevConsoleService and related dev console widgets
Eliminates `DevConsoleService` and `NullDevConsoleService`, along with all code that registers or manages dev console widgets across the backend. Developer messages and notifications are now logged directly to the console. Removes related commands and test mocks, simplifying the developer experience and reducing code complexity.
* Remove MinLogService and related registration code
Deleted MinLogService.js and removed its registration from SelfHostedModule.js. This cleans up unused or deprecated logging functionality.
* Remove `DevSocketService` and related registration
* Increase test job timeouts in CI workflow
* Remove dev environment widget ops counter
Eliminated increment and decrement of the dev_batch-widget ops counter in BatchExecutor. This simplifies the code and removes dev-only UI tracking logic from the batch operation flow.
* Remove console Puter logo feature and related code
Deleted the src/fun/logos.js file and removed all references to the Puter logo display in WebServerService and documentation. This streamlines the server startup output and eliminates unused or unnecessary code.
* Update WebServerService.js
* Standardize console banner formatting in services
* Remove tag cache refresh logic from AppInformationService
Eliminated the _refresh_tags method and its scheduled interval from AppInformationService. This change removes the tag cache refresh functionality, likely due to refactoring or deprecation of tag-based app discovery.
* Remove AI usage testing contributor docs
* Remove dev-console-ui-utils and update related services
* Remove debug console.log statements from backend code
Eliminated various leftover console.log and debug print statements across multiple backend modules and services to clean up the codebase and reduce unnecessary logging in production.
* Remove unnecessary console.log statements
Deleted the CommentService implementation and its test file, and unregistered the service from CoreModule. This removes all comment-related backend functionality.
* Refactor puter-js to remove putility and service layer
* Add fallback for IPC listener registration
* Remove TeePromise in favor of `createDeferred` pattern
* Update utils.js
* Bump version to 2.2.0 in package.json
* Remove model name normalization and driver mapping logic
Eliminated the code responsible for normalizing model names and mapping models to specific AI drivers. The default driver is now set to 'ai-chat', simplifying the model selection and driver assignment process.
* Simplify AIService selection logic in image generation
* Remove unused Together image model constants
* Remove terminal and phoenix built-in apps and emulator
This commit removes the terminal and phoenix built-in apps from the backend, database migrations, and permissions. It also deletes the entire emulator and phoenix/terminal app source directories, assets, and related configuration files. References to these apps in the backend module loader and router are removed, and related SQL migrations are updated to reflect their removal.
* Remove emulator references from SelfHostedModule
* Remove emulator integration and related references
* Remove parsers and pty modules
* Update package-lock.json
Deleted ThirdPartyDriversModule.js, html_footer.js, and html_head.js from the backend source directory. These files are no longer needed and have been removed to clean up the codebase.
Deleted the src/backend-core-0 package and moved its validation helpers directly into src/backend/src/validation.js. Updated references in CoreModule.js and helpers.js to use the new local validation module. Adjusted ESLint configs to remove backend-core-0 references.
* Revert "fix: together ai image prices (#2130)"
This reverts commit 04c8b06616.
* Revert "feat: single image ai endpoint (#2129)"
This reverts commit 161ca74aa3.
* Revert "fix: prevent loot qp if failing ai models? (#2122)"
This reverts commit 8d52cefe47.
* Revert "feat: rename ai models to match norm (#2121)"
This reverts commit 9da8aa0849.
* feat: refactor ai to have single entry point and follow defined model structure
* fix: missing openrouter registration
* fix: dedupe models
* feat: provide usage in stream mode 🚀
We weren't able to see any custom spans, only the builtin
instrumentations for node.js. This commit downgrades opentelemetry so
that we can see custom spans in tools like jaeger as before.
Previously a new ConsoleSpanExporter was passed to the constructor of
NodeSDK. This was possibly unintentional but it did not cause any
issues. After the recent update to opentelemetry, or perhaps the changes
introduced in 3c579dcc0d, this no longer
works as it prevents tools like Jaeger from getting any spans from
Puter's backend.
* Add dashboard UI and routing support
Introduces a new Dashboard UI component with sidebar navigation and user options. Updates backend routing to redirect /dashboard to the root path. Integrates dashboard mode detection and initialization in the GUI, including responsive styles and logic to open the dashboard or desktop as appropriate.
* Improve dashboard user menu and UI behavior
Added support for multiple logged-in users, session saving for temporary users, and improved context menu options in the dashboard. Updated CSS for user button state and adjusted font size for signup terms. Changed dashboard initialization to use UIDashboard instead of UIWindow.
* Add dynamic apps section to dashboard UI
* Add specific class for dashboard apps section
* Refactor dashboard tabs into modular components
* Update style.css
* Add Developers menu and improve signup window behavior
Added a 'Developers' menu item to the dashboard linking to developer.puter.com. Updated login and signup window logic to ensure the signup window opens centered and dominant, improving user experience when transitioning from login to signup.
* Update UIWindowLogin.js
* Refactor apps tab UI and improve app card interaction
It calls requestPermission on the UI module. The method on the UI model
needs to still exist because the UI module is tightly-coupled with IPC.
A refactor of the IPC mechanism on the puter.js side could solve this.
This commit adds methods to request standard directories like the
Desktop, Documents, Pictures, or Videos directory. Additionally, the
message displayed when permission for these directories is requested is
easier to read.
This bug took a long time to diagnose, so I also made an async/await
wrapper around #postMessageWithCallback called #postMessageAsync so that
similar promise resolving errors are less likely here in the future.
The vitest test suite can import different states of the same module, so
this value was very helpful in determining that this was happening and
eventually the cause.
Permission endpoints would trigger 500 errors in cases where the request
did not have correct types for values in the request body. This migrates
all of these endpoints to use the new `validate_fields` function, which
is intended to make validation of fields clearer and more consistent.
This commit also adds a new check to verify that the app which owns the
entity being edited matches. Previously this was not necessary because a
read on the same entity would have always performed the same check and
caused this operation to stop early. (now that an app may have
permission to read entities created by other apps, this is no longer the
case.)
...entity (app, subdomain, etc). When trying to update some non-existing
entity the error message can state that an entity with a particular UID
was not found even if a UID wasn't specified. The UID reported will in
fact be a randomly generated UID because of how default properties work
in entities. This fix makes the error message more specific about which
identifier was used when an entity was not found. This is accomplished
by printing the predicate in a human-readable format.
This update fixes configuration issues in the TypeScript setup by standardizing the tsconfig.json. It sets modern compiler targets (ES2024), uses Node16 module resolution, enables strict type checking, and cleans up test-related exclusions. These changes improve build reliability, prevent casing inconsistencies, and ensure accurate source mapping during development.
By default node has a global `crypto` variable conforming to the
standard for the Web Crypto API. However, this `crypto` object does not
have the `createHash` function, so 'node:crypto' must be imported
instead.
* docs: add Punjabi translation link to README
The Punjabi (ਪੰਜਾਬੀ) translation README.pa.md was added 2 weeks ago but was missing from the translations list in the main README. This adds it to maintain completeness of the translations section.
* Fix Punjabi link formatting in README.md
---------
Co-authored-by: Nariman Jelveh <[email protected]>
* WIP Gemini OpenAI refactor
* refactor: gemini open ai service + geminiCostMap
* Gemini Service fixes
* Cleaning up old Gemini cruft
---------
Co-authored-by: Daniel Salazar <[email protected]>
* Add ElevenLabs TTS provider integration
Adds ElevenLabs text-to-speech support in the backend and frontend. Adds `ElevenLabsTTSService`, updates `PuterAIModule` to register the service, documents configuration, and integrates cost tracking with zero cost in `MeteringService` for now (todo). updates `AI.js` to support 11labs as a provider and adds related tests for `txt2speech` functionality.
* Update 11labs cost map values
* fix: debounce toolbar display after dragging a window
* change naming convention for debounce to match others. (snake case)
* revert changes to package.json that werent meant to be comitted
* Revert "change naming convention for debounce to match others. (snake case)"
This reverts commit aaedee0dfa.
* revert commit aaedee0dfa
* use snake case for drag_release_debounce_timer
This commit adds verification for statically identifiable definite
errors. Sometimes global variables used will be falsely reported as
undefined variables in which case the new file
`mandatory.eslint.config.js` should be updated to include these
definitions in the narrowest scope possible that has these definitions
This is the last error for the mandatory eslint rules. Now we can put a
rule into place so that CI always fails when there's an undefined
variable, which I think is pretty cool.
There's a potential issue here because of an undefined reference, but I
can't seem to reproduce any problem caused by this. However without this
fix this line of code is guarenteed to throw an exception so this fix
should be safe.
This is an error in a handler for a failure case so it shouldn't be
affecting users, but let's handle this error gracefully.
This was a symbol that became not defined after moving PuterFSProvider
to the extension.
LocalDiskStorageController was dependent on putility for TeePromise, but
since putility is a workspace module it's difficult for extensions to
access it (Puter backend core would need to expose it). Since TeePromise
itself is very small and will rarely (if ever) be changed I decided to
move it to a separate package on npm.
Begin work on LocalDiskStorageController in the `puterfs` extension.
This replaces LocalDiskStorageStrategy and LocalDiskStorageService from
the core. The `upload()` method is implemented to verify that it's
working.
This commit by itself will break other storage strategies. The next step
is to allow extensions to register storage controllers for puterfs. Part
of that work is done in this commit by emitting an event to register
storage controllers, but this commit does not include a way to
configure/select storage controllers.
Adding the hasChild method of FSNodeContext as well as a corresponding
method to filesystem providers is prerequisite to moving
FSEntryFetcher's logic into the new puterfs extension.
...use readdir from the provider instead of calling
fast_get_direct_descendants directly on fsEntryService.
This change is prerequisite to removing FSEntryService from core.
The get_capabilities and update_thumbnail methods in PuterFSProvider are
moved to the extension by this commit. This is prerequisite to the
removal of PuterFSProvider in the core.
Now that most of the functionality from PuterFSProvider in core has been
moved to PuterFSProvider in the `puterfs` extension, there are a lot of
unused symbols which need to be cleaned up.
This cleanup reveals that `update_thumbnail` and `get_capabilities` are
the only remaining functions left before PuterFSProvider in core can be
fully removed.
Introduces Mistral OCR integration in backend and updates the `AIInterfaceService` and `MistralAIService` to support new OCR options and response normalization. Updates metering cost map for OCR and annotation usage. Refactors `DriverService` to support interface-specific service aliases. Expands the puter.js `AI.img2txt` API to support flexible options and provider selection, including Mistral OCR.
FileCacheService was still a legacy service extending AdvancedBase. This
commit changes it to extend BaseService and implement the lifecycle
methods consistent with other services. This is a prerequisite for
moving write_overwrite which needs to import the service via
`extension.import` (not possible for legacy services) so that it may
invalidate file cache when a file is written to.
We want this to be fast enough that this benchmark doesn't take a long
time, but part of the effort of making it faster will be running the
benchmark repeatedly, and if it takes a long time then it will take
longer for us to make it faster.
This commit reduces the benchmark size for stat_intensive and
write_intensive so that they don't take several minutes to complete.
These two issues have affected us, but go away without rollup:
- https://github.com/npm/cli/issues/4828
- https://github.com/rollup/rollup/issues/6168
We can just use webpack instead; it has never caused build/npm issues.
This migration was done using AI, by pasting error messages over and
over again until everything worked. Since we're not actively working on
terminal and phoenix (dependents of rollup) currently it doesn't make
sense to focus on doing this migration manually, and any errors not
observed in basic use can be remedied later.
- Added a full French translation of the main README.
- Preserved all formatting, links, code blocks, and HTML elements.
- Ensures feature parity with the English version for French-speaking users.
* feat: comprehensive settings and modal UI/UX improvements
Redesigned settings interface and modal windows with improved visual
hierarchy, spacing, and modern styling throughout the application.
Settings UI improvements:
- Enhanced section headers with proper flexbox layout and centering
- Simplified storage usage display to single percentage with clearer info
- Improved settings cards with consistent spacing and hover states
- Redesigned session manager with horizontal card layout
- Reordered account settings (username → email → password)
- Removed duplicate password option from security tab
Form and input improvements:
- Increased container padding (20px → 24px) for better breathing room
- Tightened label-to-input gap (8px → 6px) for better visual grouping
- Enhanced labels with bolder weight (500 → 600) and refined color
- Larger input fields (12px 14px padding) with smoother corners (6px)
- Added hover states with border color transitions
- Removed distracting box-shadow focus rings across all inputs/selects
Button improvements:
- Modernized primary buttons with solid colors (removed gradients)
- Added flexbox centering for consistent text alignment
- Reduced button text size (13px) for cleaner appearance
- Improved default button styling with refined gray palette
- Better active/hover state transitions
Select dropdown improvements:
- Custom SVG chevron arrow with proper 12px right spacing
- Fixed select resizing issue on focus (removed global border/padding override)
- Full-width selects in modals with consistent styling
- Smooth hover states without size changes
Modal windows:
- Consistent 380px width for form modals, 400px for desktop bg settings
- Unified .settings-form-container class across all modals
- Proper ARIA labels and semantic HTML structure
- Error/success messages with refined colors and better contrast
Desktop background settings:
- Color blocks increased to 32px for easier interaction
- Fixed focus outline clipping with proper overflow handling
- Removed scale effects for cleaner interactions
- Flexbox layout for color grid with proper spacing
- Fixed palette icon display with inline background image
Window chrome:
- Increased default shadow (0 12px 24px, 0.12 opacity)
- Enhanced active window shadow (0 16px 40px, 0.18 opacity)
- Better visual depth and window hierarchy
File organization:
- Moved UIWindowManageSessions to Settings folder
- Created helpers/build_settings_card.js for reusable components
- Updated all imports to reflect new structure
* bring back shadow
* improve 2fa + fix theme not changing on cancel bug + fix couple more issues
* style polish
* remove unused styles
* i18n
* fix search bar clipping
* group reset & customize color buttons
* more polish
* enforce min width/height on resizable
* resizable settings and show full name on hover
* style tweaks
When ll_mkdir functionality was moved to PuterFSProvider, ACL and FSLock
concerns were erroneously moved into PuterFSProvider. The intended
design has ll_mkdir responsible for ACL and FSLock, and providers should
never be responsible for ACL.
An important note: it was noticed during this change that mkdir in
PuterFSProvider implements its own ACL check, instead of the ACL check
being performed in ll_mkdir. This means permissions won't be checked for
other implementors of mkdir! This needs to be fixed before custom
filesystem implementations can be considered production-ready.
According to the package documentation: https://www.npmjs.com/package/mime
> null is returned in cases where an extension is not detected or recognized
This call to `.startsWith()` was causing an exception to be thrown upon
right-clicking files without an extension, making it impossible to fix
them.
The styleguide for Puter's backend expects spaces after top-level not
operators inside conditions. This commit adds an AI-generated eslint
plugin and, since it conflicts with the existing space-unary-ops plugin
from stylistic, also adds a wrapped version of space-unary-ops that
ignores top-level not operators so that this plugin will work as
expected.
This service was registered within FilesystemService for legacy reasons
but now it needs to be accessed by an extension. In order for the
extension import to work as expected this service needs to be registered
at the same phase as other services.
This fixes PD incident Q3ZNFWILVOFKU3. This issue was not caught in
testing - in fact after deleting a user the files were deleted as
expected, but it's unclear to me how I observed that with this issue
present.
This temporary proxy provider will allow methods of the puterfs
filesystem type to be moved to an extension incrementally instead of all
at once. See comment above the class for a more detailed explanation.
There is a case where this.entry.id has a value in FSNodeContext while
this.mysql_id does not. I was under the impression that this state was
not possibole. The cause of this eludes me. This commit does not correct
the root cause - it only adds a workaround to this issue by falling back
to this.entry.id if this.mysql_id is `undefined`.
It might not be okay to assume an fsentry was already fetched when
updating the accessed time in ll_read. I'd like to know what changed
this to make this be the case, if it happens to be the case.
There were two references to `storage` in file.js but the search string
I used only detected one of them. I was looking for more references to
`storage` when I found this one. Also, I realized the metering updates
in file.js become redundant if ll_read is used instead so I've removed
those as well.
Adds an appropriate error at a couple different levels. The first is in
FilesystemService. Callers of FilesystemService.node are expected to
provide either an absolute path or an instance of a filesystem node
selector, but there wasn't an explicit check for this so instead an
arbitrary error (read property of undefined) would be thrown. The second
is a higher-level APIError in the batch executor that's a bit more
helpful than a 500 Internal Server Error.
This commit reduces the indentation level and complex arithmetic inside
the createTempUser function in initgui. It is suspected that this change
should greatly reduce measures of the "cognitive complexity" metric.
Apparently the callback operand of $.fn.fadeOut may be called more than
once if there are multiple matching elements. Although we expect there
to only be one element matching the selector `".captcha-modal"`, someone
editing the CSS and HTML would not expect such consequences to the
logic of captcha.
Calling `.fadeOut()` on the result of a jquery selector (i.e. the
evaluation of `$('.some-element-class')`, when it returns an object with
`length=0`) is a NOOP. That's right, it doesn't throw an error; it just
does nothing. This was preventing a temporary user from being created
when `.captcha-modal` isn't present because [the code intended to execute
after the animation] was never run. (square brackets for clarity because
the English is inherently ambiguous)
The PR I merged before putting this one up had my changes to api.d.ts
which I thought where on this branch - turns out I only thought that
because this branch had that one as a parent.
However #1818 has a simplification that this change overwrites. I'd like
to keep this simplification so this commit is restoring it.
The previous implementation of deleteUser was hard-coded to use the
PuterFSProvider file system type's storage implementation specifically,
even if a different filesystem type is mounted as root or for a
particular user.
This change was tested by creating a user, adding some fsentries, and
then deleting that user. The following classes of filesystem entry were
checked:
- [x] user created directory (with contents)
- [x] directory fsentry was deleted
- [x] user created directory (empty)
- [x] directory fsentry was deleted
- [x] immutable directory
- [x] directory fsentry was deleted
- [x] user created file
- [x] file fsentry was deleted
- [x] file storage was deleted
- [x] user created file in trash
- [x] file fsentry was deleted
- [x] file storage was deleted
Accessing the storage object directly duplicates effort of locating the
correct filesystem provider based on the mountpoint of the file with the
contents being requested; an effort that file.js did not perform which
made it incompatible with filesystem mountpoints.
This change has been made to make it easier to move filesystem type
implementations to extensions, because accessing storage directly will
not be supported after puterfs is an extension.
- A new stt driver in `AIInterfaceService` and `PuterAIModule`.
- added methods for audio transcription and translation in the speech-to-text interface.
- updated cost mapping for stt models in `openAiCostMap.ts`.
- Updated permissions and interfaces to support new speech-to-text features.
- added support for OpenAI as a tts provider in `AIInterfaceService` and `PuterAIModule`.
- Updated cost mapping for OpenAI tts models in `openAiCostMap.ts`.
- improved `Txt2SpeechOptions` interface to include new parameters for provider, model, and response format.
- added tests for OpenAI provider in `txt2speech.test.js` to ensure functionality.
This extension has a copy of memoryfs which is exposed as `testfs`. The
purpose of this is to register a new filesystem type from an extension
to ensure it works as expected and to get feedback on a working example.
* Don't update URL when opening public files via direct URL
* Alert user when attempting to open a nonexistent file
* Fix toolbar autohide in public file urls
* Remove extraneous debug logs
* Properly define stat var in public folder URL handling
* Update window URL when focusing an app opened through file URL
* Localize error messages
* Update OpenAI package to version 6.7.0 and add video generation capabilities
- Updated `openai` dependency in `package-lock.json` and `package.json`.
- Introduced new permissions for video generation in `hardcoded-permissions.js`.
- Added video generation service in `AIInterfaceService.js` and registered it in `PuterAIModule.js`.
- Implemented coercion for video streams in `CoercionService.js`.
- Updated driver service to include video generation.
- Added `txt2video` method and options in `AI.js` and corresponding TypeScript definitions in `index.d.ts`.
* Update openaiVideoCostMap.ts
* Revert "Update openaiVideoCostMap.ts"
This reverts commit 9e66f93605.
* change `txt2video` to `txt2vid`
Instead of switching to test mode, which responds with "Lorem Ipsum"
sample output to test the API, throw an appropriate error message for
content moderation failures. This is especially useful when OpenAI's
moderation is way way way way too aggressive as this confuses users.
I was not able to locate a change causing a configuration regression,
however I do know AI was working in my OSS clone and that I had no
reason to change my AI configuration in my `local.json` file. In any
case, it is clear that configuration was not working as intended.
This commit fixes PuterAIModule which was not enabling OpenAI services
when `openai` was configured within the `services` block, even though
the `services` block configuration is supposed to be the recommended
configuration and the global `openai` config object is supposed to be
deprecated.
This commit also fixes OpenAIImageGenerationService which was not
accepting the current parameter name for the API key (`apiKey`) and
instead only accepted the legacy key (`secret_key`) which created this
interesting problem where using the recommended parameter name would
prevent Puter from booting successfully.
This commit begins the plan towards moving PuterFS to an extension. It
is first necessary to analyze the dependencies and determine which
services and modules are part of PuterFS and which ones are not.
Added a constant for PANEL_WIDTH to standardize panel width across the application. Refactored UIWindow logic to utilize this constant for positioning and resizing, ensuring consistent behavior when panels are open. Restored the getSnapDimensions function to adjust available dimensions based on the taskbar position and open panels.
In the prod environment there is no instance of DevConsoleService. If
methods are called on the service without a check to see if it exists,
this results in "read on undefined" errors that can only be produced in
a prod environment. This was the cause of the issue caused by the
previous log cleanup PR where it looked like "websockets were broken".
The missing undefined check is fixed by #1734, but the change in this
commit will catch future cases.
Additionally, this change will help with moving away from the dev
console.
Often fsentry stats are used to see if an fsentry exists, so fsentry not
found logs are common and expected. This commit disables those by
default. Additionally, logging for cache events is disabled as well,
since those are only helpful when debugging cache specifically.
* Implement detailed usage report table
- Added `number_format` function for flexible number formatting with options for decimals, separators, and negative formatting.
- Updated `UITabUsage.js` to include a toggle for viewing driver usage details, fetching and displaying usage data dynamically.
- Improved CSS styles for driver usage details to improve layout and interactivity.
* Update style.css
* Refactor driver usage display in UITabUsage.js
- Updated UITabUsage.js to improve the layout of driver usage information, including a new header structure for better organization.
- Added CSS styles for the new header layout and adjusted existing styles for improved visual consistency and interactivity.
* fix progress bar logic
* fix: adjust toolbar positioning for sidepanel based on taskbar location
* fix: update window width calculation for left position based on open panels
* chore: add http-server as a dev dependency and update package scripts
* refactor: move maximized window positioning logic to UIWindow and remove from UITaskbar
Removes init/construct logs, moves many boot logs to debug level,
introduces debug level in BootLogger, moves "CONFIGURATION MUTATED AT
RUNTIME" message to debug level and allows config.js to output logs to
the standard logger in context.
- Adjust `UIPopover` positioning when a sidepanel is visible.
- Update `UIWindow` to manage visibility states and adjust toolbar positions accordingly.
- Modify CSS for AI Button to change z-index for better layering.
* perf: move user-user perm checks to flat kv entries
* feat: manage permission for user to user and dev to app file sharing
* fix typings cuz macos sucks
* fix: mac os typecase
* fix: chore macOs typecase
* fix: bad join of permissions
* feat: add check-permissions endpoint for checking an users perms
* Add 'manage' to permission lists in the Sharing dialog
* fix: manage being allowed through our ACL
---------
Co-authored-by: Nariman Jelveh <[email protected]>
* add AI side panel to UIDesktop
* integrated `UIAIChat` component into `UIDesktop` for AI interactions.
* added styles for AI side panel, including buttons and chat message formatting in style.css, enhancing user experience with AI features.
* add support for window-based side panels
* remove window resizing logic that is simply broken
* whitelisting added
* Add `showWindow` and `hideWindow` methods to Puter.js
When /user-protected/change-password (and presumably other endpoints
under /user-protected) receive a preflight request they respond with
HTTP status 401. This is because `.use()` calls on the router apply to
all request methods erroneously.
This commit fixes the issue. Further investigation is required to
determine when preflight requests started happening on this endpoint.
* feat(Translation): added support for Armenian and also added Bulgarian
* fixed
* add license header to bg.js
* Update package-lock.json
---------
Co-authored-by: jelveh <[email protected]>
* improve UIItem and UIWindow to support internationalization for system directory names. Updated UIItem to display localized names for trash, desktop, home, documents, pictures, videos, and public directories. Modified UIWindow to set the window title using localized names for the desktop and home paths.
* refactor UIWindow to use i18n for system directory titles. Updated window title settings for desktop, documents, pictures, videos, public, and trash paths to use localized names, improving user experience across different languages.
* add option to automatically set window title to opened file's name
A new checkbox in the app edit section to allow users to automatically set the window title to the name of the opened file. Updated related functions to handle this new setting, ensuring it is saved and reset correctly.
* Update launch_app.js
Using services such as `kv` which expect an actor in context would not
work in a handler for a lifecycle event such as `'init`' in an
extension. In core backend modules is it generally expected that if a
user actor is not in context a backend service will explicitly specify
that the system actor should be used with the `su` service's `sudo`
method. We cannot require extension developers to add this wrapping code
whenever they want to use kv.
In the future it might be better to have a specific "ExtensionActorType"
for this purpose.
The basic `.get()` and `.set()` calls should be the same between
persistent key-value store (puter-kvstore) and in-memory cache (kv.js).
This commit wraps these methods to support the "shorthand" usage.
The `/drivers/call` endpoint hangs when the JSON middleware produces
(or, is going to produce?) a PayloadTooLargeError. Increasing the limit
avoids this issue for typical use.
The extension documentation mentions imports and exports together very
early on, but extension exports should be used sparingly. I suspect most
extensions with exports will be among Puter's builtin extensions.
Extensions now read configuration objects under the "extensions" block
in the backend configuration. Additionally, a `config.json` for default
values directly in the extension's directory is now supported.
* Add 'Set as Desktop Background' context menu item
* Use the `mime` library to detect images in the `UIItem` context menu
---------
Co-authored-by: Nariman Jelveh <[email protected]>
Removes dead code and reduces branching. In the get_service_or_throw_
method, the changes in this commit show how the branching got more
redundnat in the previous change.
Adds new events that DriverService emits: `create.interfaces` and
`create.drivers`. Returns the functionality of the "drivers" registry,
which now expects objects provided by extensions.
- Implemented `tarItems` function to create tar archives from selected files or directories.
- Added `untarItem` function to extract tar archives.
- Updated UI to include options for downloading and tarring files.
- Enhanced item icon handling to display tar file icons.
- Added translations for tar and untar operations.
- Fixes#1629
The Anthropic SDK preemptively throws an error if it thinks a response
is going to take longer than 10 minutes:
https://github.com/anthropics/anthropic-sdk-typescript#long-requests
According to this documentation, overriding the `timeout` option
disables this error. In this commit the option is changed to the default
value of 10 minutes plus an additional 1 second; it is assumed based on
the documentation's phrasing that it is not necessary to make the
timeout higher but simply to specify a value.
RuntimeModules (a feature for extensions) can be accessed by core
modules through a registry exposed in Context by Kernel. However,
TestKernel was not exposing this same registry which caused an error
when module installation occurred during tests.
Updated the `bindSocketEvents` method to check the `original_client_socket_id` before posting updates for 'cache.updated' and 'item.renamed' events. This prevents unnecessary updates when the event originates from the same client socket.
Updated the `WSPushService` to pass additional metadata during user timestamp updates and event emissions for file system operations. This includes modifications to the `_on_fs_create`, `_on_fs_update`, `_on_fs_move`, and `_on_fs_pending` methods to ensure metadata is consistently included, improving the context for GUI updates.
We do update the path of all child directories by calling
filesystem.update_child_paths(), but this was never done for the user's
actual home directory itself (only everything under it).
The most ideal solution would be to delegate this behavior to the move
operation instead of updating the fsentries table directly, but making
this change right now has a high risk of breaking changes since this the
behavior in this file is very old.
The data extension adds convenient access to the database and kvstore
via it's 'db' and 'kv' exports.
Example usage:
const { db, kv } = extensions.import('data');
await kv.set('some-key', 'some-value');
await db.write('INSERT INTO something (a, b) VALUES (1, 2)');
This commit adds the `extension:list` command for listing extensions.
This command is itself defined in an extension. To make this possible,
an event called 'create.commands' is emitted form CommandService with
the event object holding a function that can be used to add commands.
The custom eslint pluggin for the formatting rule I have for the
expressions in control structures isn't a good fit when the condition is
a single variable named by a single character. This happens a lot with
`catch`. `catch ( e ) {` has too much spacing, but `catch (e) {` looks
relatively normal.
Extensions need to be documented at different layers of concern:
1. How to use/run extensions
2. How to create extensions as a contributor
3. How extensions work under the hood
This documentation addresses the third layer, describing how Kernel
and core modules interact with extensions.
I thought you could:
method() {}
set method (v) { /* ... /* }
but you can't. You have to:
get method() { return (function () {}).bind(this) }
set method (v) { /* ... /* }
I don't know why a setter can't just only shadow setting, but that's
how they designed the language. ¯\_(ツ)_/¯
This change makes sure Kernel skips `.git` directories when scanning
for extensions. This allows me to make a git repository containing
example extensions for Puter.
Previously '{source}' was added but this is a bit difficult to work
with since it's the path from the source file, which is usually the
'src/' directory under the repository. This won't be obvious anyone
who doesn't already know this. '{repo}' just points to the path of
the repository itself.
Extension developers should not have to remember what comes form
where between two different globals. This change makes Extension
effectively a facade (Facade Pattern) containing the behaviors
of both extensions and runtime modules.
RuntimeModule is a new construct which represents the import/export
mechanism for Puter extensions. This can be thought of as analogous
to node's Module class. These are called "runtime modules" because
extensions have less control of what they're consuming than a typical
npm module; i.e. `runtime.import('database')` will provide a version
of 'database' that's compatible with the importing extension, but the
version used can't be locked or otherwise determined by the extension.
* client-cache: remove pulling
* client-cache: fix wrong ts field
* client-cache: purge cache on any local update
* client-cache: last_updated_time -> last_valid_time
* client-cache: update cache on remote update
* client-cache: update last_valid_ts every sec
* client-cache: switch to localstorage
* do the cache and purge test when `setAuthToken` is called
---------
Co-authored-by: Nariman Jelveh <[email protected]>
This commit fixes the block that's meant to match backend files. There
was an error in the arguments for '@stylistic/indent' which was
effectively disabling the entire block. In vscode, it is very unclear
that this is happening, so I had to manually run this command:
npx eslint "src/backend/**/*.js" --debug
This commit also disables @stylistic/quotes; I disagree with this
rule for several reasons:
1. Sometimes the appropriate quote depends on the contents:
i.e. '""""' + "''''" is cleaner than '""""\'\'\'\''.
2. If you argue that mixing quotes between concatenated strings
(like the previous example) is a bad idea, then I can further
state that this rule forces me to mix quotes:
`we use a ${templateString}` + "but can't do it here"
* Complete Bahasa Malaysia (Malay) translation of Puter
* Fix code styling
* Add Malay README.md
* Removed dash from `sub-projek`
* Make `Library` italic
* Add Malay language to `Translations` section
Adds a configuration parameter called "slow" to database config which
adds a hardcoded delay 70ms to database operations. This is useful
when testing for performance issues.
* Add context menu to apps in the start menu
* Start menu context menus: Close other menus
* More bugfixes for start menu context menus
* Start menu context menus: Add/remove from taskbar
* Bugfixes for adding to taskbar through start menu
* Highlight start menu icons when ctxmenu is opened
* Close context menus on start menu kbd navigation
* Reset start menu icon state when ctx menu closed
* Fix multiple start item context menus opening simultaneously
* Remove parent argument from start icon context menus
I translated the last part of the document for the italian language.
All the updates are typo-checked for errors , and there's none.
The translation has been made keeping in mind the italian use of various terms, some of the english words haven't been translated due to the extended use of the orignal term in everyday vocabulary.
* Refactor file system operations in GUI and puter.js to use eventual consistency for stat and readdir calls
This update modifies multiple instances of file system operations to include a consistency option set to 'eventual'. This change aims to improve performance and responsiveness by allowing for eventual consistency in file system interactions across various components, including helpers, UI elements, and IPC handling.
* Update cache expiration time for file system operations in readdir and stat to 1 hour
* feat: add network connectivity monitoring and cache purging
This update introduces a new feature that monitors network connectivity and purges the cache when the connection is lost. The implementation includes event listeners for online/offline changes and visibility changes to ensure cache consistency during network disruptions.
* clean up logs
* Implement the first naive version of `readdir` cache
* Purge the entire cache on every single mutation
Right now we're going to use the very naive, but safe, approach to purge the entire cache whenever there is change in the user's fs. We're going to incrementally improve this; but for now, better safe than sorry!
* Add socket event listeners to flush cache on file system item changes
This update introduces event listeners for 'item.added', 'item.renamed', and 'item.moved' events, triggering a cache flush on each event to ensure data consistency in the file system module.
* increase exp time for the cache
* Update readdir.js
* Update index.js
* refactor: update available_templates function for non-blocking template loading
- Changed the available_templates function to initiate loading templates asynchronously without blocking the UI.
- Initialized window.file_templates with an empty array and updated it once the templates are loaded.
- Added a console log in UIDesktop to track transaction duration upon completion.
* Update UIDesktop.js
Fixed spelling and missing accentuations
Adjusted capitalization for consistency with other strings
Made wording more natural in PT-BR (e.g. “site” instead of “website”, “Login” instead of “Início de Sessão”)
This commit removes debug logs that meet these criteria:
- used console.log instead of the log service
- were left in the source tree accidentally
- show up at boot or during stat/readdir operations
This is not a comprehensrve removal; this is a first pass to get a
few of the trivial cases.
- Introduced `input_image` and `input_image_mime_type` as optional parameters in the AIInterfaceService schema to enhance image processing capabilities.
- Updated `GeminiImageGenerationService` to differentiate between data URLs and web URLs for image handling.
- Added coercion support in CoercionService for converting data URLs to streams, including extraction of content type.
- Documented the txt2img method in AI.js to clarify usage for text and image-to-image generation.
Usually Puter has a UID by this point, but if it ever doesn't we can
fall back on using the path with a `LIKE ? + '%'` query. However,
users before a particular date might have fsentries without a path,
so we need to perform a check on the user's timestamp to avoid issues.
is_empty wasn't working correctly while running concurrently with
fetchEntry because because the check in fetchIsEmpty was too
specific. This commit fixes this issue while also adding support for
a 'path' parameter to is_empty.
- Enhanced the `generate` method to accept base64 encoded input images and their MIME types.
- Implemented validation for input image and MIME type to ensure proper usage.
- Updated the content construction logic to handle both text-to-image and image-to-image generation scenarios.
Earlier I actually thought this wasn't running in prod because when I
run Puter locally the "refresh app cache" message doesn't appear.
I ensured that minlog was off but I forgot that around the same time
I also disabled the "tick" log level by default. If it weren't for
that I would've realized this an hour ago. That said, it's kind of
odd that this seems to be the source of the leak, because this isn't
new behavior.
Replaced inline styles with CSS classes for the captcha modal to improve maintainability and readability. Adjusted JavaScript to accommodate the new structure and ensure proper functionality. Enhanced error handling and loading state management during the captcha verification process.
There used to be an app cache here that would be invalidated but I
think this may have been removed because the invalidation logic
was causing issues. A 30 second cache seems reasonable though, so
let's do that for now.
* chore(i18n/emoji): improve clarity of confirmation and name validation emojis
* chore(i18n/emoji): improve clarity of confirmation and name validation emojis
Previously ES6 Module extensions would only work on versions of node
with --experimental-require-module enabled by default, and provided the
entry file had no top-level await. This commit uses "await import"
conditionally if the "type" in package.json is set to "module".
Sometimes the same fs entry is fetched multiple times concurrently
because of parallel methods with separation of concerns.
After this commit, only one parallel fetch will go through and the
others will wait for it. Subsequent fetches will not occur is the
data that was needed is already there.
The 'quick_check' increases the amount of time it takes to perform a
stat operation significantly proportional to the time it takes to do
a stat because an fsentry fetch occurs before a transient
memoization map is available for an operation.
* the Arabic (العربية) translation of Puter is Completed
* Update ar.js
* updating the Arabic (العربية) translation of Puter
---------
Co-authored-by: jelveh <[email protected]>
For instances where svc_fs.node was called and explicitly passed a
NodePathSelector (instead of being passed a legacy-style object
with a path attribute) this code was failing. This commit moves the
affected code snippet after input coercion and updates references
to use the coerced input.
style: formatting changes were applied to the code. Instead of using
nested conditional blocks we use labelled breaks
Not sure when this went away, but we were always getting the
permission though the file path instead of ID/UUID from what it
looks like, which was hiding this problem.
Add a simple 20 second cache with kv.js to the scan_ method of
PermissionService. This will not improve the performance for
the permission system, but it will invoke it less often.
This is a quick solution for javascript files that should not have Puter
extension code prepended to the top of them. We may want to do something
different in the future like skipping directories named "gui" or
following imports (we can only do that with ESM though) or actually
having a way to run ES modules in their own global context (which is
avaialble in node.js as vm.Module under an experimental flag, but there
is no way to use the default linker for imports in the module);
basically there's no good way to do this and it is very unfortunate.
Previous commit to do this contained accidental other changes that I
staged and forgot about. This commit really only contains the sync for
package-json. This was broken for a while - since when we did work on
AWS secrets manager.
* feat: Differentiate tablets by pointer type
Reclassifies tablets with a mouse/trackpad to use the desktop UI.
This is detected by checking for `(hover: hover)` media query capabilities. This ensures that touch-only tablets retain their original, touch-friendly mobile UI while fixing the bug for users with pointer devices.
* Make sure `matchMedia` exists before using it
---------
Co-authored-by: Nariman Jelveh <[email protected]>
This error message in UIDesktop caused me confusion earlier because it
didn't provide any indication of where the error came from. This commit
adds a string behind the error to specify that it happened while trying
to launch an app.
This commit adds an undefined check for metadata from Puter's desktop
GUI inside a filesystem operation frame; this information won't always
be available.
Allows disabling abuse checks undefined origin checks with config
parameters to make development more convenient. The approach before this
change has been to manually comment out these lines of code.
The extension pseudo-global was only available at the root synchronous
execution context of a module loaded as an extension, which meant it
wasn't available for such things as handler functions for listeners even
though it looks like it should be lexically scoped.
This commit writes a `const` to the top of javascript files in the
runtime copy of an extension so that it works as nearly to a real global
as possible.
A real global isn't possible here for two reasons. First, running in the
same v8 VM as Puter means we can't have distinct global objects with the
same name across different extensions. Second, we can't use node:vm
because we would then be unable to support ES modules, which are
experimental in node:vm and also there's no equivalent to createRequire
for the linker even if we wanted to require the
--experimental-vm-modules flag in our package.json. This seems to be the
best we can do given the state of affairs of the runtime.
Some monitoring services want a system to look like it's failing hard
instead of a system being able to report that it's failing successfully.
This commit adds an alternative to healthcheck that throws 500 when any
service is failing, as though reporting such depended on the services
working, to appease these monitoring services and their semantically
incorrect nature of operation.
This commit message sets the precedent for "mon:" as a conventional
commit style prefix for changes related to system health and monitoring.
This optimization speends up load time for Puter significantly when many
extensions are present. This is also necessary for subsequent changes
which may require prepending code to all the source files inside an
extension, which would be too slow without this optimization.
We can assume Arch users are comfortable with making configuration
changes and observing high volume log output (maybe not true for
alternative distributions of arch, but for base Arch absolutely) so it
probably makes sense to have the log minimizer off for these cases.
* fix(gui): prevent background apps from stealing focus
* remove the `background` option as it's not really needed or used in other parts
---------
Co-authored-by: Nariman Jelveh <[email protected]>
While previously the /rename endpoint sent only a websocket message to
the client, move didn't fire a rename event if the name of the file had
changed. This commit adds a more generalized rename event that can be
reliably used to update a UI whenever the name of a file changes.
* Fix buggy arrow key navigation in start menu
* More fixes for start menu keyboard navigation
* Fix issue with start menu searchbar focus
* Rewritten start menu keyboard navigation
When you need to transform strings or other primitives inside an object
and preserve the object's structure in an optimally memory-efficient
way, this does that.
When /sign is called with UIDs instead of paths, it is possible to get a
response without 'path' properties present in "signed fs item" objects.
This commit addresses the issue by fetching paths from FS node objects
as a last resort.
- Implement a new method to serve a custom 404.html file if it exists in the subdomain root path.
- Update existing error responses to utilize the new custom 404 handling.
- Ensure fallback to default error handling if the custom file is not found or an error occurs during reading.
- Add translations for all previously missing keys in nn.js
- Add translations for UI elements including window titles, alerts, and desktop UI
- Maintain consistent formatting with proper indentation
- Add contextual English comments to aid future translators
- Ensure all keys follow correct naming conventions
Fixes#366
This commit expands on the previously implemented '%appdata%' value for
the 'path' option for "Open File" dialogs and allows it to be a prefix
for arbitrary subdirectories under an app's AppData directory.
This commit adds a 'path' option to showOpenFileDialog by supporting it
in the relevant conditional block in IPC.js. A special path "%appdata%",
which would otherwise produce an error in the file explorer (so no
conflict is possible), will resolve to the appdata directory of the
current app.
* Windows WebDav support
* feat: 2fa support for dav
* fix auth cookie when Basic auth present
* dev: dav: refactor handler, support root level navigation
* dev: dav: JSDOCing important things
* fix: possible edge case of password containing colon character
* feat: direct token login for webdav
* set cookie to not be session cookie
* fx: webdav undefined origin support
Allow apps to launch new instances or other apps with specific files.
The files must be passed as file signature objects, ensuring it was a
file the app was granted access to through a user action.
Adds a 'copy' mode to showSaveFilePicker. In this mode, a source file is
copied to the target file. The file may not exist in another apps
AppData directory. Unlike the 'move' mode, the file can be outside of
the app's AppData directory (a "user" file); in this situation the user
will be prompted to grant permission for the copy action. The app will
have access to the newly-created copy.
Adds service for querying controlling user for a domain. If no user is
verified as allowed to control the domain then we give control to the
'admin' user (to support local configurations of Puter).
After this point, I find myself a bit stuck because DNS queries are
incredibly difficult to test locally when you use tailscale.
With this commit alone, any user can specify "domain" on their
subdomains. This means they could affect the route for domains they
don't control, so this is not production-ready without further changes.
Temporary users can go through email confirmation which effectively
makes these users registered/permanent users. When email is confirmed
they should be moved to the default group for registered users.
* no more global puter object in workers
* also support my as a global in workers
* support incoming user object in workers
* also support myself in puter workers
In EntityStoreService, update and upsert both make use of the
detect_identifier utility function to get an identifier to pass through
to (eventually) SQLES.
For `update`, the `id` object is passed as the argument. Properties are
removed from this object when "redundant identifiers" are extracted to
create the update predicate.
For `upsert`, the `entity` object is passed and `id` is ignored. It is
suspected that this was done for reasons of improved developer
experience for developers using the API. The mutation behavior of
detect_identifier caused issues when trying to modify a property that
can also be used as an identifier, without having another identifier
available. (i.e. need to get UID of a subdomain to change the
`subdomain` property instead of just using `subdomain` to identify it).
This commit modifies the default behavior of detect_identifier to not
remove properties, then adds a flag to preserve the previous behavior
which is set TRUE by `update` since it's widelely used by puter.js and
has higher impact for potential regressions.
This doesn't completely fix the misalignment of selection area but improves a lot of issues with it. A temporary, middle-ground solution until I implement the full-on selection area rendering
* feat(gui): Enhance taskbar functionality and positioning
- Implement dynamic taskbar position management with options for left, bottom, and right placements.
- Update desktop dimensions and window positioning based on taskbar position.
- Add context menu options for changing taskbar position on desktop devices.
- Ensure mobile devices always display the taskbar at the bottom.
- Introduce CSS styles for taskbar positioning and adjust desktop padding accordingly.
* feat(gui): Reinitialize tooltips based on taskbar position
- Implement dynamic tooltip positioning for taskbar items based on the current taskbar location (left, right, bottom).
- Ensure tooltips are destroyed and recreated when the taskbar position is updated, enhancing user experience and consistency.
* feat(gui): Improve taskbar and tooltip positioning
- Add support for dynamic tooltip positioning for the 'top' taskbar location.
- Adjust CSS styles for arrow tooltips to enhance visual alignment and positioning.
- Refine taskbar item positioning for left and right placements to ensure consistent appearance.
* Improve popover positioning based on taskbar location
- Improve `UIPopover` positioning logic to account for left and right taskbar placements.
- Adjust Y position of popovers to ensure they appear correctly below toolbars for left/right taskbars.
- Update CSS styles for arrow tooltips to enforce consistent positioning with !important declarations.
* Refactor context menu positioning logic in UITaskbarItem
- Introduce a helper function to dynamically calculate context menu position based on the taskbar's location (top, bottom, left, right).
- Ensure context menus are positioned correctly relative to the taskbar item, improving usability across different taskbar placements.
* Fix UITaskbar window height calculation for consistent positioning
- Adjust the height calculation for windows in the UITaskbar to remove an unnecessary offset, ensuring accurate window sizing relative to the toolbar height.
- This change improves the visual consistency of maximized windows across different taskbar placements.
* Enhance window snapping and positioning based on taskbar location
- Introduce a new function to calculate snap dimensions and positions dynamically based on the taskbar's location (left, right, bottom).
- Update window snapping logic to ensure windows are positioned correctly relative to the taskbar, improving usability and visual consistency.
- Adjust boundary checks for window placement to account for taskbar height and position, enhancing the overall user experience.
* Update default taskbar position to 'left' and adjust CSS padding for desktop layout
- Change the default taskbar position from 'bottom' to 'left' in UITaskbar.
- Modify CSS to increase left padding for desktop taskbar positioning, enhancing layout consistency.
* Improve CSS for desktop layout with height adjustments
- Update CSS styles for input fields and desktop taskbar to set height to 100vh, ensuring consistent full-page layout across different screen sizes.
- This change improves the visual consistency and usability of the interface.
* Improve desktop selectable interactivity and taskbar tooltip behavior
- Add functionality to mark the desktop as selectable active, improving user interaction with desktop elements.
- Update tooltip display logic to only show when the desktop is not in a selectable state, enhancing usability.
- Adjust CSS styles for desktop layout, ensuring consistent behavior and appearance when the desktop is active or inactive.
* Update default taskbar position logic for first-time and existing users
- Set the taskbar position to 'left' for first-time visitors and default to 'bottom' for returning users without a saved preference.
- This change improves the user experience by providing a more intuitive initial layout for new users while maintaining consistency for existing users.
- Add new animation functionality to the taskbar; icons will enlarge when the mouse hovers over them
- Introduce new CSS properties and styles to support the animation effects
- Implement mouse move and leave event handling in UITaskbar
- Add UITaskBarCreateCurve and UITask components
* Update README.md
* Fixed issue: #1033 (Added app category display in Dev Center in main app list)
* Fixed issue: #1033 (Added app category display in Dev Center in main app list)
* test 1033
* Fixed issue: #1033 (Added app category display in Dev Center in main app list)
* Fixed issue: #1033 (Added app category display in Dev Center in main app list)
* Center the app checkbox
---------
Co-authored-by: jelveh <[email protected]>
- Added login and logout functionality with corresponding UI elements.
- Enhanced layout for user information display and login button.
- Integrated authentication state checks to update UI based on user sign-in status.
- Improved button styles and interactions for better user experience.
- Added user-select: none to disable text selection for better UX.
- Adjusted margins for buttons and elements to improve spacing and alignment.
- Modified the layout of the navigation bar for a cleaner appearance.
- Added a settings button to open a modal for configuring Puter.js URL and API Origin.
- Implemented functions to load and save settings to localStorage.
- Dynamically load the Puter.js script based on user-defined settings.
- Styled the modal and its components for better user experience.
This commit implements uploading Puter files through ai.chat using
Claude's beta "file inputs" feature. To use this, simply specify
`puter_path` in a content part, and that content part will be
transformed into the correct type of content part for the specified file
and the file will be uploaded.
- Introduced a "Reset results" button to clear test container backgrounds and remove error messages.
- Implemented hover styles for the reset button to enhance user interaction.
- Ensured the reset functionality hides the progress panel and resets progress tracking.
- Introduced two new tests: testGetPerformance and testSetPerformance.
- Each test measures the execution time of the respective method and asserts that it completes in under 100ms.
- Ensured correct value retrieval and performance metrics are logged for both tests.
- Added a progress panel to display real-time test execution status, including current test, progress percentage, and elapsed time.
- Introduced styles for the progress panel and its components to enhance visibility and user experience.
- Implemented JavaScript functions to manage progress tracking, including starting and stopping timers, and updating the panel with test results.
- Ensured the progress panel is responsive to test selections and updates dynamically during test execution.
- Adjusted the styles for the test counter to enhance its appearance.
- Removed inline styles from the test counter span for cleaner HTML structure.
- Ensured consistent font size and color for better readability.
- Added a fixed navigation bar for improved accessibility and layout.
- Introduced a test counter to display the number of selected tests.
- Updated styles for better alignment and spacing in the test UI.
- Ensured the counter updates dynamically based on checkbox selections.
- Updated the test UI to include a master checkbox that controls the selection of individual test checkboxes.
- Implemented logic to update the master checkbox state based on the selection of individual checkboxes and group checkboxes.
- Adjusted the margin for h2 checkboxes for improved layout.
- Added sticky positioning for h2 headers in the test section.
- Updated h2 elements to include checkboxes for grouping tests (File System, Key Value Store, AI).
- Implemented event listeners to synchronize individual test checkboxes with their respective group checkboxes.
- Simplified select/unselect all functionality to update group checkboxes accordingly.
All users have access to KV, however the permission system is used
because:
1. KV is a driver, and all drivers have access checks
2. The rate limit policy comes from the permission system
This change uses support for implicit permission shortcuts to prevent
any of the permission association tables from being read. It also
hard-codes the policy so that KV's rate-limit policy is not read from
the policy.json file.
Permission implicators with the "shortcut" option will be checked prior
to concurrent permission scanning. If any of these permissions are
granted, then the concurrent phase of permission scanning will not be
invoked; instead, the user will only see the shortcut permission.
It may be useful to add an option in the future for a full permission
scan, which could be useful in such things as a user interface to help
with permission management.
* experimental Cloudflare Workers for Platforms support
* add support for the puter driver
* stop hardcoding api.puter.localhost
* support destroy from express route as well
* initial worker support
* xhrshim + fixes (incomplete)
* change order of readyState + load event
* remove some debug logs
* change worker/puterUtils into a cjs module
* Cloudflare workers eventtarget workaround
* worker preamble webpack
* edit worker readme to reflect reality
* allow a way to code in api endpoint instead of hardcoding it to api.puter.com
* move cloudflare eventtarget fix to puter-portable template
This is so it gets run before the rest of puter-js initializes
* remove express route for worker
Backend had tests written in mocha as well as a test written for jest
(created by an AI utility, wasn't compatible with mocha tests). The AI
generated test had merit so it was migrated to vitest along with all the
mocha tests, which supports conventions from both frameworks.
Vitest also has an excellent watcher cli.
The root repo package.json now runs unit tests in backend. Before it was
only running tests defined in the _test method of backend services.
* fix: return proper error message when the model is not found
* use global source for the domain
Co-authored-by: Eric Dubé <[email protected]>
---------
Co-authored-by: Eric Dubé <[email protected]>
Closes#1326
- fix mis-handling of aliased models and DRY so it doesn't happen again
- fix where we try to get model details for a pseudo model
(usage-limited)
- fix metering with non-streaming mistral requests
Using LLOWrite outside of HLWrite, which is useful inside a Puter
extension when a simple write operation is being invoked by the backend,
required passing a thumbnail. However, sometimes this is not necessary.
This commit makes it possible run an LLOWrite operation without passing
a thumbnail stream.
The following changes make it easier to host web apps from inside a
Puter extension:
- expose express module to prevent mixing versoins
- allow registration of URLs exempt from origin requirement
Stack traces aren't logged when a health check failure occurs. This was
caused by interfacing with AlarmService directly instead of using the
error service.
The large if...else block for single-item vs multi-item selection
context menu items makes it difficult to extract common behaviors
between the two. For example, the "create shortcut" menu item could be
added by the same code snippet in both cases, and that snippet might
have conditional logic for the number of items (with 1 as a special
case).
The reason to move branching logic to the code snippets that handle
individual menu items is because the previous change to fix shortcuts in
shared directories revealed cross-cutting concerns in branching logic.
Since both single-item and multi-item "create shortcut" options both
have branching to handle the shared directory case, they are now more
similar than different.
Fallbacks from or to the fake-chat service should not be allowed.
Fallbacks to the "costly" model from fake-chat could result in
unintended charges and fallbacks to real models from fake-chat could
result in service abuse.
The SQL statement for creating a group uses syntax that only works under
sqlite. This was caused by introducing anomaly detection when a user
creates a large number of groups in quick succession.
This adds an experimental custom token authentication endpoint to Puter.
This is disabled unless the firebase-auth service is explicitly
configured, and is not yet ready for production use.
* Removed css property overflow: hidden at the parent container which was interfering with the layout calculations and was forcefully clipping child elements
* Replace css property overflow: hidden with contain: paint to fix stacking without masking border-radius
Fixes#1233
Already existing was the functionality to go to puter.local/@username to
access the Public folder belonging to "username". This commit adds the
ability for relative paths such as puter.local/@username/document.md to
access /username/Public/document.md in the suggested app for handling
".md" files.
This is the product of a couple hours of debugging. We can now remove
the uuid entry from the cache for a deleted user without the strange
lockup behavior that was being observed previously. However, it is still
explained exactly how this happened; while this commit addresses the
cause it does not represent an actual understanding of the issue.
What is known is the following:
- /delete-own-user can trigger a complete lockup
- this happens when invalidate_cached_user is called
- kv.del('users:uuid:<uuid of user>') triggers the issue
- ... because get_user returns null and
- configurable_auth middleware accepts the null value
- configurable_auth middleware DOES call next()
- it is unknown why a lockup occurs after this
This allows a logger to be specified in the execution context. If
LogService sees this, it will perform its usual logging but also call
the injected logger.
Driver interfaces don't require specifying the structure of the return
value when it's a JSON object, but parameters require specifying what
parameters can be provided. This commit adds a special wildcard
parameter for interface definitions. When the wildcard parameter is set,
the entire input object is considered as if it were the value of one
parameter.
Instead of puter.drivers.call, make it puter.call. This is accomplished
by allowing puter.js modules to mutate the `puter` object on
initialization. Support for an optional `_init` method, similar to
backend services, is added to Puter modules to help with this.
This commit modifies puter.js to allow calling an
interface+service+method with matching names without redundantly
specifying. The 'ip-geo' service is also renamed to ipgeo to match its
method name and allow a simple:
puter.drivers.call('ipgeo', { ip: '1.2.3.4' })
This commit adds the concept of a toLogFields method on objects which
will determine how they're turned into log fields in LogService. This
method is now implemented on actor to prevent errors when the object is
passed to log functions without being stringified first.
I wasn't able to reprod any memory leak from a user having a large
number of files locally, but it's showing up in logs and maybe could add
up with lots of temp users getting auto-removed. It's worth a shot.
There were issues with async handling in events which can make it
difficult to use event handlers to mutate values provided by an emitter.
This is not an optimal solution: this will await event listeners in
sequence. Ideally, event listeners should be awaited concurrently.
Usage/cost tracking per user was over-fitted to LLM/AI services. This
commit adds CostService and updates AIChatService to use that instead of
updating the `ai_usage` table. The `ai_usage` table is now considered
deprecated.
A service called PermissiveCreditService is enabled by default in
SelfHostedModule. This is so users who host their own Puter instances
don't have to worry about usage limits, since they're providing their
own keys anyway.
Previous logic was:
- on email change, update temporary value
- send email to confirm new email
- temporary value is moved to real email
This doesn't work when an account has not yet confirmed their email
after signup (i.e. user's email_confirmed is still 0). Well, it actually
does work, but the user is only able to confirm the change to their
email and not set their account as having a confirmed email.
New logic has a branch for this case; IFF email_confirmed=0:
- change account confirm code
- send new account confirm email
A logo addition from another PR snuck in. This definitely makes it
consistent with signup, but this logo broken! This commit makes it be
not broken anymore.
* refactor: migrate interfaces.js to new registration mechanism
- Created EntityStoreInterfaceService for crud-q interface\n- Created AnalyticsInterfaceService for puter-analytics interface\n- Added InterfacesModule to load these services\n- Removed interfaces.js\n\nCloses #1131
ai: true
* chore: remove interfaces.js file
ai: true
* fix: DRY CRUD interfaces
This comment is flagged as AI-generated, but Claude rate-limited before
it could actually make the commit so this commit was made by hand. Well,
while I'm writing this commit message I may as well mention that Claud's
rate limits are relentless and it has become impossible to use Claude
for some purposes as a result.
ai: true
* refactor: replace interfaces module with separate Module.js files for entitystore and analytics
- Removed interfaces module\n- Added EntityStoreModule.js to entitystore module\n- Added AnalyticsModule.js to analytics module\n- Updated main index.js to use the new modules directly\n\nai: true
ai: true
* fix: modules exported and registered incorrectly
* feat: add KVStoreModule for puter-kvstore interface
- Created KVStoreModule.js\n- Created KVStoreInterfaceService.js to register the puter-kvstore interface\n- Updated exports.js to include the new module\n\nai: true
* fix: remove index.js from kvstore module
- Removed unnecessary index.js file from kvstore module\n\nai: true
* fix: remove index.js files from analytics and entitystore modules
- Removed unnecessary index.js files from analytics and entitystore modules\n\nai: true
* fix: cleanup mycoder mistakes again
...because it actually threw out my previous commit where I already did
this.
* Added Revis distributed cash to enhance our Captcha Verification system so that we prevent our system from replay attacks
* Fix: There was an error with the implementation of Redis, so I reverted to our previous version that uses in memory storage
* Integrated the captcha verification system into our sign in Form. The captcha verification system now works on both login and sign int
* Remove test files from captcha module
* Update src/backend/src/modules/captcha/middleware/captcha-middleware.js
Co-authored-by: Eric Dubé <[email protected]>
* Update src/backend/src/modules/captcha/middleware/captcha-middleware.js
Co-authored-by: Eric Dubé <[email protected]>
* Now the captcha can be requested on condition, this llaows extenstions to control wether a captcha should be required,
I fixed the code in CaptchaModule to use config
and got rid of the lines that made captcha middleware available since it wasn't used anywhre
* I split the middleware into two distinct parts, so that the frontend can now determine captach requirements. PuterHomePageService can set GUI parameters for captcha requirements. The /whoarewe endpoint provides captcha requirement information and the extensuo system integration is maintained
* Fix security issues with password handling in URL query parameters
* Made sure that the enter key, submits the login request instead of refreshing the captcha
* In development we can now disable the Captcha verification system by running it with CAPTCHA_ENABLED=false npm start
* Went back and modified checkCaptcha so that it checks at the start to check what CAPTCHA_ENABLED is equal to
* Refactor captcha system to use configuration values instead of environment variables
* Fix captcha verification and align with project standards
* Update src/backend/src/modules/captcha/README.md
Co-authored-by: Eric Dubé <[email protected]>
* fix: incorrect service name
* dev: use Endpoint for captcha endpoints
Use Endpoint class, which uses eggspress behind the scenes, which handles
async errors in handlers automatically.
* dev: add extension support and simplify captcha
- removed extra error handling
- removed dormant code
- no distinction between login and signup (for now)
* clean: remove local files
* fix: undefined edge case
---------
Co-authored-by: Eric Dubé <[email protected]>
* feat: add public endpoint for models list
- Created ChatAPIService for public endpoints\n- Added /chat/models and /chat/models/details endpoints\n- Registered service in CoreModule\n- Added tests for the new service\n\nCloses #1227
ai: true
* Update src/backend/src/services/ChatAPIService.js
* Enhanced ai command to perfom other commands
* Enhance AI Command in Puter's shell
* Enahanced ai command to use tooling/function calling
* Fixed circular dependency and added list function to Builtincommand
* Fixed circular dependency and system prompt
- Clarified that the Nodemailer example is for testing MailHog setup\n- Added information about how Puter uses Nodemailer\n- Added references to the EmailService class
ai: true
* docs: improve PuterAI module documentation structure
- Update docmeta.md to describe top-level doc structure\n- Create README.md for PuterAI module documentation\n- Move requests.md content to api_examples.md\n- Add ai_usage_testing.md in contributors directory\n\nCloses #1215\n\nai: true
* docs: remove original requests.md after content migration
Content has been migrated to api_examples.md with improved organization and structure.\n\nai: true
- Renamed 'options' to 'requestParams' to clearly indicate parameters sent to the backend driver\n- Renamed 'settings' to 'userParams' to clearly indicate parameters provided by the user\n- Updated comments to be more descriptive about the purpose of each variable\n\nFixes #1212\n\nai: true
Modified the event handler in AIChatService to only skip usage reporting for fake-chat when it's not using the costly model, allowing the costly model to properly report its usage and costs.
ai: true
Added _init method to FakeChatService to register itself as a provider with AIChatService, ensuring that the service and its models are properly recognized by the system.
ai: true
Added a new 'costly' model to FakeChatService that simulates incurring costs similar to real AI services. This model can be used for testing cost tracking without incurring actual external API costs.
ai: true
This change modifies the SQL query in check_usage_ to only consider AI usage from the past month when checking against limits, rather than all historical usage.
ai: true
* Add support for pasting multiple file extensions at once in Dev Center
* Fix bulk file extension paste functionality in Dev Center
* fix: add try-catch around tippy
* Fix issues with bulk file extension pasting and add comma key support
* Fix issue with duplicate red tags appearing temporarily
* Implement robust bulk file extension paste functionality in Dev Center
* Fix security issue with JSON.stringify to properly escape < characters
* feat: hide icons/show icons feature added to the right-click/secondary click menu on the desktop
* Fix: Changes made to the hide/show desktop icons feature after receiving feedback in the first pull request
* CSS rule added to static CSS file instead of being implemented dynamically
PR 1175 introduced a bug that wasn't caught where alert messages are not
properly assigned. Additionally, the default alert type was "warning"
which is a regression. This commit makes "info" the default alert type
and ensures options.message is the first candidate for the alert message
contents.
* Update README.pl.md
Things I would change:
Line 1: System Operacyjny Internetu -> System Operacyjny Internet
Line 25: system operacyjny internetu -> internetowy system operacyjny
(Original Translation is more like Internet's OS, not Internet OS)
Line 36: Rozwój Lokalny -> Instalacja Lokalna
(Original does not mean programming, but more like growth or evolution)
Line 97: Połącz się z opiekunami -> Skontaktuj się z opiekunami
(Original has meaning, like connecting by cable, not contacting)
* Update README.pl.md
Changed:
Instalacja Lokalna -> Lokalne Środowisko Programistyczne.
This is a step towards getting puter.js to run in node instead of just
in the browser. In node, all the relative imports need to end with the
file extension, and the "type" option in package.json needs to match the
import mechanism used. It was also necessary to migrate
webpack.config.js to ESM syntax, which I would not have done if the
tooling didn't force me to.
* documentation: new documentation for emit features
* Update events documentation and doc_helper.js script
* Update package.json
Co-authored-by: Eric Dubé <[email protected]>
* added manual_overrides.json.js file
* Update doc_helper.js to resolve paths relative to project root and update events documentation
* created a new events.md generated file, differences can be seen.
* added and populated events.md file. Can now compare new and old versions
---------
Co-authored-by: Eric Dubé <[email protected]>
ESLint cannot support our preferred code style for backend without
writing custom plugins. On frontend, we already decided ESLint wasn't a
good fit several months ago. This commit removes the eslint config to
avoid other developer's editors making unwanted whitespace changes.
In backend, we use spaces within control structure parens. This really
does make the code easier to read. In the future, maybe we'll write our
own linter.
* add API to get a list of all available models
* modified listModels() and listModelProviders() for readability.
* remove dead code
---------
Co-authored-by: avijh <[email protected]>
* feat: create and export UsageLimitedChatService for when user exceeds usage limit
* tweak: change comment on usage-limited-chat to better explain action
* fixed whitespace
* tweak: remove test-app from gitignore
* tweak: remove extra spacing in AIChatService usage-limited-chat comment
* tweak: fixed whitespace
* tweak: remove tabbed whitespace in AIChatService
* tweak: remove .qodo from gitignore
* tweak: remove extra enter in AIChatService
* Revert "tweak: remove .qodo from gitignore"
tweak: correct mistake on removing extra enter
This reverts commit e066e294fa.
* tweak: add space at fallback and remove whitespace tabs
* tweak: remove whitespace on brackets
* tweak: remove .qodo and test-app from gitignore
* tweak: add accidentally deleted enter back in
---------
Co-authored-by: Rishabh Shinde <[email protected]>
* Added requestPermission endpoint in SDK, updated IPC handler HeyPuter/puter#1150
* - Updated UIWindowRequestPermission.js to accept multiple permission types
- Updated dialog message for permission window in UIWindowRequestPermission.js
- Updated parameters for call to UIWindowRequestPermission in IPC.js
- Added search_uid.js endpoint to allow GUI searches for fsentry by file UUID HeyPuter#1150
* Updated body and header for Permission Request Dialog HeyPuter#1150
- Replace app uid with app name for header in UIWindowRequestPermission.js
- Added path for file permission request body in UIWindowRequestPermission.js
- Removed previously added search_uid.js api implementation previously as it is replaced by simpler call in gui
* Updated permission description generation in UIWindowRequestPermission.js HeyPuter#1150
* Removed incorrect web handling in IPC.js HeyPuter#1150
* Formatting fixes
* UIAlert with dynamic icon types and default button configurations
* Update src/gui/src/UI/UIAlert.js
Co-authored-by: Eric Dubé <[email protected]>
* Update src/gui/src/UI/UIAlert.js
Co-authored-by: Eric Dubé <[email protected]>
* fix: improve error handling in UIAlert component and reseting package-lock
* fix: update UIAlert to use 'type' for alert type selection
* fix: update UIAlert to use 'type' for button configuration
---------
Co-authored-by: Eric Dubé <[email protected]>
Flex isn't being used in the top bar correctly, which is causing
unpredictable issues when people implement new elements on the top bar.
The best solution for this is to use proper flex values but right now
it's important to get the layout back to normal for production so I'm
implementing this sub-par fix where we always include a spacer element.
* Update README.md
Without clear instructions it wasted a few hours just for setting up.
Atleast no one will face issues with domain name in localhost now
* Making LocalHost website visible
* Making LocalHost website visible v2
I really screwed that up on my first attempt. Puter apps don't trigger
the user-connected websocket event, which rendered thread subscriptions
in apps useless. Furthermore, the uuid of the thread that was subscribed
too wasn't present in the event, which is also pretty useless.
As far as I remember, PermissionService was not using APIError because
it was considered to be only for errors from API endpoints and not
internal calls. However, this never made very much sense: APIError is
really more like "error that Puter's backend actually knows how to
handle" at this point; everything should be APIError and APIError should
probably eventually be renamed.
We were sending a JSON error in what should have been an HTML response.
Additionally, the error message wasn't very clear about the nature of
the problem.
This commit makes everything a ton easier for deployers, adding
configuration options to allow nip.io domains or all origins to access
Puter for ideal LAN or VPN configurations.
I used 'fix' for this instead of 'doc' because I am also adding a
package for code that generates markdown, so this doesn't have the
zero-risk nature typically associated with a "doc: " commit.
I uploaded a video for this one but just realized I never made a commit
for it - it was hiding in my git stash.
So here will be a rare situation that the video link is able to be
placed inside the commit message: https://youtu.be/8XiFR1o5Vuk
As far as I can tell from the block post:
https://blakeembrey.com/posts/2024-09-web-redos/
this vulnerability should not affect releases of Puter before this
update because we do not have any routes with multiple parameters where
the second parameter does not start with '.' or '/'.
However, for the sake of good security hygiene and so `npm audit` looks
nice, we're upgrading the package. (better late than never)
Change username doesn't go through ll_move, and does not adhere to DRY
alongside the /rename operation. This led to an inconsistency where the
rename behavior in the change username operation didn't update the
cached fsentry path.
Some services can't tolerate a message with tool calls and an empty
array set on the content property, despite the fact that OpenAI does
seem to support this.
Mistral has a lot of unnecessary quirks because the SDK coerces to
snake_case. We should see if the OpenAI client works with Mistral, and
it it does we'll use that instead so we don't have to maintain all these
exceptional cases.
This adds an incremental migration from models reporting input and
output tokens, to models reporting full token information. This means
AIChatService doesn't need to lookup the model details or know about the
different types of tokens supported by every model.
The current implementation would break for XAIService because it gets
cumulative usage reports as the stream goes on (whereas OpenAI and
DeepSeek only provide this at the end of the stream).
If these APIs were standardized this would have been so much less
painful, but alas, tool calls are implemented completely differently
between Claude and OpenAI. Good job guys.
- add merging of same-role messages for all normalized inputs
- generalize Claude-specific system message extraction
- remove redundant behavior from Claude
TimeWindow is used by TrackSpendingService for two purposes:
- tracking cost within a time window
- preventing duplicate alarms within a cooldown period
It is important to test this to ensure alarms related to AI costs are
accurate.
Sometimes tool use requests are streamed as JSON, but sometimes they're
streamed as an empty string (causing the JSON parser to error). Had they
not streamed anything we actually would've responded correctly, but
what they stream implies "this empty string is the JSON input" which is
incorrect. Oh well.
The call to sock.write() wasn't waiting for the 'open' event, which
worked fine over non-TLS sockets by chance. Also, responses with only
a single WISP packet were resulting in buffered response data not
being sent to the caller.
One of the test cases has been rendered redundant so it has been
removed. Another test was changed to overwrite a file as it's expected
to already exist.
There was an issue affecting mkdir requests with create_missing_parents
set to true which prevented the correct behavior if some of the listed
parents were already present. This commit ensures mkdir selects the
deepest existing node as the parent before proceeding.
These used to serve a purpose but now they only cause a dependency loop
between LL*/HL* operations and FilesystemService itself, making it
difficult to strategize filesystem behavior.
When getting a stream for an SVG icon from AppIconService with a
previously-fetched stored icon provided, a double-encoding bug was
preventing a valid image from being obtained.
Adds an event for app invalidation.
Moves iconify_apps to AppIconService and adds RecommenededAppsService,
which holds some logic that used to be in get-launch-apps. The event for
app invalidation is then used by RecommenededAppsService to determine
when to clear the recommended apps cache.
Moves AppIconService, OldAppNameService, and ProtectedAppService to the
new apps module to keep things organized, and updates imports. There
were no interesting init errors. Services creating a database at init
were tested for failures but this wasn't an issue. It turns out
initializing with a database accessor before the db service inits is
okay, but using that database accessor at init is not.
There are now several services related to apps, and
RecommendedAppsService is about to be added, making this a good time to
create a separate module for these services and migrate the legacy
service AppInformationService.
During migration it was realized that most of the initialization needed
to occur at boot.consolidation rather than boot.init because the
database needs to be initialized first.
There were a few things which made this rather difficult:
- AWS SDK doesn't appear to have a utility to validate message
signatures.
- The only available node.js module that does this is known to be
unreliable.
- SNS sends 'text/plain' MIME type even though the data is in JSON
format, so a middleware had to be added to account for this.
- We don't accept POST requests with no Origin header. Since SNS doesn't
send the Origin header, an exception had to be made for this.
- The endpoint needs to be public and SNS doesn't seem to have a
proxying utility for developers such as what Stripe has.
- Because of the above point, debugging time was affected by deployment
time to the staging server.
This commit fixes the timing of the /whoami call used for the
PrefixLogger (a logger for puter.js that displays app names) to ensure
the API origin and token are available. This is done by waiting for a
service called 'api-access' to be initialized first.
This was discovered while testing changes for /whoami responses that
display icons, because the current behavior breaks the call for
non-puter.com instances.
Calls to `/whoami` generally don't require app icons. Fetching icons of
the smallest size still incurs round-trip latency from the database and
S3, as well as additional delay for any retries due to failed icon
generation.
Although this is technically a regression in `/whoami`, the impact is
localized to Puter's desktop only because apps are not allowed to
receive taskbar icons.
Current issue with get-launch-apps wasn't fixed by catching errors while
reading the stream so this next attempt catches errors from the call to
start reading.
If the error occurs asynchronously this may not work either.
This happened because the return signature of get_app_icon was changed
so that the MIME type can be returned when the uploaded or default icon
is being used as a fallback. AppES was not updated to account for this
change.
Fix explorer table was always too wide with extra white space on right side causing an unnecessary horizontal scrollbar. Changed width for both the header row and item rows from 100vw to 100%, and added min-width.
Apparently there were two things:
- had to remove contextlink from the test command (that was expected)
- can't import libs from putility in the test environment. The error
produced for this doesn't really explain why.
Updated the romanian translations.
I kept the terms "Professional" and "Business" in English as they are commonly used this way in Romanian in IT services context
I adapted the forms of address to second person singular ("tu") instead of formal ("dumneavoastră") to maintain a friendly and modern tone
I maintained consistency with existing translations in the file
Placeholders (%strong%, %%) were kept in grammatically correct positions for Romanian language
A legacy mkdir function was still being used by the
generate_system_fsentries function. However, it wasn't necessary because
we now associate fsentries by uuid, eliminating the requirement to
create the home directory separately from its subdirectories.
The old mkdir function was removed, and generate_system_fsentries was
moved to a new service called UserService, which is intended to
eventually hold all methods related creating, removing, and updating
users.
* added validation function
* tagify implementation (incomplete)
* tagify implementation (completed)
* feat:implemented Tagify and filetype validation on filetype associaction in dev center
* tweak: removed unnessary tagify from dependency (its streamed from CDN)
* removed unnecessary tagify import
Currently the AI comment writer is trusting the AI to write comment
markers. This means sometimes the syntax of a source file is broken by
comment generation. The instructions in the prompt were pretty clear, so
rather than --fixup'ing the previous commit I'm adding these changes
separately as an interesting case study of how different models behave.
Following this result, I am going to be removing mistral from the
comment writer. It is the most likely to misbehave.
I will also be removing gpt-4o-mini, which sometimes included source
lines despite the "no surrounding text" instruction.
Complete missing Igbo translations in src/gui/src/i18n/translations/ig.js
- Translated all missing keys in the Igbo localization file.
- Ensured cultural appropriateness and accurate representation of English text.
- Carefully handled placeholders like %strong% for proper placement within the translated text.
Adds AIChatService, an implementor of puter-chat-completion which can
delegate to other implementors (implementors that have registered with
AIChatService at initialization) based on details of the request.
Makes AIChatService the test implementation. AIChatService then
delegates to FakeChatService when in test mode.
Adds `models()` method to puter-chat-completion. This method, instead of
returning only the names of supported models, includes other details
such as the cost and maximum output size.
Implements `models()` on Claude and XAI.
Registers Claude and XAI with AIChatService.
Replaces Claude with Grok pretending to be Claude. This is in lieu of a
proper fallback system which will be implemented later.
Grok will always say it's pretending to be Claude rather than
identifying itself as Claude.
This new endpoint shows permissions granted by the current user to the
specified user in the scope of a specified filesystem node, including
permissions on the affecting parent nodes.
This is related to two future tasks:
- prevent users from sharing a file with the same user twice
- add an endpoint to modify the access mode of a shared file
Recursively checking for files with 'see' permission? What was I
thinking? This replaces the disasterously awful approach of scanning a
user's entire file tree to find shares, with an approach which instead
selects on the permissions table and extracts file UUIDs from
permissions.
I need this for development/debugging purposes. I figure I may as well
start developing the system dialog we'll eventually have to create
rather than make a temporary debugging element. This window could
eventually become a full-featured group manager, and can easily be moved
to a settings tab.
This was a really small refactor - about 30mins - that moves the concern
of common constructor args for modules outside of each individual call.
A Context object is now used for common constructor arguments. Some of
the values on this object - such as APIOrigin and authToken - are
following values on the instance of the Puter class. This means that for
some modules it is already possible to eliminate the setAuthToken and
setAPIOrigin listeners (out of scope for this commit). Any which remain
could eventually be replaced with a listener on the Context object
itself.
This commit also moves the initSubmodules method to the top of the class
so that it's easier for new devs to find, in case they're looking into
an issue on a specific module rather than the Puter class itself.
The kdmod module was broken since we renamed packages/ to src/. Also,
the update to mod loading for some unknown reason now requires each call
to require to end with `.js`. As far as I know, this was working
previously.
Allows modules to register a listener to the 'install' event without
creating a Module class. This changes how external modules are
installed.
External modules are now referred to as "extensions"; this commit does
not update the term but does use 'extension' as the name of the global.
This was hilariously difficult to debug. This isn't the first time an
issue like this occurred; this happens because of a deviation between
mysql and sqlite, where a JSON-typed column in mysql will return as a
native object in queries, whereas a JSON-typed column in sqlite is a
string column and will therefore return as an un-parsed JSON string in
queries.
Fixes errors that were noticed being thrown by launch_app, specifically
in the branch of logic when launch_app is called NOT via ExecService.
This branch of logic was added to fix an issue where notepad wasn't
prompting to save unsaved changes on close because data-appusessdk was
not properly set to true. The fix still worked, despite throwing these
errors, because setting data-appUsesSDK to true is the first thing it
does. However, broadcast messages to apps launched with launch_app NOT
via ExecService would have been broken.
Adds a filesystem relay service to GUI-side which currently reports an
exmaple fsentry for /stat and /readdir. Added filesystem services for
both sides. Moved filesystem implementations from src/modules to src/lib
since they're being called by services now rather than modules.
This functionality is effectively disabled unless
src/puter-js/src/services/Filesystem.js is updated to use init_app_fs_()
when the environment is 'app'.
Adds XDIncomingService to manage messages from another window. IPC now
registers with XDIncoming and reports whether it was handled, that way
messages intended to reach GUI can be reliably ignored.
On GUI-side, XDIncomingService will be used by FSRelayService (not yet
implemented) to handle requests for filesystem operations from another
window.
On App-side, XDIncomingService might be used by the PostMessageFS
client-side filesystem implementation terminal to listen for filesystem
events that were relayed by GUI (after a permission check) from their
original websocket source. Either that, or we'll open a filesystem
socket for each app using that app's token.
NoPuterYetService was added because IPC.js is loaded before
globalThis.puter exists, and was the easiest way to still allow IPC's
listener to be registered with XDIncomingService.
APIAccessService was added. This service currently holds auth_token and
api_token and does nothing else. FilesystemService listens to this to
maintain a websocket connection. APIAccessService will help to manage
the complexity of all further code dependent on being informed about
changes to the auth token or origin. Currently in puter.js these are
passed around to several modules which manage the same piece of state
information independantly.
mkdir operation was passing user instead if actor. I really think I
changed this already; getting a crazy deja-vu feeling about it. Maybe a
commit was lost somewhere along the road, but not sure.
Dispatching and listening to events is non-trivial. The apparent
triviality is in implementing a list of listeners and calling them. The
non-triviality is in the nature of what happens to a system when it has
multiple different interfaces to register listeners and publish events.
This commit adds TopicsFeature, which allows any class extending
AdvancedBase to declare topics. A topic is a simple pub/sub channel.
TopicsFeature will manage the state of listeners so the class doesn't
need to. A GC-friendly mechanism for detaching listeners is also provided.
The ServiceManager will replace manual management of services within
initgui, and will also be used within puter.js. Eventually Puter's
backend might use this instead of the existing Container class, although
this will be a large change that needs to be done incrementally.
The difference between ServiceManager and Container is the logic behind
when initialization occurs. Rather than have all services initialized at
once when Container's init() method is called, services are initialized
as soon as their dependencies have been initialized.
Adds CachedFilesystem layer to client filesystem chain. Currently only
stat is implemented. The stat implementation will hold onto an entry for
3 seconds as per hardcoded configuration. Eventually, once invalidation
via websockets is working, this TTL should be extended.
Support for trait method overrides will make it possible to use putility
traits with the decorator pattern while using a proxy class to avoid
redundant re-implementation of proxy methods.
Use of the pattern described above will occur in the implementation of
client-side filesystem caching.
- de-coupled xhr callback passing from the interface of the underlying
filesystem implementation.
- This makes the interface to delegate calls more suitable for use with
the decorator pattern.
- The decorator pattern will be used to manage the complexity of the
caching layer by separating the concerns of different caching methods.
This hides database entries with empty types from the list of suggested
apps for files that have no extension. These entries should also be
removed from the database and the bug causing them should be fixed in
dev center.
This could not be tested locally due to another but only affecting
self-hosted installations. This will be tested in staging in the
meantime while the other bug is being fixed.
Return to phoenix shell when a pty stream is closed by twisp.
Pipes in phoenix with commands from the emulator do not appear to be
working properly, but something in there is working.
This involves establishing the protocol through which phoenix instances
run a command on the emulator. The pty is able to communicate with the
terminal in both directions. This commit adds logs to be removed later.
There are a few things left that this commit does not address:
- handling close of delegate process
- handling sigint from phoenix to delegate process
- closing the connection to twisp
I'll elaborate here because the commit name is confusing. Any time an
app gets a connection to another app, either because it launched that
app (or was launched by that app) or requested a connection to that app,
the ID the app gets to represent the app it's communicating with is now
a pseudo app id rather than the app instance ID. This accomplishes two
things:
1. It's more secure. There are multiple places where GUI assumes that
knowing an app's instance ID means you can do things as that app.
2. Between the same two apps, there may now be more than one connection.
This is useful for situations like Phoenix shell talking to the
emulator in multiple separate instances to pipe commands. (this is
coming later)
Changing the email address on an account that did not already have a
confirmed email would result in the email_confirmed column never being
set. This commit fixes that.
Additionally, an SQL statement using the unconfirmed email to identify a
row was changed so it now uses the user ID instead, which is safer.
Resolves: 759
The literal translation for Pictures IS Gambar-gambar, but after reviewing how it looks on live demo Puter, this translation seems a bit off, since other word like Videos is not Video-video, documents is not Dokumen-dokumen.
So, I think it's better to just translate Pictures to Gambar only. Indonesian actually does not care about singular and plural. If we really need to emphasize it plural, we just repeat the word. Which in this context, it is not that necessary to emphasize it.
This is in preparation for the chat completions driver. OpenAI asks that
a user ID be provided in requests when service is being provided to
other users, so we deterministically generate different UUIDs for this
purpose to prevent user information from being exposed.
This issue was caused by an INSERT statement which adds the admin user
to the admin group. The admin user is created at initialization, so for
new installs it does not exist at the time migration scripts are run.
Additionally, new javascript-coded migrations (.mig.js) would not have
run for new installs because of redundant (WET; not DRY) code for
initial setup.
This commit also improves error handling of the migration service, which
was necessary to diagnose this issue.
In the future, setup always needs to be tested after updating migration
scripts, even though migration of existing databases is where most of
the issues will happen.
Resolves: #639
From what I understand, we shouldn't need both `\x1B[2J` and `\x1B[3J`
sequences to clear everything, but xterm.js would not correctly clear
the visible region with only `\x1B[3J`. So, we have both.
filesystem.readdir() can throw, which previously would crash Phoenix and
leave the terminal unresponsive. This change makes it return no results
instead.
Having the parent app send us arbitrary config values was a holdover
from when phoenix was an embedded iframe and not a separate app. It led
to a security issue previously. Let's only take the auth parameters
since we can't get those otherwise, and they're safe to read.
Everything else should be available in our own URL params.
I tried implementing --source=foo too, but was bumping into weird
behaviour with isomorphic-git, so I've removed that for now. Eventually
we'll want it, but it seems fairly niche.
Specifically, we previously didn't resolve short commit hashes into the
full ones.
These functions provide a single place to later add more ways of
selection a commit, such as `HEAD~1`.
Previously, this:
```sh
> rm deleted.txt
> git add deleted.txt
```
...would unhelpfully complain that deleted.txt cannot be found. Now, it
records the deleted file to the index, just as canonical git does.
These allow the user to force color on or off. The chalk library is used
for the output, because it's already used elsewhere in Puter and seems
like a good choice.
Ideally, the default will be based on whether stdout is a tty, but Puter
doesn't yet have that concept, so we just default to color.
For now, the authentication is by --username and --password options,
which obviously is not good because the password is visible. But doing
it in a nicer way requires features that Phoenix or Puter are currently
missing.
I prefer the other names, but being able to type `{ dir, gitdir }` is
shorter and a lot less error-prone than `{ dir: repository_dir, gitdir:
git_dir }`.
A command can optionally define a `completer(args)` function. It takes
an array of strings for the current arguments, and returns an array of
completion results for the last argument.
Includes a few completers:
- alarm:info/clear/inspect completes the first argument as an alarm id
or short_id
- script:run completes the first argument as a script name
- params:get/set completes the first argument as a parameter name
Using npm install appears to have different results depending on whether
or not the parent directory of the puter repository happens to have a
package.json file (ex: nested workspaces).
A package called "useapi" is introduced to provide a dynamic import
system. This import system, rather than relying on the state of the
filesystem, is populated as modules are installed into Puter's kernel.
The "useapi" package is then used to add support for loading external
mod directories as Puter kernel modules, making it possible to mod puter
without any tooling.
* Update docker-image.yaml
* Update docker-image.yaml
* Update docker-image.yaml
* Update docker-image.yaml
* Update docker-image.yaml
* Create Docker on Tag and push on main
Some shell apps care about what order the arguments appear in. When
`parseArgs()` is called with `tokens: true`, it produces this `tokens`
array which represents all the command line options and arguments, in
order, which is useful for these more advanced cases.
This is ported over from an old forgotten branch I'd deleted, then
thankfully managed to dig up again. 😅
Instead of making GroupCommand contain child commands, use a flat array
for commands and implement groups as GroupStartCommand and
GroupEndCommand. This makes it much simpler to iterate the commands
list in order to jump to labels.
Then implement those labels and the commands that use them: b, t, and T.
Also add the s SubstituteCommand, and combine the code for the q and Q
commands.
The following improvements were made:
- do not require empty object in constructor
- allow components to override render mode based on constructor values
- improve error handling in get()
- allow array of property names in on_ready()->listen()
- allow components to be attached to shadow roots
ExportService gets removed and instead a global class registry is added.
The `init.js` file is split into `init_sync.js` and `init_async.js`
so that synchronous code that isn't dependent on imports is guarenteed
to run before initgui.js. The globalThis scope and service-script API
now expose `def`, a function for registering class definitions, and
`use`, a function for obtaining registered classes.
In the first pass I add a `register` method and update `defineComponent`
so it calls `register` as well. This made it possible to create a
proof-of-concept for registered classes. Additionally ExportService was
added to expose registered classes to service scripts. This first pass
works, but it would be better if all types of classes (components or
otherwise) were registered via the same method.
THe `a.stringOf(' \r\n\t'.split('')),` pattern works fine for small sets
of characters, but is horrible for situations like "any alphanumeric".
Instead, let's make it take a callback function that is run on each
character.
- Detect exit status of Puter apps, now that that's available.
- Store the exit status of each pipeline.
- Display a message when the exit status was non-zero.
That message is temporary, until we have a better way of displaying or
querying it, such as the `$?` shell variable.
`puter.exit()` now takes a status code, similar to the exit status on
desktop OSes. This is passed to the appClosed event, so that eg a
parent app can know whether its child app ran successfully.
This is also basic:
git config key # To read a value
git config key value # To set a value
git config --unset key # To delete a value
As noted, --list is not possible to implement currently.
Previously, this would crash in upload() when trying to iterate the
`entries` array, which is undefined when the `items` parameter is an
unsupported type.
Xterm.js produces two kinds of events: onKey and onData. On a desktop,
these are effectively the same, but on mobile, IME inputs produce data
but not key presses. By listening to onData instead of onKey, we get
that input.
With some experimentation, I also found that we don't need the code to
handle enter, home, end, or Ctrl-Shift-V. All of these function as
expected without that code, so we can remove it and simplify this
further. :^)
From version 5.4.0 onwards, xterm scopes its package names as
`@xterm/foo` instead of just `xterm-foo`.
We currently have a copy of xterm.css which we use instead of directly
including the one from the `@xterm/xterm` package, so I've updated the
contents of that too.
We were triggering webserver events in Kernel. This change improves
adherence to separation-of-concerns and ensures event cascading is
working as expected. This also better formalizes the boot sequence.
Every user previously set the max_length as window.TRUNCATE_LENGTH, so
I've moved that constant into the truncate_filename file and set it as
the default if max_length is not specified.
Most of the time, we'll already have a TaskManagerRow for the given
process, so we can just update its properties.
Iterating the results from #iter_tasks means we also insert the rows in
the correct order, regardless of their previous order.
If the Component gets removed from the DOM and then re-added, it already
has contents, and we don't need to create them again. It also has
already had on_ready called, so that doesn't need to happen again
either.
This fix stops Components duplicating their content elements and
listener callbacks whenever they're moved around the document.
This currently behaves the same as it did before: It still recreates the
table contents every half a second. It should also look identical,
though it's possible I missed some small differences.
The component structure is:
TaskManagerTable
- Table
- TaskManagerRow
- TaskManagerRow
- TaskManagerRow
- ...
TaskManagerRow is implemented so that we can later move to modifying
them in place as the process tree changes, instead of having to replace
them all.
Otherwise, most of the code is just moved around, and not changed much.
The object returned from UIWindowProgress() now has a `show_error()`
method, taking a title and message. Calling it will replace the content
of the window with those messages.
I've made use of this for file uploads. The only other place we
currently have errors we could show is for zipping and downloading
files, but we do not always have a progress dialog in that case, so I'll
leave that for now.
I think ideally, we would always create a progress dialog, and it would
then support being invisible initially, but appearing after a delay.
Then we'd always have an object to call `show_error()` on, and it could
then immediately show the dialog. But I'll get to that another day. :^)
Previously we showed "Moving /foo" which was confusing.
Also, make use of i18n replacements instead of gluing strings together,
because other languages might put the words in a different order. For
now, I've modified all the translations so that the "Moving foo" text
will appear as it did before, but these will require someone who
actually knows the different languages to check and correct them.
I noticed during this that emptying the trash from inside the Trash
window uses a different code path without a progress dialog, so I've
added a TODO to merge that in. I tried just using it directly but the
behaviour is a bit different. (The Trash one makes all the items fade
out.)
Run the ESLint static analysis tool on any code that is submitted, to
find possible bugs such as undefined functions and variables. We may
want to adjust the ESLint settings over time, but this seems like a
good start.
This is merged into the previous check-translations.yml action, because
that's also a form of linting. Possibly that could be reimplemented as
an ESLint plugin.
These two seem like bugs but are unclear to me how to fix, so I've added
FIXMEs.
/puter/packages/backend/src/routers/kvstore/clearItems.js
41:32 error 'DB_MODE_WRITE' is not defined no-undef
/puter/packages/backend/src/routers/whoami.js
104:35 error 'db' is not defined no-undef
/puter/src/UI/Settings/UITabSecurity.js
13:13 error 'user' is not defined no-undef
31:13 error 'user' is not defined no-undef
32:70 error 'user' is not defined no-undef
36:30 error 'user' is not defined no-undef
40:82 error 'user' is not defined no-undef
41:83 error 'user' is not defined no-undef
87:41 error 'api_origin' is not defined no-undef
/puter/src/UI/UIWindow2FASetup.js
39:33 error 'api_origin' is not defined no-undef
51:37 error 'api_origin' is not defined no-undef
69:37 error 'api_origin' is not defined no-undef
/puter/src/UI/UIWindowLogin.js
202:73 error 'api_origin' is not defined no-undef
271:73 error 'api_origin' is not defined no-undef
When exiting a window there should be a confirmation if exiting that window will irreversibly destroy work. For example, when you're working on a document and if you exit unsaved changes will be lost.
This doesn't seem to be the case. What work will be irreversibly lost?
I couldn't figure out how to get a name for the no_suitable_app error
unfortunately, so that's just commented out.
/puter/packages/backend/src/routers/sign.js
65:74 error 'subject' is not defined no-undef
114:59 error 'subject' is not defined no-undef
/puter/src/index.js
58:15 error 'loadScript' is not defined no-undef
59:15 error 'loadScript' is not defined no-undef
65:13 error 'gui_env' is not defined no-undef
66:15 error 'loadScript' is not defined no-undef
68:15 error 'loadCSS' is not defined no-undef
69:15 error 'loadScript' is not defined no-undef
73:5 error 'initgui' is not defined no-undef
Almost entirely clarifying use of window fields
/puter/src/initgui.js
82:28 error 'api_origin' is not defined no-undef
118:34 error 'url_query_params' is not defined no-undef
120:17 error 'app_query_params' is not defined no-undef
136:8 error 'url_query_params' is not defined no-undef
136:51 error 'url_query_params' is not defined no-undef
136:105 error 'url_query_params' is not defined no-undef
138:14 error 'url_query_params' is not defined no-undef
138:57 error 'url_query_params' is not defined no-undef
138:110 error 'url_query_params' is not defined no-undef
154:8 error 'url_query_params' is not defined no-undef
154:54 error 'url_query_params' is not defined no-undef
154:110 error 'url_query_params' is not defined no-undef
164:17 error 'openerOrigin' is not defined no-undef
171:30 error 'openerOrigin' is not defined no-undef
173:37 error 'is_auth' is not defined no-undef
184:23 error 'getUserAppToken' is not defined no-undef
184:39 error 'openerOrigin' is not defined no-undef
186:41 error 'is_auth' is not defined no-undef
195:23 error 'getUserAppToken' is not defined no-undef
195:39 error 'openerOrigin' is not defined no-undef
205:8 error 'url_query_params' is not defined no-undef
206:32 error 'url_query_params' is not defined no-undef
218:23 error 'url_query_params' is not defined no-undef
219:22 error 'openerOrigin' is not defined no-undef
219:38 error 'url_query_params' is not defined no-undef
220:26 error 'url_query_params' is not defined no-undef
228:29 error 'embedded_in_popup' is not defined no-undef
238:20 error 'url_query_params' is not defined no-undef
239:21 error 'url_query_params' is not defined no-undef
270:36 error 'openerOrigin' is not defined no-undef
271:30 error 'checkUserSiteRelationship' is not defined no-undef
271:56 error 'openerOrigin' is not defined no-undef
274:44 error 'logged_in_users' is not defined no-undef
274:76 error 'userAppToken' is not defined no-undef
274:92 error 'url_query_params' is not defined no-undef
284:17 error 'userAppToken' is not defined no-undef
288:25 error 'is_auth' is not defined no-undef
302:13 error 'url_query_params' is not defined no-undef
303:38 error 'url_query_params' is not defined no-undef
309:17 error 'logout' is not defined no-undef
331:13 error 'update_auth_data' is not defined no-undef
363:8 error 'is_auth' is not defined no-undef
388:13 error 'update_auth_data' is not defined no-undef
394:23 error 'get_auto_arrange_data' is not defined no-undef
395:31 error 'desktop_path' is not defined no-undef
403:30 error 'url_query_params' is not defined no-undef
405:38 error 'getUserAppToken' is not defined no-undef
405:62 error 'openerOrigin' is not defined no-undef
415:35 error 'user' is not defined no-undef
417:24 error 'openerOrigin' is not defined no-undef
430:24 error 'openerOrigin' is not defined no-undef
438:20 error 'openerOrigin' is not defined no-undef
439:37 error 'getAppUIDFromOrigin' is not defined no-undef
439:57 error 'openerOrigin' is not defined no-undef
444:35 error 'url_query_params' is not defined no-undef
508:46 error 'url_query_params' is not defined no-undef
630:54 error 'busy_indicator_hide_delay' is not defined no-undef
636:49 error 'busy_indicator_hide_delay' is not defined no-undef
647:13 error 'update_sites_cache' is not defined no-undef
656:9 error 'refresh_desktop_background' is not defined no-undef
661:9 error 'is_auth' is not defined no-undef
661:23 error 'first_visit_ever' is not defined no-undef
662:12 error 'logged_in_users' is not defined no-undef
679:14 error 'is_auth' is not defined no-undef
679:27 error 'first_visit_ever' is not defined no-undef
693:12 error 'url_query_params' is not defined no-undef
696:47 error 'url_query_params' is not defined no-undef
704:18 error 'gui_origin' is not defined no-undef
715:17 error 'update_auth_data' is not defined no-undef
728:8 error 'feature_flags' is not defined no-undef
746:19 error 'get_auto_arrange_data' is not defined no-undef
747:27 error 'desktop_path' is not defined no-undef
755:26 error 'url_query_params' is not defined no-undef
758:34 error 'getUserAppToken' is not defined no-undef
758:58 error 'openerOrigin' is not defined no-undef
768:31 error 'user' is not defined no-undef
770:20 error 'openerOrigin' is not defined no-undef
783:20 error 'openerOrigin' is not defined no-undef
792:16 error 'openerOrigin' is not defined no-undef
793:33 error 'getAppUIDFromOrigin' is not defined no-undef
793:53 error 'openerOrigin' is not defined no-undef
801:31 error 'url_query_params' is not defined no-undef
864:42 error 'url_query_params' is not defined no-undef
987:50 error 'busy_indicator_hide_delay' is not defined no-undef
993:45 error 'busy_indicator_hide_delay' is not defined no-undef
1021:13 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1057:13 error 'active_item_container' is not defined no-undef
1061:17 error 'active_item_container' is not defined no-undef
1065:21 error 'active_item_container' is not defined no-undef
1071:9 error 'active_element' is not defined no-undef
1179:21 error 'select_ctxmenu_item' is not defined no-undef
1185:21 error 'select_ctxmenu_item' is not defined no-undef
1198:21 error 'select_ctxmenu_item' is not defined no-undef
1211:21 error 'select_ctxmenu_item' is not defined no-undef
1222:25 error 'select_ctxmenu_item' is not defined no-undef
1255:22 error 'active_item_container' is not defined no-undef
1256:39 error 'active_item_container' is not defined no-undef
1257:21 error 'active_element' is not defined no-undef
1258:23 error 'active_item_container' is not defined no-undef
1263:27 error 'active_item_container' is not defined no-undef
1264:39 error 'active_item_container' is not defined no-undef
1267:27 error 'active_item_container' is not defined no-undef
1268:39 error 'active_element' is not defined no-undef
1268:74 error 'active_element' is not defined no-undef
1268:93 error 'active_element' is not defined no-undef
1271:27 error 'active_item_container' is not defined no-undef
1272:39 error 'active_item_container' is not defined no-undef
1275:39 error 'active_element' is not defined no-undef
1275:74 error 'active_element' is not defined no-undef
1275:93 error 'active_element' is not defined no-undef
1323:114 error 'active_item_container' is not defined no-undef
1331:21 error 'active_element' is not defined no-undef
1334:27 error 'active_item_container' is not defined no-undef
1390:37 error 'active_element' is not defined no-undef
1407:31 error 'delete_item' is not defined no-undef
1419:37 error 'active_element' is not defined no-undef
1419:115 error 'trash_path' is not defined no-undef
1436:31 error 'delete_item' is not defined no-undef
1438:55 error 'trash_path' is not defined no-undef
1445:59 error 'trash_path' is not defined no-undef
1446:61 error 'trash_path' is not defined no-undef
1452:37 error 'active_element' is not defined no-undef
1456:25 error 'move_items' is not defined no-undef
1456:53 error 'trash_path' is not defined no-undef
1467:16 error 'keypress_item_seach_term' is not defined no-undef
1468:30 error 'keypress_item_seach_buffer_timeout' is not defined no-undef
1470:13 error 'keypress_item_seach_buffer_timeout' is not defined no-undef
1471:17 error 'keypress_item_seach_term' is not defined no-undef
1474:13 error 'keypress_item_seach_term' is not defined no-undef
1477:38 error 'active_item_container' is not defined no-undef
1480:108 error 'keypress_item_seach_term' is not defined no-undef
1485:30 error 'active_item_container' is not defined no-undef
1487:78 error 'keypress_item_seach_term' is not defined no-undef
1505:19 error 'active_item_container' is not defined no-undef
1509:17 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1509:63 error 'active_element' is not defined no-undef
1518:16 error 'keypress_item_seach_term' is not defined no-undef
1519:30 error 'keypress_item_seach_buffer_timeout' is not defined no-undef
1521:13 error 'keypress_item_seach_buffer_timeout' is not defined no-undef
1522:17 error 'keypress_item_seach_term' is not defined no-undef
1525:13 error 'keypress_item_seach_term' is not defined no-undef
1531:97 error 'keypress_item_seach_term' is not defined no-undef
1538:67 error 'keypress_item_seach_term' is not defined no-undef
1581:39 error 'active_element' is not defined no-undef
1583:39 error 'active_element' is not defined no-undef
1590:17 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1600:36 error 'active_element' is not defined no-undef
1602:36 error 'active_element' is not defined no-undef
1615:15 error 'mouseover_window' is not defined no-undef
1616:15 error 'mouseover_window' is not defined no-undef
1616:55 error 'trash_path' is not defined no-undef
1621:38 error 'active_element' is not defined no-undef
1623:38 error 'active_element' is not defined no-undef
1628:21 error 'clipboard' is not defined no-undef
1629:21 error 'clipboard_op' is not defined no-undef
1632:58 error 'trash_path' is not defined no-undef
1636:25 error 'clipboard' is not defined no-undef
1648:38 error 'active_element' is not defined no-undef
1650:38 error 'active_element' is not defined no-undef
1655:21 error 'clipboard' is not defined no-undef
1656:21 error 'clipboard_op' is not defined no-undef
1658:25 error 'clipboard' is not defined no-undef
1668:107 error 'last_enter_pressed_to_rename_ts' is not defined no-undef
1682:21 error 'launch_app' is not defined no-undef
1705:21 error 'select_ctxmenu_item' is not defined no-undef
1713:21 error 'active_item_container' is not defined no-undef
1714:37 error 'active_item_container' is not defined no-undef
1717:25 error 'open_item' is not defined no-undef
1736:16 error 'clipboard' is not defined no-undef
1745:37 error 'trash_path' is not defined no-undef
1745:74 error 'trash_path' is not defined no-undef
1745:96 error 'clipboard_op' is not defined no-undef
1748:20 error 'clipboard_op' is not defined no-undef
1749:21 error 'copy_clipboard_items' is not defined no-undef
1750:25 error 'clipboard_op' is not defined no-undef
1751:21 error 'move_clipboard_items' is not defined no-undef
1760:13 error 'undo_last_action' is not defined no-undef
1767:9 error 'mouseX' is not defined no-undef
1768:9 error 'mouseY' is not defined no-undef
1771:13 error 'mouseX' is not defined no-undef
1771:29 error 'mouseY' is not defined no-undef
1771:38 error 'toolbar_height' is not defined no-undef
1771:63 error 'mouseX' is not defined no-undef
1771:78 error 'mouseY' is not defined no-undef
1772:13 error 'current_active_snap_zone' is not defined no-undef
1774:17 error 'mouseX' is not defined no-undef
1774:32 error 'mouseY' is not defined no-undef
1774:49 error 'mouseY' is not defined no-undef
1774:58 error 'desktop_height' is not defined no-undef
1775:13 error 'current_active_snap_zone' is not defined no-undef
1777:17 error 'mouseX' is not defined no-undef
1777:32 error 'mouseY' is not defined no-undef
1777:41 error 'desktop_height' is not defined no-undef
1778:13 error 'current_active_snap_zone' is not defined no-undef
1780:17 error 'mouseX' is not defined no-undef
1780:26 error 'desktop_width' is not defined no-undef
1780:48 error 'mouseY' is not defined no-undef
1780:65 error 'mouseY' is not defined no-undef
1780:74 error 'desktop_height' is not defined no-undef
1781:13 error 'current_active_snap_zone' is not defined no-undef
1783:18 error 'mouseX' is not defined no-undef
1783:27 error 'desktop_width' is not defined no-undef
1783:50 error 'mouseY' is not defined no-undef
1783:59 error 'toolbar_height' is not defined no-undef
1783:84 error 'mouseX' is not defined no-undef
1783:93 error 'desktop_width' is not defined no-undef
1783:115 error 'mouseY' is not defined no-undef
1784:13 error 'current_active_snap_zone' is not defined no-undef
1786:17 error 'mouseX' is not defined no-undef
1786:26 error 'desktop_width' is not defined no-undef
1786:48 error 'mouseY' is not defined no-undef
1786:58 error 'desktop_height' is not defined no-undef
1787:13 error 'current_active_snap_zone' is not defined no-undef
1789:17 error 'mouseY' is not defined no-undef
1789:26 error 'toolbar_height' is not defined no-undef
1789:49 error 'mouseX' is not defined no-undef
1789:66 error 'mouseX' is not defined no-undef
1789:75 error 'desktop_width' is not defined no-undef
1790:13 error 'current_active_snap_zone' is not defined no-undef
1793:13 error 'current_active_snap_zone' is not defined no-undef
1802:21 error 'mouseX' is not defined no-undef
1802:41 error 'mouseX' is not defined no-undef
1802:75 error 'mouseY' is not defined no-undef
1802:95 error 'mouseY' is not defined no-undef
1819:21 error 'mouseX' is not defined no-undef
1819:41 error 'mouseX' is not defined no-undef
1819:75 error 'mouseY' is not defined no-undef
1819:95 error 'mouseY' is not defined no-undef
1840:12 error 'mouseover_window' is not defined no-undef
1841:15 error 'mouseover_window' is not defined no-undef
1876:17 error 'upload_items' is not defined no-undef
1934:21 error 'logout' is not defined no-undef
1936:17 error 'logout' is not defined no-undef
1946:22 error 'gui_origin' is not defined no-undef
1951:50 error 'auth_token' is not defined no-undef
1958:18 error Empty block statement no-empty
/puter/src/helpers/determine_active_container_parent.js
22:30 error 'active_element' is not defined no-undef
25:30 error 'active_element' is not defined no-undef
29:30 error 'active_element' is not defined no-undef
32:41 error 'active_element' is not defined no-undef
32:61 error 'active_element' is not defined no-undef
33:30 error 'active_element' is not defined no-undef
36:41 error 'active_item_container' is not defined no-undef
37:28 error 'active_item_container' is not defined no-undef
/puter/src/helpers/download.js
51:27 error 'api_origin' is not defined no-undef
52:59 error 'auth_token' is not defined no-undef
92:16 error 'operation_cancelled' is not defined no-undef
/puter/src/helpers/new_context_menu_item.js
38:21 error 'create_folder' is not defined no-undef
48:21 error 'create_file' is not defined no-undef
56:21 error 'create_file' is not defined no-undef
70:25 error 'create_file' is not defined no-undef
/puter/src/helpers/refresh_item_container.js
83:13 error 'update_window_layout' is not defined no-undef
86:13 error 'update_details_layout_sort_visuals' is not defined no-undef
124:35 error 'trash_path' is not defined no-undef
162:29 error Empty block statement no-empty
166:51 error 'path' is not defined no-undef
168:34 error 'trash_path' is not defined no-undef
168:62 error 'appdata_path' is not defined no-undef
171:38 error 'desktop_item_positions' is not defined no-undef
178:37 error 'item_icon' is not defined no-undef
207:31 error 'trash_path' is not defined no-undef
216:21 error 'sort_items' is not defined no-undef
217:26 error Empty block statement no-empty
222:13 error 'sort_items' is not defined no-undef
233:17 error 'update_explorer_footer_item_count' is not defined no-undef
/puter/src/helpers/update_title_based_on_uploads.js
21:41 error 'active_uploads' is not defined no-undef
22:59 error 'active_uploads' is not defined no-undef
23:51 error 'active_uploads' is not defined no-undef
27:51 error 'active_uploads' is not defined no-undef
Most of these are window fields that wanted `window.` prepended, but a
couple of issues are code that was using undefined variables (`ht` and
`dir_uuid`) and some switch-cases that I believe are intentionally
falling through.
/puter/src/helpers.js
39:55 error 'auth_token' is not defined no-undef
47:14 error 'api_origin' is not defined no-undef
55:40 error 'auth_token' is not defined no-undef
59:17 error 'logout' is not defined no-undef
199:14 error 'api_origin' is not defined no-undef
208:40 error 'auth_token' is not defined no-undef
212:17 error 'logout' is not defined no-undef
224:14 error 'api_origin' is not defined no-undef
234:40 error 'auth_token' is not defined no-undef
238:17 error 'logout' is not defined no-undef
316:13 error Expected a 'break' statement before 'case' no-fallthrough
323:13 error Expected a 'break' statement before 'case' no-fallthrough
330:13 error Expected a 'break' statement before 'case' no-fallthrough
337:13 error Expected a 'break' statement before 'case' no-fallthrough
367:47 error Unnecessary escape character: \/ no-useless-escape
411:14 error 'isString' is not defined no-undef
420:47 error 'config' is not defined no-undef
519:21 error 'globToRegExp' is not defined no-undef
651:14 error Empty block statement no-empty
656:9 error 'update_auth_data' is not defined no-undef
678:36 error 'api_origin' is not defined no-undef
722:5 error 'update_user_preferences' is not defined no-undef
740:24 error 'uuidv4' is not defined no-undef
746:9 error 'appCallbackFunctions' is not defined no-undef
789:14 error 'api_origin' is not defined no-undef
794:40 error 'auth_token' is not defined no-undef
861:33 error 'trash_path' is not defined no-undef
867:21 error Empty block statement no-empty
889:70 error 'trash_path' is not defined no-undef
891:59 error 'trash_path' is not defined no-undef
894:49 error 'trash_path' is not defined no-undef
907:29 error 'docs_path' is not defined no-undef
909:35 error 'pictures_path' is not defined no-undef
911:35 error 'home_path' is not defined no-undef
913:35 error 'videos_path' is not defined no-undef
915:35 error 'desktop_path' is not defined no-undef
1037:5 error 'getItem' is not defined no-undef
1041:17 error 'setItem' is not defined no-undef
1070:54 error Empty block statement no-empty
1089:51 error 'ht' is not defined no-undef
1091:20 error 'desktop_loading_fade_delay' is not defined no-undef
1150:27 error 'operation_id' is not defined no-undef
1151:5 error 'operation_cancelled' is not defined no-undef
1169:21 error 'activate_item_name_editor' is not defined no-undef
1172:21 error 'actions_history' is not defined no-undef
1181:54 error 'copy_progress_hide_delay' is not defined no-undef
1187:37 error 'copy_progress_hide_delay' is not defined no-undef
1211:21 error 'activate_item_name_editor' is not defined no-undef
1214:21 error 'actions_history' is not defined no-undef
1245:22 error 'operation_id' is not defined no-undef
1246:5 error 'operation_cancelled' is not defined no-undef
1249:5 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1263:24 error 'clipboard' is not defined no-undef
1264:29 error 'clipboard' is not defined no-undef
1273:20 error 'operation_cancelled' is not defined no-undef
1302:38 error 'clipboard' is not defined no-undef
1303:38 error 'clipboard' is not defined no-undef
1327:9 error 'actions_history' is not defined no-undef
1335:40 error 'copy_progress_hide_delay' is not defined no-undef
1341:29 error 'copy_progress_hide_delay' is not defined no-undef
1354:22 error 'operation_id' is not defined no-undef
1377:20 error 'operation_cancelled' is not defined no-undef
1432:9 error 'actions_history' is not defined no-undef
1440:40 error 'copy_progress_hide_delay' is not defined no-undef
1446:29 error 'copy_progress_hide_delay' is not defined no-undef
1486:17 error 'update_explorer_footer_item_count' is not defined no-undef
1487:17 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1500:8 error 'clipboard' is not defined no-undef
1501:24 error 'clipboard' is not defined no-undef
1502:61 error 'clipboard' is not defined no-undef
1505:13 error 'move_items' is not defined no-undef
1508:5 error 'clipboard' is not defined no-undef
1537:23 error 'api_origin' is not defined no-undef
1537:84 error 'auth_token' is not defined no-undef
1556:34 error 'uuidv4' is not defined no-undef
1565:45 error 'get_apps' is not defined no-undef
1572:13 error This branch can never execute. Its condition is a duplicate or covered by previous conditions in the if-else-if chain no-dupe-else-if
1639:21 error 'root_dirname' is not defined no-undef
1684:37 error 'gui_origin' is not defined no-undef
1711:60 error 'app_domain' is not defined no-undef
1723:64 error 'auth_token' is not defined no-undef
1737:49 error 'auth_token' is not defined no-undef
1748:12 error 'api_origin' is not defined no-undef
1749:64 error 'api_origin' is not defined no-undef
1800:13 error 'launch_apps' is not defined no-undef
1803:13 error 'launch_apps' is not defined no-undef
1803:43 error 'launch_apps' is not defined no-undef
1806:13 error 'launch_apps' is not defined no-undef
1806:34 error 'launch_apps' is not defined no-undef
1810:22 error 'api_origin' is not defined no-undef
1819:48 error 'auth_token' is not defined no-undef
1867:56 error 'trash_path' is not defined no-undef
1873:34 error 'trash_path' is not defined no-undef
1942:30 error 'busy_indicator_hide_delay' is not defined no-undef
1948:25 error 'busy_indicator_hide_delay' is not defined no-undef
1954:48 error 'user_preferences' is not defined no-undef
1955:9 error 'launch_app' is not defined no-undef
1956:19 error 'user_preferences' is not defined no-undef
1967:9 error 'launch_app' is not defined no-undef
1978:25 error 'item_icon' is not defined no-undef
1992:9 error 'window_nav_history' is not defined no-undef
1992:45 error 'window_nav_history' is not defined no-undef
1992:88 error 'window_nav_history_current_position' is not defined no-undef
1993:9 error 'window_nav_history' is not defined no-undef
1994:9 error 'window_nav_history_current_position' is not defined no-undef
1996:9 error 'update_window_path' is not defined no-undef
2009:22 error 'api_origin' is not defined no-undef
2017:48 error 'auth_token' is not defined no-undef
2021:25 error 'logout' is not defined no-undef
2025:20 error Empty block statement no-empty
2029:70 error 'suggest_apps_for_fsentry' is not defined no-undef
2040:17 error 'unzipItem' is not defined no-undef
2057:17 error 'trigger_download' is not defined no-undef
2065:13 error 'launch_app' is not defined no-undef
2087:22 error 'operation_id' is not defined no-undef
2088:5 error 'operation_cancelled' is not defined no-undef
2129:12 error 'operation_cancelled' is not defined no-undef
2166:30 error Empty block statement no-empty
2173:20 error 'operation_cancelled' is not defined no-undef
2182:34 error 'trash_path' is not defined no-undef
2196:55 error 'trash_path' is not defined no-undef
2196:116 error 'trash_path' is not defined no-undef
2197:57 error 'trash_path' is not defined no-undef
2201:46 error 'trash_path' is not defined no-undef
2215:47 error 'trash_path' is not defined no-undef
2254:25 error 'update_explorer_footer_item_count' is not defined no-undef
2255:25 error 'update_explorer_footer_selected_items_count' is not defined no-undef
2260:34 error 'trash_path' is not defined no-undef
2270:25 error 'update_window_path' is not defined no-undef
2274:34 error 'trash_path' is not defined no-undef
2279:46 error 'dir_uuid' is not defined no-undef
2302:33 error 'item_icon' is not defined no-undef
2303:42 error 'trash_path' is not defined no-undef
2309:47 error 'trash_path' is not defined no-undef
2331:41 error 'item_icon' is not defined no-undef
2343:21 error 'sort_items' is not defined no-undef
2348:21 error 'sort_items' is not defined no-undef
2391:47 error 'trash_path' is not defined no-undef
2397:51 error 'trash_path' is not defined no-undef
2398:53 error 'trash_path' is not defined no-undef
2413:34 error 'trash_path' is not defined no-undef
2414:9 error 'actions_history' is not defined no-undef
2418:40 error 'trash_path' is not defined no-undef
2419:9 error 'actions_history' is not defined no-undef
2428:12 error 'copy_progress_hide_delay' is not defined no-undef
2641:21 error 'upload_items' is not defined no-undef
2659:21 error 'trash_path' is not defined no-undef
2679:21 error 'show_save_account_notice_if_needed' is not defined no-undef
2683:17 error 'active_uploads' is not defined no-undef
2695:17 error 'active_uploads' is not defined no-undef
2714:17 error 'actions_history' is not defined no-undef
2722:25 error 'show_save_account_notice_if_needed' is not defined no-undef
2723:33 error 'upload_progress_hide_delay' is not defined no-undef
2726:24 error 'active_uploads' is not defined no-undef
2733:24 error 'active_uploads' is not defined no-undef
2739:24 error 'active_uploads' is not defined no-undef
2766:17 error 'uuidv4' is not defined no-undef
2772:16 error 'trash_path' is not defined no-undef
2782:47 error 'trash_path' is not defined no-undef
2782:108 error 'trash_path' is not defined no-undef
2783:37 error 'trash_path' is not defined no-undef
2786:36 error 'trash_path' is not defined no-undef
2788:13 error 'update_explorer_footer_item_count' is not defined no-undef
2788:71 error 'trash_path' is not defined no-undef
2793:28 error 'copy_progress_hide_delay' is not defined no-undef
2799:28 error 'copy_progress_hide_delay' is not defined no-undef
2815:18 error 'api_origin' is not defined no-undef
2818:42 error 'auth_token' is not defined no-undef
2991:28 error 'copy_progress_hide_delay' is not defined no-undef
2998:28 error 'copy_progress_hide_delay' is not defined no-undef
3066:24 error 'copy_progress_hide_delay' is not defined no-undef
3074:24 error 'copy_progress_hide_delay' is not defined no-undef
3086:17 error 'actions_history' is not defined no-undef
3095:17 error 'suggest_apps_for_fsentry' is not defined no-undef
3104:95 error 'truncate_filename' is not defined no-undef
3104:123 error 'TRUNCATE_LENGTH' is not defined no-undef
3111:84 error 'item_icon' is not defined no-undef
3150:23 error 'update_sites_cache' is not defined no-undef
3153:27 error 'determine_website_url' is not defined no-undef
3158:17 error 'update_window_path' is not defined no-undef
3166:17 error 'sort_items' is not defined no-undef
3171:34 error 'truncate_filename' is not defined no-undef
3171:66 error 'TRUNCATE_LENGTH' is not defined no-undef
3205:9 error 'actions_history' is not defined no-undef
3206:29 error 'actions_history' is not defined no-undef
3211:13 error 'undo_create_file_or_folder' is not defined no-undef
3214:13 error 'rename_file' is not defined no-undef
3217:13 error 'undo_upload' is not defined no-undef
3220:13 error 'undo_copy' is not defined no-undef
3223:13 error 'undo_move' is not defined no-undef
3226:13 error 'undo_delete' is not defined no-undef
3249:26 error 'get_html_element_from_options' is not defined no-undef
3251:9 error 'move_items' is not defined no-undef
3257:26 error 'get_html_element_from_options' is not defined no-undef
3259:9 error 'move_items' is not defined no-undef
3265:21 error 'global_element_id' is not defined no-undef
3282:23 error 'determine_website_url' is not defined no-undef
3324:42 error 'byte_format' is not defined no-undef
3381:116 error 'truncate_filename' is not defined no-undef
3381:148 error 'TRUNCATE_LENGTH' is not defined no-undef
3396:5 error 'is_auto_arrange_enabled' is not defined no-undef
3398:5 error 'desktop_item_positions' is not defined no-undef
3408:8 error 'reset_item_positions' is not defined no-undef
3409:9 error 'delete_desktop_item_positions' is not defined no-undef
3415:26 error 'desktop_item_positions' is not defined no-undef
3426:44 error 'desktop_item_positions' is not defined no-undef
3430:5 error 'desktop_item_positions' is not defined no-undef
3438:28 error 'is_fullscreen' is not defined no-undef
3462:14 error 'window_for_app_instance' is not defined no-undef
3469:31 error 'iframe_for_app_instance' is not defined no-undef
3483:23 error 'window_for_app_instance' is not defined no-undef
3514:42 error Unnecessary escape character: \[ no-useless-escape
3514:59 error Unnecessary escape character: \/ no-useless-escape
/puter/src/UI/UIWindowSignup.js
154:22 error 'is_email' is not defined no-undef
170:35 error 'check_password_strength' is not defined no-undef
188:22 error 'gui_origin' is not defined no-undef
203:21 error 'update_auth_data' is not defined no-undef
/puter/src/UI/UIWindowSessionList.js
33:117 error 'icons' is not defined no-undef
34:41 error 'logged_in_users' is not defined no-undef
35:32 error 'logged_in_users' is not defined no-undef
134:36 error 'logged_in_users' is not defined no-undef
141:17 error 'update_auth_data' is not defined no-undef
/puter/src/UI/UIWindowSaveAccount.js
130:22 error 'api_origin' is not defined no-undef
142:48 error 'auth_token' is not defined no-undef
145:21 error 'update_auth_data' is not defined no-undef
/puter/src/UI/UIWindowRefer.js
25:20 error 'gui_origin' is not defined no-undef
25:37 error 'user' is not defined no-undef
73:30 error 'socialLink' is not defined no-undef
/puter/src/UI/UIWindowRecoverPassword.js
84:16 error 'is_email' is not defined no-undef
91:22 error 'api_origin' is not defined no-undef
101:25 error 'logout' is not defined no-undef
Line 107 tries to use `url` but can't see it.
Also, clarify usage of window fields.
/puter/src/UI/UIWindowPublishWebsite.js
67:67 error 'generate_identifier' is not defined no-undef
107:54 error 'url' is not defined no-undef
110:17 error 'update_sites_cache' is not defined no-undef
/puter/src/UI/UIWindowNewPassword.js
48:38 error 'api_origin' is not defined no-undef
153:35 error 'check_password_strength' is not defined no-undef
163:22 error 'api_origin' is not defined no-undef
/puter/src/UI/UIWindowMyWebsites.js
156:30 error 'api_origin' is not defined no-undef
164:56 error 'auth_token' is not defined no-undef
168:33 error 'logout' is not defined no-undef
/puter/src/UI/UIWindowMoveProgress.js
74:9 error 'operation_cancelled' is not defined no-undef
/puter/src/UI/UIWindowNewFolderProgress.js
67:9 error 'operation_cancelled' is not defined no-undef
/puter/src/UI/UIWindowProgressEmptyTrash.js
67:9 error 'operation_cancelled' is not defined no-undef
/puter/src/UI/UIWindowLogin.js
141:16 error 'is_email' is not defined no-undef
160:22 error 'gui_origin' is not defined no-undef
167:21 error 'update_auth_data' is not defined no-undef
180:59 error 'gui_origin' is not defined no-undef
186:29 error 'app_domain' is not defined no-undef
188:54 error 'gui_origin' is not defined no-undef
/puter/src/UI/UIWindowItemProperties.js
135:26 error Empty block statement no-empty
147:120 error 'byte_format' is not defined no-undef
155:395 error 'extractSubdomain' is not defined no-undef
/puter/src/UI/UIWindowDesktopBGSettings.js
168:26 error 'api_origin' is not defined no-undef
178:52 error 'auth_token' is not defined no-undef
182:29 error 'logout' is not defined no-undef
188:24 error Empty block statement no-empty
/puter/src/UI/UIWindowEmailConfirmationRequired.js
113:26 error 'api_origin' is not defined no-undef
121:52 error 'auth_token' is not defined no-undef
125:29 error 'logout' is not defined no-undef
131:29 error 'refresh_user_data' is not defined no-undef
160:22 error 'api_origin' is not defined no-undef
165:48 error 'auth_token' is not defined no-undef
169:25 error 'logout' is not defined no-undef
188:13 error 'logout' is not defined no-undef
/puter/src/UI/UIWindowChangePassword.js
107:31 error 'check_password_strength' is not defined no-undef
117:18 error 'api_origin' is not defined no-undef
121:44 error 'auth_token' is not defined no-undef
And also add some missing imports.
/puter/src/UI/UIWindow.js
33:20 error 'global_element_id' is not defined no-undef
34:5 error 'last_window_zindex' is not defined no-undef
48:5 error 'window_stack' is not defined no-undef
69:52 error 'uuidv4' is not defined no-undef
90:9 error 'is_embedded' is not defined no-undef
174:52 error 'last_window_zindex' is not defined no-undef
174:94 error 'last_window_zindex' is not defined no-undef
244:77 error 'is_embedded' is not defined no-undef
289:57 error 'navbar_path' is not defined no-undef
436:25 error 'launch_app' is not defined no-undef
456:9 error 'window_nav_history' is not defined no-undef
457:9 error 'window_nav_history_current_position' is not defined no-undef
524:9 error 'animate_window_opening' is not defined no-undef
599:17 error 'validate_fsentry_name' is not defined no-undef
790:9 error 'navbar_path_droppable' is not defined no-undef
791:9 error 'sidebar_item_droppable' is not defined no-undef
801:33 error 'window_nav_history' is not defined no-undef
801:63 error 'window_nav_history_current_position' is not defined no-undef
804:46 error 'root_dirname' is not defined no-undef
812:17 error 'window_nav_history_current_position' is not defined no-undef
812:68 error 'window_nav_history_current_position' is not defined no-undef
813:34 error 'window_nav_history' is not defined no-undef
813:64 error 'window_nav_history_current_position' is not defined no-undef
815:17 error 'update_window_path' is not defined no-undef
825:29 error 'window_nav_history_current_position' is not defined no-undef
826:38 error 'window_nav_history' is not defined no-undef
834:25 error 'window_nav_history_current_position' is not defined no-undef
835:42 error 'window_nav_history' is not defined no-undef
835:72 error 'window_nav_history_current_position' is not defined no-undef
840:59 error 'root_dirname' is not defined no-undef
847:29 error 'update_window_path' is not defined no-undef
869:33 error 'window_nav_history' is not defined no-undef
869:63 error 'window_nav_history_current_position' is not defined no-undef
872:46 error 'root_dirname' is not defined no-undef
880:17 error 'window_nav_history_current_position' is not defined no-undef
882:37 error 'window_nav_history' is not defined no-undef
882:67 error 'window_nav_history_current_position' is not defined no-undef
885:21 error 'update_window_path' is not defined no-undef
896:29 error 'window_nav_history_current_position' is not defined no-undef
896:86 error 'window_nav_history' is not defined no-undef
897:38 error 'window_nav_history' is not defined no-undef
905:25 error 'window_nav_history_current_position' is not defined no-undef
906:42 error 'window_nav_history' is not defined no-undef
906:72 error 'window_nav_history_current_position' is not defined no-undef
911:59 error 'root_dirname' is not defined no-undef
918:29 error 'update_window_path' is not defined no-undef
941:50 error 'root_dirname' is not defined no-undef
950:17 error 'window_nav_history' is not defined no-undef
950:46 error 'window_nav_history' is not defined no-undef
950:82 error 'window_nav_history_current_position' is not defined no-undef
951:17 error 'window_nav_history' is not defined no-undef
952:17 error 'window_nav_history_current_position' is not defined no-undef
954:17 error 'update_window_path' is not defined no-undef
968:25 error 'update_window_layout' is not defined no-undef
983:25 error 'update_window_layout' is not defined no-undef
986:25 error 'update_window_layout' is not defined no-undef
997:13 error 'is_auth' is not defined no-undef
1023:13 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1106:21 error 'active_element' is not defined no-undef
1117:13 error 'update_explorer_footer_selected_items_count' is not defined no-undef
1143:18 error 'mouseover_window' is not defined no-undef
1205:82 error 'mouseX' is not defined no-undef
1205:107 error 'mouseY' is not defined no-undef
1219:83 error 'mouseover_window' is not defined no-undef
1244:31 error 'mouseover_window' is not defined no-undef
1246:17 error 'copy_items' is not defined no-undef
1246:45 error 'mouseover_window' is not defined no-undef
1252:21 error 'create_shortcut' is not defined no-undef
1255:27 error 'mouseover_window' is not defined no-undef
1264:17 error 'move_items' is not defined no-undef
1264:45 error 'mouseover_window' is not defined no-undef
1286:13 error 'scale_window' is not defined no-undef
1302:13 error 'scale_window' is not defined no-undef
1359:21 error 'upload_items' is not defined no-undef
1413:47 error 'window_width_threshold_for_sidebar' is not defined no-undef
1414:49 error 'window_width_threshold_for_sidebar' is not defined no-undef
1420:53 error 'window_width_threshold_for_sidebar' is not defined no-undef
1435:17 error 'last_window_zindex' is not defined no-undef
1460:29 error 'current_active_snap_zone' is not defined no-undef
1469:50 error 'current_active_snap_zone' is not defined no-undef
1473:43 error 'desktop_height' is not defined no-undef
1474:40 error 'toolbar_height' is not defined no-undef
1476:44 error 'last_window_zindex' is not defined no-undef
1480:55 error 'current_active_snap_zone' is not defined no-undef
1484:43 error 'desktop_height' is not defined no-undef
1485:40 error 'toolbar_height' is not defined no-undef
1487:44 error 'last_window_zindex' is not defined no-undef
1491:55 error 'current_active_snap_zone' is not defined no-undef
1495:43 error 'desktop_height' is not defined no-undef
1496:40 error 'toolbar_height' is not defined no-undef
1497:41 error 'desktop_width' is not defined no-undef
1498:44 error 'last_window_zindex' is not defined no-undef
1502:55 error 'current_active_snap_zone' is not defined no-undef
1506:43 error 'desktop_height' is not defined no-undef
1507:40 error 'toolbar_height' is not defined no-undef
1510:44 error 'last_window_zindex' is not defined no-undef
1514:55 error 'current_active_snap_zone' is not defined no-undef
1517:42 error 'desktop_width' is not defined no-undef
1518:43 error 'desktop_height' is not defined no-undef
1519:40 error 'toolbar_height' is not defined no-undef
1521:44 error 'last_window_zindex' is not defined no-undef
1525:55 error 'current_active_snap_zone' is not defined no-undef
1528:40 error 'toolbar_height' is not defined no-undef
1528:57 error 'desktop_height' is not defined no-undef
1531:43 error 'desktop_height' is not defined no-undef
1532:44 error 'last_window_zindex' is not defined no-undef
1536:55 error 'current_active_snap_zone' is not defined no-undef
1539:40 error 'toolbar_height' is not defined no-undef
1539:57 error 'desktop_height' is not defined no-undef
1540:41 error 'desktop_width' is not defined no-undef
1542:43 error 'desktop_height' is not defined no-undef
1543:44 error 'last_window_zindex' is not defined no-undef
1559:52 error 'current_active_snap_zone' is not defined no-undef
1590:28 error 'current_active_snap_zone' is not defined no-undef
1592:40 error 'toolbar_height' is not defined no-undef
1595:43 error 'desktop_height' is not defined no-undef
1599:33 error 'current_active_snap_zone' is not defined no-undef
1601:40 error 'toolbar_height' is not defined no-undef
1604:43 error 'desktop_height' is not defined no-undef
1608:33 error 'current_active_snap_zone' is not defined no-undef
1610:40 error 'toolbar_height' is not defined no-undef
1613:43 error 'desktop_height' is not defined no-undef
1617:33 error 'current_active_snap_zone' is not defined no-undef
1619:40 error 'toolbar_height' is not defined no-undef
1619:57 error 'desktop_height' is not defined no-undef
1622:43 error 'desktop_height' is not defined no-undef
1626:33 error 'current_active_snap_zone' is not defined no-undef
1628:40 error 'toolbar_height' is not defined no-undef
1628:57 error 'desktop_height' is not defined no-undef
1629:41 error 'desktop_width' is not defined no-undef
1631:43 error 'desktop_height' is not defined no-undef
1635:33 error 'current_active_snap_zone' is not defined no-undef
1637:40 error 'toolbar_height' is not defined no-undef
1640:43 error 'desktop_height' is not defined no-undef
1644:33 error 'current_active_snap_zone' is not defined no-undef
1645:29 error 'scale_window' is not defined no-undef
1656:51 error 'window_width_threshold_for_sidebar' is not defined no-undef
1657:53 error 'window_width_threshold_for_sidebar' is not defined no-undef
1663:57 error 'window_width_threshold_for_sidebar' is not defined no-undef
1674:71 error 'taskbar_height' is not defined no-undef
1676:51 error 'taskbar_height' is not defined no-undef
1703:35 error 'window_width_threshold_for_sidebar' is not defined no-undef
1718:36 error 'window_width_threshold_for_sidebar' is not defined no-undef
1719:49 error 'window_width_threshold_for_sidebar' is not defined no-undef
1725:42 error 'window_width_threshold_for_sidebar' is not defined no-undef
1733:50 error 'toolbar_height' is not defined no-undef
1734:38 error 'toolbar_height' is not defined no-undef
1736:32 error 'toolbar_height' is not defined no-undef
1773:13 error 'setItem' is not defined no-undef
1820:21 error 'scale_window' is not defined no-undef
1867:51 error 'trash_path' is not defined no-undef
1881:41 error 'sort_items' is not defined no-undef
1882:41 error 'set_sort_by' is not defined no-undef
1889:41 error 'sort_items' is not defined no-undef
1890:41 error 'set_sort_by' is not defined no-undef
1897:41 error 'sort_items' is not defined no-undef
1898:41 error 'set_sort_by' is not defined no-undef
1905:41 error 'sort_items' is not defined no-undef
1906:41 error 'set_sort_by' is not defined no-undef
1918:41 error 'sort_items' is not defined no-undef
1919:41 error 'set_sort_by' is not defined no-undef
1927:41 error 'sort_items' is not defined no-undef
1928:41 error 'set_sort_by' is not defined no-undef
1973:40 error 'clipboard' is not defined no-undef
1975:36 error 'clipboard_op' is not defined no-undef
1976:37 error 'copy_clipboard_items' is not defined no-undef
1977:41 error 'clipboard_op' is not defined no-undef
1978:37 error 'move_clipboard_items' is not defined no-undef
1986:39 error 'actions_history' is not defined no-undef
1988:33 error 'undo_last_action' is not defined no-undef
1998:33 error 'init_upload_using_dialog' is not defined no-undef
2014:48 error 'UIWindowSaveAccount' is not defined no-undef
2023:85 error 'UIWindowEmailConfirmationRequired' is not defined no-undef
2036:33 error 'launch_app' is not defined no-undef
2059:44 error 'mouseX' is not defined no-undef
2063:43 error 'mouseY' is not defined no-undef
2102:68 error 'trash_path' is not defined no-undef
2103:37 error 'delete_item' is not defined no-undef
2110:67 error 'trash_path' is not defined no-undef
2110:128 error 'trash_path' is not defined no-undef
2146:21 error 'upload_items' is not defined no-undef
2163:13 error 'enter_fullpage_mode' is not defined no-undef
2173:8 error 'active_element' is not defined no-undef
2174:9 error 'active_element' is not defined no-undef
2195:25 error 'item_icon' is not defined no-undef
2210:9 error 'window_nav_history' is not defined no-undef
2210:45 error 'window_nav_history' is not defined no-undef
2210:88 error 'window_nav_history_current_position' is not defined no-undef
2211:9 error 'window_nav_history' is not defined no-undef
2212:9 error 'window_nav_history_current_position' is not defined no-undef
2214:9 error 'update_window_path' is not defined no-undef
2257:37 error 'item_icon' is not defined no-undef
2364:9 error 'update_window_path' is not defined no-undef
2380:38 error 'root_dirname' is not defined no-undef
2389:9 error 'window_nav_history' is not defined no-undef
2389:45 error 'window_nav_history' is not defined no-undef
2389:88 error 'window_nav_history_current_position' is not defined no-undef
2390:9 error 'window_nav_history' is not defined no-undef
2391:9 error 'window_nav_history_current_position' is not defined no-undef
2391:62 error 'window_nav_history' is not defined no-undef
2392:9 error 'update_window_path' is not defined no-undef
2436:59 error 'root_dirname' is not defined no-undef
2453:19 error 'clipboard' is not defined no-undef
2455:16 error 'clipboard_op' is not defined no-undef
2456:17 error 'copy_clipboard_items' is not defined no-undef
2457:21 error 'clipboard_op' is not defined no-undef
2458:17 error 'move_clipboard_items' is not defined no-undef
2484:18 error 'mouseover_window' is not defined no-undef
2503:21 error 'create_shortcut' is not defined no-undef
2515:17 error 'move_items' is not defined no-undef
2525:18 error 'mouseover_window' is not defined no-undef
2605:12 error 'window_nav_history' is not defined no-undef
2605:42 error 'window_nav_history' is not defined no-undef
2605:84 error 'window_nav_history_current_position' is not defined no-undef
2612:12 error 'window_nav_history_current_position' is not defined no-undef
2626:55 error 'navbar_path' is not defined no-undef
2687:17 error 'update_window_layout' is not defined no-undef
2690:21 error 'update_details_layout_sort_visuals' is not defined no-undef
2698:13 error 'update_window_path' is not defined no-undef
2707:54 error 'root_dirname' is not defined no-undef
2712:9 error 'navbar_path_droppable' is not defined no-undef
2715:5 error 'update_explorer_footer_selected_items_count' is not defined no-undef
2727:18 error 'mouseover_window' is not defined no-undef
2746:21 error 'create_shortcut' is not defined no-undef
2758:17 error 'move_items' is not defined no-undef
2768:18 error 'mouseover_window' is not defined no-undef
2807:36 error 'sendWindowWillCloseMsg' is not defined no-undef
2819:23 error 'window_stack' is not defined no-undef
2829:17 error 'remove_taskbar_item' is not defined no-undef
2836:17 error 'exit_fullpage_mode' is not defined no-undef
2853:31 error 'window_stack' is not defined no-undef
2854:73 error 'window_stack' is not defined no-undef
2854:86 error 'window_stack' is not defined no-undef
2857:47 error 'window_stack' is not defined no-undef
2857:60 error 'window_stack' is not defined no-undef
2916:22 error 'window_stack' is not defined no-undef
2924:13 error 'active_item_container' is not defined no-undef
2949:20 error 'toolbar_height' is not defined no-undef
3007:14 error 'api_origin' is not defined no-undef
3017:40 error 'auth_token' is not defined no-undef
3021:17 error 'logout' is not defined no-undef
3083:43 error 'last_window_zindex' is not defined no-undef
3123:38 error 'last_window_zindex' is not defined no-undef
3127:98 error 'last_window_zindex' is not defined no-undef
3131:100 error 'last_window_zindex' is not defined no-undef
3147:81 error 'mouseX' is not defined no-undef
3147:106 error 'mouseY' is not defined no-undef
3151:9 error 'active_item_container' is not defined no-undef
3153:34 error 'active_item_container' is not defined no-undef
3155:9 error 'window_stack' is not defined no-undef
3157:11 error 'active_item_container' is not defined no-undef
3252:5 error 'sort_items' is not defined no-undef
3253:5 error 'set_sort_by' is not defined no-undef
3258:14 error 'api_origin' is not defined no-undef
3267:40 error 'auth_token' is not defined no-undef
3271:17 error 'logout' is not defined no-undef
3280:21 error 'update_details_layout_sort_visuals' is not defined no-undef
/puter/src/UI/UITaskbarItem.js
31:24 error 'global_element_id' is not defined no-undef
124:21 error 'launch_app' is not defined no-undef
143:21 error 'empty_trash' is not defined no-undef
158:25 error 'remove_taskbar_item' is not defined no-undef
160:21 error 'update_taskbar' is not defined no-undef
174:21 error 'update_taskbar' is not defined no-undef
250:73 error 'mouseover_window' is not defined no-undef
254:33 error 'path' is not defined no-undef
297:21 error 'launch_app' is not defined no-undef
328:89 error 'mouseover_window' is not defined no-undef
/puter/src/UI/UITaskbar.js
24:5 error 'global_element_id' is not defined no-undef
31:14 error 'api_origin' is not defined no-undef
36:40 error 'auth_token' is not defined no-undef
44:33 error 'global_element_id' is not defined no-undef
77:17 error 'launch_apps' is not defined no-undef
77:33 error 'launch_apps' is not defined no-undef
77:55 error 'launch_apps' is not defined no-undef
79:17 error 'launch_apps' is not defined no-undef
80:26 error 'api_origin' is not defined no-undef
85:52 error 'auth_token' is not defined no-undef
99:16 error 'launch_apps' is not defined no-undef
105:88 error 'launch_apps' is not defined no-undef
106:38 error 'launch_apps' is not defined no-undef
119:16 error 'launch_apps' is not defined no-undef
121:107 error 'launch_apps' is not defined no-undef
125:45 error 'launch_apps' is not defined no-undef
126:38 error 'launch_apps' is not defined no-undef
179:17 error 'launch_app' is not defined no-undef
201:25 error 'launch_app' is not defined no-undef
215:39 error 'trash_path' is not defined no-undef
228:68 error 'trash_path' is not defined no-undef
230:17 error 'launch_app' is not defined no-undef
236:13 error 'move_items' is not defined no-undef
236:31 error 'trash_path' is not defined no-undef
240:5 error 'make_taskbar_sortable' is not defined no-undef
262:22 error Empty block statement no-empty
284:29 error 'launch_app' is not defined no-undef
297:17 error 'update_taskbar' is not defined no-undef
301:17 error 'update_taskbar' is not defined no-undef
/puter/src/UI/UIPopover.js
28:5 error 'global_element_id' is not defined no-undef
33:30 error 'global_element_id' is not defined no-undef
40:59 error 'global_element_id' is not defined no-undef
76:59 error 'taskbar_height' is not defined no-undef
The click handler also makes use of the `options` parameter from
UINotification(), which isn't available there, so I've commented that
out. This needs more work.
/puter/src/UI/UINotification.js
21:5 error 'global_element_id' is not defined no-undef
26:39 error 'global_element_id' is not defined no-undef
34:73 error 'global_element_id' is not defined no-undef
47:14 error 'toolbar_height' is not defined no-undef
55:12 error 'options' is not defined no-undef
55:36 error 'options' is not defined no-undef
56:13 error 'options' is not defined no-undef
/puter/src/UI/UIItem.js
42:21 error 'global_element_id' is not defined no-undef
62:23 error 'determine_website_url' is not defined no-undef
100:58 error 'timeago' is not defined no-undef
104:42 error 'byte_format' is not defined no-undef
161:151 error 'truncate_filename' is not defined no-undef
161:183 error 'TRUNCATE_LENGTH' is not defined no-undef
171:5 error 'show_or_hide_empty_folder_message' is not defined no-undef
178:64 error 'trash_path' is not defined no-undef
186:9 error 'update_explorer_footer_item_count' is not defined no-undef
190:10 error 'is_auto_arrange_enabled' is not defined no-undef
217:21 error 'upload_items' is not defined no-undef
336:16 error 'mouseover_window' is not defined no-undef
337:39 error 'mouseover_window' is not defined no-undef
338:23 error 'mouseover_window' is not defined no-undef
341:24 error 'mouseX' is not defined no-undef
341:46 error 'mouseX' is not defined no-undef
341:69 error 'mouseY' is not defined no-undef
341:90 error 'mouseY' is not defined no-undef
342:88 error 'mouseX' is not defined no-undef
342:113 error 'mouseY' is not defined no-undef
350:18 error 'is_auto_arrange_enabled' is not defined no-undef
350:78 error 'trash_path' is not defined no-undef
352:17 error 'mouseover_window' is not defined no-undef
358:17 error 'desktop_item_positions' is not defined no-undef
359:17 error 'save_desktop_item_positions' is not defined no-undef
383:73 error 'mouseover_window' is not defined no-undef
427:21 error 'launch_app' is not defined no-undef
448:25 error 'copy_items' is not defined no-undef
450:25 error 'copy_items' is not defined no-undef
455:25 error 'create_shortcut' is not defined no-undef
468:32 error 'desktop_item_positions' is not defined no-undef
469:25 error 'save_desktop_item_positions' is not defined no-undef
471:21 error 'move_items' is not defined no-undef
483:89 error 'mouseover_window' is not defined no-undef
525:13 error 'open_item' is not defined no-undef
540:13 error 'open_item' is not defined no-undef
579:9 error 'update_explorer_footer_selected_items_count' is not defined no-undef
596:13 error 'update_explorer_footer_selected_items_count' is not defined no-undef
651:34 error 'truncate_filename' is not defined no-undef
651:66 error 'TRUNCATE_LENGTH' is not defined no-undef
661:9 error 'rename_file' is not defined no-undef
678:13 error 'last_enter_pressed_to_rename_ts' is not defined no-undef
679:13 error 'update_explorer_footer_selected_items_count' is not defined no-undef
718:25 error 'activate_item_name_editor' is not defined no-undef
763:78 error 'trash_path' is not defined no-undef
775:29 error 'move_items' is not defined no-undef
796:25 error 'zipItems' is not defined no-undef
810:25 error 'zipItems' is not defined no-undef
875:39 error 'delete_item' is not defined no-undef
877:63 error 'trash_path' is not defined no-undef
885:67 error 'trash_path' is not defined no-undef
885:116 error 'trash_path' is not defined no-undef
886:69 error 'trash_path' is not defined no-undef
906:29 error 'create_shortcut' is not defined no-undef
925:25 error 'move_items' is not defined no-undef
925:53 error 'trash_path' is not defined no-undef
936:63 error 'trash_path' is not defined no-undef
936:122 error 'trash_path' is not defined no-undef
945:25 error 'open_item' is not defined no-undef
962:49 error 'suggest_apps_for_fsentry' is not defined no-undef
984:37 error 'user_preferences' is not defined no-undef
987:43 error 'user_preferences' is not defined no-undef
989:42 error 'user_preferences' is not defined no-undef
1007:41 error 'user_preferences' is not defined no-undef
1008:72 error 'user_preferences' is not defined no-undef
1011:33 error 'launch_app' is not defined no-undef
1047:29 error 'open_item' is not defined no-undef
1093:25 error 'launch_app' is not defined no-undef
1114:25 error 'empty_trash' is not defined no-undef
1127:29 error 'zipItems' is not defined no-undef
1129:29 error 'trigger_download' is not defined no-undef
1140:25 error 'zipItems' is not defined no-undef
1151:41 error 'JSZip' is not defined no-undef
1180:25 error 'move_items' is not defined no-undef
1219:31 error 'clipboard' is not defined no-undef
1221:28 error 'clipboard_op' is not defined no-undef
1222:29 error 'copy_clipboard_items' is not defined no-undef
1223:33 error 'clipboard_op' is not defined no-undef
1224:29 error 'move_clipboard_items' is not defined no-undef
1247:25 error 'create_shortcut' is not defined no-undef
1265:25 error 'move_items' is not defined no-undef
1265:47 error 'trash_path' is not defined no-undef
1290:35 error 'delete_item' is not defined no-undef
1292:63 error 'trash_path' is not defined no-undef
1299:67 error 'trash_path' is not defined no-undef
1299:128 error 'trash_path' is not defined no-undef
1300:57 error 'trash_path' is not defined no-undef
1313:25 error 'activate_item_name_editor' is not defined no-undef
1373:9 error 'sort_items' is not defined no-undef
1376:9 error 'activate_item_name_editor' is not defined no-undef
1433:31 error 'copy_to_clipboard' is not defined no-undef
1517:9 error 'show_or_hide_empty_folder_message' is not defined no-undef
/puter/src/UI/UIDesktop.js
44:24 error 'gui_origin' is not defined no-undef
46:25 error 'auth_token' is not defined no-undef
86:5 error 'socket' is not defined no-undef
95:5 error 'socket' is not defined no-undef
104:5 error 'socket' is not defined no-undef
105:43 error 'trash_path' is not defined no-undef
106:45 error 'trash_path' is not defined no-undef
109:49 error 'trash_path' is not defined no-undef
112:5 error 'socket' is not defined no-undef
118:9 error 'launch_apps' is not defined no-undef
121:9 error 'launch_apps' is not defined no-undef
121:39 error 'launch_apps' is not defined no-undef
124:9 error 'launch_apps' is not defined no-undef
124:30 error 'launch_apps' is not defined no-undef
127:5 error 'socket' is not defined no-undef
146:5 error 'socket' is not defined no-undef
153:85 error 'truncate_filename' is not defined no-undef
153:114 error 'TRUNCATE_LENGTH' is not defined no-undef
156:77 error 'item_icon' is not defined no-undef
192:13 error 'update_window_path' is not defined no-undef
199:13 error 'sort_items' is not defined no-undef
203:5 error 'socket' is not defined no-undef
206:9 error 'sendItemChangeEventToWatchingApps' is not defined no-undef
220:25 error 'fsentry.path' is assigned to itself no-self-assign
233:17 error 'update_explorer_footer_item_count' is not defined no-undef
234:17 error 'update_explorer_footer_selected_items_count' is not defined no-undef
239:26 error 'trash_path' is not defined no-undef
249:17 error 'update_window_path' is not defined no-undef
253:26 error 'trash_path' is not defined no-undef
280:25 error 'item_icon' is not defined no-undef
281:34 error 'trash_path' is not defined no-undef
287:39 error 'trash_path' is not defined no-undef
308:37 error 'item_icon' is not defined no-undef
319:17 error 'sort_items' is not defined no-undef
324:13 error 'sort_items' is not defined no-undef
328:5 error 'socket' is not defined no-undef
333:9 error 'refresh_user_data' is not defined no-undef
336:5 error 'socket' is not defined no-undef
341:9 error 'refresh_user_data' is not defined no-undef
344:5 error 'socket' is not defined no-undef
346:9 error 'sendItemChangeEventToWatchingApps' is not defined no-undef
360:85 error 'truncate_filename' is not defined no-undef
360:114 error 'TRUNCATE_LENGTH' is not defined no-undef
363:77 error 'item_icon' is not defined no-undef
398:13 error 'update_window_path' is not defined no-undef
405:13 error 'sort_items' is not defined no-undef
409:5 error 'socket' is not defined no-undef
415:9 error 'sendItemChangeEventToWatchingApps' is not defined no-undef
440:81 error 'item_icon' is not defined no-undef
445:17 error 'sort_items' is not defined no-undef
455:29 error 'item_icon' is not defined no-undef
463:17 error Duplicate key 'associated_app_name' no-dupe-keys
470:17 error 'sort_items' is not defined no-undef
491:42 error 'desktop_path' is not defined no-undef
496:5 error 'getItem' is not defined no-undef
508:8 error 'url_query_params' is not defined no-undef
525:9 error 'update_user_preferences' is not defined no-undef
560:17 error 'upload_items' is not defined no-undef
560:52 error 'desktop_path' is not defined no-undef
577:16 error 'mouseover_window' is not defined no-undef
585:69 error 'desktop_path' is not defined no-undef
613:17 error 'copy_items' is not defined no-undef
613:43 error 'desktop_path' is not defined no-undef
617:17 error 'move_items' is not defined no-undef
617:43 error 'desktop_path' is not defined no-undef
649:39 error 'is_auto_arrange_enabled' is not defined no-undef
651:37 error 'is_auto_arrange_enabled' is not defined no-undef
651:64 error 'is_auto_arrange_enabled' is not defined no-undef
652:37 error 'store_auto_arrange_preference' is not defined no-undef
652:67 error 'is_auto_arrange_enabled' is not defined no-undef
653:40 error 'is_auto_arrange_enabled' is not defined no-undef
654:41 error 'sort_items' is not defined no-undef
655:41 error 'set_sort_by' is not defined no-undef
656:41 error 'clear_desktop_item_positions' is not defined no-undef
658:41 error 'set_desktop_item_positions' is not defined no-undef
668:44 error 'is_auto_arrange_enabled' is not defined no-undef
671:37 error 'sort_items' is not defined no-undef
672:37 error 'set_sort_by' is not defined no-undef
677:44 error 'is_auto_arrange_enabled' is not defined no-undef
680:37 error 'sort_items' is not defined no-undef
681:37 error 'set_sort_by' is not defined no-undef
686:44 error 'is_auto_arrange_enabled' is not defined no-undef
689:37 error 'sort_items' is not defined no-undef
690:37 error 'set_sort_by' is not defined no-undef
695:44 error 'is_auto_arrange_enabled' is not defined no-undef
698:37 error 'sort_items' is not defined no-undef
699:37 error 'set_sort_by' is not defined no-undef
708:44 error 'is_auto_arrange_enabled' is not defined no-undef
712:37 error 'sort_items' is not defined no-undef
713:37 error 'set_sort_by' is not defined no-undef
718:44 error 'is_auto_arrange_enabled' is not defined no-undef
722:37 error 'sort_items' is not defined no-undef
723:37 error 'set_sort_by' is not defined no-undef
757:43 error 'desktop_path' is not defined no-undef
767:35 error 'clipboard' is not defined no-undef
769:32 error 'clipboard_op' is not defined no-undef
770:33 error 'copy_clipboard_items' is not defined no-undef
770:54 error 'desktop_path' is not defined no-undef
771:37 error 'clipboard_op' is not defined no-undef
772:33 error 'move_clipboard_items' is not defined no-undef
780:35 error 'actions_history' is not defined no-undef
782:29 error 'undo_last_action' is not defined no-undef
791:29 error 'init_upload_using_dialog' is not defined no-undef
818:9 error 'is_embedded' is not defined no-undef
911:12 error 'user' is not defined no-undef
922:13 error 'is_embedded' is not defined no-undef
940:8 error 'url_query_params' is not defined no-undef
941:28 error 'url_query_params' is not defined no-undef
943:35 error 'home_path' is not defined no-undef
944:16 error 'url_query_params' is not defined no-undef
945:34 error 'url_query_params' is not defined no-undef
950:29 error 'item_icon' is not defined no-undef
966:13 error 'launch_app' is not defined no-undef
967:23 error 'app_launched_from_url' is not defined no-undef
970:25 error 'app_query_params' is not defined no-undef
1017:40 error 'taskbar_height' is not defined no-undef
1023:40 error 'user' is not defined no-undef
1024:9 error 'getItem' is not defined no-undef
1031:21 error 'setItem' is not defined no-undef
1125:47 error 'user' is not defined no-undef
1128:48 error 'user' is not defined no-undef
1131:25 error 'update_auth_data' is not defined no-undef
1170:37 error 'listSupportedLanguages' is not defined no-undef
1249:29 error 'logout' is not defined no-undef
1253:25 error 'logout' is not defined no-undef
1261:9 error 'is_fullscreen' is not defined no-undef
1308:5 error 'launch_app' is not defined no-undef
1381:9 error 'launch_apps' is not defined no-undef
1460:14 error 'api_origin' is not defined no-undef
1468:40 error 'auth_token' is not defined no-undef
1488:14 error 'toolbar_height' is not defined no-undef
1502:9 error 'reset_window_size_and_position' is not defined no-undef
1513:5 error 'refresh_desktop_background' is not defined no-undef
1520:26 error 'window_border_radius' is not defined no-undef
/puter/src/UI/UIContextMenu.js
23:21 error 'global_element_id' is not defined no-undef
117:57 error 'taskbar_height' is not defined no-undef
118:52 error 'taskbar_height' is not defined no-undef
260:17 error 'make_taskbar_sortable' is not defined no-undef
Solves these eslint issues:
/puter/src/UI/Settings/UITabAccount.js
34:13 error 'user' is not defined no-undef
47:99 error 'user' is not defined no-undef
55:12 error 'user' is not defined no-undef
59:105 error 'user' is not defined no-undef
/puter/src/UI/Settings/UITabLanguage.js
35:37 error 'listSupportedLanguages' is not defined no-undef
/puter/src/UI/Settings/UITabUsage.js
45:18 error 'api_origin' is not defined no-undef
50:46 error 'auth_token' is not defined no-undef
54:21 error 'logout' is not defined no-undef
96:18 error 'api_origin' is not defined no-undef
101:46 error 'auth_token' is not defined no-undef
105:21 error 'logout' is not defined no-undef
116:51 error 'byte_format' is not defined no-undef
123:41 error 'byte_format' is not defined no-undef
124:45 error 'byte_format' is not defined no-undef
/puter/src/UI/Settings/UIWindowChangeEmail.js
96:18 error 'api_origin' is not defined no-undef
100:44 error 'auth_token' is not defined no-undef
/puter/src/UI/Settings/UIWindowFinalizeUserDeletion.js
29:12 error 'user' is not defined no-undef
97:16 error 'user' is not defined no-undef
115:22 error 'api_origin' is not defined no-undef
120:50 error 'auth_token' is not defined no-undef
127:25 error 'logout' is not defined no-undef
139:25 error 'logout' is not defined no-undef
/puter/src/UI/Settings/UIWindowSettings.js
48:162 error 'icons' is not defined no-undef
86:13 error Duplicate key 'height' no-dupe-keys
Solves these eslint issues:
/puter/run-selfhosted.js
49:9 error 'console' is not defined no-undef
64:5 error 'console' is not defined no-undef
127:5 error 'console' is not defined no-undef
Resolves these eslint errors:
/puter/src/IPC.js
53:69 error 'appCallbackFunctions' is not defined no-undef
55:9 error 'appCallbackFunctions' is not defined no-undef
57:16 error 'appCallbackFunctions' is not defined no-undef
81:33 error 'window_for_app_instance' is not defined no-undef
84:27 error 'iframe_for_app_instance' is not defined no-undef
105:48 error Empty block statement no-empty
180:18 error 'api_origin' is not defined no-undef
190:44 error 'auth_token' is not defined no-undef
194:21 error 'logout' is not defined no-undef
207:18 error 'api_origin' is not defined no-undef
216:44 error 'auth_token' is not defined no-undef
220:21 error 'logout' is not defined no-undef
239:18 error 'api_origin' is not defined no-undef
248:44 error 'auth_token' is not defined no-undef
252:21 error 'logout' is not defined no-undef
268:13 error 'is_auth' is not defined no-undef
309:13 error 'is_auth' is not defined no-undef
348:27 error 'window_for_app_instance' is not defined no-undef
360:27 error 'window_for_app_instance' is not defined no-undef
576:35 error 'uuidv4' is not defined no-undef
582:9 error 'launch_app' is not defined no-undef
597:37 error 'appdata_path' is not defined no-undef
629:12 error 'appdata_signatures' is not defined no-undef
633:23 error 'appdata_signatures' is not defined no-undef
638:30 error 'appdata_path' is not defined no-undef
647:25 error 'appdata_signatures' is not defined no-undef
664:29 error 'appdata_signatures' is not defined no-undef
682:13 error 'is_auth' is not defined no-undef
717:13 error 'is_auth' is not defined no-undef
745:13 error 'is_auth' is not defined no-undef
773:13 error 'is_auth' is not defined no-undef
783:22 error 'api_origin' is not defined no-undef
793:48 error 'auth_token' is not defined no-undef
797:25 error 'logout' is not defined no-undef
825:13 error 'is_auth' is not defined no-undef
857:36 error 'operation_id' is not defined no-undef
872:41 error 'auth_token' is not defined no-undef
873:41 error 'api_origin' is not defined no-undef
939:45 error 'item_icon' is not defined no-undef
951:33 error 'sort_items' is not defined no-undef
954:29 error 'show_save_account_notice_if_needed' is not defined no-undef
998:38 error 'busy_indicator_hide_delay' is not defined no-undef
1004:33 error 'busy_indicator_hide_delay' is not defined no-undef
1018:37 error 'pictures_path' is not defined no-undef
1020:37 error 'desktop_path' is not defined no-undef
1022:37 error 'documents_path' is not defined no-undef
1024:37 error 'videos_path' is not defined no-undef
1026:37 error 'audio_path' is not defined no-undef
1028:37 error 'appdata_path' is not defined no-undef
1032:13 error 'is_auth' is not defined no-undef
1044:28 error 'operation_id' is not defined no-undef
1059:33 error 'auth_token' is not defined no-undef
1060:33 error 'api_origin' is not defined no-undef
1145:31 error 'iframe_for_app_instance' is not defined no-undef
1163:31 error 'window_for_app_instance' is not defined no-undef
1178:36 error 'get_apps' is not defined no-undef
1199:11 error 'window_for_app_instance' is not defined no-undef
Solves these eslint issues:
/puter/packages/puter-js/src/modules/UI.js
418:20 error 'itemWatchCallbackFunctions' is not defined no-undef
418:74 error 'itemWatchCallbackFunctions' is not defined no-undef
419:21 error 'itemWatchCallbackFunctions' is not defined no-undef
A couple of issues here:
- We didn't pass the line number to do_grep_line() so `i` was undefined
- Operator precedence messed with the ternary so when line numbers were
requested, the line wouldn't be output.
Found thanks to this now-solved eslint issue:
/puter/packages/phoenix/src/puter-shell/coreutils/grep.js
100:60 error 'i' is not defined no-undef
This was confusing its fallthrough detection:
/puter/packages/phoenix/src/puter-shell/coreutils/date.js
132:21 error Expected a 'break' statement before 'case' no-fallthrough
Found by this eslint issue:
/puter/packages/phoenix/src/puter-shell/coreutils/coreutil_lib/echo_escapes.js
107:59 error 'hexchars' is not defined no-undef
Also make tmp_value non-const because it gets modified later.
Solves these eslint issues:
/puter/packages/phoenix/src/ansi-shell/ioutil/SignalReader.js
45:14 error Unexpected negating the left operand of 'instanceof' operator no-unsafe-negation
46:13 error 'tmp_value' is constant no-const-assign
The `return` looks temporary but I don't know this code well enough.
Solves this eslint issue:
/puter/packages/backend/src/services/runtime-analysis/ExpectationService.js
94:9 error Unreachable code no-unreachable
Fixes these eslint issues:
/puter/packages/backend/src/services/auth/TokenService.js
3:1 error 'def' is not defined no-undef
18:1 error 'defv' is not defined no-undef
61:11 error 'def' is not defined no-undef
69:21 error 'defv' is not defined no-undef
The variable doesn't exist, and we never use it after this. Seems like a
copy-paste error.
Solves these eslint errors:
/puter/packages/backend/src/routers/save_account.js
90:9 error 'uuid_user' is not defined no-undef
91:9 error 'uuid_user' is not defined no-undef
91:21 error 'uuid_user' is not defined no-undef
/puter/packages/backend/src/util/stdioutil.js
26:24 error Unexpected control character(s) in regular expression: \x1b no-control-regex
/puter/packages/backend/src/util/streamutil.js
368:1 error 'string_to_stream' is not defined no-undef
463:5 error 'string_to_stream' is not defined no-undef
/puter/packages/backend/src/util/strutil.js
42:1 error 'format_as_usd' is not defined no-undef
56:5 error 'format_as_usd' is not defined no-undef
/puter/packages/backend/src/services/ContextInitService.js
57:18 error 'async_factory' is not defined no-undef
/puter/packages/backend/src/services/StorageService.js
22:5 error Expected to call 'super()' constructor-super
/puter/packages/backend/src/services/WebServerService.js
258:35 error 'services' is not defined no-undef
/puter/packages/backend/src/services/auth/AuthService.js
52:13 error Unreachable code no-unreachable
/puter/packages/backend/src/services/drivers/implementations/BaseImplementation.js
64:25 error 'services' is not defined no-undef
75:39 error 'services' is not defined no-undef
117:39 error 'services' is not defined no-undef
123:42 error 'services' is not defined no-undef
149:42 error 'services' is not defined no-undef
168:38 error 'services' is not defined no-undef
/puter/packages/backend/src/services/drivers/implementations/PuterDriverProxy.js
43:5 error Expected to call 'super()' constructor-super
44:9 error 'this' is not allowed before 'super()' no-this-before-super
/puter/packages/backend/src/services/drivers/meta/Construct.js
125:9 error Unreachable code no-unreachable
/puter/packages/backend/src/services/runtime-analysis/PagerService.js
49:41 error 'util' is not defined no-undef
/puter/packages/backend/src/routers/open_item.js
48:10 error Unexpected negating the left operand of 'instanceof' operator no-unsafe-negation
/puter/packages/backend/src/routers/save_account.js
106:34 error 'get_user' is not defined no-undef
/puter/packages/backend/src/routers/sign.js
37:10 error Unexpected negating the left operand of 'instanceof' operator no-unsafe-negation
/puter/packages/backend/src/routers/auth/list-permissions.js
36:15 error 'APIError' is not defined no-undef
/puter/packages/backend/src/routers/auth/list-sessions.js
17:15 error 'APIError' is not defined no-undef
/puter/packages/backend/src/routers/auth/revoke-user-app.js
34:15 error 'APIError' is not defined no-undef
43:15 error 'APIError' is not defined no-undef
/puter/packages/backend/src/routers/delete-site.js
43:11 error Unexpected empty object pattern no-empty-pattern
/puter/packages/backend/src/routers/drivers/usage.js
146:11 error 'k' is not defined no-undef
147:21 error 'k' is not defined no-undef
147:52 error 'k' is not defined no-undef
/puter/packages/backend/src/routers/drivers/xd.js
68:5 error 'window' is not defined no-undef
69:21 error Parsing error: The keyword 'interface' is reserved
/puter/packages/backend/src/routers/filesystem_api/batch/all.js
51:21 error 'get_app' is not defined no-undef
224:13 error Unexpected constant condition no-constant-condition
/puter/packages/backend/src/routers/filesystem_api/copy.js
70:10 error Unexpected constant condition no-constant-condition
106:13 error Duplicate key 'new_name' no-dupe-keys
/puter/packages/backend/src/routers/filesystem_api/read.js
80:5 error Unreachable code no-unreachable
/puter/packages/backend/src/routers/filesystem_api/token-read.js
53:9 error Unreachable code no-unreachable
58:9 error Unreachable code no-unreachable
104:5 error Unreachable code no-unreachable
/puter/packages/backend/src/routers/hosting/puter-site.js
65:21 error Unexpected constant nullishness on the left-hand side of a `??` expression no-constant-binary-expression
/puter/packages/backend/src/om/entitystorage/ValidationES.js
89:25 error Do not assign to the exception parameter no-ex-assign
/puter/packages/backend/src/om/proptypes/__all__.js
166:17 warning Unexpected 'debugger' statement no-debugger
/puter/packages/backend/src/routers/_default.js
405:31 error 'err' is not defined no-undef
/puter/packages/backend/src/helpers.js
682:9 error 'sharing_users' is not defined no-undef
689:12 error 'sharing_users' is not defined no-undef
690:28 error 'sharing_users' is not defined no-undef
695:28 error 'sharing_users' is not defined no-undef
720:9 error 'shared_fsentries' is not defined no-undef
733:12 error 'shared_fsentries' is not defined no-undef
734:28 error 'shared_fsentries' is not defined no-undef
735:17 error 'shared_fsentries' is not defined no-undef
735:58 error 'shared_fsentries' is not defined no-undef
736:31 error 'shared_fsentries' is not defined no-undef
900:57 error 'e' is not defined no-undef
1849:18 error Empty block statement no-empty
These currently work in a way that's different from what eslint expects,
so disable it. At some point it would be good if it could check them
(and if the tests could run on CI) but right now they just make a lot of
noise.
Removes or disables the following eslint errors/warnings:
/puter/packages/backend/src/api/filesystem/FlagParam.js
33:19 error 'APIError' is not defined no-undef
47:19 error 'APIError' is not defined no-undef
58:15 error 'APIError' is not defined no-undef
/puter/packages/backend/src/api/filesystem/StringParam.js
32:19 error 'APIError' is not defined no-undef
39:13 error 'APIError' is not defined no-undef
46:19 error 'APIError' is not defined no-undef
/puter/packages/backend/src/filesystem/FilesystemService.js
141:17 warning Unexpected 'debugger' statement no-debugger
366:21 error 'services' is not defined no-undef
/puter/packages/backend/src/filesystem/batch/BatchExecutor.js
121:21 error Do not assign to the exception parameter no-ex-assign
/puter/packages/backend/src/filesystem/hl_operations/hl_data_read.js
44:19 error 'APIError' is not defined no-undef
47:22 error 'chkperm' is not defined no-undef
48:19 error 'APIError' is not defined no-undef
51:29 error 'LLRead' is not defined no-undef
54:13 error 'version_id' is not defined no-undef
88:35 error 'PassThrough' is not defined no-undef
/puter/packages/backend/src/filesystem/hl_operations/hl_mkdir.js
68:49 error 'fs' is not defined no-undef
/puter/packages/backend/src/filesystem/hl_operations/hl_move.js
102:33 error 'get_user' is not defined no-undef
104:35 error 'get_user' is not defined no-undef
110:33 error 'df' is not defined no-undef
/puter/packages/backend/src/filesystem/hl_operations/hl_read.js
54:13 error 'stream' is constant no-const-assign
/puter/packages/backend/src/filesystem/hl_operations/hl_stat.js
40:37 error 'APIError' is not defined no-undef
/puter/packages/backend/src/filesystem/lib/PuterPath.js
67:5 error Expected to return a value in getter 'hasRelativePortion' getter-return
/puter/packages/backend/src/filesystem/ll_operations/ll_copy_idea.js
53:21 error 'UploadProgressTracker' is not defined no-undef
73:17 error 'PuterS3StorageStrategy' is not defined no-undef
137:22 error 'LLFilesystemOperation' is not defined no-undef
/puter/packages/backend/src/filesystem/ll_operations/ll_read.js
102:65 error 'offset' is not defined no-undef
102:73 error 'offset' is not defined no-undef
102:80 error 'length' is not defined no-undef
/puter/packages/backend/src/filesystem/ll_operations/ll_rmnode.js
43:23 error 'APIError' is not defined no-undef
/puter/packages/backend/src/filesystem/storage/SystemFSEntryService.js
101:26 error '_path' is not defined no-undef
/puter/packages/backend/src/filesystem/validation.js
27:29 error Unexpected control character(s) in regular expression: \x00, \x1f no-control-regex
28:29 error Unexpected control character(s) in regular expression: \x00, \x1f no-control-regex
28:31 error Unnecessary escape character: \/ no-useless-escape
eslint is a static analysis tool that tries to identify bugs and
mistakes in the code. We have quite a variety of code in this repo so
the config is a little complicated, but I've tried to make it clear.
It's found a *lot* of issues (over 1700), and while many of which will
not be actual problems, (it doesn't like us using window properties
without `window.`,) but some definitely are.
When using axios, its dependency follow-redirects only clears authorization header during cross-domain redirect, but allows the proxy-authentication header which contains credentials too.
## Steps To Reproduce & PoC
```js
const axios = require('axios');
axios.get('http://127.0.0.1:10081/', {
headers: {
'AuThorization': 'Rear Test',
'ProXy-AuthoriZation': 'Rear Test',
'coOkie': 't=1'
}
})
.then((response) => {
console.log(response);
})
```
When I meet the cross-domain redirect, the sensitive headers like authorization and cookie are cleared, but proxy-authentication header is kept.
```diff
- removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
+ removeMatchingHeaders(/^(?:authorization|proxy-authorization|cookie)$/i, this._options.headers);
```
CWE-200
`CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N`
CVE-2024-28849
Gives CommandProviders a `complete(query, {ctx})` method where they can provide completed command names, and then make use of this in CommandCompleter.
Supported CommandProvider sources:
- Shell built-ins (was supported previously)
- PATH executables (when running under Node)
- Puter app names (when running in Puter)
Script filenames are not yet supported.
`../bin/foo` should only find `foo` relative to the current working
directory, not to directories in PATH.
Also switch to using the Node path library since PathCommandProvider is
Node-only, and this means getting the correct path separator and
delimiter values on Windows.
> Drivers are services that apps on Puter can use. For example, drivers support many of the features in the [Puter SDK](https://docs.puter.com/). If you're not sure if what you're suggesting is a driver, you should use the "Feature Request" template instead.
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name:Node.js CI
on:
push:
branches:["main"]
pull_request:
branches:["main"]
jobs:
build:
runs-on:ubuntu-latest
strategy:
matrix:
node-version:[16.x, 18.x, 20.x, 21.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
We at **Puter** are committed to maintaining a secure experience for our users and community. We greatly value the contributions of security researchers and welcome responsible disclosure of security issues.
## Scope
The following are in scope for this program:
* **The Puter open-source project** (available at [github.com/HeyPuter](https://github.com/HeyPuter/puter))
* **`puter.com`**
* **`api.puter.com`**
Out-of-scope:
* Third-party services, applications, or libraries not maintained by Puter.
* Social engineering attacks (e.g., phishing against staff).
* Denial of Service (DoS), spam, or volumetric attacks.
* Physical security issues.
## Rules of Engagement
To participate, you must:
1.**Report responsibly**: Provide detailed steps to reproduce the issue, including proof-of-concept code or screenshots where applicable.
2.**Do no harm**: Do not exfiltrate, modify, or delete data. Only access your own account or test data.
3.**Respect availability**: Do not perform denial-of-service attacks or automated scans that degrade service.
4.**Follow disclosure policy**: Do not publicly disclose vulnerabilities until we have confirmed and patched the issue.
5.**Act in good faith**: Make every effort to avoid privacy violations, destruction of data, and interruption or degradation of services.
Reports that do not meet these guidelines may not be eligible for a reward.
We aim to acknowledge receipt within **72 hours** and provide a resolution timeline.
## Reward Structure
We offer monetary rewards based on the severity of the vulnerability, as determined by our internal assessment (using CVSS as a guide).
* **Critical: \$1,000 – \$2,000**
* **High: \$500 – \$1,000**
* **Medium: \$200 – \$500**
* **Low: \$50 – \$100**
Non-security issues, suggestions, and best practices feedback are always welcome, but may not qualify for a reward.
If multiple researchers report the same issue, the bounty will be awarded to the first eligible report we receive.
## Payments Disclaimer
All reward amounts are **guidelines only**. Final decisions about eligibility, severity classification, and payout amount are made at the sole discretion of the Puter security team. We reserve the right to determine whether a report qualifies for a bounty, and whether any payment will be issued at all. Submitting a report does not guarantee compensation.
### Payment Method Requirement
At this time, **payments will only be made via PayPal**. To be eligible to receive a bounty, researchers must have a valid PayPal account capable of receiving payments. We are unable to process payments through other services or methods at this time.
## Legal Safe Harbor
If you make a good-faith effort to comply with this policy, we will consider your research to be authorized. If you inadvertently access data outside your own account, stop immediately and include details in your report so we can investigate and remediate.
Welcome to Puter, the open-source distributed internet operating system. We're excited to have you contribute to our project, whether you're reporting bugs, suggesting new features, or contributing code. This guide will help you get started with contributing to Puter in different ways.
<br>
# Report bugs
Before reporting a bug, please check our [the issues on our GitHub repository](https://github.com/HeyPuter/puter/issues) to see if the bug has already been reported. If it has, you can add a comment to the existing issue with any additional information you have.
If you find a new bug in Puter, please [open an issue on our GitHub repository](https://github.com/HeyPuter/puter/issues/new). We'll do our best to address the issue as soon as possible. When reporting a bug, please include as much information as possible, including:
- A clear and descriptive title
- A description of the issue
- Steps to reproduce the bug
- Expected behavior
- Actual behavior
- Screenshots, if applicable
- Your host operating system and browser
- Your Puter version, location, ...
Please open a separate issue for each bug you find.
Maintainers will apply the appropriate labels to your issue.
<br>
# Suggest new features
If you have an idea for a new feature in Puter, please open a new discussion thread on our [GitHub repository](https://github.com/HeyPuter/puter/discussions) to discuss your idea with the community. We'll do our best to respond to your suggestion as soon as possible.
When suggesting a new feature, please include as much information as possible, including:
- A clear and descriptive title
- A description of the feature
- The problem the feature will solve
- Any relevant screenshots or mockups
- Any relevant links or resources
<br>
# Contribute code
If you'd like to contribute code to Puter, you need to fork the project and submit a pull request. If this is your first time contributing to an open-source project, we recommend reading this short guide by GitHub on [how to contribute to a project](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project).
We'll review your pull request and work with you to get your changes merged into the project.
## Your first code contribution
We maintain a list of issues that are good for first-time contributors. You can find these issues by searching for the [`good first issue`](https://github.com/HeyPuter/puter/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label in our [GitHub repository](https://github.com/HeyPuter/puter). These issues are designed to be relatively easy to fix, and we're happy to help you get started. Pick an issue that interests you, and leave a comment on the issue to let us know you're working on it.
<br>
## Documentation for Contributors
See [doc/contributors/index.md](./doc/contributors/index.md) for more information.
<br>
## Commit Messages
Use the imperative, as is the convention in the Linux kernel:
- correct: `Improve performance of readdir`
- incorrect: `Improved readdir`
- incorrect: `Improving readdir`
We have the following exceptions to this rule:
- If the commit message is in _past tense_, it's a shorthand for the following:
-`Apply changes that would be applied after one had <past tense message>`
- If the commit message is in _present tense_, it's shorthand for the following:
-`Apply changes that would be applied after <present-tense message>`
For example, the following are correct:
-`Improved readdir`
- interpret this as: `Apply changes that would be applied after one had improved readdir`
-`Improving readdir`
- interpret this as: `Apply changes that would be applied after improving readdir`
<br>
## Code Review
Once you've submitted your pull request, the project maintainers will review your changes. We may suggest some changes or improvements. This is a normal part of the process, and your contributions are greatly appreciated!
<br>
## Contribution License Agreement (CLA)
Like many open source projects, we require contributors to sign a Contribution License Agreement (CLA) before we can accept your code. When you open a pull request for the first time, a bot will automatically add a comment with a link to the CLA. You can sign the CLA electronically by following the link and filling out the form.
<br>
# Getting Help
If you have any questions about Puter, please feel free to reach out to us through the following channels:
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">The Internet OS! Free, Open-Source, and Self-Hostable.</h3>
<h3 align="center">The Open-Source Internet Computer!</h3>
<p align="center">
<a href="https://puter.com/"><strong>« LIVE DEMO »</strong></a>
<a href="https://puter.com/?ref=github.com"><strong>« LIVE DEMO »</strong></a>
Puter is an advanced, open-source internet operating system designed to be feature-rich, exceptionally fast, and highly extensible. It can be used to build remote desktop environments or serve as an interface for cloud storage services, remote servers, web hosting platforms, and more.
Puter is an advanced, open-source, self-hostable internet computer designed to be feature-rich, fast, and highly extensible. Puter's goal is to provide you with every app and feature you need to work, create, and play under one roof.
<br/>
## Getting Started
After reading this section, please proceed to **Self-Hosting** and **Configuration** below.
Read these instructions carefully or you may see errors due to
an invalid setup.
### Local Development
### 💻 Local Development
```bash
git clone https://github.com/HeyPuter/puter
@@ -43,140 +40,91 @@ cd puter
npm install
npm start
```
**→** This should launch Puter at http://puter.localhost:4100 (or the next available port).
This will launch Puter at http://localhost:4000 (or the next available port).
<br/>
### Using Docker
### 🚀 Self-Hosting
**note:** it is **not** necessary to run this within a clone of this repository. For contributors, it is recommended to use the [Local Development](#local-development) instructions.
**note:** it is **not** necessary to run this within a clone of this repository. For contributors, it is recommended to use the [Local Development](#local-development) instructions.
See [Configuration](#configuration) for next steps.
**→** For more details, see [Self-Hosting Puter](./doc/self-hosting.md).
<br/>
## ⚠️ Self-Hosting ⚠️
The self-hosted version of Puter is currently in alpha stage and should not be used in production yet. It is under active development and may contain bugs, other issues. Please exercise caution and use it for testing and evaluation purposes only.
### ☁️ Puter.com
Puter is available as a hosted service at [**puter.com**](https://puter.com).
<br/>
## Configuration
## Support
Running the server will generate a configuration file in one of these locations:
-`config/config.json` when [Using Docker](#using-docker)
-`volatile/config/config.json` in [Local Development](#local-development)
-`/etc/puter/config.json` on a server (or within a Docker container)
Connect with the maintainers and community through these channels:
### Domain Name
- Bug report or feature request? Please [open an issue](https://github.com/HeyPuter/puter/issues/new/choose).
To access Puter on your device, you can simply go to the address printed in
the server console (usually `puter.localhost:4100`).
To access Puter from another device, a domain name must be configured, as well as
an `api` subdomain. For example, `example.local` might be the domain name pointing
to the IP address of the server running puter, and `api.example.com` must point to
this address as well. This domain must be specified in the configuration file
(usually `volatile/config/config.json`) as well.
See [domain configuration](./doc/self-hosters/domains.md) for more information.
### Configure the Port
- You can specify a custom port by setting `http_port` to a desired value
- If you're using a reverse-proxy such as nginx or cloudflare, you should
also set `pub_port` to the public (external) port (usually `443`)
- If you have HTTPS enabled on your reverse-proxy, ensure that
`protocol` in config.json is set accordingly
### Default User
By default, Puter will create a user called `default_user`.
This user will have a randomly generated password, which will be printed
in the development console.
A warning will persist in the dev console until this user's
password is changed. Please login to this user and change the password as
your first step.
We are always happy to help you with any questions you may have. Don't hesitate to ask!
<br/>
## License
## License
This repository is licensed under AGPL-3.0; However, our SDK (puter.js) is also available under Apache 2.0, as indicated by the license file in that section (packages/puter-js) of this repository.
This repository, including all its contents, sub-projects, modules, and components, is licensed under [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) unless explicitly stated otherwise. Third-party libraries included in this repository may be subject to their own licenses.
<br/>
## FAQ
## Translations
### ❓ What's the use case for Puter?
Puter can be used as:
-An alternative to Dropbox, Google Drive, OneDrive, etc. with a fresh interface and powerful features.
-Remote desktop environment for servers and workstations.
-A platform for building and hosting websites, web apps, and games.
-A friendly, open-source project and community to learn about web development, cloud computing, distributed systems, and much more!
<br/>
### ❓ Why isn't Puter built with React, Angular, Vue, etc.?
For performance reasons, Puter is built with vanilla JavaScript and jQuery. Additionally, we'd like to avoid complex abstractions and to remain in control of the entire stack, as much as possible.
Also partly inspired by some of our favorite projects that are not built with frameworks: [VSCode](https://github.com/microsoft/vscode), [Photopea](https://www.photopea.com/), and [OnlyOffice](https://www.onlyoffice.com/).
<br/>
### ❓ Why jQuery?
Puter interacts directly with the DOM and jQuery provides an elegant yet powerful API to manipulate the DOM, handle events, and much more. It's also fast, mature, and battle-tested.
The default wallpaper is created by [Milad Fakurian](https://unsplash.com/photos/blue-orange-and-yellow-wallpaper-E8Ufcyxz514) and published on [Unsplash](https://unsplash.com/).
Icons by [Papirus](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme) under GPL-3.0 license.
Icons by [Iconoir](https://iconoir.com/) under MIT license.
Icons by [Elementary Icons](https://github.com/elementary/icons) under GPL-3.0 license.
Icons by [Tabler Icons](https://tabler.io/) under MIT license.
Icons by [bootstrap-icons](https://icons.getbootstrap.com/) under MIT license.
<img src="https://puter.com/images/logo.png" alt="Puter Technologies Inc. Logo" width="150"/>
<br>
This trademark policy was prepared to help you understand how to use the Puter trademarks, service marks and logos with Puter Technologies Inc.'s Puter software.
While some of our software is available under a free and open source software license, that copyright license does not include a license to use our trademark, and this Policy is intended to explain how to use our marks consistent with background law and community expectation.
This Policy covers:
1. Our **word** trademarks and service marks: Puter Technologies Inc., Puter, Puter.com
2. Our **logos**: The Puter Technologies Inc. logo at the top of this policy
This policy encompasses all trademarks and service marks, whether they are registered or not.
<br>
<br>
## 1. GENERAL GUIDELINES
Whenever you use one of our marks, you must always do so in a way that does not mislead anyone about what they are getting and from whom. For example, you cannot say you are providing the Puter software when you're providing a modified version of it, because recipients may not understand the differences between your modified versions and our own.
You also cannot use our logo on your website in a way that suggests that your website is an official website or that we endorse your website.
You can, though, say you like the Puter software, that you participate in the Puter community, that you are providing an unmodified version of the Puter software.
You may not use or register our marks, or variations of them as part of your own trademark, service mark, domain name, company name, trade name, product name or service name.
Trademark law does not allow your use of names or trademarks that are too similar to ours. You therefore may not use an obvious variation of any of our marks or any phonetic equivalent, foreign language equivalent, takeoff, or abbreviation for a similar or compatible product or service. We would consider the following too similar to one of our Marks:
- MyPuter
- PuterFooBar
<br>
<br>
## 2. ACCEPTABLE USES
<br>
### Distribution of Unmodified Software
When you redistribute an unmodified copy of Puter software, you must retain all trademarks, logos, and notices we have placed on the software to identify its origin. This includes:
* Binary distributions exactly as we provide them
* Source code distributions exactly as we provide them
* Documentation and other materials directly from our official repositories
<br>
### Distribution of Modified Software
If you distribute a modified version of Puter software, you:
* Must remove all Puter logos from the modified software
* May use our word marks (but not logos) to accurately describe the software's origin
* Must clearly indicate that the software has been modified
* Must include a notice stating: "This software is a modified version of Puter software and is not endorsed by Puter Technologies Inc."
Example of acceptable description: "This software is derived from Puter software and includes modifications for [describe your changes]."
<br>
### Compatibility Statements
You may use our word marks (but not logos) to accurately describe your software's compatibility with Puter software under these conditions:
* Your statements about compatibility must be accurate and not misleading
* You must include the following notice: "Puter is a trademark of Puter Technologies Inc. This [product/service] is not affiliated with or endorsed by Puter Technologies Inc."
* You may not suggest that Puter Technologies Inc. has certified or approved your software
<br>
### Products Built for Puter
You may describe your product as working with or being built for Puter if:
* Your product is fully compatible with the documented Puter APIs
* Your product name follows this format: "[Your Product Name] for Puter"
* You include this notice in all materials: "Puter is a trademark of Puter Technologies Inc. [Your Product Name] is not affiliated with or endorsed by Puter Technologies Inc."
* Your branding and marketing materials do not create confusion about the source of your product
<br>
### Open Source Projects
For open source projects that interact with or extend Puter software:
* You may use "puter" as part of your project name only if:
* The name is in the format "[descriptor]-puter" (e.g., "auth-puter", "backup-puter")
* The project's README clearly states it's not officially associated with Puter
* The project maintains compatibility with current Puter APIs
* You must not use our logos without explicit permission
* You must include appropriate trademark attribution notices
<br>
### Community Activities
You may use our word marks (but not logos) for non-commercial community activities:
* User groups and meetups focused on Puter software
* Educational content about Puter software
* Blog posts, videos, articles, or tutorials about Puter software
Conditions for community use:
* Activities must be non-commercial
* Any fees charged must only cover actual costs
* You must include appropriate trademark attribution
* You must not suggest official endorsement without explicit permission
<br>
### Merchandise and Promotional Items
You may not create merchandise or promotional items bearing our marks without explicit written permission from Puter Technologies Inc.
<br>
### Academic and Research Use
You may use our word marks (but not logos) in:
* Academic papers
* Research publications
* Technical documentation
* Educational materials
Include appropriate citations and trademark attributions in such uses.
<br>
### Online Content and Social Media
When using our marks in online content:
* You may use our word marks in hashtags, handles, or usernames if:
* The content is clearly about Puter software
* You don't imply official status
* You include appropriate trademark attribution
* You must not register social media accounts that could be confused with official Puter accounts
<br>
### APIs and Development
When developing with Puter APIs:
* You may use our word marks to accurately describe your integration
* You must not use our marks in a way that suggests your API or service is endorse by
Puter or provided by Puter
* You must include appropriate trademark attribution
All uses described above must also comply with the General Guidelines section of this policy and maintain the integrity of our marks as described in the How to Display Our Marks section.
<br>
### No Domain Names
You must not register any domain that includes our word marks or any variant or combination of them.
<br>
<br>
## 3. HOW TO DISPLAY OUR MARKS
When you have the right to use our mark, here is how to display it.
<br>
### Trademark marking and legends
The first or most prominent mention of a mark on a webpage, document, or documentation should be accompanied by a symbol indicating whether the mark is a registered trademark ("®") or an unregistered trademark ("™"). If you don't know which applies, contact us.
Place the following notice at the foot of the page where you have used the mark: "Puter is trademark of Puter Technologies Inc."
<br>
### Use of trademarks in text
**Always use trademarks in their exact form with the correct spelling, neither abbreviated, hyphenated, or combined with any other word or words.**
Unacceptable: Puter-DB
**Don't pluralize a trademark.**
Unacceptable: I have seventeen Puters running in my lab.
**Always use a trademark as an adjective modifying a noun.**
Unacceptable: This is a Puter.
Acceptable: This is a Puter software application.
<br>
### Use of Logos
You may not change any logo except to scale it. This means you may not add decorative elements, change the colors, change the proportions, distort it, add elements, or combine it with other logos.
However, when the context requires the use of black-and-white graphics and the logo is color, you may reproduce the logo in a manner that produces a black-and-white image.
<br>
<br>
## This Document
These guidelines are based on the Model Trademark Guidelines, available at http://www.modeltrademarkguidelines.org., used under a Creative Commons Attribution 3.0 Unported license: https://creativecommons.org/licenses/by/3.0/deed.en_US.
short_description:`Puter is a privacy-first personal cloud that houses all your files, apps, and games in one private and secure place, accessible from anywhere at any time.`,
}));
})
app.use(express.static('./'));
if(env==="prod"){
// make sure to serve the ./dist/ folder maps to the root of the website
<h3 align="center"><img width="80" alt="Puter.com، الحاسوب السحابي الشخصي: جميع ملفاتك وتطبيقاتك وألعابك في مكان واحد يمكن الوصول إليه من أي مكان في أي وقت." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">نظام تشغيل الإنترنت! مجاني ومفتوح المصدر وقابل للاستضافة الذاتية.</h3>
<p>بيوتر هو نظام تشغيل إنترنت متقدم ومفتوح المصدر، مصمم ليكون غنيًا بالميزات وسريعًا بشكل استثنائي وقابلًا للتوسع بدرجة كبيرة. يمكن استخدام بيوتر كـ:</p>
<ul>
<li>سحابة شخصية تعطي الأولوية للخصوصية لحفظ جميع ملفاتك وتطبيقاتك وألعابك في مكان آمن واحد، يمكن الوصول إليه من أي مكان وفي أي وقت.</li>
<li>منصة لبناء ونشر المواقع الإلكترونية وتطبيقات الويب والألعاب</li>
<li>بديل لـ Dropbox وGoogle Drive وOneDrive وغيرها، مع واجهة جديدة وميزات قوية.</li>
<li>بيئة سطح مكتب عن بُعد للخوادم ومحطات العمل.</li>
<li>مشروع ومجتمع ودود ومفتوح المصدر للتعلم عن تطوير الويب والحوسبة السحابية والأنظمة الموزعة والكثير غير ذلك!</li>
</ul>
</div>
<br/>
## البدء
### 💻 التطوير المحلي
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
سيؤدي هذا إلى تشغيل Puter على http://puter.localhost:4100 (أو المنفذ التالي المتاح).
نحن دائمًا سعداء لمساعدتك في أي أسئلة قد تكون لديك. لا تتردد في السؤال!
<br/>
## الترخيص
هذا المستودع، بما في ذلك جميع محتوياته ومشاريعه الفرعية ووحداته ومكوناته، مرخص تحت [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) ما لم ينص على خلاف ذلك صراحةً. قد تخضع المكتبات الخارجية المدرجة في هذا المستودع لتراخيصها الخاصة.
<h3 align="center"><img width="80" alt="Puter.com, ব্যক্তিগত ক্লাউড কম্পিউটার: আপনার সমস্ত ফাইল, অ্যাপস, এবং গেম এক জায়গায়, যেকোনো সময়, যেকোনো স্থান থেকে অ্যাক্সেসযোগ্য।" src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">ইন্টারনেট ওএস! ফ্রি, ওপেন-সোর্স, এবং সেল্ফ-হোস্টেবল।</h3>
Puter একটি উন্নত, ওপেন-সোর্স ইন্টারনেট অপারেটিং সিস্টেম যা বৈশিষ্ট্যপূর্ণ, অত্যন্ত দ্রুত এবং উচ্চ মাত্রায় সম্প্রসারণযোগ্য। Puter ব্যবহার করা যেতে পারে:
- একটি প্রাইভেসি-প্রথম পার্সোনাল ক্লাউড হিসাবে যা আপনার সমস্ত ফাইল, অ্যাপস এবং গেমসকে এক জায়গায় নিরাপদে রাখে, যেকোনো সময় যেকোনো স্থান থেকে অ্যাক্সেসযোগ্য।
- ওয়েবসাইট, ওয়েব অ্যাপ এবং গেম তৈরি ও প্রকাশ করার একটি প্ল্যাটফর্ম হিসাবে।
- ড্রপবক্স, গুগল ড্রাইভ, ওয়ানড্রাইভ ইত্যাদির বিকল্প হিসাবে একটি নতুন ইন্টারফেস এবং শক্তিশালী বৈশিষ্ট্য সহ।
- সার্ভার এবং ওয়ার্কস্টেশনের জন্য একটি রিমোট ডেস্কটপ এনভায়রনমেন্ট হিসাবে।
- ওয়েব ডেভেলপমেন্ট, ক্লাউড কম্পিউটিং, ডিস্ট্রিবিউটেড সিস্টেম এবং আরও অনেক কিছু শিখতে একটি বন্ধুত্বপূর্ণ, ওপেন-সোর্স প্রকল্প এবং কমিউনিটি হিসাবে!
<br/>
## শুরু করার জন্য
## 💻 লোকাল ডেভেলপমেন্ট
```bash
Copy code
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
এটি Puter কে http://puter.localhost:4100 (অথবা পরবর্তী উপলব্ধ পোর্টে) চালু করবে।
মেইনটেইনার এবং কমিউনিটির সাথে এই চ্যানেলগুলির মাধ্যমে সংযোগ করুন:
- বাগ রিপোর্ট বা ফিচার রিকোয়েস্ট? অনুগ্রহ করে একটি ইস্যু খুলুন।
- ডিসকর্ড: discord.com/invite/PQcx7Teh8u
- X (টুইটার): x.com/HeyPuter
- রেডিট: reddit.com/r/puter/
- মাস্টডন: mastodon.social/@puter
- সিকিউরিটি ইস্যু? security@puter.com
- মেইনটেইনারদের ইমেইল করুন hi@puter.com এ
আপনার যেকোনো প্রশ্নের জন্য আমরা সবসময় সাহায্য করতে প্রস্তুত। জিজ্ঞাসা করতে দ্বিধা করবেন না!
<br/>
## লাইসেন্স
এই রিপোজিটরি, এর সমস্ত বিষয়বস্তু, সাব-প্রকল্প, মডিউল, এবং কম্পোনেন্ট সহ [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) লাইসেন্সের অধীনে লাইসেন্সকৃত, যদি অন্যথায় স্পষ্টভাবে উল্লেখ না করা হয়। এই রিপোজিটরিতে অন্তর্ভুক্ত তৃতীয় পক্ষের লাইব্রেরিগুলি তাদের নিজস্ব লাইসেন্সের অধীনে হতে পারে।
<h3 align="center"><img width="80" alt="Puter.com, Den Personlige Cloudcomputer: Alle dine filer, apps og spil på ét sted tilgængelige fra hvor som helst til enhver tid." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Internet OS'et! Gratis, Open-Source og kan selvhostes.</h3>
Puter er et avanceret, open-source internetoperativsystem designet til at være funktionsrigt, exceptionelt hurtigt og meget udvideligt. Puter kan bruges som:
- En privatlivsfokuseret personlig sky til at opbevare alle dine filer, apps og spil på ét sikkert sted, tilgængeligt hvor som helst og når som helst.
- En platform til at bygge og publicere hjemmesider, webapplikationer og spil.
- Et alternativ til Dropbox, Google Drive, OneDrive osv. med et friskt interface og kraftfulde funktioner.
- Et fjernskrivebordsmiljø for servere og arbejdsstationer.
- Et venligt, open-source projekt og fællesskab til at lære om webudvikling, cloud computing, distribuerede systemer og meget mere!
<br/>
## Kom godt i gang
### 💻 Lokal Udvikling
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Dette vil starte Puter på http://puter.localhost:4100 (eller den næste tilgængelige port).
Vi er altid glade for at hjælpe dig med eventuelle spørgsmål, du måtte have. Tøv ikke med at spørge!
<br/>
## Licens
Dette repository, inklusive alt dets indhold, underprojekter, moduler og komponenter, er licenseret under [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), medmindre andet er udtrykkeligt angivet. Tredjepartsbiblioteker inkluderet i dette repository kan være underlagt deres egne licenser.
<h3 align="center"><img width="80" alt="Puter.com, Der persönliche Cloud-Computer: Alle Ihre Dateien, Apps und Spiele an einem Ort, jederzeit und überall zugänglich." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Das Internet-Betriebssystem! Kostenlos, Open-Source und selbst hostbar.</h3>
Puter ist ein fortschrittliches, Open-Source-Internet-Betriebssystem, das funktionsreich, außergewöhnlich schnell und hochgradig erweiterbar konzipiert wurde. Puter kann verwendet werden als:
- Eine datenschutzfreundliche persönliche Cloud, um alle Ihre Dateien, Apps und Spiele an einem sicheren Ort aufzubewahren, jederzeit und überall zugänglich.
- Eine Plattform zum Erstellen und Veröffentlichen von Websites, Webanwendungen und Spielen.
- Eine Alternative zu Dropbox, Google Drive, OneDrive usw. mit einer frischen Benutzeroberfläche und leistungsstarken Funktionen.
- Eine Remote-Desktop-Umgebung für Server und Workstations.
- Ein freundliches, Open-Source-Projekt und eine Community, um mehr über Webentwicklung, Cloud Computing, verteilte Systeme und vieles mehr zu lernen!
<br/>
## Erste Schritte
### 💻 Lokale Entwicklung
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Dies startet Puter unter http://puter.localhost:4100 (oder dem nächsten verfügbaren Port).
Wir helfen Ihnen gerne bei allen Fragen, die Sie haben könnten. Zögern Sie nicht zu fragen!
<br/>
## Lizenz
Dieses Repository, einschließlich aller Inhalte, Unterprojekte, Module und Komponenten, ist unter [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) lizenziert, sofern nicht ausdrücklich anders angegeben. In diesem Repository enthaltene Bibliotheken von Drittanbietern können ihren eigenen Lizenzen unterliegen.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">The Internet OS! Free, Open-Source, and Self-Hostable.</h3>
Puter is an advanced, open-source internet operating system designed to be feature-rich, exceptionally fast, and highly extensible. Puter can be used as:
- A privacy-first personal cloud to keep all your files, apps, and games in one secure place, accessible from anywhere at any time.
- A platform for building and publishing websites, web apps, and games.
- An alternative to Dropbox, Google Drive, OneDrive, etc. with a fresh interface and powerful features.
- A remote desktop environment for servers and workstations.
- A friendly, open-source project and community to learn about web development, cloud computing, distributed systems, and much more!
<br/>
## Getting Started
### 💻 Local Development
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
This will launch Puter at http://puter.localhost:4100 (or the next available port).
We are always happy to help you with any questions you may have. Don't hesitate to ask!
<br/>
## License
This repository, including all its contents, sub-projects, modules, and components, is licensed under [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) unless explicitly stated otherwise. Third-party libraries included in this repository may be subject to their own licenses.
<h3 align="center"><img width="80" alt="Puter.com, El Computador Personal en Nube: Todos tus archivos, apps y juegos en un solo lugar accesible desde cualquier lugar en cualquier momento" src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">El Sistema Operativo de Internet! Gratis, de Código abierto, y Autohospedable.</h3>
<p align="center">
<a href="https://puter.com/"><strong>« DEMO EN VIVO »</strong></a>
Puter es un sistema operativo en internet avanzado y de código abierto, diseñado para ser rico en funcionalidades, excepcionalmente rápido y altamente extensible. Puter puede ser usado como:
- Una nube personal privada para almacenar todos tus archivos, aplicaciones y juegos en un lugar seguro, accesible y desde cualquier lugar en cualquier momento.
- Una plataforma para construir y publicar páginas web, aplicativos sobre la web y juegos.
- Una alternativa a Dropbox, Google Drive, OneDrive, etc. con una interfaz fresca y llena de funcionalidades.
- Un entorno de escritorio remoto para servidores y estaciones de trabajo.
- Un proyecto y comunidad abiertas y amigables para aprender sobre desarrollo web, computación en la nube, sistemas distribuidos y mucho más!
<br/>
## Primeros Pasos
### 💻 Desarrollo Local
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
✨ Esto ejecutará Puter en http://puter.localhost:4100 (o el siguiente puerto disponible).
Si esto no funciona, consulta [First Run Issues](./doc/self-hosters/first-run-issues.md) para obtener pasos de solución de problemas.
✨ Esto ejecutará Puter en http://puter.localhost:4100 (o el siguiente puerto disponible).
<br/>
### 🚀 Auto-Hospedaje
Para guías detalladas sobre cómo auto-hospedar Puter, incluyendo opciones de configuración y mejores prácticas, consulta nuestra [Documentación de Auto-Hospedaje](https://github.com/HeyPuter/puter/blob/main/doc/self-hosters/instructions.md).
### ☁️ Puter.com
Puter está disponible como servicio alojado en [**puter.com**](https://puter.com).
<br/>
## Requerimientos del sistema
- **Sistemas operativos:** Linux, macOS, Windows
- **RAM:** 2GB mínimo (4GB recomendados)
- **Almacenamiento:** 1GB de espacio libre
- **Node.js:** Versión 16+ (Versión 23+ recomendada)
- **npm:** Última version estable
<br/>
## Soporte
Conéctate con los mantenedores y la comunidad a través de estos canales:
- Reporte de bug o solicitud de funcionalidad? Por favor [abrir un issue](https://github.com/HeyPuter/puter/issues/new/choose).
Estamos siempre felices de ayudar con cualquier pregunta que puedas tener. No dudes en preguntar!
<br/>
## Licencia
Este repositorio, incluyendo todo su contenido, sub-proyectos, modulos y componentes, esta licenciado bajo [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) a menos que se indique explícitamente lo contrario. Librerías de terceros incluidos en este repositorio pueden estar sujetas a sus propias licencias.
<h3 align="center"><img width="80" alt="Puter.com، رایانش ابری شخصی: همه فایلها، برنامهها و بازیهای شما در یک مکان قابل دسترسی از هر جا و در هر زمان." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">سیستمعامل اینترنت! رایگان، متنباز، و قابل میزبانی شخصی.</h3>
<p>پیوتر یک سیستم عامل تحت وب پیشرفتهی متنباز است که به منظور ایجاد ویژگیهای متنوع، سرعت بسیار بالا، و مقیاسپذیری طراحی شده است. از پیوتر میتوان بهعنوان:</p>
<ul>
<li>یک فضای ابری شخصی که بر حریم خصوصی تمرکز دارد و تمام فایلها، برنامهها، و بازیهای شما را در یک مکان امن ذخیره میکند، قابل دسترسی از هر جا و در هر زمان.</li>
<li>پلتفرمی برای ساخت و انتشار وبسایتها، اپلیکیشنهای وب، و بازیها.</li>
<li>جایگزینی برای Dropbox، Google Drive، OneDrive، و سایر موارد، با یک رابط کاربری مدرن و قابلیتهای قدرتمند.</li>
<li>یک محیط دسکتاپ از راه دور برای سرورها و ایستگاههای کاری.</li>
<li> یک پروژه و جامعهی متنباز دوستانه برای یادگیری توسعه وب، رایانش ابری، سیستمهای توزیعشده، و موارد دیگر نام برد!</li>
</ul>
</div>
<br/>
## نحوهی استفاده
### 💻 توسعهی محلی
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
این کار پیوتر را در http://puter.localhost:4100 (یا پورت در دسترس بعدی) اجرا میکند.
ما همیشه از پاسخگویی به سوالات شما خرسند هستیم. در سوال پرسیدن درنگ نکنید!
## گواهی
این مخزن، شامل تمام محتویات، پروژههای فرعی، ماژولها و اجزای آن، تحت مجوز [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) است مگر آنکه خلاف آن بهطور صریح ذکر شده باشد. کتابخانههای خارجی ممکن است گواهیهای جداگانه داشته باشند.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Internetin käyttöjärjestelmä! Ilmainen, avoimen lähdekoodin ja itse isännöitävä.</h3>
Puter on kehittynyt, avoimen lähdekoodin internetin käyttöjärjestelmä, joka on suunniteltu olemaan ominaisuuksiltaan rikas, poikkeuksellisen nopea ja erittäin laajennettava. Puteria voidaan käyttää:
- Yksityisyyttä kunnioittavana henkilökohtaisena pilvenä, johon voit tallentaa kaikki tiedostosi, sovelluksesi ja pelisi turvallisesti yhdessä paikassa, josta ne ovat saatavilla missä tahansa ja milloin tahansa.
- Alustana verkkosivustojen, web-sovellusten ja pelien rakentamiseen ja julkaisemiseen.
- Vaihtoehtona Dropboxille, Google Drivelle, OneDrivelle jne. tuoreella käyttöliittymällä ja tehokkailla ominaisuuksilla.
- Etätyöpöytäympäristönä palvelimille ja työasemille.
- Ystävällisenä, avoimen lähdekoodin projektina ja yhteisönä, jossa voit oppia verkkokehityksestä, pilvipalveluista, hajautetuista järjestelmistä ja paljon muusta!
<br/>
## Aloittaminen
### 💻 Paikallinen kehitys
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Tämä käynnistää Puterin osoitteessa http://puter.localhost:4100 (tai seuraavassa vapaassa portissa).
Olemme aina valmiita auttamaan sinua kaikissa kysymyksissäsi. Älä epäröi kysyä!
<br/>
## Lisenssi
Tämä repository, mukaan lukien kaikki sen sisältö, aliprojektit, moduulit ja komponentit, on lisensoitu [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt)-lisenssillä, ellei toisin mainita. Tämän repositoryn mukana tulevat kolmannen osapuolen kirjastot voivat olla omien lisenssiensä alaisia.
<h3 align="center"><img width="80" alt="Puter.com, L'ordinateur cloud personnel : Tous vos fichiers, applications et jeux en un seul endroit accessible de partout à tout moment." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">L'OS Internet ! Gratuit, open-source et auto-hébergeable.</h3>
Puter est un système d'exploitation internet avancé, open-source, conçu pour être riche en fonctionnalités, extrêmement rapide et hautement extensible. Puter peut être utilisé comme :
- Un cloud personnel axé sur la confidentialité pour garder tous vos fichiers, applications et jeux en un seul endroit sécurisé, accessible de partout à tout moment.
- Une plateforme pour créer et publier des sites web, des applications web et des jeux.
- Une alternative à Dropbox, Google Drive, OneDrive, etc. avec une interface renouvelée et des fonctionnalités puissantes.
- Un environnement de bureau à distance pour serveurs et stations de travail.
- Un projet et une communauté open-source accueillants pour apprendre le développement web, l'informatique en nuage, les systèmes distribués, et bien plus encore !
<br/>
## Démarrage
### 💻 Développement Local
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Cela lancera Puter à http://puter.localhost:4100 (ou au port disponible suivant).
Nous sommes toujours heureux de vous aider avec toutes les questions que vous pourriez avoir. N'hésitez pas à nous demander !
<br/>
## License
Ce dépôt, y compris tout son contenu, sous-projets, modules et composants, est licencié sous [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) sauf indication contraire explicite. Les bibliothèques tierces incluses dans ce dépôt peuvent être soumises à leurs propres licences.
אנחנו תמיד שמחים לעזור עם כל שאלה שיש. אל תהסס לשאול!
<br/>
## רישיון
ספריה זו, כולל כל התכנים שלה, תתי הפרויקטים, המודולים והרכיבים שלה, מורשית תחת [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) אלא אם נאמר אחרת במפורש. לספריות צד שלישי הכלולות בספרייה זו עשויות להיות רישיונות משלהן.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: आपकी सारी फाइलें, ऐप्स, और गेम एक ही जगह, जिसे कहीं से भी कभी भी एक्सेस किया जा सकता है।" src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">इंटरनेट ओएस! फ्री, ओपन-सोर्स, और सेल्फ-होस्टेबल।</h3>
Puter एक एडवांस्ड, ओपन-सोर्स इंटरनेट ऑपरेटिंग सिस्टम है जिसे फीचर-रिच, तेज़ और एक्सटेंडेबल बनाने के लिए डिज़ाइन किया गया है। Puter का उपयोग आप निम्नलिखित चीजों के लिए कर सकते हैं:
- एक प्राइवेसी-फर्स्ट पर्सनल क्लाउड, जो आपकी सभी फाइलों, ऐप्स और गेम्स को एक सेफ जगह पर रखता है, जिसे आप कहीं से भी कभी भी एक्सेस कर सकते हैं।
- वेबसाइट्स, वेब ऐप्स और गेम्स बनाने और पब्लिश करने का एक प्लेटफ़ॉर्म।
- Dropbox, Google Drive, OneDrive आदि का एक शानदार और पावरफुल इंटरफ़ेस वाला विकल्प।
- सर्वर और वर्कस्टेशन के लिए एक रिमोट डेस्कटॉप एनवायरनमेंट।
- एक फ्रेंडली ओपन-सोर्स प्रोजेक्ट और कम्युनिटी, जहां आप वेब डेवलपमेंट, क्लाउड कंप्यूटिंग, डिस्ट्रीब्यूटेड सिस्टम्स और बहुत कुछ सीख सकते हैं।
<br/>
## शुरुआत कैसे करें?
### 💻 लोकल डेवलपमेंट
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
✨ यह Puter को
<font color="red"> http://puter.localhost:4100 </font> (या अगले उपलब्ध पोर्ट) पर लॉन्च करेगा।
अगर यह काम नहीं करता, तो [First Run Issues](./doc/self-hosters/first-run-issues.md) देखें।
<font color="red"> http://puter.localhost:4100 (or the next available port). </font> (या अगले उपलब्ध पोर्ट) पर लॉन्च करेगा।
<br/>
### 🚀 सेल्फ-होस्टिंग
सेल्फ-होस्टिंग के लिए विस्तृत गाइड, कॉन्फ़िगरेशन ऑप्शन्स और बेस्ट प्रैक्टिसेज जानने के लिए हमारी [Self-Hosting Documentation](https://github.com/HeyPuter/puter/blob/main/doc/self-hosters/instructions.md) देखें।
<br/>
### ☁️ Puter.com
Puter [**puter.com**](https://puter.com) पर एक होस्टेड सर्विस के रूप में भी उपलब्ध है।
<br/>
## सिस्टम आवश्यकताएँ
* **ऑपरेटिंग सिस्टम्स:** Linux, macOS, Windows
* **RAM:** कम से कम 2GB (4GB रिकमेंडेड)
* **डिस्क स्पेस:** 1GB फ्री स्पेस
* **Node.js:** वर्जन 16+ (वर्जन 23+ रिकमेंडेड)
* **npm:** लेटेस्ट स्टेबल वर्जन
<br/>
## सपोर्ट
नीचे दिए गए माध्यमों से आप मेंटेनर्स और कम्युनिटी से जुड़ सकते हैं:
* बग रिपोर्ट या फीचर रिक्वेस्ट? [यहाँ issue खोलें](https://github.com/HeyPuter/puter/issues/new/choose)।
आपके किसी भी सवाल में मदद करने के लिए हम हमेशा तैयार हैं!
<br/>
## लाइसेंस
यह रिपॉज़िटरी और इसके सभी कंटेंट्स [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) लाइसेंस के अंतर्गत आते हैं जब तक कि कुछ और स्पष्ट रूप से ना लिखा हो। इसमें शामिल थर्ड-पार्टी लाइब्रेरीज़ अपने-अपने लाइसेंस के अधीन हो सकती हैं।
<br/>
## अनुवाद
Puter के डॉक्यूमेंटेशन कई भाषाओं में उपलब्ध हैं, जिनमें शामिल हैं:
<h3 align="center"><img width="80" alt="Puter.com, A személyi felhő számítógép: Minden fájl, alkalmazás és játék egy helyen elérhető bárhonnan, bármikor." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Az internetes oprendszer! Ingyenes, nyílt-forráskódú, saját szerveren futtatható.</h3>
A Puter egy fejlett, nyílt forráskódú internetes operációs rendszer, amelyet úgy terveztek, hogy funkciókban gazdag, kivételesen gyors és nagymértékben bővíthető legyen. A Puter a következőképpen használható:
- Egy adatvédelmet előtérbe helyező személyes felhő, amely minden fájlt, alkalmazást és játékot egy biztonságos helyen tart. Bárhonnan és bármikor elérhető.
- Egy platform weboldalak, web-appok, és játékok készítéséhez/közzétételéhez.
- A Dropbox, Google Drive, OneDrive (stb.) alternatívája megújult felülettel és hatékony funkciókkal.
- Egy távoli desktop-környezet szervereknek és workstation-öknek.
- Egy barátságos, nyílt forráskódú projekt és közösség, amely a webfejlesztéssel, a felhőalapú számítástechnikával, elosztott rendszerekkel és sok más érdekes témával foglalkozik!
<br/>
## Első lépések
### 💻 Helyi (lokális) fejlesztés
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Ezzel a http://puter.localhost:4100 -on futtatjuk Putert. (vagy a legközelebbi elérhető porton).
Mindig örömmel segítünk bármilyen felmerülő kérdésben. Bátran kérdezz tőlünk!
<br/>
## License
Ez a repo, beleértve annak minden tartalmát, alprojektjeit, moduljait és komponenseit, az [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) licenc alatt áll, hacsak másképp nem rendelkeznek róla. A repoban szereplő harmadik fél által fejlesztett könyvtárak saját licencfeltételek alá eshetnek.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Ինտերնետ ՕՀ! Անվճար, բաց կոդով և ինքնահոսթ հնարավորությամբ։</h3>
Puter-ը առաջադեմ, բաց կոդով ինտերնետային օպերացիոն համակարգ է, որը նախագծված է լինել ֆունկցիոնալ հարուստ, բացառիկ արագ և բարձր ընդլայնելի։ Puter-ը կարող է օգտագործվել հետևյալ կերպ․
- Անձնական ամպային համակարգ՝ առաջնային գաղտնիությամբ, որը թույլ է տալիս պահել ձեր բոլոր ֆայլերը, հավելվածները և խաղերը մեկ անվտանգ վայրում, որը հասանելի է ցանկացած վայրից և ցանկացած ժամանակ։
- Պլատֆորմ կայքերի, վեբ հավելվածների և խաղերի ստեղծման և հրապարակման համար։
- Dropbox, Google Drive, OneDrive և այլ ծառայությունների այլընտրանք՝ նոր ինտերֆեյսով և հզոր գործառույթներով։
- Հեռավոր աշխատասեղանի միջավայր սերվերների և աշխատանքային կայանների համար։
- Պարզ, բաց կոդով նախագիծ և համայնք՝ վեբ ծրագրավորման, ամպային հաշվարկների, բաշխված համակարգերի և այլ թեմաների մասին սովորելու համար։
<br/>
## Սկսել
### 💻 Լոկալ ծրագրավորում
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Սա կգործակի Puter-ը հետևյալ հասցեով՝ http://puter.localhost:4100 (կամ հաջորդ հասանելի պորտով)։
Մենք միշտ ուրախ ենք օգնել ձեզ ցանկացած հարցում։ Մի կաշկանդվեք հարցնել։
<br/>
## Լիցենզիա
Այս պահոցարանը, ներառյալ բոլոր իր բովանդակությունը, ենթա-պրոյեկտները, մոդուլները և բաղադրիչները, լիցենզավորվում են [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) լիցենզիայի տակ, եթե այլ կերպ հստակ նշված չէ։ Այս պահոցարանում ներառված երրորդ կողմի գրադարանները կարող են ենթարկվել իրենց սեփական լիցենզիաներին։
<h3 align="center"><img width="80" alt="Puter.com, Komputer Cloud Pribadi: Semua file, aplikasi, dan permainan Anda berada di satu tempat yang dapat diakses dari mana saja kapan saja." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Sistem Operasi Internet! Gratis, Sumber Terbuka, dan Dapat Dihosting Sendiri.</h3>
Puter adalah sistem operasi internet canggih, open-source, yang dirancang untuk menjadi kaya fitur, sangat cepat, dan sangat dapat diperluas. Puter dapat digunakan sebagai:
- Cloud pribadi yang mengutamakan privasi untuk menyimpan semua file, aplikasi, dan permainan Anda di satu tempat yang aman, yang dapat diakses dari mana saja kapan saja.
- Platform untuk membangun dan mempublikasikan situs web, aplikasi web, dan permainan.
- Alternatif untuk Dropbox, Google Drive, OneDrive, dll. Dengan antarmuka baru dan fitur-fitur canggih.
- Lingkungan desktop jarak jauh untuk server dan workstation.
- Proyek dan komunitas open-source yang ramah untuk belajar tentang pengembangan web, komputasi gemawan (cloud), sistem terdistribusi, dan banyak lagi!
<br/>
## Memulai
### 💻 Pengembangan Lokal
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Ini akan menjalankan Puter di http://puter.localhost:4100 (atau di port berikutnya yang tersedia)
Kami selalu senang membantu Anda dengan pertanyaan apa pun yang Anda miliki. Jangan ragu untuk bertanya!
<br/>
## Lisensi
Repositori ini, termasuk semua isinya, sub-proyek, modul, dan komponen, dilisensikan di bawah [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) kecuali dinyatakan sebaliknya secara eksplisit. Perpustakaan pihak ketiga yang termasuk dalam repositori ini mungkin tunduk pada lisensinya sendiri.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Il sistema operativo di Internet! Gratuito, Open-Source e Auto-Hostabile.</h3>
Puter è un sistema operativo di Internet avanzato e open-source, progettato per essere ricco di funzionalità, eccezionalmente veloce e altamente estensibile. Puter può essere utilizzato come:
- Un cloud personale che tiene conto della privacy per conservare tutti i file, le app e i giochi in un luogo sicuro, accessibile da qualsiasi luogo e in qualsiasi momento.
- Una piattaforma per creare e pubblicare siti web, app e giochi.
- Un'alternativa a Dropbox, Google Drive, OneDrive, ecc. con un'interfaccia nuova e funzioni potenti.
- Un ambiente desktop remoto per server e workstation.
- Un progetto e una comunità open-source amichevole per imparare lo sviluppo web, il cloud computing, i sistemi distribuiti e molto altro ancora!
<br/>
## Getting Started
### 💻 Local Development
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
In questo modo Puter verrà avviato all'indirizzo http://puter.localhost:4100 (o alla prossima porta disponibile).
Siamo sempre felici di aiutarvi con qualsiasi domanda. Non esitate a chiedere!
<br/>
## Licenza
Questo repository, compresi tutti i suoi contenuti, sottoprogetti, moduli e componenti, è concesso in licenza [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), a meno che non sia esplicitamente indicato diversamente. Le librerie di terze parti incluse in questo repository possono essere soggette alle loro licenze.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Puter: 인터넷 OS! 무료이고 오픈소스이며 자체 호스팅이 가능합니다.</h3>
이 저장소는 모든 내용, 하위 프로젝트, 모듈 및 구성 요소를 포함하여 명시적으로 달리 명시되지 않는 한 [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) 라이선스 하에 제공됩니다. 이 저장소에 포함된 제3자 라이브러리는 해당 라이브러리의 고유 라이선스를 따를 수 있습니다.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">ഇന്റർനെറ്റ് ഓപ്പറേറ്റിംഗ് സിസ്റ്റം!<br> സൗജന്യവും, ഓപ്പൺ സോഴ്സും സ്വയം ഹോസ്റ്റ് ചെയ്യാൻ പറ്റുന്നതും</h3>
ഫീച്ചറുകളാൽ സമ്പുഷ്ടവും അസാധാരണമാംവിധം വേഗതയേറിയതും,വളരെ വിപുലീകരിക്കാവുന്നതുമായ ഒരു നൂതന, ഓപ്പൺ സോഴ്സ് ഇന്റർനെറ്റ് ഓപ്പറേറ്റിംഗ് സിസ്റ്റമാണ് പ്യൂട്ടർ. പ്യൂട്ടർ ഇനിപ്പറയുന്ന രീതിയിൽ ഉപയോഗിക്കാം:
- നിങ്ങളുടെ എല്ലാ ഫയലുകളും ആപ്പുകളും ഗെയിമുകളും ഒരു സുരക്ഷിത സ്ഥലത്ത് സൂക്ഷിക്കുന്നതിനുള്ള, സ്വകാര്യതയ്ക്ക് മുൻഗണന കൊടുക്കുന്ന ആദ്യത്തെ വ്യക്തിഗത ക്ലൗഡ്, എവിടെ നിന്നും എപ്പോൾ വേണമെങ്കിലും ആക്സസ് ചെയ്യാൻ കഴിയും.
- വെബ്സൈറ്റുകൾ, വെബ് ആപ്പുകൾ, ഗെയിമുകൾ എന്നിവ നിർമ്മിക്കുന്നതിനും പ്രസിദ്ധീകരിക്കുന്നതിനുമുള്ള ഒരു പ്ലാറ്റ്ഫോം.
- പുതിയ ഇന്റർഫേസും, ശക്തമായ ഫീച്ചറുകളും അടങ്ങിയ, ഡ്രോപ്പ്ബോക്സ്, ഗൂഗിൾ ഡ്രൈവ്, വൺഡ്രൈവ് മുതലായവയ്ക്കുള്ള ബദൽ.
- സെർവറുകൾക്കും വർക്ക്സ്റ്റേഷനുകൾക്കും, ഒരു വിദൂര ഡെസ്ക്ടോപ്പ് പരിസ്ഥിതി.
- വെബ് ഡെവലപ്മെന്റ്, ക്ലൗഡ് കംപ്യൂട്ടിംഗ്, ഡിസ്ട്രിബ്യൂട്ടഡ് സിസ്റ്റങ്ങൾ എന്നിവയെ കുറിച്ചും, അതിലേറെ കാര്യങ്ങളെ കുറിച്ചും അറിയാനുള്ള സൗഹൃദപരവും ഓപ്പൺ സോഴ്സുമായ പ്രോജക്റ്റും കമ്മ്യൂണിറ്റിയും!
<br/>
## തുടങ്ങാനായി
### 💻 ലോക്കൽ ഡെവലപ്മെന്റ്
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
ഇത് http://puter.localhost:4100 (അല്ലെങ്കിൽ അടുത്ത ലഭ്യമായ പോർട്ടിൽ) എന്നതിൽ Puter സമാരംഭിക്കും
നിങ്ങൾക്ക് ഉണ്ടായേക്കാവുന്ന ഏത് ചോദ്യങ്ങളിലും നിങ്ങളെ സഹായിക്കുന്നതിൽ ഞങ്ങൾക്ക് എപ്പോഴും സന്തോഷമുണ്ട്. ചോദിക്കാൻ മടിക്കേണ്ട!
<br/>
## ലൈസൻസ്
ഈ ശേഖരം, അതിന്റെ എല്ലാ ഉള്ളടക്കങ്ങളും, ഉപപദ്ധതികളും, മൊഡ്യൂളുകളും, ഘടകങ്ങളും ഉൾപ്പെടെ, [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) എന്നതിന് കീഴിൽ ലൈസൻസുള്ളതാണ്. ഈ ശേഖരത്തിൽ ഉൾപ്പെടുത്തിയിരിക്കുന്ന മൂന്നാം കക്ഷി ലൈബ്രറികൾ അവരുടെ സ്വന്തം ലൈസൻസുകൾക്ക് വിധേയമായിരിക്കാം.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: Semua fail, apl, dan permainan anda di satu tempat yang boleh diakses dari mana sahaja pada bila-bila masa." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Sistem Operasi Internet! Percuma, Sumber Terbuka, dan Boleh Dihoskan Sendiri.</h3>
Puter ialah sistem operasi internet sumber terbuka yang maju dan direka untuk kaya dengan ciri kefungsian, kepantasan luar biasa dan kebolehluasan yang tinggi. Puter boleh digunakan sebagai:
- Storan awan peribadi yang mendahulukan privasi untuk menyimpan semua fail, aplikasi dan permainan anda di satu tempat yang selamat dan boleh diakses dari mana sahaja pada bila-bila masa.
- Platform untuk membina dan menerbitkan laman web, aplikasi web dan permainan.
- Alternatif kepada Dropbox, Google Drive, OneDrive, dan lain-lain dengan antara muka yang baharu dan ciri kefungsian berkuasa tinggi.
- Persekitaran desktop awan untuk server dan stesen kerja.
- Projek dan komuniti sumber terbuka yang mesra untuk mempelajari pembangunan laman web, pengkomputeran awan, sistem teragih, dan banyak lagi!
<br/>
## Mulakan
### 💻 Pembangunan Lokal
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Ini akan melancarkan Puter di http://puter.localhost:4100 (atau port seterusnya yang tersedia).
Kami sentiasa gembira untuk membantu anda dengan apa-apa soalan. Jangan takut untuk bertanya!
<br/>
## Lesen
Repositori ini, termasuklah kandungannya, subprojek, modul dan komponen, dilesenkan di bawah [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) melainkan dinyatakan sebaliknya. *Library* pihak ketiga yang terkandung dalam repositori ini tertakluk kepada lesen mereka sendiri.
<!-- The word `Library` is kept as is to avoid confusion since the direct translation `Perpustakaan/Pustaka` is never used in the tech context and doesn't convey the same meaning among Malay community if used in this situation -->
<h3 align="center"><img width="80" alt="Puter.com, De Persoonlijke Cloud Computer: Al je bestanden, apps en games op één plek, overal en altijd toegankelijk." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Het Internet OS! Gratis, Open-Source en Zelf te Hosten.</h3>
Puter is een geavanceerd, open-source internetbesturingssysteem ontworpen om functierijk, uitzonderlijk snel en zeer uitbreidbaar te zijn. Puter kan worden gebruikt als:
- Een privacy-gerichte persoonlijke cloud om al je bestanden, apps en games op één veilige plek te bewaren, overal en altijd toegankelijk.
- Een platform voor het bouwen en publiceren van websites, web-apps en games.
- Een alternatief voor Dropbox, Google Drive, OneDrive, etc. met een frisse interface en krachtige functies.
- Een externe desktopomgeving voor servers en werkstations.
- Een vriendelijk, open-source project en gemeenschap om te leren over webontwikkeling, cloud computing, gedistribueerde systemen en veel meer!
<br/>
## Aan de slag
### 💻 Lokale Ontwikkeling
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Dit zal Puter starten op http://puter.localhost:4100 (of de eerstvolgende beschikbare poort).
We helpen je graag met al je vragen. Aarzel niet om te vragen!
<br/>
## Licentie
Deze repository, inclusief alle inhoud, subprojecten, modules en componenten, is gelicentieerd onder [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) tenzij expliciet anders vermeld. Bibliotheken van derden die in deze repository zijn opgenomen, kunnen onderworpen zijn aan hun eigen licenties.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center"><img width="80" alt="Puter.com, Osobisty Komputer Chmurowy: Wszystkie twoje pliki, aplikacje i gry w jednym miejscu, dostępne z dowolnego miejsca o dowolnej porze." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center"> System Operacyjny Internet! Darmowy, Open-Source i Możliwy do Samodzielnego Hostowania.</h3>
Puter to zaawansowany, open-source'owy internetowy system operacyjny, zaprojektowany tak, aby był bogaty w funkcje, wyjątkowo szybki i wysoce rozszerzalny. Puter może być używany jako:
- Prywatna chmura osobista do przechowywania wszystkich plików, aplikacji i gier w jednym bezpiecznym miejscu, dostępnym z dowolnego miejsca o dowolnej porze.
- Platforma do budowania i publikowania stron internetowych, aplikacji webowych i gier.
- Alternatywa dla Dropbox, Google Drive, OneDrive itp. ze świeżym interfejsem i potężnymi funkcjami.
- Zdalne środowisko pulpitu dla serwerów i stacji roboczych.
- Przyjazny, open-source'owy projekt i społeczność do nauki o tworzeniu stron internetowych, chmurze obliczeniowej, systemach rozproszonych i wielu innych!
<br/>
## Rozpoczęcie pracy
## 💻 Lokalne środowisko developerskie
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
To uruchomi Puter na http://puter.localhost:4100 (lub na następnym dostępnym porcie).
Puter jest dostępny jako usługa hostowana na [**puter.com**](https://puter.com).
<br/>
## Wymagania systemowe
- **Systemy operacyjne:** Linux, macOS, Windows
- **RAM:** Minimum 2GB (zalecane 4GB)
- **Przestrzeń dyskowa:** 1GB wolnego miejsca
- **Node.js:** Wersja 16+ (zalecana wersja 22+)
- **npm:** Najnowsza stabilna wersja
<br/>
## Wsparcie
Skontaktuj się z opiekunami i społecznością przez te kanały:
- Raport o błędzie lub prośba o funkcję? Proszę otworzyć zgłoszenie.
- Discord: discord.com/invite/PQcx7Teh8u
- X (Twitter): x.com/HeyPuter
- Reddit: reddit.com/r/puter/
- Mastodon: mastodon.social/@puter
- Problemy z bezpieczeństwem? security@puter.com
- Email do opiekunów: hi@puter.com
Zawsze chętnie pomożemy Ci z wszelkimi pytaniami, jakie możesz mieć. Nie wahaj się pytać!
<br/>
## Licencja
To repozytorium, w tym cała jego zawartość, podprojekty, moduły i komponenty, jest licencjonowane na podstawie [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), chyba że wyraźnie zaznaczono inaczej. Biblioteki stron trzecich zawarte w tym repozytorium mogą podlegać własnym licencjom.
<h3 align="center"><img width="80" alt="Puter.com, O Computador Pessoal em Nuvem: Todos os seus arquivos, aplicativos e jogos em um único lugar, acessíveis de qualquer lugar e a qualquer hora." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">O Sistema Operacional da Internet! Gratuito, de Código Aberto e Auto-Hospedável.</h3>
<p align="center">
<a href="https://puter.com/"><strong>« DEMONSTRAÇÃO AO VIVO »</strong></a>
Puter é um sistema operacional de internet avançado e de código aberto, projetado para ser rico em recursos, excepcionalmente rápido e altamente extensível. Puter pode ser usado como:
- Um serviço de nuvem pessoal com foco na privacidade para manter todos os seus arquivos, aplicativos e jogos em um local seguro, acessível de qualquer lugar e a qualquer hora.
- Uma plataforma para construir e publicar websites, aplicativos web e jogos.
- Uma alternativa ao Dropbox, Google Drive, OneDrive, etc., com uma interface renovada e recursos poderosos.
- Um ambiente de desktop remoto para servidores e estações de trabalho.
- Um projeto e comunidade de código aberto e amigável para aprender sobre desenvolvimento web, computação em nuvem, sistemas distribuídos e muito mais!
<br/>
## Iniciando o Projeto
### 💻 Desenvolvimento Local
```
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
✨ Isso iniciará o Puter em http://puter.localhost:4100 (ou na próxima porta disponível).
Se isso não funcionar, consulte [First Run Issues](./doc/self-hosters/first-run-issues.md) para solucionar os problemas.
✨ Isso iniciará o Puter em http://puter.localhost:4100 (ou na próxima porta disponível).
<br/>
### 🚀 Auto-Hospedagem
Para guia detalhados sobre como auto-hospedar o Puter, incluindo opções de configuração e melhores práticas, consulte nossa [Documentação de Auto-Hospedagem](https://github.com/HeyPuter/puter/blob/main/doc/self-hosters/instructions.md).
### ☁️ Puter.com
O Puter está disponível como um serviço hospedado em [**puter.com**](https://puter.com).
<br/>
## Requerimentos do sistema
- **Sistema operacional:** Linux, macOS, Windows
- **RAM:** 2GB mínimo (4GB recomendado)
- **Espaço de disco:** 1GB de espaço disponível
- **Node.js:** Versão 16+ (Versão 23+ recomendada)
- **npm:** Última versão estável
<br/>
## Suporte
Conecte-se com os mantenedores e a comunidade através destes canais:
- Relato de bug ou solicitação de recurso? Por favor, [abra um tópico](https://github.com/HeyPuter/puter/issues/new/choose).
Estamos sempre felizes em ajudá-lo com quaisquer perguntas que você possa ter. Não hesite em perguntar!
<br/>
## Licença
Este repositório, incluindo todos os seus conteúdos, subprojetos, módulos e componentes, está licenciado sob [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) a menos que explicitamente indicado de outra forma. Bibliotecas de terceiros incluídas neste repositório podem estar sujeitas às suas próprias licenças.
<h3 align="center"><img width="80" alt="Puter.com, calculatorul personal în cloud: toate fișierele, aplicațiile și jocurile tale într-un singur loc, accesibile de oriunde și oricând." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Sistemul de operare al internetului! Gratuit, open-source și găzduibil autonom.</h3>
<p align="center">
<img alt="Dimensiunea repoului GitHub" src="https://img.shields.io/github/repo-size/HeyPuter/puter"> <img alt="Versiunea de pe GitHub" src="https://img.shields.io/github/v/release/HeyPuter/puter?label=ultima%20versiune"> <img alt="Licență GitHub" src="https://img.shields.io/github/license/HeyPuter/puter">
</p>
<p align="center">
<a href="https://puter.com/"><strong>« DEMO LIVE »</strong></a>
<a href="https://hackerone.com/puter_h1b">Program de recompense pentru identificarea bugurilor</a>
</p>
<h3 align="center"><img width="800" style="border-radius:5px;" alt="captură de ecran" src="https://assets.puter.site/puter.com-screenshot-3.webp"></h3>
<br/>
## Puter
Puter este un sistem de operare pe internet, avansat, open-source, conceput să fie bogat în funcționalități, excepțional de rapid și foarte extensibil. Puter poate fi folosit ca:
* Un cloud personal cu accent pe confidențialitate, pentru a-ți păstra toate fișierele, aplicațiile și jocurile într-un singur loc securizat, accesibil de oriunde și oricând.
* O platformă pentru a construi și publica site-uri, aplicații web și jocuri.
* O alternativă la Dropbox, Google Drive, OneDrive etc., cu o interfață nouă și funcționalități puternice.
* Un mediu desktop la distanță pentru servere și stații de lucru.
* Un proiect și o comunitate, open-source și prietenoase, pentru a învăța despre dezvoltare web, cloud computing, sisteme distribuite și multe altele!
<br/>
## Fă primii pași
### 💻 Dezvoltare locală
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Aceasta va porni Puter la [http://puter.localhost:4100](http://puter.localhost:4100) (sau pe următorul port disponibil).
Suntem întotdeauna bucuroși să te ajutăm cu orice întrebări ai. Nu ezita să ne pui întrebări!
<br/>
## Licență
Acest repository, inclusiv tot conținutul său, subproiectele, modulele și componentele, este licențiat sub [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), cu excepția cazurilor în care se menționează explicit altfel. Bibliotecile terțe incluse în acest repository pot fi supuse propriilor lor licențe.
<h3 align="center"><img width="80" alt="Puter.com, персональный облачный компьютер: все ваши файлы, приложения и игры в одном месте, доступные из любой точки мира в любое время." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Интернет ОС! Бесплатная, с открытым исходным кодом и возможностью самостоятельной установки.</h3>
Puter — это передовая операционная система с открытым исходным кодом, разработанная для обеспечения широкого функционала, исключительной скорости и высокой масштабируемости. Puter можно использовать как:
- Персональное облако с приоритетом конфиденциальности для хранения всех ваших файлов, приложений и игр в одном безопасном месте, доступном из любой точки мира в любое время.
- Платформа для создания и публикации веб-сайтов, веб-приложений и игр.
- Альтернатива Dropbox, Google Drive, OneDrive и т. д. с новым интерфейсом и мощными функциями.
- Удаленное рабочее окружение для серверов и рабочих станций.
- Дружественный проект с открытым исходным кодом и сообщество для изучения веб-разработки, облачных вычислений, распределенных систем и многого другого!
<br/>
## Начало работы
### 💻 Локальная разработка
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Это запустит Puter по адресу http://puter.localhost:4100 (или на следующем доступном порту).
Мы всегда рады помочь вам с любыми вопросами. Не стесняйтесь спрашивать!
<br/>
## Лицензия
Этот репозиторий, включая все его содержимое, подпроекты, модули и компоненты, лицензирован в соответствии с [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), если явно не указано иное. Сторонние библиотеки, включенные в этот репозиторий, могут подпадать под действие их собственных лицензий.
<h3 align="center"><img width="80" alt="Puter.com, Den personliga molndatorn: Alla dina filer, appar och spel på ett ställe tillgängliga var som helst när som helst." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Internet OS! Gratis, öppen källkod och självhostad.</h3>
Puter är ett avancerat, öppen källkod internetoperativsystem designat för att vara funktionsrikt, exceptionellt snabbt och mycket utbyggbart. Puter kan användas som:
- Ett integritetsfokuserat personligt moln för att hålla alla dina filer, appar och spel på ett säkert ställe, tillgängligt var som helst när som helst.
- En plattform för att bygga och publicera webbplatser, webbappar och spel.
- Ett alternativ till Dropbox, Google Drive, OneDrive, etc. med ett fräscht gränssnitt och kraftfulla funktioner.
- En fjärrskrivbordsmiljö för servrar och arbetsstationer.
- Ett vänligt, öppen källkod-projekt och gemenskap för att lära sig om webbutveckling, molndatorer, distribuerade system och mycket mer!
<br/>
## Komma igång
### 💻 Lokal Utveckling
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Detta kommer att starta Puter på http://puter.localhost:4100 (eller nästa lediga port).
Vi hjälper dig gärna med eventuella frågor du kan ha. Tveka inte att fråga!
<br/>
## Licens
Detta arkiv, inklusive allt dess innehåll, delprojekt, moduler och komponenter, är licensierat under [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) om inte annat uttryckligen anges. Tredjepartsbibliotek som ingår i detta arkiv kan vara föremål för sina egna licenser.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: உங்கள் கோப்புகள், ஆப்ஸ் மற்றும் கேம்கள் அனைத்தும் ஒரே இடத்தில் எங்கிருந்தும் எந்த நேரத்திலும் அணுகலாம்." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">இன்டர்நெட் OS! இலவசம், ஓப்பன் சோர்ஸ் மற்றும் Self-Hostable</h3>
புட்டர்(putter) என்பது ஒரு மேம்பட்ட, திறந்த மூல இலவசமாக இணைய இயக்க முறைமையாகும், இது அம்சம் நிறைந்ததாகவும், விதிவிலக்காக வேகமாகவும், அதிக விரிவாக்கக்கூடியதாகவும் வடிவமைக்கப்பட்டுள்ளது. புட்டரை இவ்வாறு பயன்படுத்தலாம்:
- உங்கள் கோப்புகள், பயன்பாடுகள் மற்றும் கேம்கள் அனைத்தையும் ஒரே பாதுகாப்பான இடத்தில் வைத்திருக்க, எந்த நேரத்திலும் எங்கிருந்தும் அணுகக்கூடிய தனியுரிமை-முதல் தனிப்பட்ட கிளவுட்.
- இணையதளங்கள், இணைய பயன்பாடுகள் மற்றும் கேம்களை உருவாக்கி வெளியிடுவதற்கான தளம் இதுவாகும்.
- புதிய இடைமுகம் மற்றும் சக்திவாய்ந்த அம்சங்களுடன் Dropbox, Google Drive, OneDrive போன்றவற்றுக்கு மாற்றீடாக உபயோகிக்க கூடியது.
- சர்வர்கள் மற்றும் பணிநிலையங்களுக்கான தொலைநிலை டெஸ்க்டாப்(desktop) சூழல்.
- வலை மேம்பாடு, கிளவுட் கம்ப்யூட்டிங், விநியோகிக்கப்பட்ட அமைப்புகள் மற்றும் பலவற்றைப் பற்றி அறிந்து ஒரு நட்பு ரீதியான, திறந்த மூல திட்டம் மற்றும் சமூக அறிவியலில் சார்ந்த ஒன்று.
<br/>
## தொடங்குதல்
### 💻 உள்ளூர் வளர்ச்சி
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
``` தொடக்கம்
```
இது புட்டரை <http://puter.localhost:4100> இல் தொடங்கும் (அல்லது அடுத்து கிடைக்கும் இடம்).
உங்களுக்கு ஏதேனும் கேள்விகள் இருந்தால் உங்களுக்கு உதவ நாங்கள் எப்போதும் மகிழ்ச்சியடைகிறோம். தயங்காமல் கேளுங்கள்!
<br/>
## உரிமம்
இந்தக் களஞ்சியமானது, அதன் அனைத்து உள்ளடக்கங்கள், துணைத் திட்டங்கள், தொகுதிகள் மற்றும் கூறுகள் உட்பட, வெளிப்படையாகக் கூறப்படாவிட்டால், [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) இன் கீழ் உரிமம் பெற்றுள்ளது. . இந்தக் களஞ்சியத்தில் சேர்க்கப்பட்டுள்ள மூன்றாம் தரப்பு நூலகங்கள் அவற்றின் சொந்த உரிமங்களுக்கு உட்பட்டதாக இருக்கும்.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: మీ అన్ని ఫైల్లు, యాప్లు మరియు గేమ్లను ఒకే స్థలంలో ఎక్కడి నుండైనా ఎప్పుడైనా యాక్సెస్ చేయవచ్చు." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center"> ఇంటర్నెట్ OS! ఉచిత, ఓపెన్ సోర్స్, and Self-Hostable.</h3>
పుటర్ అనేది అధునాతన, ఓపెన్ సోర్స్ ఇంటర్నెట్ ఆపరేటింగ్ సిస్టమ్, ఇది ఫీచర్-రిచ్, అనూహ్యంగా వేగవంతమైన మరియు అత్యంత విస్తరించదగినదిగా రూపొందించబడింది. పుటర్ను ఇలా ఉపయోగించవచ్చు:
- మీ అన్ని ఫైల్లు, యాప్లు మరియు గేమ్లను ఒకే సురక్షిత స్థలంలో ఉంచడానికి గోప్యత-మొదటి వ్యక్తిగత క్లౌడ్, ఎప్పుడైనా ఎక్కడి నుండైనా యాక్సెస్ చేయవచ్చు.
- వెబ్సైట్లు, వెబ్ యాప్లు మరియు గేమ్లను రూపొందించడానికి మరియు ప్రచురించడానికి ఒక వేదిక.
- తాజా ఇంటర్ఫేస్ మరియు శక్తివంతమైన ఫీచర్లతో Dropbox, Google Drive, OneDrive మొదలైన వాటికి ప్రత్యామ్నాయం.
- సర్వర్లు మరియు వర్క్స్టేషన్ల కోసం రిమోట్ డెస్క్టాప్ వాతావరణం.
- వెబ్ డెవలప్మెంట్, క్లౌడ్ కంప్యూటింగ్, డిస్ట్రిబ్యూట్ సిస్టమ్లు మరియు మరిన్నింటి గురించి తెలుసుకోవడానికి స్నేహపూర్వక, ఓపెన్ సోర్స్ ప్రాజెక్ట్ మరియు కమ్యూనిటీ!
<br/>
## ప్రారంభించడం
### లోకల్ డెవలప్మెంట్
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
ఇది http://puter.localhost:4100 (లేదా తదుపరి అందుబాటులో ఉన్న పోర్ట్) వద్ద పుటర్ని ప్రారంభిస్తుంది.
ఇది పని చేయకపోతే, దీని కోసం [మొదటి రన్ సమస్యలు](./doc/first-run-issues.md) చూడండి
మీకు ఏవైనా సందేహాలు ఉంటే మీకు సహాయం చేయడానికి మేము ఎల్లప్పుడూ సంతోషిస్తాము. అడగడానికి సంకోచించకండి!
<br/>
## లైసెన్సు
ఈ రిపోజిటరీ, దాని మొత్తం కంటెంట్లు, ఉప-ప్రాజెక్ట్లు, మాడ్యూల్స్ మరియు కాంపోనెంట్లతో సహా, [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) కింద లైసెన్స్ని కలిగి ఉంటుంది. . ఈ రిపోజిటరీలో చేర్చబడిన థర్డ్-పార్టీ లైబ్రరీలు వాటి స్వంత లైసెన్స్లకు లోబడి ఉండవచ్చు.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: All your files, apps, and games in one place accessible from anywhere at any time." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center"><img width="80" alt="Puter.com, Kişisel Bulut Bilgisayar: Tüm dosyalarınız, uygulamalarınız ve oyunlarınız her zaman her yerden erişilebilen tek bir yerde." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">İnternet İşletim Sistemi! Ücretsiz, Açık Kaynaklı ve Kendi Kendine Barındırılabilir</h3>
Puter, zengin özelliklere sahip, son derece hızlı ve son derece genişletilebilir olacak şekilde tasarlanmış gelişmiş, açık kaynaklı bir internet işletim sistemidir. Puter şu şekilde kullanılabilir:
- Tüm dosyalarınızı, uygulamalarınızı ve oyunlarınızı tek bir güvenli yerde tutmak için gizlilik öncelikli bir kişisel bulut, her yerden her zaman erişilebilir.
- Web siteleri, web uygulamaları ve oyunlar oluşturmak ve yayınlamak için bir platform.
- Yeni bir arayüz ve güçlü özelliklerle Dropbox, Google Drive, OneDrive vb. uygulamalara bir alternatif.
- Sunucular ve iş istasyonları için bir uzak masaüstü ortamı.
- Web geliştirme, bulut bilişim, dağıtık sistemler ve çok daha fazlası hakkında bilgi edinmek için dost canlısı, açık kaynaklı bir proje ve topluluk!
<br/>
## Başlarken
### 💻 Yerel Geliştirme
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Bu, Puter'ı http://puter.localhost:4100 adresinde (veya bir sonraki kullanılabilir portta) başlatacaktır.
Sorularınız varsa size her zaman yardımcı olmaktan mutluluk duyarız. Sormaktan çekinmeyin!
<br/>
## Lisans
Bu depo, tüm içeriği, alt projeleri, modülleri ve bileşenleri dahil olmak üzere, aksi açıkça belirtilmedikçe [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) altında lisanslanmıştır. Bu depoda yer alan üçüncü taraf kütüphaneler kendi lisanslarına tabi olabilir.
<h3 align="center"><img width="80" alt="Puter.com, The Personal Cloud Computer: Всі ваші файли, додатки та ігри в одному місці, доступні з будь-якого куточка світу в будь-який час." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Інтернет ОС! Безкоштовна, відкрита та self-hosted.</h3>
<p align="center">
<img alt="Розмір репозиторію на GitHub" src="https://img.shields.io/github/repo-size/HeyPuter/puter"> <img alt="Остання версія на GitHub" src="https://img.shields.io/github/v/release/HeyPuter/puter?label=latest%20version"> <img alt="Ліцензія GitHub" src="https://img.shields.io/github/license/HeyPuter/puter">
Puter — це просунута, інтернет-ОС, з відкритим кодом, створена для того, щоб бути багатофункціональною, надзвичайно швидкою та розширюваною. Puter може використовуватися як:
- Приватний хмарний сервіс для збереження всіх ваших файлів, додатків і ігор у безпечному місці, доступному в будь-який час з будь-якого місця.
- Платформа для створення та публікації вебсайтів, вебдодатків і ігор.
- Альтернатива Dropbox, Google Drive, OneDrive і тд, з свіженьким інтерфейсом та потужними функціями.
- Віддалене робоче середовище для серверів і робочих станцій.
- Дружній, відкритий проєкт та спільнота для вивчення веброзробки, хмарних обчислень, розподілених систем і багато іншого!
<br/>
## Початок роботи
### Локальна розробка
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Це запустить Puter на http://puter.localhost:4100 (або на наступному доступному порті).
Ми завжди готові допомогти Вам з будь-якими питаннями, що можуть виникнути. Не соромтеся ставити нам питання!
<br/>
## License
Цей репорзиторій, включаючи увесь його контент, дочірні проєкти, модулі, і компоненти, ліцензовано за [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), якщо явно не вказано інше. Сторонні бібліотеки, включені в цей репозиторій, можуть підпадати під дію інших ліцензій.
<h3 align="center"><img width="80" alt="Puter.com, ذاتی کلاؤڈ کمپیوٹر: آپ کی تمام فائلیں، ایپس، اور کھیل ایک جگہ پر، کہیں سے بھی اور کسی بھی وقت قابل رسائی۔" src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">انٹرنیٹ OS! مفت، اوپن سورس، اور خود میزبان.</h3>
ایک جدید، اوپن سورس انٹرنیٹ آپریٹنگ سسٹم ہے جو کہ خصوصیات سے بھرپور، بہت تیز، اور انتہائی توسیع پذیر ہے۔ Puter
: کو استعمال کیا جا سکتا ہے Puter
- ایک پرائیویسی فرسٹ ذاتی کلاؤڈ کے طور پر تاکہ آپ کی تمام فائلیں، ایپس، اور کھیل ایک محفوظ جگہ پر رکھی جا سکیں، کہیں سے بھی اور کسی بھی وقت قابل رسائی ہوں۔
- ویب سائٹس، ویب ایپس، اور کھیل بنانے اور شائع کرنے کے لئے ایک پلیٹ فارم کے طور پر۔
- وغیرہ کا متبادل، نئے انٹرفیس اور طاقتور خصوصیات کے ساتھ۔ Dropbox، Google Drive، OneDrive
- سرورز اور ورک اسٹیشنز کے لیے ایک ریموٹ ڈیسک ٹاپ ماحول کے طور پر۔
- ویب ڈویلپمنٹ، کلاؤڈ کمپیوٹنگ، تقسیم شدہ نظاموں، اور بہت کچھ سیکھنے کے لیے ایک دوستانہ، اوپن سورس پروجیکٹ اور کمیونٹی!
<br/>
## شروع کرنے کا طریقہ
### 💻 مقامی ترقی
```bash
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
یہ Puter کو http://puter.localhost:4100 (یا اگلے دستیاب پورٹ) پر لانچ کرے گا۔
ہم ہمیشہ آپ کی مدد کے لیے خوش ہیں۔ سوالات پوچھنے میں ہچکچاہٹ نہ کریں
!
<br/>
## لائسنس
اس ریپوزٹری، بشمول اس کے تمام مواد، ذیلی پروجیکٹس، ماڈیولز، اور کمپوننٹس، کو [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt) کے تحت لائسنس کیا گیا ہے جب تک کہ واضح طور پر کہیں اور نہ کہا گیا ہو۔ اس ریپوزٹری میں شامل تھرڈ پارٹی لائبریریاں اپنی لائسنس کے تابع ہو سکتی ہیں۔
<h3 align="center"><img width="80" alt="Puter.com, Máy Tính Đám Mây Cá Nhân: Tất cả các tệp, ứng dụng, và trò chơi của bạn ở một nơi, có thể truy cập từ bất cứ đâu vào bất kỳ lúc nào." src="https://assets.puter.site/puter-logo.png"></h3>
<h3 align="center">Hệ điều hành Internet! Miễn phí, Mã nguồn mở và Có thể tự lưu trữ.</h3>
<p align="center">
<img alt="Kích thước repo GitHub" src="https://img.shields.io/github/repo-size/HeyPuter/puter"> <img alt="Phiên bản phát hành GitHub" src="https://img.shields.io/github/v/release/HeyPuter/puter?label=Phi%C3%AAn%20b%E1%BA%A3n%20ph%C3%A1t%20h%C3%A0nh%20GitHub"> <img alt="Giấy phép GitHub" src="https://img.shields.io/github/license/HeyPuter/puter">
</p>
<p align="center">
<a href="https://puter.com/"><strong>« DEMO TRỰC TIẾP »</strong></a>
Puter là một hệ điều hành internet tiên tiến, mã nguồn mở được thiết kế để có nhiều tính năng, tốc độ vượt trội và khả năng mở rộng cao. Puter có thể được sử dụng như:
- Một đám mây cá nhân ưu tiên quyền riêng tư để lưu trữ tất cả các tệp, ứng dụng và trò chơi của bạn ở một nơi an toàn, có thể truy cập từ bất cứ đâu, bất cứ lúc nào.
- Một nền tảng để xây dựng và xuất bản các trang web, ứng dụng web và trò chơi.
- Một sự thay thế cho Dropbox, Google Drive, OneDrive, v.v. với giao diện mới mẻ và nhiều tính năng mạnh mẽ.
- Một môi trường máy tính từ xa cho các máy chủ và máy trạm.
- Một dự án thân thiện, mã nguồn mở và cộng đồng để học hỏi về phát triển web, điện toán đám mây, hệ thống phân tán và nhiều hơn nữa!
<br/>
## Bắt Đầu
## 💻 Phát Triển Cục Bộ
```bash
Copy code
git clone https://github.com/HeyPuter/puter
cd puter
npm install
npm start
```
Điều này sẽ khởi chạy Puter tại http://puter.localhost:4100 (hoặc cổng kế tiếp có sẵn).
Puter có sẵn dưới dạng dịch vụ lưu trữ tại [**puter.com**](https://puter.com).
<br/>
## Yêu Cầu Hệ Thống
- **Hệ Điều Hành:** Linux, macOS, Windows
- **RAM:** Tối thiểu 2GB (Khuyến nghị 4GB)
- **Dung Lượng Ổ Cứng:** Còn trống 1GB
- **Node.js:** Phiên bản 16+ (Khuyến nghị phiên bản 22+)
- **npm:** Phiên bản ổn định mới nhất
<br/>
## Hỗ Trợ
Kết nối với các nhà bảo trì và cộng đồng thông qua các kênh sau:
- Báo cáo lỗi hoặc yêu cầu tính năng? Vui lòng mở một vấn đề.
- Discord: discord.com/invite/PQcx7Teh8u
- X (Twitter): x.com/HeyPuter
- Reddit: reddit.com/r/puter/
- Mastodon: mastodon.social/@puter
- Vấn đề bảo mật? security@puter.com
- Email các nhà bảo trì tại hi@puter.com
Chúng tôi luôn sẵn sàng giúp đỡ bạn với bất kỳ câu hỏi nào bạn có. Đừng ngần ngại hỏi!
<br/>
## Giấy Phép
Kho lưu trữ này, bao gồm tất cả nội dung, dự án con, mô-đun và thành phần của nó, được cấp phép theo [AGPL-3.0](https://github.com/HeyPuter/puter/blob/main/LICENSE.txt), trừ khi được tuyên bố rõ ràng khác. Các thư viện của bên thứ ba được bao gồm trong kho lưu trữ này có thể phải tuân theo các giấy phép riêng của chúng.
<metaname="description"content="Puter is a privacy-first personal cloud to keep all your files, apps, and games in one private and secure place, accessible from anywhere at any time.">
<metaproperty="og:description"content="Puter is a privacy-first personal cloud to keep all your files, apps, and games in one private and secure place, accessible from anywhere at any time.">
<metaname="twitter:description"content="Puter is a privacy-first personal cloud to keep all your files, apps, and games in one private and secure place, accessible from anywhere at any time.">
The GUI is a single page application (SPA) and as best practice any route under root (`/*`) should preferably load the `index.html` file. However, there are situations where we want to load a custom page for a specific route: for example, the `/privacy` route may need to load a page that contains your privacy policy and has nothing to do with the GUI application. In these cases it is ok to load a custom page as long as the following essential GUI routes are loaded with the GUI (i.e. `index.html` file):
-`/app/*`
-`/action/*`
In other words, consider the routes above as "reserved" for Puter.
### Best Practices
- The `title` tags and meta tags (`<title></title>`, `<meta property="og:title"`, `<meta name="twitter:title"`, ...) should be dynamically set by the server. For example, if the URL is of an app (e.g. `https://puter.com/app/editor`) the `title` tags and meta tags should contain the app's title rather than the generic Puter title.
- The `description` meta tags (`<meta name="description"`, `<meta property="og:description"`, `<meta name="twitter:description"`, ...) should be dynamically set by the server. For example, if the URL is of an app (e.g. `https://puter.com/app/editor`) the `description` meta tags should contain the app's description rather than the generic Puter description.
- Make sure to escape any HTML code that is dynamically added to the HTML page. For example, if the app's description is `Puter is a <b>privacy-first</b> personal cloud to keep all your files, apps, and games in one private and secure place, accessible from anywhere at any time.` the `<b>` tag should be escaped to `<b>` so that the browser doesn't interpret it as an HTML tag.
- Make sure to replace all new line characters with space when dynamically adding text to the HTML page.
- Generally, for UX and SEO reasons make sure that the tags are filled with relevant information about the state the URL is representing. E.g. is the user on the desktop or an app?
Ensure the hosting device has a static IP address to prevent potential connectivity issues due to IP changes. This setup will enable seamless access to Puter and its services across your local network.
### Using Hosts Files
The hosts file is a straightforward way to map domain names to IP addresses on individual devices. It's simple to set up but requires manual changes on each device that needs access to the domains.
#### Windows
1. Open Notepad as an administrator.
2. Open the file located at `C:\Windows\System32\drivers\etc\hosts`.
3. Add lines for your domain and subdomain with the server's IP address, in the
following format:
```
192.168.1.10 puter.local
192.168.1.10 api.puter.local
```
#### For macOS and Linux:
1. Open a terminal.
2. Edit the hosts file with a text editor, e.g., `sudo nano /etc/hosts`.
3. Add lines for your domain and subdomain with the server's IP address, in the
following format:
```
192.168.1.10 puter.local
192.168.1.10 api.puter.local
```
4. Save and exit the editor.
### Using Router Configuration
Some routers allow you to add custom DNS rules, letting you configure domain names network-wide without touching each device.
1. Access your router’s admin interface (usually through a web browser).
2. Look for DNS or DHCP settings.
3. Add custom DNS mappings for `puter.local` and `api.puter.local` to the hosting device's IP address.
4. Save the changes and reboot the router if necessary.
This method's availability and steps may vary depending on your router's model and firmware.
### Using Local DNS
Setting up a local DNS server on your network allows for flexible and scalable domain name resolution. This method works across all devices automatically once they're configured to use the DNS server.
#### Options for DNS Software:
- **Pi-hole**: Acts as both an ad-blocker and a DNS server. Ideal for easy setup and maintenance.
- **BIND9**: Offers comprehensive DNS server capabilities for complex setups.
- **Dnsmasq**: Lightweight and suitable for smaller networks or those new to running a DNS server.
**contributors note:** feel free to add any software you're aware of
which might help with this to the list. Also, feel free to add instructions here for specific software; our goal is for Puter to be easy to setup with tools you're already familiar with.
#### General Steps:
1. Choose and install DNS server software on a device within your network.
2. Configure the DNS server to resolve `puter.local` and `api.puter.local` to the IP address of your Puter hosting device.
3. Update your router’s DHCP settings to distribute the DNS server's IP address to all devices on the network.
By setting up a local DNS server, you gain the most flexibility and control over your network's domain name resolution, ensuring that all devices can access Puter and its API without manual configuration.
## Production Configuration
Please note the self-hosting feature is still in alpha and a public production
deployment is not recommended at this time. However, if you wish to host
publically you can do so following the same steps you normally would to configure
a domain name and ensuring the `api` subdomain points to the server as well.
`docker-compose.yml` brings up Puter **plus every external service it needs** — MariaDB, Valkey, DynamoDB-local, RustFS S3, nginx — wired together. Closest thing to a production deployment you can self-manage on a single host.
## One-line installer (recommended)
```bash
curl -fsSL https://raw.githubusercontent.com/HeyPuter/puter/main/install.sh | sh
```
Generates secrets, writes `.env` + `puter/config/config.json`, downloads `docker-compose.yml` from the OSS repo, and runs `docker compose up -d`. Re-running is safe — it won't overwrite existing config (set `PUTER_FORCE=1` to rotate). Use the manual steps below if you want to inspect or tweak each step yourself.
## Requirements
- **Docker** with the `compose` plugin.
- A **domain** with DNS access — you need a wildcard record (`*.your-domain.com` → server IP). Puter routes by subdomain (`api.<domain>`, `site.<domain>`, `app.<domain>`).
- Optional: **TLS certs** (or `certbot` to grab them — see Step 4).
| `puter-ollama-init` | `ollama/ollama` | One-shot — pulls the default model (`tinyllama`) on first boot |
State lives under `./puter/data/<service>/`.
---
## Step 1 — Create `.env` and `puter/config/config.json`
> ⚠️ **Run this whole block in one shell session.** It generates secrets once and writes them into both `.env` (read by docker compose) and `config.json` (read by Puter). The two files **must** agree on the MariaDB password and the S3 secret — if they drift, MariaDB initialises with one password and Puter tries to log in with another, and you get `ER_ACCESS_DENIED_ERROR`.
```bash
MARIADB_ROOT_PASSWORD=$(openssl rand -hex 32)
MARIADB_PASSWORD=$(openssl rand -hex 32)
S3_SECRET_KEY=$(openssl rand -hex 32)
JWT_SECRET=$(openssl rand -hex 64)
URL_SIGNATURE_SECRET=$(openssl rand -hex 64)
cat > .env <<EOF
HTTP_PORT=80
# HTTPS_PORT=443 # uncomment after enabling TLS in Step 3
Replace `puter.localhost`, `site.puter.localhost`, `host.puter.localhost`, `dev.puter.localhost` and `app.puter.localhost` with your actual domain (or leave it for a localhost-only trial).
Why these knobs:
-`env: "prod"` — the bundled `config.default.json` ships with `env: "dev"` (matches the source-tree `npm run start=gui` workflow, which expects webpack-dev-server emitting a CSS manifest). Self-host runs against pre-built static bundles, so `env: "prod"` makes the homepage emit the `/dist/bundle.min.css``<link>` tag instead of waiting on a manifest that doesn't exist.
-`database.migrationPaths` — Puter applies the bundled MySQL schema on boot. `mysql_mig_1.sql` (tables) and `mysql_mig_2.sql` (default apps: editor, viewer, pdf, camera, player, recorder, git, dev-center, puter-linux). Idempotent — safe to re-run.
-`dynamo.bootstrapTables: true` — Puter creates its KV table on boot. **Only set against a local emulator**, never real AWS.
-`dynamo.aws` keys are dummies; DynamoDB-local doesn't validate them but the AWS SDK requires _something_. **Note:** DynamoDB uses `access_key` / `secret_key` (snake_case); S3 below uses `accessKeyId` / `secretAccessKey` (camelCase). Not interchangeable.
-`providers.ollama.enabled: false` — Puter auto-probes a local Ollama at `127.0.0.1:11434` by default; without one running you'd see `ECONNREFUSED` on every boot. To run a bundled Ollama, see [Optional: local LLM (Ollama)](#optional-local-llm-ollama) below.
-`s3.s3Config.forcePathStyle: true` — RustFS / MinIO / fauxqs need path-style URLs (`<endpoint>/<bucket>`). Real AWS S3 wants virtual-hosted (`<bucket>.<endpoint>`) — drop this flag (or set `false`) when you swap to real S3.
-`s3.s3Config.publicEndpoint` — `endpoint` (`http://s3:9000`) only resolves inside the docker network; presigned upload/download URLs handed to the browser need a host-reachable URL. nginx routes the `s3.<domain>` subdomain to RustFS internally and preserves the Host header end-to-end (required for S3 signature validation), so the browser hits the same port/protocol as the rest of the app — no separate published port, no mixed-content surprises when you turn on TLS. Switch to `https://s3.<your-domain>` once you enable TLS in Step 3. Real AWS S3 doesn't need this — its endpoint is already public; drop the field entirely.
-`trust_proxy: 1` — nginx terminates TLS and forwards `X-Forwarded-For`. Without this, `req.ip` is the docker-network address of the nginx container instead of the real client IP, which breaks rate limiting and IP-based audit logs. `1` = one trusted hop (nginx). Bump to `2` if you put Cloudflare in front of nginx; never set `true` (it trusts every hop and makes XFF forgeable).
> If you ever change `MARIADB_PASSWORD` after first boot, `.env` alone won't update MariaDB — its credentials are baked into `./puter/data/mariadb/` on first init. Either rotate the password inside MariaDB by hand or `docker compose down && rm -rf ./puter/data/mariadb` to start fresh.
## Step 2 — Point DNS at the server \[Optional\]
In your DNS provider, add records for the main domain plus the subdomains Puter and nginx route on (`api.*`, `site.*`, `app.*`, `s3.*`):
```
A puter.localhost → <your server's public IP>
A *.puter.localhost → <your server's public IP>
A site.puter.localhost → <your server's public IP>
A *.site.puter.localhost → <your server's public IP>
A host.puter.localhost → <your server's public IP>
A *.host.puter.localhost → <your server's public IP>
A app.puter.localhost → <your server's public IP>
A *.app.puter.localhost → <your server's public IP>
A dev.puter.localhost → <your server's public IP>
A *.dev.puter.localhost → <your server's public IP>
```
The wildcards are required — Puter routes via subdomains (`api.*`, `app.*`, etc.) and nginx routes browser S3 traffic via `s3.*` to RustFS.
## Step 3 — TLS (recommended for public installs) \[Optional\]
Skip this for a quick local demo. Don't skip it for users typing passwords.
**Get a wildcard cert.** Easiest path with Let's Encrypt + DNS-01 (works for wildcards):
```bash
sudo certbot certonly --manual --preferred-challenges dns \
The cert needs to cover `*.puter.localhost` so that `s3.puter.localhost` (browser S3 endpoint), plus Puter's own `api.*` / `app.*` subdomains, all validate.
Drop the resulting `fullchain.pem` and `privkey.pem` into `./puter/tls/`.
**Wire nginx to use them:**
1. Open [nginx/nginx.conf](../nginx/nginx.conf), uncomment **both**`# server { listen 443 ssl … }` blocks (one for `s3.*`, one for the catch-all).
2. (Optional) Replace the body of the port-80 blocks with `return 301 https://$host$request_uri;` to force HTTPS everywhere.
3. In [docker-compose.yml](../docker-compose.yml), uncomment the `443:443` port mapping under the `nginx` service.
First boot takes ~30s while MariaDB initialises and Puter applies the schema + default apps. Watch:
```bash
docker compose logs -f puter
```
Healthy startup:
```
[config] override from /etc/puter/config.json
[mysql] running migrations from /opt/puter/dist/src/backend/clients/database/migrations/mysql: 2 file(s)
[mysql] applied mysql_mig_1.sql (...)
[mysql] applied mysql_mig_2.sql (9 statements)
```
Then open **<https://puter.local>** (or `http://` if you skipped TLS). Login is `admin` — the temp password is printed once in the puter container logs on first boot:
```bash
docker compose logs puter | grep tmp_password
```
Change it in Settings after first login.
## Additional configuration
All optional. Drop any of the blocks below into `puter/config/config.json` and `docker compose restart puter`. See [config.template.jsonc](../config.template.jsonc) for the full list. Per-key documentation lives in [src/backend/types.ts](../src/backend/types.ts).
### Email (SMTP)
Used for password resets, email confirmation, and notifications. Without it those flows silently fail.
To require email confirmation before login, also set `"strict_email_verification_required": true`.
### Sign in with Google (or another OIDC provider)
```json
"oidc": {
"providers": {
"google": {
"client_id": "...apps.googleusercontent.com",
"client_secret": "...",
"scopes": "openid email profile"
}
}
}
```
Add `https://puter.<your-domain>/auth/oidc/callback/login` to the OAuth client's authorized redirect URIs in the Google Cloud Console. For non-Google providers, replace `google` with a custom id and supply `authorization_endpoint` / `token_endpoint` / `userinfo_endpoint` explicitly.
### AI providers
Any provider with a key set is auto-enabled. Same shape as `ollama` above:
```json
"providers": {
"claude": { "apiKey": "sk-ant-..." },
"openai-completion": { "apiKey": "sk-..." },
"gemini": { "apiKey": "..." },
"openai-image-generation": { "apiKey": "sk-..." }
}
```
Full provider list (chat, image, video, TTS, OCR) is in the template.
### Per-user storage quota
Default is 100 MB per user.
```json
"storage_capacity": 5368709120, // 5 GB
"is_storage_limited": true
```
Set `is_storage_limited: false` for unlimited (bounded by host disk).
### Captcha on signup / login
Built-in proof-of-work captcha — no external service needed.
The `ollama` and `ollama-init` services live behind a compose profile so they don't run unless you ask for them. By default, `puter/config/config.json` has `"ollama": { "enabled": false }` — Puter skips the auto-probe entirely. To run a local model:
`ollama-init` exits 0 once the model is pulled. Subsequent boots find the model already on disk and the pull is a fast no-op.
Without `--profile ai`, the `ollama` containers stay down and Puter (with `enabled: false`) doesn't try to reach them — the rest of the stack runs identically.
For GPU acceleration (NVIDIA), uncomment the `deploy:` block under the `ollama` service in [docker-compose.yml](../docker-compose.yml). Requires `nvidia-container-toolkit` on the host.
## Building from source instead of pulling
If you want to test local Dockerfile changes against the full stack, uncomment the `build:` block in [docker-compose.yml](../docker-compose.yml) under the `puter` service, change `pull_policy: always` → `pull_policy: never`, then:
```bash
docker compose up -d --build
```
---
## Managing running backend
```bash
# update
docker compose pull
docker compose up -d
# logs
docker compose logs -f puter
# stop, keep data
docker compose down
# stop, NUKE all state (irreversible)
docker compose down
rm -rf puter/data
```
Migrations re-apply idempotently across pulls. Volumes are preserved.
## Troubleshooting
**Site loads but I get "Bad Gateway" / nginx errors.**
The puter container failed to come up. `docker compose logs puter` will tell you which dependency rejected it (most often DB password mismatch between `.env` and `config.json`).
**Login screen says "admin password not set".**
First-boot temp password is logged once. Find it: `docker compose logs puter | grep "tmp_password"`. After login, change it in Settings.
**Healthcheck reports unhealthy but the site works.**
The healthcheck hits `puter.localhost:4100/test` from inside the container. If you changed `domain` or `port`, the check still uses defaults. The site itself is fine.
**Nothing resolves at `puter.example.com` after DNS changes.**
DNS propagates slowly. `dig puter.example.com` and `dig api.puter.example.com` should both return your server IP. If not, give it 5–60 minutes.
**`docker compose up` hangs at "waiting for service to be healthy".**
`docker compose ps` shows which container is unhealthy. MariaDB takes ~20–30s on a cold boot; everything else under 5s. If something stays unhealthy, `logs <service>` will tell you why.
**`Error: DynamoDB aws config requires both access_key and secret_key`.**
You wrote `accessKeyId` / `secretAccessKey` under `dynamo.aws`. That config block uses snake_case (`access_key` / `secret_key`). Only the `s3.s3Config` block uses camelCase.
Loaded 100 of 1981 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.