100 Commits
Author SHA1 Message Date
Timothy Jaeryang Baek 1f2460a6f9 refac 2026-11-04 15:01:34 +09:00
Timothy Jaeryang Baek 0f96ad5db4 refac 2026-11-04 14:57:22 +09:00
Timothy Jaeryang Baek 6444534c8a refac 2026-11-02 12:15:59 +09:00
Timothy Jaeryang Baek 975583f0ca refac 2026-11-02 12:08:58 +09:00
Timothy Jaeryang Baek e96d5c6ed2 refac 2026-11-02 11:46:10 +09:00
Timothy Jaeryang Baek 749b7fadae refac 2026-11-02 10:53:05 +09:00
Timothy Jaeryang Baek 1a4ab59e34 refac 2026-11-02 10:50:14 +09:00
Timothy Jaeryang Baek 8137834d19 refac 2026-11-02 09:53:08 +09:00
Timothy Jaeryang Baek affad6cce7 refac 2026-11-02 09:06:26 +09:00
Timothy Jaeryang Baek c758bf2ade refac 2026-11-02 09:03:11 +09:00
Timothy Jaeryang Baek 23cdf75428 refac 2026-11-02 08:53:30 +09:00
Timothy Jaeryang Baek 200b7ee445 refac 2026-11-02 08:27:16 +09:00
Timothy Jaeryang Baek b1fdd9ea1d refac 2026-11-02 02:20:33 +09:00
Timothy Jaeryang Baek 6c5c2a7333 refac 2026-11-02 01:47:00 +09:00
Timothy Jaeryang Baek f08aeb1538 refac 2026-11-02 01:27:36 +09:00
Timothy Jaeryang Baek 29cd3f00f2 refac 2026-11-02 01:16:55 +09:00
Timothy Jaeryang Baek 4aa52f398b refac 2026-11-02 00:30:01 +09:00
Timothy Jaeryang Baek 6a2030f0f9 refac 2026-11-02 00:24:44 +09:00
Timothy Jaeryang Baek dec18632cf refac 2026-11-02 00:22:51 +09:00
Timothy Jaeryang Baek eaff5a0693 refac 2026-11-02 00:15:19 +09:00
Timothy Jaeryang Baek b1d89f73b7 refac 2026-11-02 00:02:13 +09:00
Timothy Jaeryang Baek 1c894e0e8a refac 2026-11-01 23:55:04 +09:00
Timothy Jaeryang Baek 13afaba925 refac 2026-11-01 23:44:20 +09:00
Timothy Jaeryang Baek 9a9117fee0 refac 2026-11-01 23:25:26 +09:00
Timothy Jaeryang Baek f3836da92c refac 2026-11-01 23:24:10 +09:00
Timothy Jaeryang Baek bda6209717 refac 2026-11-01 23:10:42 +09:00
Timothy Jaeryang Baek a8def225a9 refac 2026-11-01 22:30:47 +09:00
Timothy Jaeryang Baek 238784880a refac 2026-11-01 22:15:46 +09:00
Timothy Jaeryang Baek 7d81297299 refac 2026-11-01 22:12:36 +09:00
Timothy Jaeryang Baek 3df29aa0fb refac 2026-10-31 06:05:33 +09:00
Timothy Jaeryang Baek a8ea18e391 refac 2026-10-31 05:58:40 +09:00
Timothy Jaeryang Baek 93fb121038 refac 2026-10-29 14:56:13 +09:00
Timothy Jaeryang Baek 431fc2bccf refac 2026-10-29 03:49:56 +09:00
Timothy Jaeryang Baek dde17e0f3c refac 2026-10-29 03:28:37 +09:00
Timothy Jaeryang Baek 3994f0939b refac 2026-10-25 12:39:40 +09:00
Timothy Jaeryang Baek 6f0b75076b refac 2026-10-24 05:14:56 +09:00
Timothy Jaeryang Baek cb09637663 refac 2026-10-24 05:03:54 +09:00
Timothy Jaeryang Baek 173fa520ef refac 2026-10-24 04:59:11 +09:00
Timothy Jaeryang Baek f369c2e51b refac 2026-10-24 04:59:06 +09:00
Timothy Jaeryang Baek 8b41136c69 refac 2026-10-24 04:32:33 +09:00
Timothy Jaeryang Baekandmazzz1y dd69911d84 refac
Co-Authored-By: mazzz1y <17034108+mazzz1y@users.noreply.github.com>
2026-10-24 04:10:31 +09:00
Timothy Jaeryang Baek 54491de05c refac 2026-10-24 04:00:02 +09:00
Timothy Jaeryang Baek 3b80fc69c3 refac 2026-10-19 04:02:44 +09:00
Timothy Jaeryang Baek 6852d4d663 refac 2026-10-19 04:00:34 +09:00
Timothy Jaeryang Baek f3d321fa4d refac 2026-10-19 03:49:20 +09:00
Timothy Jaeryang Baek 757b451cf3 refac 2026-10-19 03:42:59 +09:00
Timothy Jaeryang Baek d09d027e06 refac 2026-10-19 03:40:42 +09:00
Timothy Jaeryang Baek 01c1c4e283 refac 2026-10-19 03:40:01 +09:00
Timothy Jaeryang Baek a0ef1c0af8 refac 2026-10-19 03:38:17 +09:00
Timothy Jaeryang Baek f92cc22c04 refac 2026-10-19 03:33:37 +09:00
Timothy Jaeryang Baek 4240b4e934 refac 2026-10-19 03:32:20 +09:00
Timothy Jaeryang Baek 64a03197b7 refac 2026-10-16 14:25:49 +04:00
Timothy Jaeryang Baek b58442aa85 refac 2026-09-23 12:58:09 -04:00
Timothy Jaeryang Baek 2085cd819e refac 2026-09-13 23:02:37 -04:00
Timothy Jaeryang Baek e436b6a2b6 refac 2026-09-13 22:36:09 -04:00
Timothy Jaeryang Baek 72fb783bb9 refac 2026-09-08 20:37:16 -04:00
Timothy Jaeryang Baek 011022abb1 refac 2026-09-08 20:32:02 -04:00
Timothy Jaeryang Baek 6696428e36 refac 2026-09-06 17:36:00 -04:00
Timothy Jaeryang Baek 38d6a2b8b6 refac 2026-09-06 15:28:18 -04:00
Timothy Jaeryang Baek f0edc9ecc5 refac 2026-09-06 15:19:53 -04:00
Timothy Jaeryang Baek c0273cc39e refac 2026-08-27 19:28:22 -04:00
Timothy Jaeryang Baek c7530495a5 refac 2026-08-27 15:29:58 -04:00
Timothy Jaeryang Baek 3ea2648506 refac 2026-08-27 14:08:59 -04:00
Timothy Jaeryang Baek e0f2b69f1e refac 2026-08-25 16:42:10 -04:00
Timothy Jaeryang Baek d1f8c0e98d refac 2026-08-25 16:40:33 -04:00
Timothy Jaeryang Baek 1a71bfdd24 refac 2026-08-22 09:27:00 -04:00
Timothy Jaeryang Baek 0a82381f23 refac 2026-08-22 09:14:41 -04:00
Timothy Jaeryang Baek 11c1af09a2 refac 2026-08-22 09:11:14 -04:00
Timothy Jaeryang Baek 9c9706d475 refac 2026-08-22 08:45:43 -04:00
Timothy Jaeryang Baek 6728495e15 refac 2026-08-22 08:44:02 -04:00
Timothy Jaeryang Baek 1aaa9fa98c refac 2026-08-22 08:33:44 -04:00
Timothy Jaeryang Baek c6c2b82741 refac 2026-08-10 01:03:19 -06:00
Timothy Jaeryang Baek 690c5681c9 refac 2026-08-08 19:35:47 -06:00
Timothy Jaeryang Baek 98bd1a5fd1 refac 2026-06-23 00:08:59 +02:00
Timothy Jaeryang Baek 68f0fa1cf5 refac 2026-06-22 17:02:02 +02:00
Timothy Jaeryang Baek 811d4abc18 refac 2026-06-22 16:56:50 +02:00
Timothy Jaeryang Baek c4f47b2776 refac 2026-06-22 16:18:04 +02:00
Timothy Jaeryang Baek 0085ec7d1f refac 2026-06-22 15:57:42 +02:00
Tim Baek 2982fe94ae Merge pull request #106 from huss-mo/fix/mcp-server-auth
fix: pass API key as Bearer token in MCP server httpx client
2026-04-16 18:23:10 -07:00
Timothy Jaeryang Baek 9162e808c3 feat: add /files/serve/{path} endpoint for iframe relative URL resolution 2026-04-08 14:49:49 -07:00
Timothy Jaeryang Baek f74428ffb8 refac 2026-04-08 13:07:45 -07:00
Timothy Jaeryang Baek 8c154351df fix: default grep_search to regex mode
Closes #101
2026-04-08 13:03:47 -07:00
Timothy Jaeryang Baek 8a491e8b90 refac 2026-04-02 01:53:33 -05:00
Timothy Jaeryang BaekandDenny Pradipta 48d0ab4fe6 enh: OPEN_TERMINAL_NPM_PACKAGES
Co-Authored-By: Denny Pradipta <dennypradiptaprojects@gmail.com>
2026-03-30 19:56:58 -05:00
Tim Baek 1bc3aab492 Merge pull request #98 from EntropyYue/fix/terminals
fix: GET terminals return null
2026-03-31 04:53:15 +04:00
Timothy Jaeryang Baek 96d8134e1e feat: resolve relative paths against session cwd in all file endpoints
All LLM-exposed file endpoints (list_files, read_file, write_file,
display_file, replace_file_content, grep_search, glob_search) now
read the X-Session-Id header and resolve relative paths against the
session's working directory instead of always using fs.home.

- Added optional cwd parameter to UserFS.resolve_path()
- Relative paths join against cwd if provided, else fs.home
- Absolute paths are unaffected
- execute endpoint also resolves relative cwd param against session cwd
2026-03-29 21:34:44 -05:00
Timothy Jaeryang Baek 4db47e8cee feat: resolve relative paths against session cwd in all file endpoints
All LLM-exposed file endpoints (list_files, read_file, write_file,
display_file, replace_file_content, grep_search, glob_search) now
read the X-Session-Id header and resolve relative paths against the
session's working directory instead of always using fs.home.

- Added optional cwd parameter to UserFS.resolve_path()
- Relative paths join against cwd if provided, else fs.home
- Absolute paths are unaffected
- execute endpoint also resolves relative cwd param against session cwd
2026-03-29 21:22:28 -05:00
Timothy Jaeryang Baek fbaf2e8e69 feat: per-session working directory tracking via X-Session-Id header
Replace the process-global os.chdir() with an in-memory dictionary
keyed by session ID (passed via X-Session-Id header). Multiple
concurrent chat sessions now maintain independent working directories.

- GET/POST /files/cwd read X-Session-Id to resolve per-session cwd
- POST /execute falls back to session cwd when no cwd param provided
- POST /api/terminals spawns PTY in the session's cwd
- 7-day sliding TTL for session entries
- Fully backward compatible: no header = fs.home default
2026-03-29 20:59:47 -05:00
Timothy Jaeryang Baek 004ee891e6 security: harden API key handling and add startup warnings
- Increase auto-generated API key entropy from 192-bit to 384-bit
- Use hmac.compare_digest() for constant-time key comparison (HTTP + WS)
- Refuse to start without OPEN_TERMINAL_API_KEY configured
- Add prominent CORS wildcard warning at startup
- Bump version to 0.11.30
2026-03-25 17:15:15 -05:00
Timothy Jaeryang Baek 952c3f1314 fix: set group-write permission on files after chown in multi-user mode
_chown() transferred file ownership to the provisioned user but didn't
set group-write permission, leaving files at 644. The server process
(a group member) could create new files but couldn't overwrite them on
subsequent saves, returning PermissionError. Now sets chmod g+w after
chown, matching the 2770 treatment already applied to directories.

Fixes #93
2026-03-24 16:53:28 -05:00
Timothy Jaeryang Baek b18c15123b feat: ZIP archive download endpoint (POST /files/archive)
Add a single POST /files/archive endpoint that bundles one or more
files and directories into a ZIP archive for download.

- Accepts a list of paths (files and/or directories)
- Directories are recursively included with relative paths preserved
- Multi-user access control enforced via UserFS
- Cross-platform ZIP format (Windows, macOS, Linux)
- Archive name derived from input (single item = item name, multiple = download.zip)

Closes #92
2026-03-24 05:38:30 -05:00
Timothy Jaeryang Baek 61f50c842c refac 2026-03-23 19:43:45 -05:00
Timothy Jaeryang Baek 2c2459e876 refac 2026-03-23 19:39:15 -05:00
Timothy Jaeryang Baek d5c9fc48e7 feat: add GET /system endpoint for LLM system prompt injection
- GET /system returns a structured system prompt grounding the LLM in
  the environment (OS, hostname, user, shell, Python version) with
  directives for tool usage
- Gated by OPEN_TERMINAL_ENABLE_SYSTEM_PROMPT env var (default: true)
- Advertised via features.system in GET /api/config for consumer discovery
- OPEN_TERMINAL_SYSTEM_PROMPT env var for full prompt override
- Endpoint excluded from OpenAPI schema, auth-protected
2026-03-22 22:11:08 -05:00
Timothy Jaeryang Baek a5e44c44a7 refactor: extract document parsers into utils/documents.py
Moved all document text extraction logic from read_file() into a
dedicated utils/documents.py module with an EXTRACTORS registry.
The read_file endpoint now iterates the registry in a 15-line loop
instead of inlining ~330 lines of per-format parsing.

Adding a new format requires only a single extract_* function and
a one-line registry entry. No behaviour changes.
2026-03-20 17:23:59 -05:00
Timothy Jaeryang Baek cf3bb5c809 feat: add .rtf, .xls, .odt, .ods, .odp, .epub, .eml text extraction in read_file
Extended document text extraction to seven more formats:

- .rtf: strips formatting to plain text (striprtf, BSD)
- .xls: legacy Excel, renders sheets as tab-separated values (xlrd, BSD)
- .odt: OpenDocument text, extracts paragraphs (stdlib + lxml, BSD)
- .ods: OpenDocument spreadsheet, extracts all sheets (stdlib + lxml, BSD)
- .odp: OpenDocument presentation, extracts slide text (stdlib + lxml, BSD)
- .epub: extracts body text in spine reading order (stdlib + lxml, BSD)
- .eml: extracts headers and body with HTML stripping (stdlib + lxml, BSD)

All support start_line/end_line range selection.
2026-03-20 17:19:17 -05:00
Timothy Jaeryang Baek 2f786fcd92 feat: add .docx, .xlsx, .pptx text extraction in read_file
Office documents are now automatically converted to text and returned
in the standard JSON format, making them readable by LLMs.

- .docx: extracts paragraphs and table contents (python-docx, MIT)
- .xlsx: renders all sheets as tab-separated values (openpyxl, MIT)
- .pptx: extracts text from all slides (python-pptx, MIT)

Supports start_line/end_line range selection, consistent with the
existing PDF handler.
2026-03-20 17:13:10 -05:00
Timothy Jaeryang Baek 7738e7032a fix: enforce env/_FILE mutual exclusivity for empty values
The _FILE mutual-exclusivity guard silently passed when the plain env
var was set to an empty string, because empty strings are falsy.

Python: changed `if value and file_path` to
`if value is not None and file_path is not None`, and the fallback
return from `value or default` to
`value if value is not None else default`.

entrypoint.sh: changed ${!var:-} to ${!var+set} to test whether the
variable is defined at all, not just non-empty.

entrypoint-slim.sh: changed -n tests to ${var+set} via eval, matching
the bash entrypoint semantics.
2026-03-19 17:53:56 -05:00
Timothy Jaeryang Baek 40e1225d53 fix: /ports returns 500 in multi-user mode on restricted runtimes (#80)
list_ports triggered full user provisioning (useradd) just to filter
ports by UID. On runtimes that reject useradd (e.g. Azure Container
Apps), this crashed with an unhandled CalledProcessError.

Now catches provisioning failures and returns an empty port list —
an unprovisioned user has no listening ports to show.
2026-03-19 17:51:24 -05:00
Timothy Jaeryang Baek 2da589100c fix: port detection broken since v0.11.2 (#85, #63)
setcap cap_setgid+ep on the system Python binary made all Python
processes non-dumpable, blocking /proc/[pid]/fd/ access needed by
_pid_from_inode() to resolve socket inodes to PIDs.

Fix: copy the Python binary to python3-ot and setcap only the copy.
The open-terminal server uses python3-ot (has CAP_SETGID for
multi-user os.setgroups()), while user-spawned python3 stays
capability-free and dumpable.

Slim/Alpine: removed setcap entirely (multi-user mode requires sudo,
which only the full image has). Kept libcap packages installed.

README: corrected Image Variants table — multi-user mode is
full-image only.
2026-03-19 17:42:17 -05:00