Current section

Files

Jump to
codex_sdk examples live_app_server_filesystem.exs
Raw

examples/live_app_server_filesystem.exs

Mix.Task.run("app.start")
Code.require_file(Path.expand("support/example_helper.exs", __DIR__))
alias CodexExamples.Support
Support.init!()
defmodule CodexExamples.LiveAppServerFilesystem do
@moduledoc false
@demo_contents "hello from codex_sdk app-server filesystem\n"
def main(_argv) do
case run() do
:ok ->
:ok
{:skip, reason} ->
IO.puts("SKIPPED: #{reason}")
{:error, reason} ->
Mix.raise("Filesystem example failed: #{inspect(reason)}")
end
end
defp run do
with {:ok, codex_opts} <- Support.codex_options(%{}, missing_cli: :skip),
:ok <- Support.ensure_auth_available(),
:ok <- Support.ensure_app_server_supported(codex_opts),
{:ok, conn} <- Codex.AppServer.connect(codex_opts, init_timeout_ms: 30_000) do
root =
Path.join(
System.tmp_dir!(),
"codex_sdk_app_server_fs_#{System.unique_integer([:positive])}"
)
nested = Path.join(root, "nested")
file_path = Path.join(nested, "demo.txt")
copy_path = Path.join(root, "demo-copy.txt")
encoded = Base.encode64(@demo_contents)
try do
with {:ok, %{}} <-
request_or_skip(
Codex.AppServer.fs_create_directory(conn, nested, recursive: true),
"fs/* filesystem"
),
{:ok, %{}} <-
request_or_skip(
Codex.AppServer.fs_write_file(conn, file_path, encoded),
"fs/* filesystem"
),
{:ok, %{"dataBase64" => read_back}} <-
request_or_skip(Codex.AppServer.fs_read_file(conn, file_path), "fs/* filesystem"),
{:ok, %{"entries" => entries}} <-
request_or_skip(
Codex.AppServer.fs_read_directory(conn, root),
"fs/* filesystem"
),
{:ok, metadata} <-
request_or_skip(
Codex.AppServer.fs_get_metadata(conn, file_path),
"fs/* filesystem"
),
{:ok, %{}} <-
request_or_skip(
Codex.AppServer.fs_copy(conn, file_path, copy_path, recursive: false),
"fs/* filesystem"
),
{:ok, %{"dataBase64" => copied_back}} <-
request_or_skip(Codex.AppServer.fs_read_file(conn, copy_path), "fs/* filesystem"),
{:ok, %{}} <-
request_or_skip(
Codex.AppServer.fs_remove(conn, copy_path, force: true),
"fs/* filesystem"
) do
decoded = Base.decode64!(read_back)
copied = Base.decode64!(copied_back)
IO.puts("""
App-server filesystem demo completed.
root: #{root}
file: #{file_path}
copy: #{copy_path}
""")
IO.puts("Decoded file contents:")
IO.puts(decoded)
IO.puts("Directory entries:")
entries
|> Enum.sort_by(&Map.get(&1, "fileName", ""))
|> Enum.each(fn entry ->
IO.puts(
" - #{entry["fileName"]} (dir=#{inspect(entry["isDirectory"])}, file=#{inspect(entry["isFile"])})"
)
end)
IO.puts("""
Metadata:
isDirectory: #{inspect(metadata["isDirectory"])}
isFile: #{inspect(metadata["isFile"])}
createdAtMs: #{inspect(metadata["createdAtMs"])}
modifiedAtMs: #{inspect(metadata["modifiedAtMs"])}
copied_contents_match?: #{decoded == copied}
""")
:ok
end
after
_ = Codex.AppServer.fs_remove(conn, root, recursive: true, force: true)
:ok = Codex.AppServer.disconnect(conn)
end
end
end
defp request_or_skip({:ok, result}, _feature), do: {:ok, result}
defp request_or_skip({:error, %{"code" => code, "message" => message}}, feature)
when code in [-32_601, -32_600, -32601, -32600] do
{:skip, "#{feature} APIs are not supported by this `codex app-server` build: #{message}"}
end
defp request_or_skip({:error, reason}, _feature), do: {:error, reason}
end
CodexExamples.LiveAppServerFilesystem.main(System.argv())