TC
synced commits to v3.0.1 at TC/arozos-mirror from mirror
463c4429e3 Add CalDAV server for iOS Calendar bidirectional sync (#256)
Add CalDAV server for iOS Calendar bidirectional sync (#256)
f565c3e665 Fixed go mod issue
baa3992364 V2.026 (#254)
* Add fileOps API, folder tree UI & context menus
* Updated login icons and wall papers
* Update main.flags.go
* Fixed Web Builder display bug
* Added wip Notes App
add ao_module theme get function
* Add Calculator web module
* Add FFmpeg Factory UI and conversion backend
Introduce a complete FFmpeg-based conversion feature: add frontend UI (index.html) and AGI endpoints (convert, progress, tasks, dismiss, ensuredirs) under src/web/FFmpeg Factory for task management and progress. Extend the Go AGI module to register ffmpeg (with exec.LookPath check) and inject new VM helpers for audio, image, video and generic conversions that buffer remote files, run ffmpeg, and write results back. Implement ffmpegutil helpers with progress monitoring, ffprobe duration detection, conversion functions (audio/image/video/conv_with_progress) and JSON progress writes. Update .gitignore to add temporary paths and ignore editor backup files.
* Add Note app icons
* Add infinite scroll to Photo app
- Updated Photo app homepage
- Add infinite scroll to save bandwidth on mobile
* Add Ffmpeg factory icons
* Add modern music app for ArozOS
* Update photo icon
* Notes icon optimization
* Add calculator icons
* Add library switch function and fix folder loader bug
* Skip tmp:/ and trash:/ roots; remove sidebar logo
Avoid creating Music folders on temporary/trash volumes by skipping roots equal to "tmp:/" or "trash:/"
* Add Dashboard UI, sysinfo lib, and module list API
Adds a full Dashboard web UI and backend AGI endpoints plus a new sysinfo AGI library and module-list integration. Key changes:
- New Dashboard frontend (src/web/Dashboard/index.html) and image assets, plus AGI backend handlers to get/save settings, checklist, modules, storage and sysinfo.
- New sysinfo AGI library (src/mod/agi/agi.sysinfo.go) exposing CPU, RAM, network and disk info to AGI, including a network sampling helper to compute byte rates.
- Integrates module list provider into AGI appdata (agi.appdata.go, agi.go) and adds ModuleHandler.GetModuleListJSONForUser to return JSON of accessible modules.
- Registers the sysinfo library during module loading (moduleManager.go) and switches module default launcher handler to a switch statement for clarity (module.go).
* Fixed typo in timer init script
* Fixed wildcard bug in agi aglob
Also updated Musicif to list correctly on Artists view
* Add wip SystemAO
* feat(locale): add 100% translation coverage for zh-HK, zh-CN, en-US, ja-JP, ko-KR
- Add missing language entries across all 39 locale files in src/web/SystemAO/locale/
- Fix ko_kr (underscore) key naming to ko-kr (hyphen) in multiple files
- Fix en-US (uppercase) key naming to en-us (lowercase) in system_settings files
- Fix overview.json and power.json zh-HK/zh-CN corrupted/empty sections
- Add complete translations for: desktop, file_explorer, file_versions,
personal_homepage, personalization, sharelist, switchAccount, system_settings,
trashbin, and all system_settings/ and users/ subdirectory files
- All 6 target languages now at 100% translation rate using zh-TW as template
https://claude.ai/code/session_01HG8Pk2Yzj6gzmerGExjExV
* Updating OAuth2 login UI, oauth2: replace hardcoded providers with OIDC discovery (#216)
* feat(auth): modernise OAuth/LDAP UI, add custom OAuth provider, and add handler tests
UI:
- Rewrite oauth.html with modern card-based design matching account.html / system_setting
style: CSS variables, light/dark theme, native toggle switches, provider-aware
field visibility (GitLab server URL, Custom endpoint rows), callback URL preview
- Rewrite ldap.html with the same design language: hero header, collapsible sections,
clean form elements, inline connection-test results table with synchronise button
- Both pages integrate with the parent msgbox() toast API and fall back gracefully
Backend (OAuth2):
- Add Config fields: AuthURL, TokenURL, UserInfoURL, UserField, CustomScope
- Add GetProviders() returning [Google, Microsoft, Github, Gitlab, Custom]
- Add OauthHandler.ListProviders HTTP handler → GET /system/auth/oauth/config/providers
- Update ReadConfig / WriteConfig to handle all new fields with proper validation
(custom provider requires auth/token/userinfo URLs when OAuth is enabled)
- Add custom.go: customUserInfo() fetches from any OIDC-compatible /userinfo endpoint
- Update serviceSelector.go to route all three selector funcs through 'Custom'
branch and expose GetProviders(); switch getScope default to configurable value
Backend (LDAP):
- Fix ReadConfig to default enabled=false instead of erroring on a fresh DB
Tests:
- oauth2_handler_test.go: 17 tests covering GetProviders, ListProviders, ReadConfig,
WriteConfig (built-in & Custom providers, round-trips, GitLab server-URL handling,
scope/endpoint selectors)
- ldap_handler_test.go: 8 tests covering ReadConfig and WriteConfig (defaults,
validation, round-trip, overwrite)
https://claude.ai/code/session_017STPAsz1DkD6YmdS7iKHpW
* oauth2: replace hardcoded providers with OIDC discovery
- Remove all hardcoded provider files (Google, GitHub, GitLab, Microsoft,
custom, serviceSelector) — 6 files deleted
- Add discovery.go: FetchOIDCDiscovery pulls endpoints from any provider's
/.well-known/openid-configuration; getUserInfoFromEndpoint fetches the
username claim using a configurable field (default: email)
- Rewrite oauth2.go: OauthHandler is now provider-agnostic; config stores
raw endpoints populated either via OIDC discovery or typed manually;
exchangeCodeForUsername extracted for independent testability
- Add HandleDiscover endpoint (/system/auth/oauth/config/discover) that
returns discovered auth/token/userinfo endpoints and suggested
scopes/claims to the frontend
- Rewrite oauth.html: Issuer URL + Discover button auto-populates fields;
manual endpoint inputs provided as fallback; dark/light theme support
- Add 27 discovery tests (oauth2_discovery_test.go): URL building, full
discovery round-trip, HTTP error cases, JSON validation, network failure,
getUserInfoFromEndpoint with real mock servers (Bearer header, field
extraction, empty/non-string values)
- Add 32 handler tests (oauth2_handler_test.go): ReadConfig defaults,
WriteConfig validation, HandleDiscover with mock OIDC provider,
CheckOAuth, HandleLogin/Authorize guards, exchangeCodeForUsername
end-to-end with mock token+userinfo servers, buildOAuthConfig behaviour
- All 59 tests pass; all mod/auth/... packages green
https://claude.ai/code/session_017STPAsz1DkD6YmdS7iKHpW
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Enhance NIC info, group delete handling, locales
Expand network NIC reporting (src/mod/network/network.go): add Name/Index, IPv4 mask, IPv6 address list, operstate/speed/duplex/type detection using /sys/class/net when available; improve address/multicast parsing and error handling. Add permission management endpoints (src/permission.go): handlers to delete groups with user-handling options (reassign/remove-only/delete-users) and to list users in a group; register new routes. Small cleanup to group creation flow (src/mod/permission/request.go) removing obsolete comments. Quota change (src/quota.go): skip network drives when computing per-user file distribution. UI and localization updates: remove disk/space finder.html and add/update multiple SystemAO locale and user management web files (newgroup/newuser locales, editgroup/edituser strings, various user HTML/CSS), enabling group-deletion UI text and related frontend changes.
* Add per-OS NIC details; update AGI docs & fixes
Introduce platform-specific NIC info implementations (network_darwin.go, network_linux.go, network_windows.go, network_other.go) and refactor network.go to consume nicExtraAll(), improving operstate/speed/duplex accuracy across OSes. Update SMART handling to prefer system smartctl when available, only chmod the bundled binary, and log fallback behavior. Ensure share responses set Content-Type (UTF-8) in share handler. Prevent accidental self-deletion when removing users during group deletion by detecting the caller and removing the group from their account instead of deleting it. Large rewrite of the AGI README to reflect AGI v3 runtime, list available libs/APIs and examples; plus multiple web UI/locale/template updates and small related fixes.
* Add comprehensive tests to all packages and fix failing tests (#217)
* Add drag drop support to FFmpeg factory
* Update domain to new one
* Revised share interface design
* docs: add scheduler library to AGI README and update example files (#218)
mod/agi/README.md:
- Add EXECUTION_ID to Global Variables section
- Add new '## Scheduler Library' section documenting hasPermission,
registered, register, unregister with parameter tables and examples
- Describe the required script-location convention (./web/<App>/cron.agi)
- Add 'Background Scheduler' example under Examples showing backend.agi,
cron.agi, and the frontend snippet working together end-to-end
web/SystemAO/arsm/example/cron.agi:
- Fix incorrect appdata.set/get calls (appdata is read-only; persistent
KV storage uses newDBTableIfNotExists + writeDBItem/readDBItem)
- Add EXECUTION_ID to standard-globals comment block
- Table key is now 'AppName/USERNAME' for per-user isolation
- Remove appdata requirelib (not needed for KV storage)
web/SystemAO/arsm/example/backend.agi (new):
- Shows the server-side AGI approach: requirelib("scheduler") +
hasPermission / registered / register / unregister
- Handles status / register / unregister actions
- Documents the REST API equivalents in the header comment
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
feat: webapp scheduler registration with permission control
- Add CanCreateCronJob permission to PermissionGroup (stored in DB under
permission/canCreateCronJob/<group>); admin groups always have it enabled
- Add User.CanCreateCronJob() that checks any of the user's groups
- Add SchedulerGroup.GetCronJobPermission() / SetCronJobPermission() helpers
- Extend Job struct with AppName field so tasks track which webapp registered them
- HandleAddJob now enforces the cron permission gate before accepting new jobs
- New scheduler endpoints:
GET /system/arsm/aecron/permission – check current user's permission
POST /system/arsm/aecron/app/register – webapp registers a task on behalf of user
POST /system/arsm/aecron/app/unregister – webapp removes its task
GET /system/arsm/aecron/app/check – check if app task is already registered
POST /system/arsm/aecron/groupperm/set – admin: toggle cron permission for a group
GET /system/arsm/aecron/groupperm/list – admin: list all group permissions
- Add RegisterJobFromAGI / UnregisterJobFromAGI / RemoveJobsByApp / AppJobExists
to the Scheduler for safe cross-package access
- New AGI library 'scheduler' (requirelib("scheduler")) exposes:
scheduler.hasPermission(), scheduler.registered(), scheduler.register(),
scheduler.unregister() — registered via callback pattern to avoid circular imports
- RegisterSchedulerLib() called after Scheduler starts, injects callbacks into AGI gateway
- Module uninstall hook (ModuleHandler.OnModuleUninstall) auto-cleans cron jobs
for the uninstalled app name on removal
- Redesign aecron.html (system settings page): permission status banner,
clean table with app-badge column, admin toggle section for group permissions
- New scheduler_permission.html popup: shown by ao_module_requestSchedulerPermission(),
displays app icon / task details / interval, Allow / Don't Allow buttons,
enforces permission check before registering
- Add ao_module_requestSchedulerPermission(options, callback) to ao_module.js
- Update scheduler.html: permission check before new-task form, app badge column
in all task list views (user, all, remove)
- Add example/cron.agi template and example/scheduler_usage.html developer guide
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
scheduler: use app-folder scripts, fix nil fsh, rename scriptPath→scriptName
- agi/agi.go: handle nil fsh in ExecuteAGIScriptAsUser — app-root scripts
are read via os.ReadFile instead of the user's virtual filesystem abstraction
- agi/agi.scheduler.go: redesign scheduler.register() AGI signature
New: register(taskName, appName, intervalSecs, description, scriptName)
scriptName defaults to 'cron.agi' and is a plain filename inside the
app folder (./web/<appName>/<scriptName>), not a user virtual path.
Updated docs, comments, and JS wrapper to match.
- scheduler/scheduler.go: introduce WebRootFshID / WebRootBase constants,
add AppName to Job struct, add executeJob() supporting both app-root
and user-vpath scripts, add RegisterJobFromAGI(), AppJobExists(),
RemoveJobsByApp(), UnregisterJobFromAGI(), containsVpathSeparator()
- scheduler/handlers.go: rewrite HandleAppRegisterJob to accept 'scriptname'
(plain filename) rather than 'path' (virtual path); verify the file
exists under ./web/<appname>/<scriptname>; block path traversal via
'..' or '/' in the filename; store FshID = WebRootFshID
- ao_module.js: rename scriptPath option to scriptName in
ao_module_requestSchedulerPermission(); make scriptName optional
(defaults to 'cron.agi'); update validation accordingly
- scheduler_permission.html: update POST param from 'path' to 'scriptname';
display app-relative path (e.g. MyApp/cron.agi) instead of virtual path;
relabel row as 'App Script'
- example/scheduler_usage.html: update to new scriptName convention and
correct APP_NAME to match module folder name
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
feat: add CronDemo webapp — end-to-end scheduler registration demo
Adds web/CronDemo/ as a fully runnable demo app that shows how a webapp
registers and manages a background cron job via the new scheduler API.
Files:
init.agi — registers the module (Group: Development, 480×540 window)
cron.agi — background script: writes lastRun timestamp + increments
runCount in appdata storage each time the scheduler fires
backend.agi — AGI endpoint that returns {lastRun, runCount} for the UI
index.html — app UI: shows Active/Not-scheduled badge, last-run time,
run count; calls ao_module_requestSchedulerPermission()
to register a 60-second demo task and unregister via REST
img/module_icon.png — scheduler icon (128×128, reused from SystemAO)
img/desktop_icon.png — same icon for desktop shortcut
The app self-registers on startup via init.agi (same pattern as all other
apps in web/). The module Name 'CronDemo' matches the folder name and the
appname used in scheduler registration, so the system automatically
removes its cron jobs if the app is uninstalled.
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
fix: align baseTime to minute boundary; redesign scheduler.html
scheduler/scheduler.go:
- Add alignBaseTime(t int64) helper that floors t to the nearest whole
minute: (t/60)*60. The scheduler ticker fires at unix timestamps
divisible by 60, so (ticker - baseTime) % interval only equals 0 when
baseTime is also minute-aligned. Without this, any job with
interval < 86400 registered at a non-minute-boundary second would
never fire.
- Apply alignBaseTime in RegisterJobFromAGI.
scheduler/handlers.go:
- Apply alignBaseTime in HandleAddJob and HandleAppRegisterJob so all
three job-creation paths produce a consistent, aligned base time.
Fixes CronDemo 60-second demo task never executing.
scheduler.html — full redesign:
- Remove Semantic UI dependency entirely.
- New layout: sidebar nav (📋 My Tasks / 🌐 All Tasks / + New Task /
🗑 Remove) + scrollable content area, matching system_setting/main.css
palette exactly (--bg, --sidebar-bg, --card-bg, --card-border, etc.).
- Dark/light theme via CSS custom properties toggled by
ao_module_getSystemThemeColor.
- Task lists rendered as CSS grid rows (no <table>); app badge shown in
each row; real-time filter input in sidebar.
- New Task form uses native inputs styled to match the settings design;
permission check shows a warning bar instead of hiding the whole panel.
- Remove view shows a danger header and inline Remove buttons per row.
- moment.js retained for base-time calculation in the new task form.
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
feat: inject EXECUTION_ID into AGI VM; fix appdata misuse in CronDemo
agi/agi.system.go:
- injectStandardLibs now generates a UUIDv4 (EXECUTION_ID), sets it on
the VM, and returns it to the caller. Every AGI script can read it as
a constant to correlate log lines, avoid duplicate side-effects, etc.
- Return type changed from void to string (the execID).
agi/agi.go:
- ExecuteAGIScriptAsUser signature changed from (string, error) to
(execID string, output string, err error) so callers can surface the
same ID that was injected into the VM.
agi/externalReqHandler.go, www/www.go:
- Updated to _, result, err to ignore execID (not needed in HTTP paths).
scheduler/scheduler.go:
- Both executeJob goroutines now capture execID from ExecuteAGIScriptAsUser
and include it in every cronlog/cronlogError line as [uuid]:
[3f2a…] CronDemo_Schedule executed: ok
[3f2a…] CronDemo_Schedule execution error: …
The logged UUID matches EXECUTION_ID inside the running script, making
it trivial to correlate a scheduler log entry with a script's own logs.
CronDemo/cron.agi:
- Fix TypeError: appdata is a read-only static-file library; it has no
set/get. Replace with the correct system-DB API:
newDBTableIfNotExists(table)
writeDBItem(table, key, value)
readDBItem(table, key)
- Use per-user table key 'CronDemo/<USERNAME>' for user isolation.
- Log the EXECUTION_ID so cron.agi output can be matched to the
scheduler log line for the same run.
CronDemo/backend.agi:
- Updated to read from the same per-user DB table.
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
fix: named callback for file selector; remove top blue bar from permission popup
scheduler.html:
- ao_module_openFileSelector requires callback.name to be a non-empty
string (passed to the parent float window as the callback identifier).
Anonymous functions have name="", causing "Selection Failed. Is
parent window alive?". Extract to named function scriptSelected().
scheduler_permission.html:
- Remove #sp-topbar (the blue accent bar at the top of the popup).
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
ui: replace all emoji with inline SVG icons (ArozOS style)
All emoji in the scheduler UI replaced with inline SVG icons matching
the stroke-based currentColor pattern used throughout the ArozOS web UI
(see system_setting/main.js, users/group.html, users/account.html):
scheduler.html:
Nav items: list-bullet, grid-2x2, plus, trash icons
Warning banners: triangle-exclamation icon (3 places)
aecron.html:
Status icon (hourglass → clock outline; check-circle; lock)
Open Scheduler button (gear icon)
Permission icons set via .innerHTML instead of .textContent
scheduler_permission.html:
No-permission state: lock icon (40px)
App icon placeholder: calendar icon (30px)
Row icons: clock, document, stopwatch, info-circle
Updated sp-row-icon CSS from font-size to width/height flex layout
CronDemo/index.html:
Warning banner: triangle-exclamation icon
'Enable Schedule' button: plus icon
'Disable' button: x icon
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
Add tests for scheduler, permission, and AGI scheduler lib; fix nil-safety bugs
- scheduler: fix UnregisterJobFromAGI to return 'permission denied' (not
nil-deref) when UserHandler is nil and creator doesn't match job owner
- agi: fix RaiseError to guard against nil error argument (prevented
otto VM from surfacing a clean false-return on empty appName)
- scheduler_test.go: full coverage for alignBaseTime, containsVpathSeparator,
JobExists, AppJobExists, GetJobsByApp, RemoveJobsByApp, save/load
round-trip, RegisterJobFromAGI, UnregisterJobFromAGI
- permission_cron_test.go: coverage for GetCronJobPermission,
SetCronJobPermission, SetGroupCronJobPermission, GetGroupCronJobPermissionList,
and DB round-trip persistence
- agi_scheduler_test.go: coverage for RegisterSchedulerLib, nil-callback
guards, hasPermission, registered, register, unregister, and JS object
method exposure
https://claude.ai/code/session_01RpdCprYxAKs1bndLaHxkYa
Co-authored-by: Claude <noreply@anthropic.com>
* Add OTP Authenticator webapp (#220)
A full-featured 2FA/TOTP authenticator module for ArozOS.
Features:
- Live TOTP code generation using Web Crypto API (RFC 6238)
- Animated countdown rings per account (SVG, colour-coded)
- QR code scanning via camera (jsQR + stream capture at 5fps)
- QR code decoding from uploaded images (drag-and-drop + file picker)
- Manual secret entry with Base32 validation
- ArozOS database (OTPAuth table) as secure per-user storage
- Rename accounts inline without re-entering secrets
- One-tap copy with visual confirmation
- Danger-colour warning on timer ≤ 7 s remaining
- System settings design language: CSS variables, light/dark theme sync
- Mobile-responsive with slide-in sidebar and hamburger toggle
- Supports SHA-1/SHA-256/SHA-512, 6/8-digit codes, 30 s/60 s periods
- Keyboard shortcuts: Ctrl+N to add, Esc to dismiss modals
Structure:
src/web/OTPAuth/
├── init.agi module registration
├── index.html full SPA (CSS + JS embedded)
├── img/small_icon.svg shield-check icon
├── script/jsqr.min.js bundled jsQR 1.4.0 decoder
└── backend/
├── add.js write entry to OTPAuth DB table
├── list.js list entries for current user
├── delete.js delete entry (ownership verified)
└── update.js rename account/issuer label
https://claude.ai/code/session_01TCYAPPZKHA7xDxPHq4WDes
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add S3-compatible filesystem abstraction (s3fs) (#219)
* feat: add S3-compatible filesystem abstraction (s3fs)
Adds a new filesystem type 's3' that can mount any S3-compatible object
storage (AWS S3, MinIO, Wasabi, Backblaze B2, Cloudflare R2, etc.) as a
virtual drive in arozos, following the same patterns as smbfs and ftpfs.
Key design decisions
- RequireBuffer = true: S3 has no file-handle semantics; all I/O goes
through WriteStream / ReadStream, exactly like ftpfs and webdavfs.
- Large-file / low-memory safety: ReadStream returns an io.ReadCloser
backed by the live S3 HTTP response body — no data is buffered in RAM
until the caller calls Read(). WriteStream passes the io.Reader straight
to minio PutObject with size=-1, triggering the SDK's automatic
multipart upload which never holds the full file in memory.
- Virtual directories: S3 has no native directories; empty objects whose
keys end with '/' act as markers. ReadDir uses non-recursive listing
with the '/' delimiter so common-prefix 'folders' appear as directory
entries naturally.
- Rename is implemented as copy-then-delete (S3 has no native rename);
directories are renamed by enumerating and moving every object under
the prefix.
- Heartbeat calls BucketExists on a 5-second timeout.
New files
src/mod/filesystem/abstractions/s3fs/s3fs.go — abstraction impl
src/mod/filesystem/abstractions/s3fs/s3FileWrapper.go — FileInfo/DirEntry
Modified files
src/mod/filesystem/arozfs/arozfs.go — add 's3' to IsNetworkDrive() and
GetSupportedFileSystemTypes()
src/mod/filesystem/filesystem.go — parse S3 path/creds and instantiate
S3FSAbstraction in NewFileSystemHandler
src/go.mod / go.sum — add github.com/minio/minio-go/v7
Config path format
Path = "[http://]<endpoint>[:<port>]/<bucket>[/<prefix>]"
Username = Access Key ID
Password = Secret Access Key
SSL is on by default; prefix the endpoint with 'http://' to use plain HTTP
(e.g. local MinIO dev server on port 9000).
https://claude.ai/code/session_01JvZrrTv9E7C7KDAR3FbaWz
* refactor(s3fs): replace MinIO SDK with AWS SDK for Go v2
Swaps github.com/minio/minio-go/v7 for the official
github.com/aws/aws-sdk-go-v2 suite. Functional behaviour is identical;
only the underlying HTTP client changes.
SDK packages now used (direct dependencies)
aws-sdk-go-v2 — core types & aws.String / aws.ToString helpers
aws-sdk-go-v2/config — LoadDefaultConfig with static credentials
aws-sdk-go-v2/credentials — NewStaticCredentialsProvider
aws-sdk-go-v2/service/s3 — HeadBucket, GetObject, PutObject, HeadObject,
DeleteObject, CopyObject, ListObjectsV2 +
paginator
aws-sdk-go-v2/feature/s3/manager — Uploader (automatic multipart for large files)
S3-compatible endpoints (MinIO, Wasabi, R2, …) are handled via
o.BaseEndpoint = scheme + "://" + endpoint
o.UsePathStyle = true
on the s3.Options — the standard AWS SDK v2 pattern for non-AWS backends.
Large-file / low-memory behaviour is unchanged:
ReadStream → resp.Body is the raw HTTP response io.ReadCloser
WriteStream → manager.Uploader auto-switches to multipart above 5 MiB
https://claude.ai/code/session_01JvZrrTv9E7C7KDAR3FbaWz
* feat(ui): add S3 / S3-Compatible option to storage pool editor
Changes to src/web/SystemAO/storage/fshedit.html:
Dropdown
- Added 'S3 / S3-Compatible' item (value='s3') to the Filesystem Type
selector, next to the other network-drive options.
isNetworkFs()
- Added 's3' so selecting S3 hides the local-disk fields and reveals
the network auth section, consistent with smb/ftp/sftp/webdav.
handleFileSystemTypeChange()
- When S3 is chosen:
• Shows the .s3hint info panel with endpoint path examples
(AWS, MinIO http://, Wasabi, Cloudflare R2)
• Renames Username → Access Key ID and Password → Secret Access Key
• Updates placeholders with realistic example values
• Sets a descriptive path placeholder
- When any other type is chosen the labels/placeholders revert to their
generic defaults and the hint panel is hidden.
checkPathProtocol()
- Added s3:// prefix detection: strips the scheme and selects S3 type.
- Fixed the http(s):// branch so it does NOT clobber an already-selected
S3 type (an S3 MinIO endpoint starts with http://).
Dropdown initialisation
- #fstype is now initialised separately with an onChange callback so
handleFileSystemTypeChange fires when the user picks an option
(Semantic UI dropdowns do not fire native change events).
https://claude.ai/code/session_01JvZrrTv9E7C7KDAR3FbaWz
* fix(metadata): enable RAW image rendering on buffered file systems (S3, FTP, WebDAV)
Fixes:
[Media Server] Failed to render RAW image: RAW image rendering not
supported for buffered file systems
Root cause
Both RenderRAWImage and generateThumbnailForRAW guarded themselves
with 'if fsh.RequireBuffer { return error }' — a blanket block that
prevented RAW support on any streaming-only filesystem (S3, FTP,
WebDAV).
RenderRAWImage
This function only calls GetFileSize + ReadFile and returns raw bytes.
It never opens a file handle. Both operations are implemented by
every FileSystemAbstraction, including buffered ones. The guard was
simply wrong — removed.
generateThumbnailForRAW
The actual incompatibility was the use of fshAbs.Create() to write
the cached thumbnail, since Create() is unsupported on buffered FS.
Fix: encode the JPEG into a bytes.Buffer first, then persist via
fshAbs.WriteFile(), which delegates to WriteStream() and therefore
works on every filesystem type. The RequireBuffer guard is removed.
No behaviour change for local / SMB / SFTP filesystems.
https://claude.ai/code/session_01JvZrrTv9E7C7KDAR3FbaWz
* fix: address Copilot review findings
go.mod
- Revert Go version back to 1.24.0 + toolchain go1.24.1; the bump to
1.25 was an unintended side-effect of 'go mod tidy'.
s3fs/s3fs.go
- Region auto-discovery: build an initial client, call
manager.GetBucketRegion to find the bucket's real AWS region, then
rebuild the client with that region. For non-AWS / S3-compatible
services the header is absent and we silently stay with us-east-1.
- CopySource URL-encoding: added s3CopySource() helper that splits the
key on '/' and url.PathEscape-encodes each segment individually, so
keys containing spaces or reserved characters are handled correctly.
- Directory rename: propagate DeleteObject errors instead of discarding
them with '_, _ = ...' to prevent silent partial-rename inconsistency.
- Glob(): replace ErrOperationNotSupported stub with a working
implementation that calls ReadDir on the pattern's parent directory
and filters entries through filepath.Match.
s3fs/s3FileWrapper.go
- S3FileInfo.Mode(): return fs.ModeDir | 0755 for directories so that
info.Mode().IsDir() returns true for callers that rely on it.
raw.go
- Write thumbnail cache file with mode 0644 (not 0775) to avoid setting
the executable bit on image files.
fshedit.html
- checkPathProtocol(): do not auto-select 'webdav' when the path starts
with http(s)://, since that scheme is also used for explicit S3
endpoints (e.g. http://minio:9000/bucket). Leave the dropdown as-is
and let the user pick the correct type.
https://claude.ai/code/session_01JvZrrTv9E7C7KDAR3FbaWz
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Updated Serverless logging, and interface (#222)
* feat(serverless): modern System Settings UI + per-endpoint execution metrics
- Gateway struct gains endpointStats map (sync.RWMutex-guarded) so every
external AGI invocation is tracked in memory without touching the DB.
- Each ExtAPIHandler call now assigns a UUID request-ID, measures wall-clock
duration, and calls recordExecution() which maintains:
• total / successful / failed execution counters
• cumulative and average execution time (ms)
• last-called Unix timestamp
• ring-buffer of last 10 successful and 10 failed ExecLog entries
(request_id, timestamp, duration_ms, method, message)
- New GetEndpointStats handler returns per-endpoint stats for the current
user; endpoints with no calls yet are returned with zeroed counters.
- New GET /api/ajgi/stats route registered via the existing externalAGIRouter.
- Serverless index.html rewritten as a macOS System Settings-style SPA:
• Persistent sidebar with Endpoints / Statistics / Execution Logs nav
• Global stat strip: endpoint count, total / successful / failed calls
• Per-endpoint cards with success bar, avg exec time, last-called time
• Statistics page: full per-endpoint metric grid + dual-colour ratio bar
• Logs page: tabbed Success / Failed table (last 10 each, all endpoints
merged and sorted newest-first) with request ID, timestamp, duration,
and message columns
• Inline 'New Endpoint' panel with file picker (replaces old form)
• Toast notifications for copy / add / delete actions
• Zero external CSS frameworks — pure CSS custom properties + flexbox/grid
https://claude.ai/code/session_01RGUh8MTYU73Twu1J6PqdZx
* fix(serverless): use named fileLoader callback for file selector
ao_module_openFileSelector in virtual-desktop mode reads callback.name
and injects it as an eval string into the floating selector window.
Anonymous functions have an empty .name, causing the selector to fail
with 'Selection Failed. Is parent window alive?'.
Replace the inline anonymous function with a named top-level fileLoader
function so the selector can call back correctly in both virtual-desktop
and normal (new-tab / localStorage polling) modes.
https://claude.ai/code/session_01RGUh8MTYU73Twu1J6PqdZx
* feat(serverless): persist stats to BoltDB + dual-colour endpoint bar
Backend — externalReqHandler.go
• Added ext_agi_stats BoltDB table for persistent metrics storage.
• ensureStatsTable / loadStatsFromDB / saveStatsToDB / deleteStatsFromDB
helpers wrap the same two-level JSON encoding pattern used by the rest
of the codebase (Write stores a string; Read decodes one JSON layer).
• recordExecution: on the first execution of a given UUID the in-memory
cache is cold; we now release the mutex, load from BoltDB, re-acquire
and re-check to avoid a race, then fall back to a blank entry. After
updating the struct we marshal under the lock (consistent snapshot) and
write to BoltDB outside the lock to avoid holding it during I/O.
• GetEndpointStats: switched to a write lock so DB-loaded entries can be
promoted into the memory cache; applies the same release/reload/re-check
pattern as recordExecution to avoid TOCTOU races.
• RemoveExternalEndPoint: now also calls deleteStatsFromDB so removed
endpoints do not leave stale rows in ext_agi_stats.
• Result: all stats (counters, average time, last-called timestamp, last-10
success/failure logs with request-ID) survive process restarts.
Frontend — index.html
• renderEndpointCard: added failRate variable (mirrors what the Statistics
page already computes) and replaced the single-colour green success bar
with the same dual-colour success/failure bar used on the Statistics page
— green left segment for success %, red right segment for failure %.
• Added a two-label legend beneath the bar (● X% success ● Y% failed).
https://claude.ai/code/session_01RGUh8MTYU73Twu1J6PqdZx
* fix(serverless): grey bar for zero-execution state + SVG icons everywhere
Grey bar / no-executions state
- Statistics page: failRate was computed as (100 - rate) which caused the
bar to show 100% red and the legend to read '100% failed' when total = 0.
Now failRate = total ? round(fail/total*100) : 0 (mirrors the same fix
already applied to the endpoint card).
- Both Statistics and Endpoints pages now render a solid grey bar with a
'No executions recorded' label when total_executions == 0, instead of
an invisible or misleading coloured bar.
- When total > 0 but one side is 0%, border-radius is adjusted so the
single remaining segment stays fully rounded rather than half-flat.
SVG icons (no more emojis)
- Log tabs: '✅ Successful' / '❌ Failed' replaced with inline Material
checkmark / close SVG paths coloured via CSS variables.
- Log-table status badge: '✓ OK' / '✗ Error' text replaced with the same
SVG paths at 11 px, vertically aligned inside the badge.
- Legend dots in both Endpoints and Statistics pages: '●' bullet character
replaced with an 8×8 SVG circle element (fill:currentColor inherits the
green / red from the parent span).
- Copy-URL tooltip: '✓ Copied!' changed to plain 'Copied!' (CSS ::after
content cannot render SVG; unicode bullet removed).
https://claude.ai/code/session_01RGUh8MTYU73Twu1J6PqdZx
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Speedtest: modernize UI and fix measurement accuracy
UI (mirrors system_settings design language):
- Replace Semantic UI statistics / progress widget with custom CSS
- Add speedometer-style SVG gauge (270° arc, fills as test runs)
- Three coloured result cards: blue download, green upload, amber ping
- Slim 3-px animated progress bar beneath the cards
- Modern typography: Segoe UI / system-ui stack, matching weights/spacing
- Full light + dark theme via CSS custom properties and
ao_module_getSystemThemeColor(), consistent with system_settings tokens
- Drop unused semantic.min.css / semantic.min.js imports
- Responsive layout (shrinks on screens ≤ 360 px)
Accuracy fixes:
- Download progress: was using increment with TIME_DIFF (current batch
duration), causing the bar to overshoot 100%; now uses SET capped at
96% so the final TTL_BANDWIDTH message lands cleanly at 100%
- Download live speed: client now counts bytes from every DATA: frame
and shows a live Mbps reading inside the gauge while the test runs
- Upload progress: was computing '100 - bufferedAmount/1MB', which only
works if the buffer is exactly 100 MB; now snapshots initialBuf after
the fill loop and uses (1 - remaining/initialBuf)*100 as the reference
- Upload live speed: computes bytes-on-the-wire / elapsed each 100 ms
tick and displays it in the gauge centre during the upload phase
- Ping timing: switched from new Date() (1 ms resolution) to
performance.now() (sub-ms) for both send and receive timestamps
- Ping array alignment: was calling shift() twice on only 2 of 3 arrays,
leaving clientRecv mis-aligned; now uses splice(0,2) uniformly on both
receive arrays so index i in clientSend/clientRecv/serverResp always
maps to the same round-trip
https://claude.ai/code/session_01QP5ab5t2ZekwBFCNB57WEq
* Revamp quick access UI; update Serverless
* Speedtest: resize window to fit modernized UI (460×430)
Old size was 600×220 (flat Semantic UI statistics row).
New layout stacks gauge (172 px) + result cards + progress bar + button
vertically; content height is ~395 px so 430 px gives comfortable margin.
Width reduced from 600 to 460 to match the 400 px max-width content area.
https://claude.ai/code/session_01QP5ab5t2ZekwBFCNB57WEq
* go mod tidy
tidy up go mod and go.sum
* Speedtest: redesign UI in fast.com style
Layout:
- Remove SVG gauge and three small cards entirely
- Left-aligned phase label ("Your internet speed:") above the number
- Huge left-aligned download number (font-size 88px, weight 800) with
unit and phase sublabel to its right — matches fast.com's hero display
- Number pulses (opacity keyframe) while each test phase is active,
locking solid when the result lands
- Slim full-width progress bar beneath the hero
- Secondary metrics row (Latency | Upload) fades in with a translateY
slide once the download result is ready; each metric pulses while its
test is running and locks on completion
- Minimal dark button ("Go" / "Go again"), inverts to light in dark mode
- Clean black-on-white / white-on-black palette instead of blue-grey cards
Window resized 460×430 → 440×400 to match the more compact layout.
https://claude.ai/code/session_01QP5ab5t2ZekwBFCNB57WEq
* Add experimental Movie app
* Add CRC32 chunk checks & retry for uploads
Server and client changes to add per-chunk CRC32 verification, retry handling, and final file checksum validation for low-memory WebSocket uploads.
- src/file_system.go: import hash/crc32; implement per-chunk metadata parsing (JSON {index,checksum}), verify chunk CRC32 before writing, maintain running full-file CRC32, request client retry via {"retryChunk":N} on mismatch, and validate final file checksum on done. Also fix several JSON text responses and ensure tmp cleanup on errors.
- src/web/Recorder/index.html: add CRC32 table/helpers, implement ordered chunk queue, send metadata frame then binary frame, maintain running CRC32, per-chunk ACK timeout and retry logic, and send final done message with full-file checksum. Update recorder UI status handling.
- src/web/SystemAO/file_system/file_explorer.html: add CRC32 helpers, per-chunk timeouts and retry logic, running CRC tracking, upload retry map and retry UI/button, improved progress handling and error states, and JSON parsing fixes.
- src/web/desktop.html: add CRC32 helpers and per-chunk retry/timeouts, compute and send final checksum, handle server retry requests, plus various UI/UX tweaks for window corner resizing and close-button interaction.
These changes improve upload integrity and robustness over unstable networks by detecting chunk corruption, requesting retransmit of bad chunks, and validating the complete file on the server.
* Add comprehensive Go test coverage across all packages (#224)
* Improve Go test coverage across all packages
- auth/autologin: fix test timeout bug (authlogger db not closed between
tests), coverage now 100%
- disk/smart: add fake-binary tests covering getBinary success path,
NewSmartListener body, and csmi device filter; 68.5% → 81.5%
- network/neighbour: cover ScannerRunning true branch, StopScanning
with active channel, loopback scanning; 55.2% → 65.5%
- filesystem/renderer: add STL/OBJ render tests; 51.6% → 100%
- disk/diskcapacity/dftool: extract parseDFOutput helper with tests;
63.6% → 80%
- apt: add InstallIfNotExists success path and more PackageExists tests;
44.6% → 63.5%
- time/scheduler: expand scheduler and handler tests; 28.7% → 69%
- disk/raid: add internal helper and handler tests; 33.6% → 42.2%
- disk/diskmg: add coverage tests; 42.8% → 48.4%
- Various other packages: minor improvements from previous sessions
(dynamicproxy, dpcore, reverseproxy, websocketproxy, webdav, csrf,
shareEntry, quota, auth/oauth2, modules, timezone)
https://claude.ai/code/session_016EXJLWuLSpquzKHZEJ7NYY
* Add test coverage for metadata, raid, diskmg, and scheduler packages
- filesystem/metadata: new metadata_test.go with 35+ tests covering
IsRawImageFile, NewRenderHandler, fileIsBusy, CacheExists,
GetCacheFilePath, RemoveCache, getImageAsBase64, all thumbnail
generators (error/RequireBuffer paths), and raw.go helpers
(getSizeForType, extractLargestJPEG, extractJPEGFromTIFF,
parseTIFFIFDChain, readIFDValue, readIFDArray, extractUncompressedThumbnail)
Coverage: 0% → 25.6%
- disk/raid: expanded raid_coverage_test.go with additional branch
coverage tests; coverage raised to 54.8%
- disk/diskmg: expanded diskmg_coverage_test.go with format-path and
mount-path branch tests; coverage at 62.8%
- time/scheduler: full auth-stack tests in scheduler_test.go;
coverage raised to 80.6%
https://claude.ai/code/session_016EXJLWuLSpquzKHZEJ7NYY
* Ignore test-generated BoltDB artifacts in mod subdirectories
Tests in mod/auth/autologin create a BoltDB at the relative path
./system/auth/authlog.db. Add a glob pattern to .gitignore so these
test artifacts are never accidentally committed.
https://claude.ai/code/session_016EXJLWuLSpquzKHZEJ7NYY
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add wip cache function to musicify
* Add cache and scroll optimization to Artists playlist
* Add artist detail view with scroll state
Refactor artists UI into a dedicated artist detail view instead of inline expansion. Introduce artistDetailOpen flag and backToArtistList to toggle between the list and detail screens, and preserve/restore scroll positions via artistListScrollTop/selectedArtistListScrollTop. Add scroll handlers and helper element getters, move artist list sizing into CSS (#artist-content-body), and rebuild templates to show a full song list with Play All in the detail view. Minor UI/markup cleanups (removed inline expansion chevron behavior and loading icon).
* Add device picker and UUID-based mounting (experimental)
Add a Linux-only device listing endpoint and UI device picker, plus UUID-aware mounting.
- Expose GET /system/disk/diskmg/devices (diskmg.HandleListDevicesWithInfo) which runs lsblk --json and returns disks/partitions with name, size, model, fstype, uuid and mountpoint.
- Add ResolveDeviceByUUID (uses blkid -U) in filesystem/static.go to resolve partition UUID -> /dev/* path (Linux only) and wire it into NewFileSystemHandler so stored DiskUUID is tried before the raw device path when automounting.
- Add DiskUUID field to FileSystemOption to persist partition UUIDs.
- Register new admin route in src/disk.go for the devices endpoint.
- Update storage editor UI (fshedit.html): add Browse button, Partition UUID input, a modal device picker, and JS to fetch/select partitions (fills mountdev and diskuuid, maps common filesystems).
Also include minor logging and safe string conversions when parsing lsblk output. This improves UX for selecting storage (survives device renames) and prefers UUID-based mounts with device-path fallback.
* Add movie app folder mode
* Refactor movie scanner
* Optimized desktop and mobile UX
* Add mobile responsive notes UI & control icons
* Add RWD optimization to Movie app
* Add library status bar and cache-backed refresh
* Add RWD to FFmpeg Factory
* Add shortcut support to mobile desktop mode
* Fix minor css issues
* Clear up duplicated locales
* Fixed theme toggle css bug
* Manga app rewrite
* Add drag app from start menu to desktop to create shortcut support
* fixed desktop filename length bug
* Update speedtest and OTP icons
* Add new Text Editor
* Optimized Musicify seek bar
* Refactor Clock UI, add icons, migrate Timer assets
* Added RAW preview feature in the share interface (#226)
* Support RAW image formats (DNG, CR2, ARW, NEF, RAF, ORF) in share interface
When a shared RAW file is previewed, the server now converts it to JPEG on
the fly using the existing metadata.RenderRAWImage() pipeline, so browsers
can display it. RAW files are also routed to the image.html preview template
instead of the generic default.html template.
https://claude.ai/code/session_01ENWo7sGbH6sCw64qiU1jwp
* Fix RAW download being served as JPEG instead of original file
The download mode check was happening after the RAW→JPEG conversion, so
/media/download/?file=...dng was sending a JPEG instead of the original DNG.
Move the RAW rendering block to after the download mode detection so that
download requests always get the original file.
https://claude.ai/code/session_01ENWo7sGbH6sCw64qiU1jwp
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Fix drive handling, folder listing and artist scrolling
* Update agi unit test module
* Move Movie front-end cache flow to backend
* Add async websocket support in agi
* Replace standard log package calls with arozos logger package
Replace all log.Println, log.Printf, log.Print, log.Fatal, log.Fatalln,
and log.Fatalf calls with the arozos logger package's PrintAndLog method.
- Main package files use the existing systemWideLogger instance
- Each module package gets a new zz_logger.go file declaring a
package-level logger var (e.g. databaseLogger) via NewTmpLogger()
- log.Fatal* calls are replaced with PrintAndLog + os.Exit(1)
- Multi-arg calls are wrapped with fmt.Sprint/fmt.Sprintf as appropriate
- Non-string arguments (errors, variables) are wrapped with fmt.Sprint
- Commented-out log calls and the logger package itself are left unchanged
* Resolve merge conflict in agi.websocket.go with v2.026
Take the v2.026 rewrite (goroutine-safe wsConn, background reader,
buffered msgChan, pump_messages/available/isClosed APIs) and apply
the logger transformation to the three new log.Println calls.
* Added wip terminal app
* Optimized Musicify cache logic
* Add workaround for logger nil pointer bug
* Fix nil systemWideLogger panic on startup
systemWideLogger was called in main() before RunStartup() initialized it,
causing a nil pointer dereference in the logger goroutine. Initialize a
temporary stdout-only logger at the start of main() so all PrintAndLog
calls are safe; RunStartup() replaces it with the file-backed logger.
* Removed dependencies on WinAPI
* Add Musicify app settings store to server
* Add Terminal docs
* Redesign logview UI to match system_setting design language
Replace old Semantic UI accordion layout with the same two-panel
flex design, CSS custom-property theming (light/dark), font stack,
and nav-item styles used by system_setting/main.css.
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Replace async locale fetch with inline translation table
$.getJSON path resolution differed between embedded and floating-window
contexts, causing silent failures. Embed all 6 language strings directly
in the script so translation is synchronous and context-independent.
Includes prefix fallback so 'ja' matches 'ja-jp'.
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Fix localization and add auto-refresh to logview
Localization: replace applocale dependency with a self-contained
$.getJSON fetch of syslog.json that works in both embedded (system
settings) and standalone (floating window) contexts. Includes a
language prefix fallback so 'ja' matches 'ja-jp'.
Auto-refresh: poll the open log file every 3 seconds and append only
new lines with a brief green highlight animation. A pulsing 'Live'
badge shows in the toolbar while refresh is active. Refresh stops
cleanly when switching files or navigating away (MutationObserver).
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Fix log box display mode causing garbled horizontal layout
Changed box.style.display from 'flex' to 'block' when showing the
log content — 'flex' was turning #lv-log-box into a flex container
and laying all line spans out horizontally instead of vertically.
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Trim syslog locale to the 6 supported languages
Remove fr-fr, de-de, es-es, pt-br, ru-ru, it-it. Keep only
zh-tw, zh-hk, zh-cn, en-us, ja-jp, ko-kr to match the set
supported by the rest of the system settings.
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Fix log coloring and add i18n support to logview
Color fix: scope all token color rules under #lv-log-box and add
!important to beat body.dark span { color: ... !important } in main.css,
which was washing out all span colors in dark mode.
Also fix the regex to normalize \r\n line endings before splitting and
remove the multiline ^ anchor so it correctly matches every log line.
Localization: add locale attributes to all static strings and load
../locale/system_settings/syslog.json via applocale.init(). The new
locale file covers 12 languages: zh-tw, zh-hk, zh-cn, en-us, ja-jp,
ko-kr, fr-fr, de-de, es-es, pt-br, ru-ru, it-it.
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
Fix logview embedding and add log-line syntax coloring
- Zero out #detail-inner padding for System Log in main.js (same
pattern as Performance tab) so the two-panel layout fills the pane
- Scope all CSS to #logview-root; remove html/body rules that bled
into the parent document
- Replace textarea with a div renderer that colorizes each log line:
date (muted blue-gray), time (muted), source (italic), INFO (green),
WARN (amber), ERROR/FATAL (red), DEBUG (purple)
- Regex parser handles the pipe-delimited arozos log format
https://claude.ai/code/session_01GWVDJt5UdYpWFqc3YMRd53
* Add i18n support to Clock widget for all 6 arozos locales
- Create Clock/locale/clock.json with translations for en-us, zh-cn,
zh-tw, zh-hk, ja-jp, and ko-kr covering UI labels, status strings,
window titles, button tooltips, and the timezone search placeholder
- Load applocale.js and initialise it at boot; boot is deferred into
the applocale callback so translate() runs before any dynamic render
- Add locale/title/placeholder attributes to all static HTML strings
(tab labels, countdown units, world-clock toolbar, tz-sheet header,
stopwatch status, empty state)
- Introduce getStr() helper for dynamically generated strings
(stopwatch status, "No results", window titles, remove-button title)
- Introduce getDateLocale() that maps the stored global_language
preference to a BCP-47 tag so weekday/date strings displayed in
the digital clock and world-clock hero card respect the UI locale
https://claude.ai/code/session_019JJo6yrD9D6Cp4trTr8SHa
* Translate region labels and day offset suffix in world clock
- Add clock/region-* keys for all IANA timezone region prefixes
(Asia, America, Americas, Europe, Africa, Australia, Pacific, UTC,
Indian, Atlantic, Arctic) across all 6 locales
- Add clock/day-suffix key (d / 天 / 日 / 日 / 日 / 일) for the
+1d / -1d offset shown on world clock cards
- initLocalClock: derive region label from tz.split('/')[0] via getStr
so "GMT+9 · Asia" renders as e.g. "GMT+9 · アジア" in Japanese
- wcRefresh: use translated day suffix instead of hard-coded "d"
- tzRenderList: translate region group headers in the tz picker sheet
https://claude.ai/code/session_019JJo6yrD9D6Cp4trTr8SHa
* Translate all 72 city names in Clock widget
- Add clock/city-* translations for all cities in ALL_CITIES across
zh-cn, zh-tw, zh-hk, ja-jp, and ko-kr
- Add getCityDisplayName(englishName) helper that looks up the
translated display name while keeping the English string as the
internal storage key in wcClocks / localStorage
- Apply getCityDisplayName in three places: local clock hero card
label, world clock cards, and timezone picker list items
- Extend tzFilter to also match against translated city names so
users can search in their native language (e.g. 東京, 도쿄)
https://claude.ai/code/session_019JJo6yrD9D6Cp4trTr8SHa
* Add library caching with optional force-refresh
Introduce a simple cache for the movie library scan: CACHE_FILE (user:/Document/Appdata/Movie/library_cache.json) and STALE_MS (8 hours). getLibrary.js main() now reads and parses the cache and returns cached data when present and fresh, unless a POST parameter forceRefresh=1 is provided to bypass the cache. Also update the frontend refreshLibrary() to send { forceRefresh: '1' } when the manual Refresh button is used so it triggers a full rescan.
* Update ui of diskmg
* Fixed desktop corner dragging bug
* Updated css and theme toggle flow
* Updated Terminal icon sets
* Localize diskmg.html using existing arozos locale system
Adds locale/diskmg.json with translations for zh-tw, zh-hk, zh-cn,
en-us, ja-jp, ko-kr. Updates diskmg.html to wire locale attributes on
all static text and appLocale.getString() for all JS-generated strings
(status labels, column headers, confirm dialogs, context menu items).
https://claude.ai/code/session_01M8L5HnmmXeXBW2fmTFZKGS
* Route AGI console.log through structured logger with execID
Otto's built-in console.log maps to fmt.Println, bypassing the logger
and producing output without timestamp or context. Override it in
injectStandardLibs so every console.log call in an AGI script is routed
through agiLogger.PrintAndLog with the execution ID prepended.
Output changes from:
CronDemo tick — execID=... user=... run=...
to:
2026/06/05 00:34:00 [AGI] [<execID>] CronDemo tick — execID=... user=... run=...
https://claude.ai/code/session_01EHns6vxckbmLuuMcZnzBmS
* Wire system logger into AGI Gateway for file-backed console.log output
agiLogger was a TmpLogger (LogToFile=false), so console.log calls only
reached stdout and never the log file. Add Logger to AgiSysInfo, pass
systemWideLogger from src/agi.go, and use it in injectStandardLibs when
present (falling back to agiLogger for tests/embeddings that omit it).
https://claude.ai/code/session_01EHns6vxckbmLuuMcZnzBmS
* Localize task scheduler UI using arozos locale system
Adds scheduler.json with translations for all 6 supported languages
(zh-tw, zh-hk, zh-cn, en-us, ja-jp, ko-kr) covering all static UI
strings, form labels, dynamic JS messages, and input placeholders.
Updates scheduler.html to load applocale.js, apply locale attributes
to all static elements, and use applocale.getString() via a t() helper
for dynamically generated content (empty states, toasts, alerts,
confirm dialogs, and the remove button).
https://claude.ai/code/session_01RH5mdJBjDjUZGKaVkHbKq6
* Add --log_format flag for structured JSON console logging
Introduces a --log_format=json flag (default: text) that switches the
system-wide logger's console output from plain text to newline-delimited
JSON entries with time, level, title, and message fields.
https://claude.ai/code/session_01TvkmdBDMMeaz3qu5FGDapg
* Fix JSON logging for module-level tmp loggers
Module-level loggers (e.g. agiLogger, smartLogger) are created as
package-level variables at init time before flags are parsed, so
per-instance PrintJSON was never set on them.
Introduce SetGlobalJSONOutput() in the logger package and call it
immediately after flag.Parse() in main(). PrintAndLog now checks
globalPrintJSON so every Logger instance — including all the tmp
loggers — respects the --log_format flag without needing changes at
each call site.
https://claude.ai/code/session_01TvkmdBDMMeaz3qu5FGDapg
* Unify all package-level loggers into a single default logger
All 56 per-package zz_logger.go files (each holding an identical
NewTmpLogger() instance) are deleted. The logger package now exposes
a defaultLogger, SetDefaultLogger(), and a package-level PrintAndLog()
that all modules call directly.
main() calls logger.SetDefaultLogger() twice: once with the temp logger
before RunStartup, and again with the persistent file-backed logger
inside RunStartup. Every xxxLogger.PrintAndLog(...) call site is
rewritten to logger.PrintAndLog(...); goimports updated all affected
import blocks.
https://claude.ai/code/session_01TvkmdBDMMeaz3qu5FGDapg
* Localize task scheduler settings panel (aecron.html)
Adds translations for the system settings page including: page header,
permission status banner (checking/enabled/disabled states), Open button,
task list table with headers, group cron permissions table, admin note,
and all dynamic JS strings (empty states, error messages, admin group note,
group permission toggle error).
Also adds locale-aware time unit strings (js/time/*) used by both pages,
replacing the hardcoded English day/hour/minute/sec plurals in
parseSecondsToHuman() with t() calls that produce compact CJK output
(e.g. "1天2小時30分") and natural English output ("1 day 2 hours").
Both pages share a single scheduler.json locale file.
https://claude.ai/code/session_01RH5mdJBjDjUZGKaVkHbKq6
* Fix duplicate logger import and undefined agiLogger in mod/agi
Remove the duplicate "imuslab.com/arozos/mod/info/logger" import in agi.go
and replace the undefined agiLogger fallback in agi.system.go with a proper
logger.NewTmpLogger() call, restoring build success.
https://claude.ai/code/session_01TPKX7ABMZtSMQyj7UQUANU
* Add agi runtime manager
* Add locale, runtime manager init and fix bug in diskmg
* perf: decouple CPU sampling and redesign performance monitor UI
Backend:
- Add usageinfo/monitor.go with StartBackgroundMonitor() — a goroutine
that computes CPU usage from /proc/stat deltas once per second and
caches both CPU and RAM results behind a RWMutex.
- InfoHandleTaskInfo now reads from the cache via GetCachedStats(),
responding in microseconds instead of blocking for ~1 s per request.
Frontend (taskManager.html):
- Redesign to match system_setting/main.css design language: CSS
variables for all colours, card-based sections (border-radius 10px),
Segoe UI / system-ui font, clean stats row with divider.
- Charts use tension 0.35 (bezier curves) instead of ~0 (straight lines)
for a fluid, smooth appearance.
- Fix double-render flicker: addAndShiftChartDate called chart.update()
twice per tick; replaced with shiftChart()/shiftNetChart() that modify
all data arrays first, then call chart.update('none') once.
- Pre-fill chart datasets with 60 zeros at init (no 60-update loop).
- Poll interval changed from 100 ms to 1 s (matches backend cache TTL).
- Network and usage requests fire in parallel; next tick is scheduled
only after both complete.
- Dark-mode colours are set at chart creation time (no post-init patch),
eliminating the brief flash of wrong colours on load.
https://claude.ai/code/session_01Us3U3YHtUEzoGAq3iVr1iz
* fix: resolve pre-existing build errors in mod/agi
- Remove duplicate import of "imuslab.com/arozos/mod/info/logger" that
caused "logger redeclared in this block" on both Linux and Windows.
- Declare package-level agiLogger (*logger.Logger) initialised with
NewTmpLogger(), which agi.system.go already referenced as a stdout-only
fallback when no system-wide logger is wired into the Gateway.
https://claude.ai/code/session_01Us3U3YHtUEzoGAq3iVr1iz
* perf: cache hardware info endpoints to eliminate per-request subprocesses
Add hardwareinfo/hostcache.go:
- StartHostInfoCache() launches a background goroutine that primes every
hardware endpoint through an in-process httptest.Recorder — no network,
no refactoring of existing handler logic required.
- CPU model and total RAM are static: sampled once at startup, never
re-fetched.
- Drive stats, NIC list, and USB devices are volatile: refreshed every
60 s via a ticker.
- Each Cached* wrapper serves from the RWMutex-protected byte cache; on
the brief window before the first sample completes it falls back to a
live call, so startup behaviour is unchanged.
Update system.info.go:
- Route all five hardware endpoints to their Cached* counterparts.
- Call info.StartHostInfoCache() alongside the existing
usage.StartBackgroundMonitor() call.
Result: getCPUinfo, getRAMinfo, getDriveStat, ifconfig and usbPorts now
respond in < 1 ms instead of spawning one or more subprocesses per request.
https://claude.ai/code/session_01Us3U3YHtUEzoGAq3iVr1iz
* agi: include execution UUID in script error log messages
Add [<execID>] after the [AGI] / [Remote AGI] prefix so each error line
carries the same UUID that is injected into the script as EXECUTION_ID,
making it straightforward to correlate log entries for a single request.
Also fix the missing separator in the Remote AGI error message
("failed to execute<err>" -> "failed to execute: <err>").
https://claude.ai/code/session_01FHPkX8pCYWbGvh2pL47J8y
* feat(share): async zip with progress for folder download-all
Instead of holding the HTTP connection open while zipping (which times out
on large folders), the "Download All" button now:
1. Calls POST /share/prepare-zip/{shareId} which starts a goroutine,
stores the job in an in-memory sync.Map, and immediately returns a
jobId JSON response.
2. The frontend polls GET /share/zip-status/{jobId} every 600 ms and
renders a progress modal (percent bar + current filename).
3. On completion, the browser is redirected to
GET /share/zip-download/{jobId} which serves the pre-built zip.
4. Jobs auto-expire (zip deleted, entry removed) after 1 hour.
Backend additions:
- ZipJob struct with mutex-protected status/progress fields
- zipJobs sync.Map on the Manager for concurrent job tracking
- handleZipStatus / handleZipDownload helper methods
- ArozZipFileWithProgressAndCompression in fileOpr.go — combines
compression-level control (RegisterCompressor) with progress callbacks
and nil-fsh support for locally-buffered remote filesystems
Frontend changes (downloadPageFolder.html):
- "Download All" changed from <a href> to <button onclick=startDownloadAll()>
- Async zip progress modal with animated progress bar, status text, and
current-file indicator
- Compression checkbox state is read at click time (no stale href to update)
https://claude.ai/code/session_013a46yC7Vhy97TEVwcMKvwW
* Revamp system update UI; add launcher exe ignore
Replace the legacy Semantic UI/Angular update page with a modern, self-contained UI (new #up-root) including scoped CSS variables, responsive layout, themed dark mode support, custom status panels (warning/checking/confirm/downloading/success/pending/failed), improved launcher detection and manual restart instructions, progress bar, and enhanced JS for i18n and update flows. Remove dependence on Semantic markup, consolidate scripts, and improve fallback behavior (WebSocket/AJAX). Also add src/launcher.exe to .gitignore.
* Update updates.json
* Fixed ffmpeg not found cause sys panic bug
* Fixed Musicify ios bug
* Optimized default opener ui
* Optimized embedded player seek bar
* Add path shortcut resolution
Introduce a pathShortcuts map and resolvePathShortcut(path) helper to expand user-friendly shortcuts (e.g. "%appdata%" -> "user:/.appdata/"). Integrate resolution into listDirectory so paths provided with shortcuts are normalized before directory listing. This enables using predefined shortcut tokens when opening folders.
* Use user:/.appdata for caches and ensure dirs
Switch Movie and Musicify server-side cache paths from user:/Document/Appdata/... to user:/.appdata/... so caches are stored in the unified .appdata directory. Add directory-creation checks (mkdirIfMissing / fileExists) before writing caches and update related comments/usages in frontend and backend. Also update NotepadA to create its .appdata/NotepadA folder and return the new tmp file path. These changes ensure cache writes won't fail due to missing parent directories and consolidate storage location.
* Fixed bug in interval for agi_runtime setting ui
* Add diskmg rwd support
* Add MacOS support for diskmg
* Add wip Cal app
* Update personal homepage ux
* mobile ui optimize
* Remove macos tag from styles
* Add experimental arozcast feature
* Add Arozcast auto-reconnect logic
Implement automatic reconnection for Arozcast across Movie, Musicify and Photo UIs. Adds reconnect state (timer, count, pending room code), backoff delays, and helper flows: _startCastReconnect/_attemptCastReconnect/_castDidReconnect (and equivalents for music and photo). On socket close, code now schedules reconnect attempts (instead of immediately resuming locally) and suppresses reconnect when explicitly disconnecting. Reconnect attempts use an 8s open timeout and increasing delays [2s,4s,8s,16s,30s]; on successful reconnect the remote state (media load, position, play/pause, volume or current photo) is restored and heartbeats/watch timers resumed. Also adds visibilitychange handlers to try reconnecting immediately when the tab becomes visible, and ensures pending reconnect timers are cleared on disconnect/close.
* arozcast optimization
* Send volume after media load; add icon
Add repeat.svg asset and adjust cast volume timing. Move media.volume messages to after media.load (in connectCast and startPlayback) so the cast target receives the correct volume during media initialization and avoids being overridden by defaults. Remove earlier pre-load volume send and add explanatory comments.
* Add Arozcast docs and repeat sync support
Add a full Arozcast Developer API reference (src/web/Arozcast/README.md) documenting HTTP endpoints, WebSocket protocol and integration guidance. Update the Arozcast receiver (src/web/Arozcast/index.html) to show a repeat indicator, handle incoming media.repeat messages, and apply native loop only for 'one' mode (keep 'all' driven by sender via media.ended). Send media.repeat from Musicify (src/web/Musicify/musicify.js) when the repeat mode changes and when (re)connecting so sender and receiver stay synchronized; also add small toolbar CSS for the active state.
* Optimize status sync flow
* Normalize .fileOprBtnMobile class name
Rename CSS selector `.fileOprBtnMobile` to `.fileoprBtnMobile` across the file for consistent casing and selector usage. Also tidy up whitespace in the `p` selector. No functional styles changed aside from the selector name update.
* Cancel pending cast auto-reconnect on new session
When opening a new cast session, clear any pending auto-reconnect timers and reset reconnect counters/pending codes to prevent reconnecting to the old room. Applied to Movie (src/web/Movie/index.html), Musicify (src/web/Musicify/musicify.js) and Photo (src/web/Photo/photo.js).
* Add Arozcast sender SDK, docs, and examples
Introduce arozcast.js — a self-contained ArozCast Sender SDK for ArozOS webapps that handles WebSocket lifecycle, heartbeating, watchdog, backoff reconnection, and cross-tab takeover via BroadcastChannel. Adds comprehensive reference documentation (arozcast.md) and several example pages demonstrating audio, video and photo casting (audio-player.html, audio.html, photo.html, utilities.html, video-player.html, video.html). Provides high-level playback helpers (load/play/pause/seek/setVolume/setRepeat/stop), event hooks (connect/disconnect/reconnecting/giveup/takeover/status/ended), and utilities like ping(), notifyTakeover(), connect/disconnect/destroy to simplify integration.
* Updated theme color of arozcast
* Add receiver idle timeouts and room.closed handling
Implement server-side room lifecycle cleanup and notify senders before teardown.
* Add transcode seek to Musicify and Movie module
* Add WebRTC screen sharing support to Arozcast receiver (#240)
* Renamed arozcast to cast.go
* Fixed audio transcoder bug
* Add experimental zip file manager
* Fixed logger null pointer bug
* Add CLAUDE.md and automated enforcement of contribution rules (#241)
* Add sqlite and 7zip support in agi
* Removed movie index backup
* Add SQLite Admin web UI and backend
Introduce a new SQLite Admin web interface and its backend AGI API. Adds backend/api.agi implementing actions for tables, schema, query (with paging/sorting), exec, update, delete, insert and droptable with identifier quoting, table validation and parameter binding to reduce injection risk. Adds rich single-file frontend (index.html) with toolbar, sidebar, Browse/Structure/SQL tabs, pagination, modals for edit/insert/confirm, and client-side code that calls the AGI API. Also include desktop and small icon assets (img/) and an init script for the web app. Overall enables opening a .sqlite file, browsing and editing data, viewing schema and running SQL from the UI.
* Add 7zip support to Zip File Manager
* Add unit test for sqlite and 7zip
* Create ziplib.7z.js
* Updated UnitTest icons
* Add SQLite availability check and platform stubs
Add platform build tags and a no-op SQLite stub for platforms where modernc.org/libc/sqlite lacks a C-runtime port (e.g. linux/mipsle, windows/arm). Update tests to use matching build constraints. Expose a new API action ('available') so callers can probe SQLite support without opening a DB. Update the SQLite Admin UI: add a banner and CSS to inform users when SQLite is unavailable, and JS to probe the API on load and disable the open button when unsupported. Files changed: agi/agi.sqlite.go, agi/agi.sqlite_stub.go (new), agi/agi_sqlite_test.go, web/SQLite Admin/backend/api.agi, web/SQLite Admin/index.html.
* Fixed build issue on makefile
* Add AI Model integration library for AGI scripts (#242)
* Add aimodel AGI library for OpenAI-compatible endpoints
Introduce a new AGI class (requirelib("aimodel")) that lets AGI scripts
call any OpenAI-compatible chat completion endpoint, with both text and
file-based prompts.
Library (mod/agi/agi.aimodel.go):
- aimodel.chat(prompt, options) text prompt
- aimodel.chatWithFile(prompt, files, opts) image (vision) or text-document prompt
- aimodel.request(messages, options) low-level call, returns full response
- aimodel.usage() / aimodel.models() usage metrics and configured models
- Per-call options can override model, system prompt, endpoint, API key,
temperature and max_tokens.
System Settings > Developer Options > AI Model (admin only):
- Configure the OpenAI-compatible base URL, global API key (stored masked)
and default model, with a connectivity test that lists available models.
- Define per-model pricing (per 1M input/output tokens).
- Metrics board showing consumed tokens (prompt/completion/total), accumulated
fee and a per-model breakdown, with refresh and reset.
Token usage and cost are recorded to the system database on every call and
aggregated globally and per model.
Wiring: register the lib in LoadAllFunctionalModules, register settings tab
and admin endpoints via AIModelSettingInit, bump AGI runtime version to 3.1,
and document the library in agi-doc.md and the module README.
Adds unit/integration tests covering option parsing, key masking, file-type
classification, metrics accumulation/costing, the request flow against a mock
endpoint, and config-handler key masking/retention.
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
* Add AI Chat demo app (LM Studio style)
A WebApp that provides an LM Studio-like conversation UI on top of the
aimodel AGI library, talking to any configured OpenAI-compatible endpoint.
web/AIChat/:
- index.html LM Studio style client: dark/light theme, collapsible chat
history (persisted in localStorage), editable model selector populated
from the configured models, settings drawer (system prompt, temperature,
max tokens), markdown + code rendering with copy buttons, typewriter
reveal of replies, per-message and per-chat token counts, stop and
regenerate actions, and an empty-state with prompt suggestions.
- backend/chat.agi relays a conversation to aimodel.request()
- backend/models.agi returns configured models + default via aimodel.models()
- init.agi registers the module (Office group)
- img/icon.svg app icon
Adds Go tests that execute the real backend .agi scripts in an otto VM
against a mock endpoint, covering the chat relay (system-prompt forwarding,
content + usage passthrough), the missing-endpoint error path, and the
models listing.
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
* Add Anthropic + quota to AI Model; redesign settings; fix AI Chat
Settings (System Settings > AI Integration > AI Model):
- New "AI Integration" settings group; the AI Model tab moved here out of
Developer Options.
- Rewrote the settings page as a scoped fragment following the design of
SystemAO/info/overview.html (CSS variables + body.dark theme support) so it
renders correctly when injected into the settings host. Removed the AGI
script tutorial block.
- Added an API Format selector (OpenAI / Anthropic) and a Usage Quota card
(enable, period total/daily/monthly, max tokens, max cost) with a live
usage progress bar.
aimodel library:
- Anthropic (Claude) Messages API support alongside the OpenAI format,
selectable globally or per call via the apiFormat option. System prompts,
image attachments and token usage are translated to/from the Anthropic
wire format; responses are unified so callers and metrics are unchanged.
- Usage quota enforcement: requests are blocked once the configured token or
cost cap for the period (total/daily/monthly) is reached. Windowed usage is
tracked in the metrics record.
- New script helpers: aimodel.listModels() (live endpoint models) and
aimodel.fileParts() (build content parts from vfs files for use in
aimodel.request messages).
- New admin endpoint /system/aimodel/quota (GET/POST); config now carries the
API format; the connectivity test branches by format.
AI Chat app:
- Fixed the missing scroll bar (flexbox min-height:0 on the chat column).
- Fixed model selection: replaced the datalist combo with a real <select>
populated from configured + live endpoint models, plus a Custom option.
- Added file attachments via the ArozOS file selector (ao_module); attached
images/text documents are merged into the latest user message.
Adds tests for the Anthropic request flow, content/image conversion, quota
enforcement and window expiry; bumps AGI runtime version to 3.2.
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
* Record generation speed (tokens/sec) for AI Model usage
- Measure each request's wall-clock generation time and compute tokens/sec
(completion tokens / elapsed) for both OpenAI and Anthropic formats.
- Return tokens_per_second and generation_ms in the response usage so callers
(and the AI Chat app) can display per-message speed, LM Studio style.
- Accumulate generation time per model and overall so the metrics board can
show an average tok/s (new "Avg Speed" card and per-model tok/s column).
- AI Chat shows "x.x tok/s" alongside token counts under each reply.
recordAIModelUsage takes an optional generation-time argument (variadic, so
existing callers are unaffected). Adds a test asserting tok/s and generation
time are computed and accumulated.
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
* Fix average tok/s to be the mean of per-request speeds
The "Avg Speed" metric divided total completion tokens by total generation
time, a token-weighted throughput that skews toward large requests and does
not match the per-reply tok/s figures shown in the chat.
Now each request's speed is sampled (tokens/sec) and the board reports the
arithmetic mean of those samples, both overall and per model. Adds speedSum /
speedSamples to the metrics and a test asserting the mean (e.g. 10 and 100
tok/s average to 55, not the 91.8 throughput value).
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
* Make AI Model lib logger usage portable across AGI versions
Use the package-local agiLogger (present in every AGI build) instead of the
package-level logger.PrintAndLog helper, which only exists on newer AGI
revisions. This lets the AI Model feature compile and merge onto the
v2.026 line as well as later builds.
https://claude.ai/code/session_01L9efsqUqRV7EgsiC4gRPan
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: explain what AGI means in CLAUDE.md (#243)
Clarify that AGI in this codebase is the ArOZ Online JavaScript Gateway
Interface (the server-side Otto-based JS runtime for web app scripts), not
Artificial General Intelligence. Add a dedicated section and a cheatsheet
entry pointing at src/mod/agi/ and its API reference.
https://claude.ai/code/session_01BGdKQViZeoU4G8caNebgHU
Co-authored-by: Claude <noreply@anthropic.com>
* Add imagelib.rawToJPEG AGI function to convert RAW photos to JPEG (#244)
* Added experimental Pixel Studio
* Add photo search and indexing with SQLite backend (#245)
* Add SQLite-backed photo search with autocomplete and auto-indexing
Adds an iOS Photos–style search feature to the Photo web app, backed by a
per-user SQLite index built through the AGI sqlite library.
Search index (backend/imagedb.js)
- Designs a `photos` schema indexing file name, resolution (width/height/
megapixels/orientation), shooting parameters (camera make/model, lens, ISO,
aperture, shutter, focal length), the date taken (EXIF DateTimeOriginal, used
as the photo's created date) and the file modified date — plus an index_meta
table for schema version / exclude list / last-index time.
- Robustly extracts metadata via imagelib (dimensions + EXIF) and filelib
(mtime/size), normalising goexif's JSON-encoded values; stored per user at
user:/.appdata/photo/photoindex.db.
Auto indexing (backend/indexPhotos.js)
- Incremental indexer: walks the photo library roots, (re)indexes only new or
changed files in bounded batches and prunes deleted ones. The app kicks this
off in the background on load and loops until done, so the index stays fresh
automatically. "full" mode wipes and rebuilds.
Search + autocomplete (backend/searchPhotos.js, searchSuggest.js)
- Free-text query parser supporting tokens like `iso:1600`, `f/2.8`, `50mm`,
`model:"EOS R5"`, `2023`, `landscape`, `.jpg`, `modified:>2024-01-01`, plus
plain text over name/camera/lens; compiled to parameterised SQL.
- Autocomplete returns ranked, de-duplicated suggestions (cameras, lenses,
years, file types, file names, filter tokens) drawn from the index.
Front-end (index.html, search.js, photo.js)
- Adds a search bar with autocomplete dropdown, keyboard navigation, result
count and a background-indexing status chip with a Rebuild action; results
reuse the existing grid and viewer.
Also implements getExcludeFolders/setExcludeFolders in imagedb.js, which the
existing backend/exclude.js included but were previously missing; the indexer
honours the exclude list.
https://claude.ai/code/session_014XBV87rHxBy1BHwn89rgd8
* Photo search: tags/chips input and month searching
Turns the photo search box into a tags input and adds calendar-month search.
Tags input (index.html, search.js, photo.js)
- The search box now holds removable filter chips instead of a single text
field. Typing + Enter/Space (or picking a suggestion) commits the token as a
chip; Backspace on an empty box removes the last chip; each chip has an × and
a type-coloured icon (camera/date/lens/filter). Results update live as chips
change, and the autocomplete dropdown is repositioned to sit under the
variable-height box.
- New helpers photoParseTagToken / photoInputCommittable / month helpers turn a
raw token into a friendly {label, value, type} chip.
Month searching (backend/imagedb.js, searchSuggest.js)
- Adds a calendar-month filter that matches across years via
strftime('%m', taken_date). Supports bare month names/abbreviations ("june",
"dec"), `month:6`, comma lists (`month:june,july`, OR-ed), and combining with
a year ("june 2023"). Autocomplete now suggests months by name prefix.
- Fixes end-of-period date math so "2023-06" / "2023-02" bound their month
correctly regardless of month length.
https://claude.ai/code/session_014XBV87rHxBy1BHwn89rgd8
* Photo search: stop autocomplete dropdown from flashing shut
The live/debounced search runs ~400ms after each keystroke and runSearch()
was closing the suggestions dropdown, so it appeared (~150ms after typing)
then vanished (~400ms) — looking like it disappeared right after showing.
- runSearch() no longer sets showSuggestions=false; the dropdown is now hidden
only by explicit actions (picking/committing a tag, Escape, clear, or a click
outside the search area).
- Moved click.outside from the dropdown to the search-input wrapper so clicking
the input or a chip no longer dismisses the suggestions.
https://claude.ai/code/session_014XBV87rHxBy1BHwn89rgd8
* Photo search: OR within a category, AND across categories
Selecting several tags of the same kind now broadens the search instead of
contradicting itself. Previously every token was AND-ed, so e.g. "2025 2026"
asked for photos taken in both years at once and returned nothing.
The query builder now groups parsed tokens by category and OR-s the values
within each category, while different categories stay AND-ed:
2025 2026 iso:1600 -> (year 2025 OR year 2026) AND iso = 1600
- Each filter category (text, filename, camera model/make, lens, orientation,
month, ISO/aperture/focal/MP/width/height ranges, taken/modified dates) is now
a list; buildWhere emits an OR group per category and joins groups with AND.
A single range token (e.g. iso:800-3200) is still one min..max condition.
- The front-end ignores exact duplicate chips.
Verified against a real SQLite engine: "2023 2024" returns both years' photos,
"canon nikon"/"iso:1600 iso:200" OR-match, while "canon 2023" and
"landscape 2024" still AND across categories.
https://claude.ai/code/session_014XBV87rHxBy1BHwn89rgd8
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add photo rating, grid zoom, and date grouping features (#246)
* Photo: wheel zoom, date-grouped grid, download & rating filter
Add four user-facing capabilities to the Photo app:
- Mouse-wheel zoom. Ctrl/Cmd + wheel (and trackpad pinch) over the grid
resizes every thumbnail by changing the column count (2-12); a plain
wheel inside the viewer zooms the open photo, anchored at the cursor.
- Year / Month grid sections, Google-Photos style. The grid is split into
contiguous date headers driven by EXIF taken date (search) or file mtime
(folder listing), with a sticky header per section and a "Group by date"
sidebar toggle (on by default). listFolder.js now returns mtime so folder
views can group without hitting the index.
- Download the current photo from the viewer toolbar via the media server's
download mode (serves the original, RAW included).
- Filter by star rating. User-assigned ratings are stored per-user in a new
photo_ratings table that survives re-indexing/schema rebuilds; set them
from a star widget in the viewer (setRating.js / getRating.js) and filter
with a sidebar star selector, a rating: search token, and autocomplete
suggestions. searchPhotos.js LEFT JOINs the ratings so results carry them.
https://claude.ai/code/session_01LJecFtVoDYKDoZMUGMaRPf
* Photo: group folder views by EXIF shoot time, not file mtime
Year / Month grid sections were driven by the EXIF taken date only for
search results; plain folder browsing grouped by the file's last-modified
time. Folder listings now resolve each photo's shoot time from the
per-user photo index (which stores EXIF DateTimeOriginal) with a single
folder-scoped query, falling back to mtime only for photos the background
indexer has not reached yet. When auto-indexing or a rebuild finishes with
newly indexed photos, the grid reloads so the sections pick up the EXIF
shoot times without a manual refresh.
https://claude.ai/code/session_01LJecFtVoDYKDoZMUGMaRPf
* Photo: skip .metadata cache folders when indexing
ArozOS generates thumbnail caches under <folder>/.metadata/.cache/ inside
every browsed directory. The recursive walk in indexPhotos.js was indexing
those cached JPEGs, polluting search results, date grouping and the photo
count. Add db_isHiddenPath() to imagedb.js (true for any dot-prefixed path
segment) and skip such paths during the index walk — checked before the
file is marked present, so cache rows already in the index are pruned
automatically by the existing delete sweep on the next pass.
Also hide dot-prefixed files (e.g. AppleDouble "._IMG.jpg" sidecars) from
folder listings, matching the existing rule for dot-folders.
https://claude.ai/code/session_01LJecFtVoDYKDoZMUGMaRPf
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Update initial window size for photo app
* Added Musicify full buffer mode
* Add floating color picker, palettes, and guides
Introduce a non-modal floating color picker and supporting UI, plus rulers/guides and improved clipboard image paste. Added new js/colorpicker.js and styles for tool flyouts, color picker, floating panels, rulers, and palettes. Updated index.html to include ruler canvases and load the new scripts. editor.js: extended hex parsing (3/6/8-digit), rgbToHex to emit alpha when present, added PS.floatingPanel helper, integrated guide/ruler drawing into overlay loop, added palettes/custom color management, and adjusted setFg/setBg handling. fileio.js: replaced modal New Document with a floating panel (supports mandatory fallback), serialized/deserialized guides, rulers and customColors, and added async clipboard image paste helpers (pasteFromClipboard, pasteImageAsLayer, loadImageBlobAsLayer). UI prefs now persist custom palettes and ruler state.
* Fix css and racing bug
* Update arozcast icons
* Update Recorder type
* Update core structure
* Document ziplib 7z support and sqlite API
Add documentation for ziplib 7z extensions and a new sqlite scripting API. README updates describe ziplib 7z functions (extract7zFile, list7zFileDir, list7zFileContents, getFileFrom7z, extractPartial7z, get7zFileInfo) with examples, and introduce the sqlite connection API (sqlite.open, db.exec, db.query, db.queryRow, db.tables, db.schema, db.close) including a platform availability note. Mirror these additions in the web/Terminal API JSON so the UI docs expose the new functions and examples.
* Fixed agi panic on exit() call
* Add SQLite open file support
* Evenly space photo viewer top-right toolbar buttons (#248)
Group the close, info, cast and download buttons into a flex toolbar with
a consistent gap instead of individual, unevenly-spaced absolute offsets
(right: 1em / 3em / 6.5em / 9.7em) and a misaligned cast/download row
(top: 1.3em vs 1em). They now sit equal-width apart and vertically
aligned, and flex automatically skips the info button (hidden on desktop)
so no empty gap is left. Button order (download, cast, info, close) is
preserved via flex-direction: row-reverse.
Co-authored-by: Claude <noreply@anthropic.com>
* Add embed movie player
* Add support for webapp defined file icon types
* Expose ext icon to agi
* Replaced all unicode arrow to ascii arrows
* Add Pixel Studio gradient tool
* docs: expand CLAUDE.md with AGI, WebApp and SubService sections (#249)
Enrich the AGI section (execution entry points, requirable library list,
gateway wiring and HTTP endpoints) and add two new sections documenting how
WebApps register via init.agi/ModuleInfo and how SubServices run as
reverse-proxied binaries. Extend the repository layout cheatsheet with the
modules and subservice packages.
https://claude.ai/code/session_01XnzhsjyirqYA7pfkJe32yZ
Co-authored-by: Claude <noreply@anthropic.com>
* Update Calendar icons
* Updated Camera App
* App icon optimize
* Add PWA support to Camera app
* Fix filter saving bug
* Add mobile responsive design with off-canvas sidebar (#250)
* Make AI Chat web app mobile-friendly (RWD)
The AIChat web app used a fixed two-column grid (268px sidebar + content)
with no media queries, so on phones the sidebar ate most of the screen and
the topbar/composer didn't adapt.
Add a responsive layout for narrow screens (<=768px):
- Off-canvas sidebar that slides in over a backdrop, toggled by a new
hamburger button in the topbar; auto-closes on chat select/new chat and
when opening Settings.
- Single-column grid; tighter gutters for messages/composer/topbar; a
flexible model picker (hidden label + spacer so the select can grow).
- Touch affordances: delete-chat and copy-code buttons always visible
(no hover on touch) and 40px tap targets.
- 100dvh, interactive-widget=resizes-content and a 16px composer font so
the composer stays visible above mobile browser chrome/keyboard and iOS
doesn't zoom on focus.
Desktop layout is unchanged: all new rules are scoped to the media query
or hidden by default.
https://claude.ai/code/session_01M5CKy2tfgt8KeRU9boH7V1
* Confirm before deleting a chat in AI Chat web app
The delete (✕) button on a chat removed it immediately. Prompt for
confirmation first, naming the chat and mirroring the existing
"This cannot be undone." wording used by "Delete all conversations".
https://claude.ai/code/session_01M5CKy2tfgt8KeRU9boH7V1
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Enhance CLAUDE.md with subservices documentation and co (#251)
* docs: document subservices in CLAUDE.md
Add a "What subservices are" section explaining the subservice system:
the child-process + reverse-proxy model, the -info/-port/-rpt startup
handshake, on-disk layout and naming, routing via StartDir, control
files (.disabled/.noproxy/.startscript/.intport) and runtime admin
control. Includes a minimal demo example and links to the canonical
src/README.md reference and the ArozOS-Subservice-Example repo.
* docs: contrast webapps and subservices in CLAUDE.md
Add a "Webapp vs. subservice" comparison table to the subservice
section, clarifying the two extension models: a webapp is static
front-end assets plus AGI/JavaScript run inside the core VM, while a
subservice is an external binary the core launches and reverse-proxies.
Both register the same ModuleInfo and look identical on the desktop.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add AGI Forge: natural-language-to-AGI-script copilot webapp (#252)
A terminal-style web app (Development group) that turns a plain-language
request into an AGI script and runs it on the server, Claude-Code style.
Flow: prompt -> backend/generate.agi asks the configured aimodel, grounded
with the live AGI API reference (Terminal/docs/api.json via appdata) and the
installed ao_module list, to emit a script -> the script is shown with syntax
highlighting -> backend/run.agi evaluates it in a captured VM (same model as
the Terminal REPL), returning stdout, console logs, errors and any file the
script registers via provideOutputFile(); generated files land in
user:/Desktop/AGI Forge/ and are offered as Download / Open-in-Files.
UI is a responsive VS Code-dark terminal: model picker, auto-run toggle,
editable code blocks, per-turn re-run, "Ask AI to fix it" on errors, and
multi-turn context for follow-ups. No Go changes: backend is pure AGI served
through the existing authenticated /system/ajgi/interface endpoint.
https://claude.ai/code/session_0193Pm4yd6mdPDqvdYfeZG3a
Co-authored-by: Claude <noreply@anthropic.com>
* css optimization
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Alan Yeung <yeungbluecat123@gmail.com>
c5f16f8fd6 Bump golang.org/x/image from 0.33.0 to 0.38.0 in /src (#214)
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.33.0 to 0.38.0.
- [Commits](https://github.com/golang/image/compare/v0.33.0...v0.38.0)
---
updated-dependencies:
- dependency-name: golang.org/x/image
dependency-version: 0.38.0
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Toby Chui <tobychui@users.noreply.github.com>
8684a35e3f Bump github.com/go-git/go-git/v5 from 5.16.5 to 5.19.1 in /src (#215)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.16.5 to 5.19.1.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Changelog](https://github.com/go-git/go-git/blob/main/HISTORY.md)
- [Commits](https://github.com/go-git/go-git/compare/v5.16.5...v5.19.1)
---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
dependency-version: 5.19.1
dependency-type: direct:production
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
- View comparison for these 10 commits »
2 weeks ago