Full Code of plandex-ai/plandex for AI

main e2d772072efa cached
656 files
3.0 MB
828.2k tokens
2489 symbols
1 requests
Download .txt
Showing preview only (3,297K chars total). Download the full file or copy to clipboard to get everything.
Repository: plandex-ai/plandex
Branch: main
Commit: e2d772072efa
Files: 656
Total size: 3.0 MB

Directory structure:
gitextract_skjdl2ff/

├── .dockerignore
├── .gitattributes
├── .github/
│   └── workflows/
│       └── docker-publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── app/
│   ├── .dockerignore
│   ├── .gitignore
│   ├── clear_local.sh
│   ├── cli/
│   │   ├── api/
│   │   │   ├── clients.go
│   │   │   ├── errors.go
│   │   │   ├── methods.go
│   │   │   └── stream.go
│   │   ├── auth/
│   │   │   ├── account.go
│   │   │   ├── api.go
│   │   │   ├── auth.go
│   │   │   ├── org.go
│   │   │   ├── state.go
│   │   │   └── trial.go
│   │   ├── cmd/
│   │   │   ├── apply.go
│   │   │   ├── archive.go
│   │   │   ├── billing.go
│   │   │   ├── branches.go
│   │   │   ├── browser.go
│   │   │   ├── build.go
│   │   │   ├── cd.go
│   │   │   ├── chat.go
│   │   │   ├── checkout.go
│   │   │   ├── claude_max.go
│   │   │   ├── clear.go
│   │   │   ├── config.go
│   │   │   ├── connect.go
│   │   │   ├── context_show.go
│   │   │   ├── continue.go
│   │   │   ├── convo.go
│   │   │   ├── current.go
│   │   │   ├── debug.go
│   │   │   ├── delete_branch.go
│   │   │   ├── delete_plan.go
│   │   │   ├── diffs.go
│   │   │   ├── invite.go
│   │   │   ├── load.go
│   │   │   ├── log.go
│   │   │   ├── ls.go
│   │   │   ├── model_helpers.go
│   │   │   ├── model_packs.go
│   │   │   ├── model_providers.go
│   │   │   ├── models.go
│   │   │   ├── new.go
│   │   │   ├── plan_exec_helpers.go
│   │   │   ├── plan_start_helpers.go
│   │   │   ├── plans.go
│   │   │   ├── ps.go
│   │   │   ├── reject.go
│   │   │   ├── rename.go
│   │   │   ├── repl.go
│   │   │   ├── revoke.go
│   │   │   ├── rewind.go
│   │   │   ├── rm.go
│   │   │   ├── root.go
│   │   │   ├── set_config.go
│   │   │   ├── set_model.go
│   │   │   ├── sign_in.go
│   │   │   ├── stop.go
│   │   │   ├── summary.go
│   │   │   ├── tell.go
│   │   │   ├── unarchive.go
│   │   │   ├── update.go
│   │   │   ├── usage.go
│   │   │   ├── users.go
│   │   │   └── version.go
│   │   ├── dev.sh
│   │   ├── format/
│   │   │   ├── file.go
│   │   │   └── time.go
│   │   ├── fs/
│   │   │   ├── fs.go
│   │   │   ├── paths.go
│   │   │   ├── projects.go
│   │   │   └── utils.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── install.sh
│   │   ├── lib/
│   │   │   ├── active_stream.go
│   │   │   ├── apply.go
│   │   │   ├── apply_cgroup_linux.go
│   │   │   ├── apply_cgroup_other.go
│   │   │   ├── apply_proc.go
│   │   │   ├── build.go
│   │   │   ├── claude_max.go
│   │   │   ├── context_auto_load.go
│   │   │   ├── context_conflict.go
│   │   │   ├── context_display.go
│   │   │   ├── context_load.go
│   │   │   ├── context_paths.go
│   │   │   ├── context_shared.go
│   │   │   ├── context_update.go
│   │   │   ├── current.go
│   │   │   ├── custom_models.go
│   │   │   ├── editor.go
│   │   │   ├── git.go
│   │   │   ├── legacy_files.go
│   │   │   ├── log_format.go
│   │   │   ├── model_credentials.go
│   │   │   ├── model_settings.go
│   │   │   ├── models_sync.go
│   │   │   ├── org_user_config.go
│   │   │   ├── plan_config.go
│   │   │   ├── plans.go
│   │   │   ├── repl.go
│   │   │   └── rewind.go
│   │   ├── main.go
│   │   ├── nodemon.json
│   │   ├── plan.json
│   │   ├── plan_exec/
│   │   │   ├── action_menu.go
│   │   │   ├── apply_exec.go
│   │   │   ├── build.go
│   │   │   ├── params.go
│   │   │   └── tell.go
│   │   ├── schema/
│   │   │   ├── json-schemas/
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── auto-modes.schema.json
│   │   │   │   │   ├── local-providers.schema.json
│   │   │   │   │   └── model-providers.schema.json
│   │   │   │   ├── model-config.schema.json
│   │   │   │   ├── model-pack-base-config.schema.json
│   │   │   │   ├── model-pack-config.schema.json
│   │   │   │   ├── model-pack-inline.schema.json
│   │   │   │   ├── model-pack-roles.schema.json
│   │   │   │   ├── model-provider-config.schema.json
│   │   │   │   ├── model-role-config.schema.json
│   │   │   │   ├── models-input.schema.json
│   │   │   │   └── plan-config.schema.json
│   │   │   └── schemas.go
│   │   ├── stream/
│   │   │   └── stream.go
│   │   ├── stream_tui/
│   │   │   ├── debouncer.go
│   │   │   ├── model.go
│   │   │   ├── run.go
│   │   │   ├── update.go
│   │   │   └── view.go
│   │   ├── term/
│   │   │   ├── color.go
│   │   │   ├── errors.go
│   │   │   ├── format.go
│   │   │   ├── help.go
│   │   │   ├── os.go
│   │   │   ├── prompt.go
│   │   │   ├── repl.go
│   │   │   ├── select.go
│   │   │   ├── spinner.go
│   │   │   └── utils.go
│   │   ├── types/
│   │   │   ├── api.go
│   │   │   ├── apply.go
│   │   │   ├── exec.go
│   │   │   ├── fs.go
│   │   │   └── types.go
│   │   ├── ui/
│   │   │   └── ui.go
│   │   ├── upgrade.go
│   │   ├── url/
│   │   │   └── url.go
│   │   ├── utils/
│   │   │   └── utils.go
│   │   ├── version/
│   │   │   └── version.go
│   │   └── version.txt
│   ├── docker-compose.yml
│   ├── plans/
│   │   ├── credits-cmd.txt
│   │   ├── credits-log-cmd.txt
│   │   ├── json-prompts-to-xml.md
│   │   └── plan-config.md
│   ├── reset_local.sh
│   ├── scripts/
│   │   ├── cmd/
│   │   │   ├── gen/
│   │   │   │   └── gen.go
│   │   │   └── provider/
│   │   │       └── gen_provider.go
│   │   ├── dev.sh
│   │   ├── litellm_deps.sh
│   │   └── wait-for-it.sh
│   ├── server/
│   │   ├── .gitignore
│   │   ├── Dockerfile
│   │   ├── db/
│   │   │   ├── account_helpers.go
│   │   │   ├── ai_model_helpers.go
│   │   │   ├── auth_helpers.go
│   │   │   ├── branch_helpers.go
│   │   │   ├── build_helpers.go
│   │   │   ├── context_helpers_conflicts.go
│   │   │   ├── context_helpers_get.go
│   │   │   ├── context_helpers_load.go
│   │   │   ├── context_helpers_map.go
│   │   │   ├── context_helpers_remove.go
│   │   │   ├── context_helpers_store.go
│   │   │   ├── context_helpers_update.go
│   │   │   ├── convo_helpers.go
│   │   │   ├── data_models.go
│   │   │   ├── db.go
│   │   │   ├── diff_helpers.go
│   │   │   ├── fs.go
│   │   │   ├── git.go
│   │   │   ├── invite_helpers.go
│   │   │   ├── locks.go
│   │   │   ├── models.go
│   │   │   ├── org_helpers.go
│   │   │   ├── plan_config_helpers.go
│   │   │   ├── plan_helpers.go
│   │   │   ├── project_helpers.go
│   │   │   ├── queue.go
│   │   │   ├── rbac_helpers.go
│   │   │   ├── result_helpers.go
│   │   │   ├── settings_helpers.go
│   │   │   ├── stream_helpers.go
│   │   │   ├── subtask_helpers.go
│   │   │   ├── summary_helpers.go
│   │   │   ├── transactions.go
│   │   │   ├── user_helpers.go
│   │   │   └── utils.go
│   │   ├── diff/
│   │   │   └── diff.go
│   │   ├── email/
│   │   │   ├── email.go
│   │   │   ├── invite.go
│   │   │   └── verification.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── handlers/
│   │   │   ├── accounts.go
│   │   │   ├── auth_helpers.go
│   │   │   ├── branches.go
│   │   │   ├── client_helper.go
│   │   │   ├── context_helper.go
│   │   │   ├── err_helper.go
│   │   │   ├── file_maps.go
│   │   │   ├── file_maps_queue.go
│   │   │   ├── invites.go
│   │   │   ├── models.go
│   │   │   ├── org_helpers.go
│   │   │   ├── orgs.go
│   │   │   ├── plan_config.go
│   │   │   ├── plans_changes.go
│   │   │   ├── plans_context.go
│   │   │   ├── plans_convo.go
│   │   │   ├── plans_crud.go
│   │   │   ├── plans_exec.go
│   │   │   ├── plans_versions.go
│   │   │   ├── projects.go
│   │   │   ├── proxy_helper.go
│   │   │   ├── sessions.go
│   │   │   ├── settings.go
│   │   │   ├── stream_helper.go
│   │   │   └── users.go
│   │   ├── hooks/
│   │   │   └── hooks.go
│   │   ├── host/
│   │   │   └── ip.go
│   │   ├── litellm_proxy.py
│   │   ├── main.go
│   │   ├── migrations/
│   │   │   ├── 2023120500_init.down.sql
│   │   │   ├── 2023120500_init.up.sql
│   │   │   ├── 2024011700_rbac.down.sql
│   │   │   ├── 2024011700_rbac.up.sql
│   │   │   ├── 2024012400_streams.down.sql
│   │   │   ├── 2024012400_streams.up.sql
│   │   │   ├── 2024012500_locks.down.sql
│   │   │   ├── 2024012500_locks.up.sql
│   │   │   ├── 2024013000_plan_build_convo_ids.down.sql
│   │   │   ├── 2024013000_plan_build_convo_ids.up.sql
│   │   │   ├── 2024020800_heartbeats.down.sql
│   │   │   ├── 2024020800_heartbeats.up.sql
│   │   │   ├── 2024022000_revert_plan_build_convo_ids.down.sql
│   │   │   ├── 2024022000_revert_plan_build_convo_ids.up.sql
│   │   │   ├── 2024032700_remove_billing_admin.down.sql
│   │   │   ├── 2024032700_remove_billing_admin.up.sql
│   │   │   ├── 2024032701_drop_users_projects.down.sql
│   │   │   ├── 2024032701_drop_users_projects.up.sql
│   │   │   ├── 2024040400_add_orgs_users_unique.down.sql
│   │   │   ├── 2024040400_add_orgs_users_unique.up.sql
│   │   │   ├── 2024041500_model_sets_models.down.sql
│   │   │   ├── 2024041500_model_sets_models.up.sql
│   │   │   ├── 2024042600_default_plan_settings.down.sql
│   │   │   ├── 2024042600_default_plan_settings.up.sql
│   │   │   ├── 2024091800_sign_in_codes.down.sql
│   │   │   ├── 2024091800_sign_in_codes.up.sql
│   │   │   ├── 2024092100_remove_trial_fields.down.sql
│   │   │   ├── 2024092100_remove_trial_fields.up.sql
│   │   │   ├── 2024100900_update_locks.down.sql
│   │   │   ├── 2024100900_update_locks.up.sql
│   │   │   ├── 2024121400_plan_config.down.sql
│   │   │   ├── 2024121400_plan_config.up.sql
│   │   │   ├── 2025012600_update_custom_models.down.sql
│   │   │   ├── 2025012600_update_custom_models.up.sql
│   │   │   ├── 2025021101_locks_unique.down.sql
│   │   │   ├── 2025021101_locks_unique.up.sql
│   │   │   ├── 2025022700_remove_models_col.down.sql
│   │   │   ├── 2025022700_remove_models_col.up.sql
│   │   │   ├── 2025031300_add_model_roles.down.sql
│   │   │   ├── 2025031300_add_model_roles.up.sql
│   │   │   ├── 2025031900_add_custom_model_cols.down.sql
│   │   │   ├── 2025031900_add_custom_model_cols.up.sql
│   │   │   ├── 2025032400_sign_in_codes_on_delete.down.sql
│   │   │   ├── 2025032400_sign_in_codes_on_delete.up.sql
│   │   │   ├── 2025051600_custom_models_refactor.down.sql
│   │   │   ├── 2025051600_custom_models_refactor.up.sql
│   │   │   ├── 2025052200_model_pack_cols.down.sql
│   │   │   ├── 2025052200_model_pack_cols.up.sql
│   │   │   ├── 2025070200_add_org_user_config.down.sql
│   │   │   └── 2025070200_add_org_user_config.up.sql
│   │   ├── model/
│   │   │   ├── client.go
│   │   │   ├── client_stream.go
│   │   │   ├── litellm.go
│   │   │   ├── model_error.go
│   │   │   ├── model_request.go
│   │   │   ├── name.go
│   │   │   ├── parse/
│   │   │   │   ├── subtasks.go
│   │   │   │   └── subtasks_test.go
│   │   │   ├── plan/
│   │   │   │   ├── activate.go
│   │   │   │   ├── build_exec.go
│   │   │   │   ├── build_finish.go
│   │   │   │   ├── build_load.go
│   │   │   │   ├── build_race.go
│   │   │   │   ├── build_state.go
│   │   │   │   ├── build_structured_edits.go
│   │   │   │   ├── build_validate_and_fix.go
│   │   │   │   ├── build_whole_file.go
│   │   │   │   ├── commit_msg.go
│   │   │   │   ├── exec_status.go
│   │   │   │   ├── shutdown.go
│   │   │   │   ├── state.go
│   │   │   │   ├── stop.go
│   │   │   │   ├── tell_build_pending.go
│   │   │   │   ├── tell_context.go
│   │   │   │   ├── tell_exec.go
│   │   │   │   ├── tell_load.go
│   │   │   │   ├── tell_missing_file.go
│   │   │   │   ├── tell_prompt_message.go
│   │   │   │   ├── tell_stage.go
│   │   │   │   ├── tell_state.go
│   │   │   │   ├── tell_stream_error.go
│   │   │   │   ├── tell_stream_finish.go
│   │   │   │   ├── tell_stream_main.go
│   │   │   │   ├── tell_stream_processor.go
│   │   │   │   ├── tell_stream_processor_test.go
│   │   │   │   ├── tell_stream_status.go
│   │   │   │   ├── tell_stream_store.go
│   │   │   │   ├── tell_stream_usage.go
│   │   │   │   ├── tell_subtasks.go
│   │   │   │   ├── tell_summary.go
│   │   │   │   ├── tell_sys_prompt.go
│   │   │   │   └── utils.go
│   │   │   ├── prompts/
│   │   │   │   ├── apply_exec.go
│   │   │   │   ├── architect_context.go
│   │   │   │   ├── build_helpers.go
│   │   │   │   ├── build_validation_replacements.go
│   │   │   │   ├── build_whole_file.go
│   │   │   │   ├── chat.go
│   │   │   │   ├── code_block_langs.go
│   │   │   │   ├── describe.go
│   │   │   │   ├── exec_status.go
│   │   │   │   ├── explanation_format.go
│   │   │   │   ├── file_ops.go
│   │   │   │   ├── implement.go
│   │   │   │   ├── missing_file.go
│   │   │   │   ├── name.go
│   │   │   │   ├── planning.go
│   │   │   │   ├── shared.go
│   │   │   │   ├── summary.go
│   │   │   │   ├── update_format.go
│   │   │   │   └── user_prompt.go
│   │   │   ├── summarize.go
│   │   │   └── tokens.go
│   │   ├── notify/
│   │   │   └── errors.go
│   │   ├── routes/
│   │   │   └── routes.go
│   │   ├── setup/
│   │   │   └── setup.go
│   │   ├── shutdown/
│   │   │   └── shutdown.go
│   │   ├── syntax/
│   │   │   ├── comments.go
│   │   │   ├── file_map/
│   │   │   │   ├── cli/
│   │   │   │   │   ├── .gitignore
│   │   │   │   │   ├── go.mod
│   │   │   │   │   ├── go.sum
│   │   │   │   │   └── main.go
│   │   │   │   ├── examples/
│   │   │   │   │   ├── bash_example.sh
│   │   │   │   │   ├── c_example.c
│   │   │   │   │   ├── cpp_example.cpp
│   │   │   │   │   ├── csharp_example.cs
│   │   │   │   │   ├── css_example.css
│   │   │   │   │   ├── cue_example.cue
│   │   │   │   │   ├── dockerfile_example
│   │   │   │   │   ├── elixir_example.ex
│   │   │   │   │   ├── elm_example.elm
│   │   │   │   │   ├── go_example.go
│   │   │   │   │   ├── groovy_example.groovy
│   │   │   │   │   ├── hcl_example.hcl
│   │   │   │   │   ├── html_example.html
│   │   │   │   │   ├── java_example.java
│   │   │   │   │   ├── javascript_example.js
│   │   │   │   │   ├── kotlin_example.kt
│   │   │   │   │   ├── lua_example.lua
│   │   │   │   │   ├── markdown_example.md
│   │   │   │   │   ├── ocaml_example.ml
│   │   │   │   │   ├── php_example.php
│   │   │   │   │   ├── protobuf_example.proto
│   │   │   │   │   ├── python_example.py
│   │   │   │   │   ├── ruby_example.rb
│   │   │   │   │   ├── rust_example.rs
│   │   │   │   │   ├── scala_example.scala
│   │   │   │   │   ├── svelte_example.svelte
│   │   │   │   │   ├── swift_example.swift
│   │   │   │   │   ├── toml_example.toml
│   │   │   │   │   ├── tsx_example.tsx
│   │   │   │   │   ├── typescript_example.ts
│   │   │   │   │   └── yaml_example.yaml
│   │   │   │   ├── map.go
│   │   │   │   ├── markup.go
│   │   │   │   ├── multi.go
│   │   │   │   ├── nodes_config.go
│   │   │   │   ├── nodes_find.go
│   │   │   │   └── svelte.go
│   │   │   ├── map.txt
│   │   │   ├── parsers.go
│   │   │   ├── structured_edits_apply.go
│   │   │   ├── structured_edits_generic.go
│   │   │   ├── structured_edits_sections.go
│   │   │   ├── structured_edits_test.go
│   │   │   ├── structured_edits_tree_sitter.go
│   │   │   ├── unique_replacement.go
│   │   │   ├── unique_replacement_test.go
│   │   │   └── validate.go
│   │   ├── types/
│   │   │   ├── active_plan.go
│   │   │   ├── active_plan_pending_builds.go
│   │   │   ├── auth.go
│   │   │   ├── convo_message_desc.go
│   │   │   ├── exec_status.go
│   │   │   ├── message.go
│   │   │   ├── model.go
│   │   │   ├── reply.go
│   │   │   ├── reply_test.go
│   │   │   ├── reply_test_examples/
│   │   │   │   ├── 1.md
│   │   │   │   ├── 10.md
│   │   │   │   ├── 2.md
│   │   │   │   ├── 3.md
│   │   │   │   ├── 4.md
│   │   │   │   ├── 5.md
│   │   │   │   ├── 6.md
│   │   │   │   ├── 7.md
│   │   │   │   ├── 8.md
│   │   │   │   └── 9.md
│   │   │   ├── safe_map.go
│   │   │   └── trial.go
│   │   ├── utils/
│   │   │   ├── whitespace.go
│   │   │   ├── whitespace_test.go
│   │   │   └── xml.go
│   │   └── version.txt
│   ├── shared/
│   │   ├── ai_models_available.go
│   │   ├── ai_models_compatibility.go
│   │   ├── ai_models_config.go
│   │   ├── ai_models_credentials.go
│   │   ├── ai_models_custom.go
│   │   ├── ai_models_data_models.go
│   │   ├── ai_models_errors.go
│   │   ├── ai_models_large_context.go
│   │   ├── ai_models_openrouter.go
│   │   ├── ai_models_packs.go
│   │   ├── ai_models_providers.go
│   │   ├── ai_models_roles.go
│   │   ├── auth.go
│   │   ├── context.go
│   │   ├── convo_message.go
│   │   ├── data_models.go
│   │   ├── email.go
│   │   ├── file_maps.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── images.go
│   │   ├── org_user_config.go
│   │   ├── plan_config.go
│   │   ├── plan_model_settings.go
│   │   ├── plan_result.go
│   │   ├── plan_result_exec_history.go
│   │   ├── plan_result_pending_summary.go
│   │   ├── plan_result_replacements.go
│   │   ├── plan_status.go
│   │   ├── rbac.go
│   │   ├── req_res.go
│   │   ├── stream.go
│   │   ├── streamed_change.go
│   │   ├── syntax.go
│   │   ├── tokens.go
│   │   ├── tygo.yaml
│   │   ├── utils.go
│   │   └── utils_struct.go
│   └── start_local.sh
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── babel.config.js
│   ├── blog/
│   │   ├── 2019-05-28-first-blog-post.md
│   │   ├── 2019-05-29-long-blog-post.md
│   │   ├── 2021-08-01-mdx-blog-post.mdx
│   │   ├── 2021-08-26-welcome/
│   │   │   └── index.md
│   │   ├── authors.yml
│   │   └── tags.yml
│   ├── docs/
│   │   ├── cli-reference.md
│   │   ├── core-concepts/
│   │   │   ├── _category_.json
│   │   │   ├── autonomy.md
│   │   │   ├── background-tasks.md
│   │   │   ├── branches.md
│   │   │   ├── configuration.md
│   │   │   ├── context-management.md
│   │   │   ├── conversations.md
│   │   │   ├── execution-and-debugging.md
│   │   │   ├── orgs.md
│   │   │   ├── plans.md
│   │   │   ├── prompts.md
│   │   │   ├── reviewing-changes.md
│   │   │   └── version-control.md
│   │   ├── development.md
│   │   ├── environment-variables.md
│   │   ├── hosting/
│   │   │   ├── _category_.json
│   │   │   ├── cloud.md
│   │   │   └── self-hosting/
│   │   │       ├── _category_.json
│   │   │       ├── advanced-self-hosting.md
│   │   │       └── local-mode-quickstart.md
│   │   ├── install.md
│   │   ├── models/
│   │   │   ├── _category_.json
│   │   │   ├── built-in/
│   │   │   │   ├── _category_.json
│   │   │   │   ├── built-in-models.md
│   │   │   │   └── built-in-packs.md
│   │   │   ├── claude-subscription.md
│   │   │   ├── custom-models.md
│   │   │   ├── model-providers.md
│   │   │   ├── model-settings.md
│   │   │   ├── models-overview.md
│   │   │   ├── ollama.md
│   │   │   └── roles.md
│   │   ├── quick-start.md
│   │   ├── repl.md
│   │   └── security.md
│   ├── docusaurus.config.ts
│   ├── package.json
│   ├── sidebars.ts
│   ├── src/
│   │   └── css/
│   │       └── custom.css
│   ├── static/
│   │   ├── .nojekyll
│   │   └── _redirects
│   └── tsconfig.json
├── plans/
│   ├── invite-commands.txt
│   ├── model-sets-custom-models-crud.txt
│   ├── pdx-file.md
│   └── race_cond_chatgpt.txt
├── releases/
│   ├── cli/
│   │   ├── CHANGELOG.md
│   │   └── versions/
│   │       ├── 0.7.1.md
│   │       ├── 0.7.2.md
│   │       ├── 0.7.3.md
│   │       ├── 0.8.0.md
│   │       ├── 0.8.1.md
│   │       ├── 0.8.2.md
│   │       ├── 0.8.3.md
│   │       ├── 0.9.0.md
│   │       ├── 0.9.1.md
│   │       ├── 1.0.0.md
│   │       ├── 1.1.0.md
│   │       ├── 1.1.1.md
│   │       ├── 1.1.2.md
│   │       ├── 2.0.0.md
│   │       ├── 2.0.1.md
│   │       ├── 2.0.2.md
│   │       ├── 2.0.3.md
│   │       ├── 2.0.4.md
│   │       ├── 2.0.5.md
│   │       ├── 2.0.6.md
│   │       ├── 2.0.7+1.md
│   │       ├── 2.0.7.md
│   │       ├── 2.0.8.md
│   │       ├── 2.1.0+1.md
│   │       ├── 2.1.0.md
│   │       ├── 2.1.1.md
│   │       ├── 2.1.2.md
│   │       ├── 2.1.3.md
│   │       ├── 2.1.5.md
│   │       ├── 2.1.6+1.md
│   │       ├── 2.1.6.md
│   │       ├── 2.2.0.md
│   │       └── 2.2.1.md
│   └── server/
│       ├── CHANGELOG.md
│       └── versions/
│           ├── 0.7.0.md
│           ├── 0.7.1.md
│           ├── 0.8.0.md
│           ├── 0.8.1.md
│           ├── 0.8.2.md
│           ├── 0.8.3.md
│           ├── 0.8.4.md
│           ├── 0.9.0.md
│           ├── 0.9.1.md
│           ├── 1.0.0.md
│           ├── 1.0.1.md
│           ├── 1.1.0.md
│           ├── 1.1.1.md
│           ├── 2.0.0+1.md
│           ├── 2.0.0+2.md
│           ├── 2.0.0.md
│           ├── 2.0.2.md
│           ├── 2.0.3.md
│           ├── 2.0.4.md
│           ├── 2.0.5.md
│           ├── 2.0.6.md
│           ├── 2.1.0+1.md
│           ├── 2.1.0.md
│           ├── 2.1.1+1.md
│           ├── 2.1.1.md
│           ├── 2.1.2.md
│           ├── 2.1.3.md
│           ├── 2.1.4.md
│           ├── 2.1.5.md
│           ├── 2.1.6+1.md
│           ├── 2.1.6.md
│           ├── 2.1.7.md
│           ├── 2.1.8.md
│           ├── 2.2.0.md
│           └── 2.2.1.md
├── scripts/
│   └── merge_from_reflog.sh
└── test/
    ├── _test_apply.sh
    ├── error-test.html
    ├── evals/
    │   └── promptfoo-poc/
    │       ├── README.md
    │       ├── build/
    │       │   ├── assets/
    │       │   │   ├── build/
    │       │   │   │   ├── changes.md
    │       │   │   │   └── post_build.go
    │       │   │   └── shared/
    │       │   │       └── pre_build.go
    │       │   ├── build.config.properties
    │       │   ├── build.parameters.json
    │       │   ├── build.prompt.txt
    │       │   ├── build.provider.yml
    │       │   ├── promptfooconfig.yaml
    │       │   └── tests/
    │       │       └── build.test.yml
    │       ├── evals.md
    │       ├── fix/
    │       │   ├── assets/
    │       │   │   ├── removal/
    │       │   │   │   ├── changes.md
    │       │   │   │   ├── post_build.go
    │       │   │   │   └── problems.txt
    │       │   │   └── shared/
    │       │   │       └── pre_build.go
    │       │   ├── fix.config.properties
    │       │   ├── fix.parameters.json
    │       │   ├── fix.prompt.txt
    │       │   ├── fix.provider.yml
    │       │   ├── promptfooconfig.yaml
    │       │   └── tests/
    │       │       └── fix.test.yml
    │       ├── templates/
    │       │   └── provider.template.yml
    │       └── verify/
    │           ├── assets/
    │           │   ├── removal/
    │           │   │   ├── changes.md
    │           │   │   ├── diff.txt
    │           │   │   └── post_build.go
    │           │   ├── shared/
    │           │   │   └── pre_build.go
    │           │   └── valid/
    │           │       ├── changes.md
    │           │       ├── diff.txt
    │           │       └── post_build.go
    │           ├── promptfooconfig.yaml
    │           ├── tests/
    │           │   ├── removal.test.yml
    │           │   └── validate.test.yml
    │           ├── verify.config.properties
    │           ├── verify.parameters.json
    │           ├── verify.prompt.txt
    │           └── verify.provider.yml
    ├── plan_deletion_test.sh
    ├── project/
    │   └── react-redux-foobar/
    │       ├── action.ts
    │       ├── component.ts
    │       ├── lib/
    │       │   ├── constants.ts
    │       │   └── utils.ts
    │       ├── package.json
    │       ├── reducer.ts
    │       ├── tests/
    │       │   ├── action.test.ts
    │       │   └── component.test.ts
    │       └── tsconfig.json
    ├── smoke_test.sh
    ├── test_custom_models.sh
    ├── test_prompts/
    │   ├── aws-infra.txt
    │   ├── pong.txt
    │   ├── robust-logging.txt
    │   ├── stripe-plan.txt
    │   └── tic-tac-toe.txt
    └── test_utils.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
dist-server/
cli/
node_modules/
plandex-server
plandex-cloud


================================================
FILE: .gitattributes
================================================
*.sh		text eol=lf

================================================
FILE: .github/workflows/docker-publish.yml
================================================
name: Build and publish Docker Image

on:
  release:
    types: [created]
  workflow_dispatch: # enable manual triggering

jobs:
  check_release:
    runs-on: ubuntu-latest
    outputs:
      should_build: ${{ steps.check_release.outputs.should_build }}
      tag: ${{ steps.check_release.outputs.tag }}
    
    steps:
      - name: Check release tag and find latest server tag
        id: check_release
        run: |
          if [ "${{ github.event_name }}" == "release" ]; then
            # This is a release event - check if the tag starts with 'server'
            if [[ "${{ github.ref_name }}" == server* ]]; then
              echo "This is a server release: ${{ github.ref_name }}"
              echo "should_build=true" >> $GITHUB_OUTPUT
              echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
            else
              echo "This is not a server release. Skipping build."
              echo "should_build=false" >> $GITHUB_OUTPUT
            fi
          else
            # This is a manual workflow_dispatch event
            echo "This is a manual workflow trigger. Proceeding to find latest server tag."
            echo "should_build=true" >> $GITHUB_OUTPUT
            echo "tag=latest_server" >> $GITHUB_OUTPUT
          fi

  build_and_push:
    needs: check_release
    if: needs.check_release.outputs.should_build == 'true'
    runs-on: ubuntu-latest

    steps:
      - name: Check out the repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0  # Fetch all history and tags

      - name: Find latest server tag
        id: find_tag
        if: needs.check_release.outputs.tag == 'latest_server'
        run: |
          # Find the latest tag that starts with 'server'
          LATEST_SERVER_TAG=$(git tag -l "server*" --sort=-creatordate | head -n 1)
          
          if [ -z "$LATEST_SERVER_TAG" ]; then
            echo "No tags starting with 'server' found."
            echo "skip=true" >> $GITHUB_OUTPUT
          else
            echo "Found latest server tag: $LATEST_SERVER_TAG"
            echo "skip=false" >> $GITHUB_OUTPUT
            echo "tag=$LATEST_SERVER_TAG" >> $GITHUB_OUTPUT
          fi
        shell: bash

      - name: Set release tag
        id: set_tag
        if: needs.check_release.outputs.tag != 'latest_server'
        run: |
          echo "skip=false" >> $GITHUB_OUTPUT
          echo "tag=${{ needs.check_release.outputs.tag }}" >> $GITHUB_OUTPUT

      - name: Skip build if no server tag found
        if: (steps.find_tag.outputs.skip == 'true' && needs.check_release.outputs.tag == 'latest_server')
        run: |
          echo "Skipping build because no tag starting with 'server' was found."
          exit 1

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Log in to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Determine tag to use
        id: determine_tag
        run: |
          if [ "${{ needs.check_release.outputs.tag }}" == "latest_server" ]; then
            TAG="${{ steps.find_tag.outputs.tag }}"
          else
            TAG="${{ needs.check_release.outputs.tag }}"
          fi
          echo "Using tag: $TAG"
          echo "tag=$TAG" >> $GITHUB_OUTPUT

      - name: Sanitize tag name
        id: sanitize
        run: echo "SANITIZED_TAG_NAME=$(echo ${{ steps.determine_tag.outputs.tag }} | tr '/' '-' | tr '+' '-')" >> $GITHUB_OUTPUT

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: ./app/
          file: ./app/server/Dockerfile
          push: true
          platforms: linux/amd64,linux/arm64
          tags: |
            plandexai/plandex-server:${{ steps.sanitize.outputs.SANITIZED_TAG_NAME }}
            plandexai/plandex-server:latest

================================================
FILE: .gitignore
================================================
.plandex/
.plandex-dev/
.plandex-v2/
.plandex-dev-v2/
.envkey
.env
.env.*
plandex
plandex-dev
plandex-server
*.exe
node_modules/
/tools/
/static/
/infra/
/payments-dashboard/
.DS_Store
.goreleaser.yml
dist/
__pycache__/

.aider.*
*.code-workspace

__pycache__/

.repo_ignore

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2025 PlandexAI Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
<h1 align="center">
 <a href="https://plandex.ai">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="images/plandex-logo-dark-v2.png"/>
    <source media="(prefers-color-scheme: light)" srcset="images/plandex-logo-light-v2.png"/>
    <img width="400" src="images/plandex-logo-dark-bg-v2.png"/>
 </a>
 <br />
</h1>
<br />

<div align="center">

<p align="center">
  <!-- Call to Action Links -->
  <a href="#install">
    <b>30-Second Install</b>
  </a>
   ·
  <a href="https://plandex.ai">
    <b>Website</b>
  </a>
   ·
  <a href="https://docs.plandex.ai/">
    <b>Docs</b>
  </a>
   ·
  <a href="#examples-">
    <b>Examples</b>
  </a>
   ·
  <a href="https://docs.plandex.ai/hosting/self-hosting/local-mode-quickstart">
    <b>Local Self-Hosted Mode</b>
  </a>
</p>

<br>

[![Discord](https://img.shields.io/discord/1214825831973785600.svg?style=flat&logo=discord&label=Discord&refresh=1)](https://discord.gg/plandex-ai)
[![GitHub Repo stars](https://img.shields.io/github/stars/plandex-ai/plandex?style=social)](https://github.com/plandex-ai/plandex)
[![Twitter Follow](https://img.shields.io/twitter/follow/PlandexAI?style=social)](https://twitter.com/PlandexAI)

</div>

<p align="center">
  <!-- Badges -->
<a href="https://github.com/plandex-ai/plandex/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome" /></a> <a href="https://github.com/plandex-ai/plandex/releases?q=cli"><img src="https://img.shields.io/github/v/release/plandex-ai/plandex?filter=cli*" alt="Release" /></a>
<a href="https://github.com/plandex-ai/plandex/releases?q=server"><img src="https://img.shields.io/github/v/release/plandex-ai/plandex?filter=server*" alt="Release" /></a>

  <!-- <a href="https://github.com/your_username/your_project/issues">
    <img src="https://img.shields.io/github/issues-closed/your_username/your_project.svg" alt="Issues Closed" />
  </a> -->

</p>

<br />

<div align="center">
<a href="https://trendshift.io/repositories/8994" target="_blank"><img src="https://trendshift.io/api/badge/repositories/8994" alt="plandex-ai%2Fplandex | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>

<br>

<h1 align="center" >
  An AI coding agent designed for large tasks and real world projects.<br/><br/>
</h1>

<!-- <h2 align="center">
  Designed for large tasks and real world projects.<br/><br/>
  </h2> -->
  <br/>

<div align="center">
  <a href="https://www.youtube.com/watch?v=SFSu2vNmlLk">
    <img src="images/plandex-v2-yt.png" alt="Plandex v2 Demo Video" width="800">
  </a>
</div>

<br/>

💻  Plandex is a terminal-based AI development tool that can **plan and execute** large coding tasks that span many steps and touch dozens of files. It can handle up to 2M tokens of context directly (~100k per file), and can index directories with 20M tokens or more using tree-sitter project maps.

🔬  **A cumulative diff review sandbox** keeps AI-generated changes separate from your project files until they are ready to go. Command execution is controlled so you can easily roll back and debug. Plandex helps you get the most out of AI without leaving behind a mess in your project.

🧠  **Combine the best models** from Anthropic, OpenAI, Google, and open source providers to build entire features and apps with a robust terminal-based workflow.

🚀  Plandex is capable of <strong>full autonomy</strong>—it can load relevant files, plan and implement changes, execute commands, and automatically debug—but it's also highly flexible and configurable, giving developers fine-grained control and a step-by-step review process when needed.

💪  Plandex is designed to be resilient to <strong>large projects and files</strong>. If you've found that others tools struggle once your project gets past a certain size or the changes are too complex, give Plandex a shot.

## Smart context management that works in big projects

- 🐘 **2M token effective context window** with default model pack. Plandex loads only what's needed for each step.

- 🗄️ **Reliable in large projects and files.** Easily generate, review, revise, and apply changes spanning dozens of files.

- 🗺️ **Fast project map generation** and syntax validation with tree-sitter. Supports 30+ languages.

- 💰 **Context caching** is used across the board for OpenAI, Anthropic, and Google models, reducing costs and latency.

## Tight control or full autonomy—it's up to you

- 🚦 **Configurable autonomy:** go from full auto mode to fine-grained control depending on the task.

- 🐞 **Automated debugging** of terminal commands (like builds, linters, tests, deployments, and scripts). If you have Chrome installed, you can also automatically debug browser applications.

## Tools that help you get production-ready results

- 💬 **A project-aware chat mode** that helps you flesh out ideas before moving to implementation. Also great for asking questions and learning about a codebase.

- 🧠 **Easily try + combine models** from multiple providers. Curated model packs offer different tradeoffs of capability, cost, and speed, as well as open source and provider-specific packs.

- 🛡️ **Reliable file edits** that prioritize correctness. While most edits are quick and cheap, Plandex validates both syntax and logic as needed, with multiple fallback layers when there are problems.

- 🔀 **Full-fledged version control** for every update to the plan, including branches for exploring multiple paths or comparing different models.

- 📂 **Git integration** with commit message generation and optional automatic commits.

## Dev-friendly, easy to install

- 🧑‍💻 **REPL mode** with fuzzy auto-complete for commands and file loading. Just run `plandex` in any project to get started.

- 🛠️ **CLI interface** for scripting or piping data into context.

- 📦 **One-line, zero dependency CLI install**. Dockerized local mode for easily self-hosting the server. Cloud-hosting options for extra reliability and convenience.

## Workflow  🔄

<img src="images/plandex-workflow.png" alt="Plandex workflow" width="100%"/>

## Examples  🎥

  <br/>

<div align="center">
  <a href="https://www.youtube.com/watch?v=g-_76U_nK0Y">
    <img src="images/plandex-browser-debug-yt.png" alt="Plandex Browser Debugging Example" width="800">
  </a>
</div>

<br/>

## Install  📥

```bash
curl -sL https://plandex.ai/install.sh | bash
```

**Note:** Windows is supported via [WSL](https://learn.microsoft.com/en-us/windows/wsl/install). Plandex only works correctly on Windows in the WSL shell. It doesn't work in the Windows CMD prompt or PowerShell.

[More installation options.](https://docs.plandex.ai/install)

## Hosting  ⚖️

| Option                     | Description                                                                                                                                                                                                                                                                                                                                                 |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plandex Cloud**          | Winding down as of 10/3/2025 and no longer accepting new users. <a href="https://plandex.ai/blog/winding-down">Learn more.</a>                                                                                                                                                                                                                              |
| **Self-hosted/Local Mode** | • Run Plandex locally with Docker or host on your own server.<br/>• Use your own [OpenRouter.ai](https://openrouter.ai) key (or [other model provider](https://docs.plandex.ai/models/model-providers) accounts and API keys).<br/>• Follow the [local-mode quickstart](https://docs.plandex.ai/hosting/self-hosting/local-mode-quickstart) to get started. |

## Provider keys  🔑

<!-- If you're going with a 'BYO API Key' option above (whether cloud or self-hosted), you'll need to set API keys for the [model providers](https://docs.plandex.ai/models/model-providers) you're using: -->

```bash
export OPENROUTER_API_KEY=... # if using OpenRouter.ai
```

<br/>

## Claude Pro/Max subscription  🖇️

If you have a Claude Pro or Max subscription, Plandex can use it when calling Anthropic models. You'll be asked if you want to connect a subscription the first time you run Plandex.

<br/>

## Get started  🚀

First, `cd` into a **project directory** where you want to get something done or chat about the project. Make a new directory first with `mkdir your-project-dir` if you're starting on a new project.

```bash
cd your-project-dir
```

For a new project, you might also want to initialize a git repo. Plandex doesn't require that your project is in a git repo, but it does integrate well with git if you use it.

```bash
git init
```

Now start the Plandex REPL in your project:

```bash
plandex
```

or for short:

```bash
pdx
```

<!-- ☁️ _If you're using Plandex Cloud, you'll be prompted at this point to start a trial._

Then just give the REPL help text a quick read, and you're ready go. The REPL starts in _chat mode_ by default, which is good for fleshing out ideas before moving to implementation. Once the task is clear, Plandex will prompt you to switch to _tell mode_ to make a detailed plan and start writing code. -->

<br/>

## Docs  🛠️

### [👉  Full documentation.](https://docs.plandex.ai/)

<br/>

## Discussion and discord  💬

Please feel free to give your feedback, ask questions, report a bug, or just hang out:

- [Discord](https://discord.gg/plandex-ai)
- [Discussions](https://github.com/plandex-ai/plandex/discussions)
- [Issues](https://github.com/plandex-ai/plandex/issues)

## Follow and subscribe

- [Follow @PlandexAI](https://x.com/PlandexAI)
- [Follow @Danenania](https://x.com/Danenania) (Plandex's creator)
- [Subscribe on YouTube](https://x.com/PlandexAI)

<br/>

## Contributors  👥

⭐️  Please star, fork, explore, and contribute to Plandex. There's a lot of work to do and so much that can be improved.

[Here's an overview on setting up a development environment.](https://docs.plandex.ai/development)


================================================
FILE: app/.dockerignore
================================================
cli/
plandex-server

================================================
FILE: app/.gitignore
================================================
.env


================================================
FILE: app/clear_local.sh
================================================
#!/usr/bin/env bash

# Get the absolute path to the script's directory, regardless of where it's run from
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

# Change to the app directory if we're not already there
cd "$SCRIPT_DIR"

echo "WARNING: This will delete all Plandex server data and reset the database."
echo "This action cannot be undone."
read -p "Are you sure you want to continue? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    echo "Reset cancelled."
    exit 1
fi

echo "Resetting local mode..."
echo "Stopping containers and removing volumes..."

# Stop containers and remove volumes
docker compose down -v

echo "Database and data directories cleared. Server stopped."

================================================
FILE: app/cli/api/clients.go
================================================
package api

import (
	"math"
	"math/rand"
	"net"
	"net/http"
	"os"
	"plandex-cli/auth"
	"plandex-cli/types"
	"time"
)

const dialTimeout = 10 * time.Second
const fastReqTimeout = 30 * time.Second
const slowReqTimeout = 5 * time.Minute

type Api struct{}

var CloudApiHost string
var Client types.ApiClient = (*Api)(nil)

func init() {
	if os.Getenv("PLANDEX_ENV") == "development" {
		CloudApiHost = os.Getenv("PLANDEX_API_HOST")
		if CloudApiHost == "" {
			CloudApiHost = "http://localhost:8099"
		}
	} else {
		CloudApiHost = "https://api-v2.plandex.ai"
	}
}

func GetApiHost() string {
	if auth.Current == nil {
		return CloudApiHost
	} else if auth.Current.IsCloud {
		return CloudApiHost
	} else {
		return auth.Current.Host
	}
}

type authenticatedTransport struct {
	underlyingTransport http.RoundTripper
}

func (t *authenticatedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	err := auth.SetAuthHeader(req)
	if err != nil {
		return nil, err
	}
	auth.SetVersionHeader(req)
	return t.underlyingTransport.RoundTrip(req)
}

type unauthenticatedTransport struct {
	underlyingTransport http.RoundTripper
}

func (t *unauthenticatedTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	auth.SetVersionHeader(req)
	return t.underlyingTransport.RoundTrip(req)
}

type retryTransport struct {
	Base          http.RoundTripper
	MaxRetries    int
	BaseDelay     time.Duration
	MaxDelay      time.Duration
	Jitter        time.Duration
	RetryStatuses map[int]bool
}

func (t *retryTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if t.Base == nil {
		t.Base = http.DefaultTransport
	}
	var resp *http.Response
	var err error

	for attempt := 0; attempt <= t.MaxRetries; attempt++ {
		resp, err = t.Base.RoundTrip(req)

		// If there's a low-level error (e.g. network), retry unless it's a timeout, as these are often transient.
		if err != nil {
			if netErr, ok := err.(net.Error); ok {
				if netErr.Timeout() {
					return resp, err
				}
			}
			// continue to next attempt
		} else {
			// If status code not in our RetryStatuses, return immediately.
			if !t.RetryStatuses[resp.StatusCode] {
				return resp, nil
			}

			// Close the body before retrying.
			_ = resp.Body.Close()
		}

		// If we reached the max, break out of loop (will return last resp).
		if attempt == t.MaxRetries {
			break
		}

		// Exponential backoff + jitter
		backoff := float64(t.BaseDelay) * math.Pow(2, float64(attempt))
		if backoff > float64(t.MaxDelay) {
			backoff = float64(t.MaxDelay)
		}
		sleepDuration := time.Duration(backoff) + time.Duration(rand.Int63n(int64(t.Jitter)))
		time.Sleep(sleepDuration)
	}
	return resp, err
}

var netDialer = &net.Dialer{
	Timeout: dialTimeout,
}

var baseTransport = &http.Transport{
	Dial: netDialer.Dial,
}

var sharedRetryTransport = &retryTransport{
	Base:          baseTransport,
	MaxRetries:    3,
	BaseDelay:     500 * time.Millisecond,
	MaxDelay:      5 * time.Second,
	Jitter:        300 * time.Millisecond,
	RetryStatuses: map[int]bool{502: true, 503: true, 504: true},
}

var unauthenticatedClient = &http.Client{
	Transport: &unauthenticatedTransport{
		underlyingTransport: sharedRetryTransport,
	},
	Timeout: fastReqTimeout,
}

var authenticatedFastClient = &http.Client{
	Transport: &authenticatedTransport{
		underlyingTransport: sharedRetryTransport,
	},
	Timeout: fastReqTimeout,
}

var authenticatedSlowClient = &http.Client{
	Transport: &authenticatedTransport{
		underlyingTransport: sharedRetryTransport,
	},
	Timeout: slowReqTimeout,
}

var authenticatedStreamingClient = &http.Client{
	Transport: &authenticatedTransport{
		underlyingTransport: sharedRetryTransport,
	},
}


================================================
FILE: app/cli/api/errors.go
================================================
package api

import (
	"encoding/json"
	"log"
	"net/http"
	"plandex-cli/auth"
	"plandex-cli/term"
	"strings"

	shared "plandex-shared"
)

func HandleApiError(r *http.Response, errBody []byte) *shared.ApiError {
	// Check if the response is JSON
	if r.Header.Get("Content-Type") != "application/json" {
		return &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: r.StatusCode,
			Msg:    strings.TrimSpace(string(errBody)),
		}
	}

	var apiError shared.ApiError
	if err := json.Unmarshal(errBody, &apiError); err != nil {
		log.Printf("Error unmarshalling JSON: %v\n", err)
		return &shared.ApiError{
			Type:   shared.ApiErrorTypeOther,
			Status: r.StatusCode,
			Msg:    strings.TrimSpace(string(errBody)),
		}
	}

	// return error if token/auth refresh is needed
	if apiError.Type == shared.ApiErrorTypeInvalidToken || apiError.Type == shared.ApiErrorTypeAuthOutdated {
		return &apiError
	}

	term.HandleApiError(&apiError)

	return &apiError
}

func refreshAuthIfNeeded(apiErr *shared.ApiError) (bool, *shared.ApiError) {
	if apiErr.Type == shared.ApiErrorTypeInvalidToken {
		err := auth.RefreshInvalidToken()
		if err != nil {
			return false, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: "error refreshing invalid token"}
		}
		return true, nil
	} else if apiErr.Type == shared.ApiErrorTypeAuthOutdated {
		err := auth.RefreshAuth()
		if err != nil {
			return false, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: "error refreshing auth"}
		}

		return true, nil
	}

	return false, apiErr
}


================================================
FILE: app/cli/api/methods.go
================================================
package api

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"plandex-cli/types"
	"strings"

	shared "plandex-shared"

	"github.com/shopspring/decimal"
)

func (a *Api) CreateCliTrialSession() (string, *shared.ApiError) {
	serverUrl := CloudApiHost + "/accounts/cli_trial_session"

	resp, err := unauthenticatedClient.Post(serverUrl, "application/json", nil)

	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		return "", apiErr
	}

	bytes, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error reading response: %v", err)}
	}

	return string(bytes), nil
}

func (a *Api) GetCliTrialSession(token string) (*shared.SessionResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/accounts/cli_trial_session/%s", CloudApiHost, token)

	resp, err := unauthenticatedClient.Get(serverUrl)

	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	if resp.StatusCode == 404 {
		return nil, nil
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		return nil, apiErr
	}

	var session shared.SessionResponse
	err = json.NewDecoder(resp.Body).Decode(&session)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &session, nil
}

func (a *Api) CreateProject(req shared.CreateProjectRequest) (*shared.CreateProjectResponse, *shared.ApiError) {
	serverUrl := GetApiHost() + "/projects"

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreateProject(req)
		}
		return nil, apiErr
	}

	var respBody shared.CreateProjectResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &respBody, nil
}

func (a *Api) ListProjects() ([]*shared.Project, *shared.ApiError) {
	serverUrl := GetApiHost() + "/projects"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListProjects()
		}
		return nil, apiErr
	}

	var projects []*shared.Project
	err = json.NewDecoder(resp.Body).Decode(&projects)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return projects, nil
}

func (a *Api) SetProjectPlan(projectId string, req shared.SetProjectPlanRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/projects/%s/set_plan", GetApiHost(), projectId)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.SetProjectPlan(projectId, req)
		}
		return apiErr
	}

	return nil
}

func (a *Api) RenameProject(projectId string, req shared.RenameProjectRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/projects/%s/rename", GetApiHost(), projectId)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.RenameProject(projectId, req)
		}
		return apiErr
	}

	return nil
}
func (a *Api) ListPlans(projectIds []string) ([]*shared.Plan, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans?", GetApiHost())
	parts := []string{}
	for _, projectId := range projectIds {
		parts = append(parts, fmt.Sprintf("projectId=%s", projectId))
	}
	serverUrl += strings.Join(parts, "&")

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.ListPlans(projectIds)
		}
		return nil, apiErr
	}

	var plans []*shared.Plan
	err = json.NewDecoder(resp.Body).Decode(&plans)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return plans, nil
}

func (a *Api) ListArchivedPlans(projectIds []string) ([]*shared.Plan, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/archive?", GetApiHost())
	parts := []string{}
	for _, projectId := range projectIds {
		parts = append(parts, fmt.Sprintf("projectId=%s", projectId))
	}
	serverUrl += strings.Join(parts, "&")

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListArchivedPlans(projectIds)
		}
		return nil, apiErr
	}

	var plans []*shared.Plan
	err = json.NewDecoder(resp.Body).Decode(&plans)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return plans, nil
}

func (a *Api) ListPlansRunning(projectIds []string, includeRecent bool) (*shared.ListPlansRunningResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/ps?", GetApiHost())
	parts := []string{}
	for _, projectId := range projectIds {
		parts = append(parts, fmt.Sprintf("projectId=%s", projectId))
	}
	serverUrl += strings.Join(parts, "&")
	if includeRecent {
		serverUrl += "&recent=true"
	}

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListPlansRunning(projectIds, includeRecent)
		}
		return nil, apiErr
	}

	var respBody *shared.ListPlansRunningResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return respBody, nil
}

func (a *Api) GetCurrentBranchByPlanId(projectId string, req shared.GetCurrentBranchByPlanIdRequest) (map[string]*shared.Branch, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/projects/%s/plans/current_branches", GetApiHost(), projectId)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPost, serverUrl, bytes.NewBuffer(reqBytes))

	if err != nil {
		return nil, &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)

	if err != nil {
		return nil, &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.GetCurrentBranchByPlanId(projectId, req)
		}
		return nil, apiErr
	}

	var respBody map[string]*shared.Branch
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return respBody, nil
}

func (a *Api) CreatePlan(projectId string, req shared.CreatePlanRequest) (*shared.CreatePlanResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/projects/%s/plans", GetApiHost(), projectId)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreatePlan(projectId, req)
		}
		return nil, apiErr
	}

	var respBody shared.CreatePlanResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &respBody, nil
}

func (a *Api) GetPlan(planId string) (*shared.Plan, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s", GetApiHost(), planId)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetPlan(planId)
		}
		return nil, apiErr
	}

	var plan shared.Plan
	err = json.NewDecoder(resp.Body).Decode(&plan)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &plan, nil
}

func (a *Api) DeletePlan(planId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s", GetApiHost(), planId)

	req, err := http.NewRequest(http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.DeletePlan(planId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) DeleteAllPlans(projectId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/projects/%s/plans", GetApiHost(), projectId)

	req, err := http.NewRequest(http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)

		if didRefresh {
			return a.DeleteAllPlans(projectId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) TellPlan(planId, branch string, req shared.TellPlanRequest, onStream types.OnStreamPlan) *shared.ApiError {

	serverUrl := fmt.Sprintf("%s/plans/%s/%s/tell", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPost, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	var client *http.Client
	if req.ConnectStream {
		client = authenticatedStreamingClient
	} else {
		client = authenticatedFastClient
	}

	resp, err := client.Do(request)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)

		if didRefresh {
			return a.TellPlan(planId, branch, req, onStream)
		}
		return apiErr
	}

	if req.ConnectStream {
		log.Println("Connecting stream")
		connectPlanRespStream(resp.Body, onStream)
	} else {
		// log.Println("Background exec - not connecting stream")
		resp.Body.Close()
	}

	return nil
}

func (a *Api) BuildPlan(planId, branch string, req shared.BuildPlanRequest, onStream types.OnStreamPlan) *shared.ApiError {

	log.Println("Calling BuildPlan")

	serverUrl := fmt.Sprintf("%s/plans/%s/%s/build", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	var client *http.Client
	if req.ConnectStream {
		client = authenticatedStreamingClient
	} else {
		client = authenticatedFastClient
	}

	resp, err := client.Do(request)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	if resp.StatusCode >= 400 {
		log.Println("Error response from build plan", resp.StatusCode)

		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)

		if didRefresh {
			return a.BuildPlan(planId, branch, req, onStream)
		}
		return apiErr
	}

	if req.ConnectStream {
		log.Println("Connecting stream")
		connectPlanRespStream(resp.Body, onStream)
	} else {
		// log.Println("Background exec - not connecting stream")
		resp.Body.Close()
	}

	return nil
}

func (a *Api) RespondMissingFile(planId, branch string, req shared.RespondMissingFileRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/respond_missing_file", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPost, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)

		if didRefresh {
			return a.RespondMissingFile(planId, branch, req)
		}
		return apiErr
	}

	return nil

}

func (a *Api) ConnectPlan(planId, branch string, onStream types.OnStreamPlan) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/connect", GetApiHost(), planId, branch)

	req, err := http.NewRequest(http.MethodPatch, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedStreamingClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)

		if didRefresh {
			return a.ConnectPlan(planId, branch, onStream)
		}

		return apiErr
	}

	connectPlanRespStream(resp.Body, onStream)

	return nil
}

func (a *Api) StopPlan(ctx context.Context, planId, branch string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/stop", GetApiHost(), planId, branch)

	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.StopPlan(ctx, planId, branch)
		}
		return apiErr
	}

	return nil
}

func (a *Api) GetCurrentPlanState(planId, branch string) (*shared.CurrentPlanState, *shared.ApiError) {
	return a.getCurrentPlanState(planId, branch, "")
}

func (a *Api) GetCurrentPlanStateAtSha(planId, sha string) (*shared.CurrentPlanState, *shared.ApiError) {
	return a.getCurrentPlanState(planId, "", sha)
}

func (a *Api) getCurrentPlanState(planId, branch, sha string) (*shared.CurrentPlanState, *shared.ApiError) {
	var serverUrl string
	if sha != "" {
		serverUrl = fmt.Sprintf("%s/plans/%s/current_plan/%s", GetApiHost(), planId, sha)
	} else {
		serverUrl = fmt.Sprintf("%s/plans/%s/%s/current_plan", GetApiHost(), planId, branch)
	}

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.getCurrentPlanState(planId, branch, sha)
		}
		return nil, apiErr
	}

	var state shared.CurrentPlanState
	err = json.NewDecoder(resp.Body).Decode(&state)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &state, nil
}

func (a *Api) ApplyPlan(planId, branch string, req shared.ApplyPlanRequest) (string, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/apply", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return "", &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return "", &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return "", &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.ApplyPlan(planId, branch, req)
		}
		return "", apiErr
	}

	// Reading the body on success
	responseData, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", &shared.ApiError{Msg: fmt.Sprintf("error reading response body: %v", err)}
	}

	return string(responseData), nil
}

func (a *Api) ArchivePlan(planId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/archive", GetApiHost(), planId)

	req, err := http.NewRequest(http.MethodPatch, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.ArchivePlan(planId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) UnarchivePlan(planId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/unarchive", GetApiHost(), planId)

	req, err := http.NewRequest(http.MethodPatch, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.ArchivePlan(planId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) RenamePlan(planId string, name string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/rename", GetApiHost(), planId)

	reqBytes, err := json.Marshal(shared.RenamePlanRequest{Name: name})
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))

	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)

	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.RenamePlan(planId, name)
		}
		return apiErr
	}

	return nil
}

func (a *Api) RejectAllChanges(planId, branch string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/reject_all", GetApiHost(), planId, branch)

	req, err := http.NewRequest(http.MethodPatch, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			return a.RejectAllChanges(planId, branch)
		}
		return apiErr
	}

	return nil
}

func (a *Api) RejectFile(planId, branch, filePath string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/reject_file", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(shared.RejectFileRequest{FilePath: filePath})

	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	req, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			a.RejectFile(planId, branch, filePath)
		}
		return apiErr
	}

	return nil
}

func (a *Api) RejectFiles(planId, branch string, paths []string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/reject_files", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(shared.RejectFilesRequest{Paths: paths})

	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	req, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		didRefresh, apiErr := refreshAuthIfNeeded(apiErr)
		if didRefresh {
			a.RejectFiles(planId, branch, paths)
		}
		return apiErr
	}

	return nil
}

func (a *Api) LoadContext(planId, branch string, req shared.LoadContextRequest) (*shared.LoadContextResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/context", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	// use the slow client since we may be uploading relatively large files
	resp, err := authenticatedSlowClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.LoadContext(planId, branch, req)
		}
		return nil, apiErr
	}

	var loadContextResponse shared.LoadContextResponse
	err = json.NewDecoder(resp.Body).Decode(&loadContextResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &loadContextResponse, nil
}

func (a *Api) UpdateContext(planId, branch string, req shared.UpdateContextRequest) (*shared.UpdateContextResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/context", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))

	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	request.Header.Set("Content-Type", "application/json")

	// use the slow client since we may be uploading relatively large files
	resp, err := authenticatedSlowClient.Do(request)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdateContext(planId, branch, req)
		}
		return nil, apiErr
	}

	var updateContextResponse shared.UpdateContextResponse
	err = json.NewDecoder(resp.Body).Decode(&updateContextResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &updateContextResponse, nil
}

func (a *Api) DeleteContext(planId, branch string, req shared.DeleteContextRequest) (*shared.DeleteContextResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/context", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodDelete, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.DeleteContext(planId, branch, req)
		}
		return nil, apiErr
	}

	var deleteContextResponse shared.DeleteContextResponse
	err = json.NewDecoder(resp.Body).Decode(&deleteContextResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &deleteContextResponse, nil
}

func (a *Api) ListContext(planId, branch string) ([]*shared.Context, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/context", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListContext(planId, branch)
		}
		return nil, apiErr
	}

	var contexts []*shared.Context
	err = json.NewDecoder(resp.Body).Decode(&contexts)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return contexts, nil
}

func (a *Api) LoadCachedFileMap(planId, branch string, req shared.LoadCachedFileMapRequest) (*shared.LoadCachedFileMapResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/load_cached_file_map", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		return nil, apiErr
	}

	var loadResp shared.LoadCachedFileMapResponse
	err = json.NewDecoder(resp.Body).Decode(&loadResp)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &loadResp, nil
}

func (a *Api) ListConvo(planId, branch string) ([]*shared.ConvoMessage, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/convo", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListConvo(planId, branch)
		}
		return nil, apiErr
	}

	var convos []*shared.ConvoMessage
	err = json.NewDecoder(resp.Body).Decode(&convos)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return convos, nil
}

func (a *Api) GetPlanStatus(planId, branch string) (string, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/status", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetPlanStatus(planId, branch)
		}
		return "", apiErr
	}

	body, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error reading response body: %v", err)}
	}

	return string(body), nil
}

func (a *Api) GetPlanDiffs(planId, branch string, plain bool) (string, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/diffs", GetApiHost(), planId, branch)

	if plain {
		serverUrl += "?plain=true"
	}

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetPlanDiffs(planId, branch, plain)
		}
		return "", apiErr
	}

	body, err := io.ReadAll(resp.Body)

	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error reading response body: %v", err)}
	}

	return string(body), nil
}

func (a *Api) ListLogs(planId, branch string) (*shared.LogResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/logs", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListLogs(planId, branch)
		}
		return nil, apiErr
	}

	var logs shared.LogResponse
	err = json.NewDecoder(resp.Body).Decode(&logs)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &logs, nil
}

func (a *Api) RewindPlan(planId, branch string, req shared.RewindPlanRequest) (*shared.RewindPlanResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/rewind", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPatch, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}

	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.RewindPlan(planId, branch, req)
		}
		return nil, apiErr
	}

	var rewindPlanResponse shared.RewindPlanResponse
	err = json.NewDecoder(resp.Body).Decode(&rewindPlanResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &rewindPlanResponse, nil
}

func (a *Api) SignIn(req shared.SignInRequest, customHost string) (*shared.SessionResponse, *shared.ApiError) {
	host := customHost
	if host == "" {
		host = CloudApiHost
	}
	serverUrl := host + "/accounts/sign_in"
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := unauthenticatedClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		return nil, apiErr
	}

	var sessionResponse shared.SessionResponse
	err = json.NewDecoder(resp.Body).Decode(&sessionResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &sessionResponse, nil
}

func (a *Api) CreateAccount(req shared.CreateAccountRequest, customHost string) (*shared.SessionResponse, *shared.ApiError) {
	host := customHost
	if host == "" {
		host = CloudApiHost
	}
	serverUrl := host + "/accounts"
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := unauthenticatedClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		return nil, apiErr
	}

	var sessionResponse shared.SessionResponse
	err = json.NewDecoder(resp.Body).Decode(&sessionResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &sessionResponse, nil
}

func (a *Api) CreateOrg(req shared.CreateOrgRequest) (*shared.CreateOrgResponse, *shared.ApiError) {
	serverUrl := GetApiHost() + "/orgs"
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreateOrg(req)
		}
		return nil, apiErr
	}

	var createOrgResponse shared.CreateOrgResponse
	err = json.NewDecoder(resp.Body).Decode(&createOrgResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &createOrgResponse, nil
}

func (a *Api) GetOrgSession() (*shared.Org, *shared.ApiError) {
	serverUrl := GetApiHost() + "/orgs/session"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetOrgSession()
		}
		return nil, apiErr
	}

	var org *shared.Org

	err = json.NewDecoder(resp.Body).Decode(&org)

	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return org, nil
}

func (a *Api) ListOrgs() ([]*shared.Org, *shared.ApiError) {
	serverUrl := GetApiHost() + "/orgs"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListOrgs()
		}
		return nil, apiErr
	}

	var orgs []*shared.Org
	err = json.NewDecoder(resp.Body).Decode(&orgs)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return orgs, nil
}

func (a *Api) GetOrgUserConfig() (*shared.OrgUserConfig, *shared.ApiError) {
	serverUrl := GetApiHost() + "/org_user_config"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetOrgUserConfig()
		}
		return nil, apiErr
	}

	var orgUserConfig shared.OrgUserConfig
	err = json.NewDecoder(resp.Body).Decode(&orgUserConfig)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &orgUserConfig, nil
}

func (a *Api) UpdateOrgUserConfig(c shared.OrgUserConfig) *shared.ApiError {
	serverUrl := GetApiHost() + "/org_user_config"

	reqBytes, err := json.Marshal(c)

	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdateOrgUserConfig(c)
		}
		return apiErr
	}

	return nil
}

func (a *Api) DeleteUser(userId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/orgs/users/%s", GetApiHost(), userId)
	req, err := http.NewRequest(http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.DeleteUser(userId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) ListOrgRoles() ([]*shared.OrgRole, *shared.ApiError) {
	serverUrl := GetApiHost() + "/orgs/roles"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListOrgRoles()
		}
		return nil, apiErr
	}

	var roles []*shared.OrgRole
	err = json.NewDecoder(resp.Body).Decode(&roles)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return roles, nil
}

func (a *Api) InviteUser(req shared.InviteRequest) *shared.ApiError {
	serverUrl := GetApiHost() + "/invites"
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.InviteUser(req)
		}
		return apiErr
	}

	return nil
}

func (a *Api) ListPendingInvites() ([]*shared.Invite, *shared.ApiError) {
	serverUrl := GetApiHost() + "/invites/pending"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListPendingInvites()
		}
		return nil, apiErr
	}

	var invites []*shared.Invite
	err = json.NewDecoder(resp.Body).Decode(&invites)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return invites, nil
}

func (a *Api) ListAcceptedInvites() ([]*shared.Invite, *shared.ApiError) {
	serverUrl := GetApiHost() + "/invites/accepted"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListAcceptedInvites()
		}
		return nil, apiErr
	}

	var invites []*shared.Invite
	err = json.NewDecoder(resp.Body).Decode(&invites)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return invites, nil
}

func (a *Api) ListAllInvites() ([]*shared.Invite, *shared.ApiError) {
	serverUrl := GetApiHost() + "/invites/all"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListAllInvites()
		}
		return nil, apiErr
	}

	var invites []*shared.Invite
	err = json.NewDecoder(resp.Body).Decode(&invites)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return invites, nil
}

func (a *Api) DeleteInvite(inviteId string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/invites/%s", GetApiHost(), inviteId)
	req, err := http.NewRequest(http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)

		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.DeleteInvite(inviteId)
		}
		return apiErr
	}

	return nil
}

func (a *Api) CreateEmailVerification(email, customHost, userId string) (*shared.CreateEmailVerificationResponse, *shared.ApiError) {
	host := customHost
	if host == "" {
		host = CloudApiHost
	}
	serverUrl := host + "/accounts/email_verifications"
	req := shared.CreateEmailVerificationRequest{Email: email, UserId: userId}
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := unauthenticatedClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		return nil, HandleApiError(resp, errorBody)
	}

	var verificationResponse shared.CreateEmailVerificationResponse
	err = json.NewDecoder(resp.Body).Decode(&verificationResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &verificationResponse, nil
}

func (a *Api) CreateSignInCode() (string, *shared.ApiError) {
	serverUrl := GetApiHost() + "/accounts/sign_in_codes"
	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", nil)
	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreateSignInCode()
		}
		return "", apiErr
	}

	var signInCode string
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error reading response body: %v", err)}
	}
	signInCode = string(body)

	return signInCode, nil
}

func (a *Api) SignOut() *shared.ApiError {
	serverUrl := GetApiHost() + "/accounts/sign_out"

	req, err := http.NewRequest(http.MethodPost, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		return HandleApiError(resp, errorBody)
	}

	return nil
}

func (a *Api) ListUsers() (*shared.ListUsersResponse, *shared.ApiError) {
	serverUrl := GetApiHost() + "/users"
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListUsers()
		}
		return nil, apiErr
	}

	var r *shared.ListUsersResponse
	err = json.NewDecoder(resp.Body).Decode(&r)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return r, nil
}

func (a *Api) ListBranches(planId string) ([]*shared.Branch, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/branches", GetApiHost(), planId)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListBranches(planId)
		}
		return nil, apiErr
	}

	var branches []*shared.Branch
	err = json.NewDecoder(resp.Body).Decode(&branches)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return branches, nil
}

func (a *Api) CreateBranch(planId, branch string, req shared.CreateBranchRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/branches", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %s", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreateBranch(planId, branch, req)
		}
		return apiErr
	}

	return nil
}

func (a *Api) DeleteBranch(planId, branch string) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/branches/%s", GetApiHost(), planId, branch)

	req, err := http.NewRequest(http.MethodDelete, serverUrl, nil)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %s", err)}
	}

	resp, err := authenticatedFastClient.Do(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.DeleteBranch(planId, branch)
		}
		return apiErr
	}

	return nil
}

func (a *Api) GetSettings(planId, branch string) (*shared.PlanSettings, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/settings", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)

	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetSettings(planId, branch)
		}
		return nil, apiErr
	}

	var settings shared.PlanSettings
	err = json.NewDecoder(resp.Body).Decode(&settings)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return &settings, nil
}

func (a *Api) UpdateSettings(planId, branch string, req shared.UpdateSettingsRequest) (*shared.UpdateSettingsResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/settings", GetApiHost(), planId, branch)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %s", err)}
	}

	// log.Println("UpdateSettings", string(reqBytes))

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %s", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdateSettings(planId, branch, req)
		}
		return nil, apiErr
	}

	var updateRes shared.UpdateSettingsResponse
	err = json.NewDecoder(resp.Body).Decode(&updateRes)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return &updateRes, nil

}

func (a *Api) GetOrgDefaultSettings() (*shared.PlanSettings, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/default_settings", GetApiHost())

	resp, err := authenticatedFastClient.Get(serverUrl)

	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetOrgDefaultSettings()
		}
		return nil, apiErr
	}

	var settings shared.PlanSettings
	err = json.NewDecoder(resp.Body).Decode(&settings)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return &settings, nil
}

func (a *Api) UpdateOrgDefaultSettings(req shared.UpdateSettingsRequest) (*shared.UpdateSettingsResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/default_settings", GetApiHost())

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %s", err)}
	}

	// log.Println("UpdateSettings", string(reqBytes))

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %s", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %s", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdateOrgDefaultSettings(req)
		}
		return nil, apiErr
	}

	var updateRes shared.UpdateSettingsResponse
	err = json.NewDecoder(resp.Body).Decode(&updateRes)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %s", err)}
	}

	return &updateRes, nil
}

func (a *Api) GetPlanConfig(planId string) (*shared.PlanConfig, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/config", GetApiHost(), planId)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetPlanConfig(planId)
		}
		return nil, apiErr
	}

	var res shared.GetPlanConfigResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return res.Config, nil
}

func (a *Api) UpdatePlanConfig(planId string, req shared.UpdatePlanConfigRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/plans/%s/config", GetApiHost(), planId)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdatePlanConfig(planId, req)
		}
		return apiErr
	}

	return nil
}

func (a *Api) GetDefaultPlanConfig() (*shared.PlanConfig, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/default_plan_config", GetApiHost())

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetDefaultPlanConfig()
		}
		return nil, apiErr
	}

	var res shared.GetDefaultPlanConfigResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return res.Config, nil
}

func (a *Api) UpdateDefaultPlanConfig(req shared.UpdateDefaultPlanConfigRequest) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/default_plan_config", GetApiHost())

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	request, err := http.NewRequest(http.MethodPut, serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}
	request.Header.Set("Content-Type", "application/json")

	resp, err := authenticatedFastClient.Do(request)
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.UpdateDefaultPlanConfig(req)
		}
		return apiErr
	}

	return nil
}

func (a *Api) CreateCustomModels(input *shared.ModelsInput) *shared.ApiError {
	serverUrl := fmt.Sprintf("%s/custom_models", GetApiHost())
	body, err := json.Marshal(input)
	if err != nil {
		return &shared.ApiError{Msg: "Failed to marshal model"}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(body))
	if err != nil {
		return &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.CreateCustomModels(input)
		}
		return apiErr
	}

	return nil
}

func (a *Api) ListCustomModels() ([]*shared.CustomModel, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/custom_models", GetApiHost())
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListCustomModels()
		}
		return nil, apiErr
	}

	var models []*shared.CustomModel
	err = json.NewDecoder(resp.Body).Decode(&models)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return models, nil
}

func (a *Api) ListCustomProviders() ([]*shared.CustomProvider, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/custom_providers", GetApiHost())
	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListCustomProviders()
		}
		return nil, apiErr
	}

	var providers []*shared.CustomProvider
	err = json.NewDecoder(resp.Body).Decode(&providers)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return providers, nil
}

func (a *Api) ListModelPacks() ([]*shared.ModelPack, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/model_sets", GetApiHost())

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.ListModelPacks()
		}
		return nil, apiErr
	}

	var sets []*shared.ModelPack
	err = json.NewDecoder(resp.Body).Decode(&sets)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return sets, nil

}

func (a *Api) GetCreditsTransactions(pageSize, pageNum int, req shared.CreditsLogRequest) (*shared.CreditsLogResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/billing/credits_transactions?size=%d&page=%d", GetApiHost(), pageSize, pageNum)

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)

		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetCreditsTransactions(pageSize, pageNum, req)
		}
		return nil, apiErr
	}

	var res *shared.CreditsLogResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return res, nil
}

func (a *Api) GetCreditsSummary(req shared.CreditsLogRequest) (*shared.CreditsSummaryResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/billing/credits_summary", GetApiHost())

	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedFastClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetCreditsSummary(req)
		}
		return nil, apiErr
	}

	var res *shared.CreditsSummaryResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return res, nil
}

func (a *Api) GetBalance() (decimal.Decimal, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/billing/balance", GetApiHost())

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return decimal.Zero, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetBalance()
		}
		return decimal.Zero, apiErr
	}

	var res *shared.GetBalanceResponse
	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return decimal.Zero, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return res.Balance, nil
}

func (a *Api) GetFileMap(req shared.GetFileMapRequest) (*shared.GetFileMapResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/file_map", GetApiHost())
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	resp, err := authenticatedSlowClient.Post(serverUrl, "application/json", bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetFileMap(req)
		}
		return nil, apiErr
	}

	var respBody shared.GetFileMapResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &respBody, nil
}

func (a *Api) GetContextBody(planId, branch, contextId string) (*shared.GetContextBodyResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/context/%s/body", GetApiHost(), planId, branch, contextId)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetContextBody(planId, branch, contextId)
		}
		return nil, apiErr
	}

	var respBody shared.GetContextBodyResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &respBody, nil
}

func (a *Api) AutoLoadContext(ctx context.Context, planId, branch string, req shared.LoadContextRequest) (*shared.LoadContextResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/auto_load_context", GetApiHost(), planId, branch)
	reqBytes, err := json.Marshal(req)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error marshalling request: %v", err)}
	}

	// Create a new request with context
	httpReq, err := http.NewRequestWithContext(ctx, "POST", serverUrl, bytes.NewBuffer(reqBytes))
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error creating request: %v", err)}
	}

	// Set the content type header
	httpReq.Header.Set("Content-Type", "application/json")

	// Use the slow client since we may be uploading relatively large files
	resp, err := authenticatedSlowClient.Do(httpReq)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.LoadContext(planId, branch, req)
		}
		return nil, apiErr
	}

	var loadContextResponse shared.LoadContextResponse
	err = json.NewDecoder(resp.Body).Decode(&loadContextResponse)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &loadContextResponse, nil
}

func (a *Api) GetBuildStatus(planId, branch string) (*shared.GetBuildStatusResponse, *shared.ApiError) {
	serverUrl := fmt.Sprintf("%s/plans/%s/%s/build_status", GetApiHost(), planId, branch)

	resp, err := authenticatedFastClient.Get(serverUrl)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error sending request: %v", err)}
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 400 {
		errorBody, _ := io.ReadAll(resp.Body)
		apiErr := HandleApiError(resp, errorBody)
		authRefreshed, apiErr := refreshAuthIfNeeded(apiErr)
		if authRefreshed {
			return a.GetBuildStatus(planId, branch)
		}
		return nil, apiErr
	}

	var respBody shared.GetBuildStatusResponse
	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return nil, &shared.ApiError{Type: shared.ApiErrorTypeOther, Msg: fmt.Sprintf("error decoding response: %v", err)}
	}

	return &respBody, nil
}


================================================
FILE: app/cli/api/stream.go
================================================
package api

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"plandex-cli/types"
	"time"

	shared "plandex-shared"
)

// 3 heartbeat misses = timeout
const HeartbeatTimeout = 16 * time.Second

func connectPlanRespStream(body io.ReadCloser, onStream types.OnStreamPlan) {
	reader := bufio.NewReader(body)
	timer := time.NewTimer(HeartbeatTimeout)
	defer timer.Stop()

	go func() {
		for {
			select {
			case <-timer.C:
				log.Println("Connection to plan stream timed out due to missing heartbeats")
				onStream(types.OnStreamPlanParams{Msg: nil, Err: fmt.Errorf("connection to plan stream timed out due to missing heartbeats")})
				body.Close()
				return
			default:
			}

			s, err := readUntilSeparator(reader, shared.STREAM_MESSAGE_SEPARATOR)
			if err != nil {
				log.Println("Error reading line:", err)
				onStream(types.OnStreamPlanParams{Msg: nil, Err: err})
				body.Close()
				return
			}

			timer.Reset(HeartbeatTimeout)

			// ignore heartbeats
			if s == string(shared.StreamMessageHeartbeat) {
				continue
			}

			var msg shared.StreamMessage
			err = json.Unmarshal([]byte(s), &msg)
			if err != nil {
				log.Println("Error unmarshalling message:", err)
				onStream(types.OnStreamPlanParams{Msg: nil, Err: err})
				body.Close()
				return
			}

			// log.Println("connectPlanRespStream: received message:", msg)

			onStream(types.OnStreamPlanParams{Msg: &msg, Err: nil})

			if msg.Type == shared.StreamMessageFinished || msg.Type == shared.StreamMessageError || msg.Type == shared.StreamMessageAborted {
				body.Close()
				return
			}

		}
	}()
}

func readUntilSeparator(reader *bufio.Reader, separator string) (string, error) {
	var result []byte
	sepBytes := []byte(separator)
	for {
		b, err := reader.ReadByte()
		if err != nil {
			return string(result), err
		}
		result = append(result, b)
		if len(result) >= len(sepBytes) && bytes.HasSuffix(result, sepBytes) {
			return string(result[:len(result)-len(separator)]), nil
		}
	}
}


================================================
FILE: app/cli/auth/account.go
================================================
package auth

import (
	"fmt"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/fatih/color"
)

const AddAccountOption = "Add another account"

func SelectOrSignInOrCreate() error {
	accounts, err := loadAccounts()

	if err != nil {
		return fmt.Errorf("error loading accounts: %v", err)
	}

	if len(accounts) == 0 {
		err := promptSignInNewAccount()
		if err != nil {
			return fmt.Errorf("error signing in to new account: %v", err)
		}

		return nil
	}

	var options []string
	for _, account := range accounts {
		options = append(options, fmt.Sprintf("<%s> %s", account.UserName, account.Email))
	}

	options = append(options, AddAccountOption)

	// either select from existing accounts or sign in/create account

	selectedOpt, err := term.SelectFromList("Select an account:", options)

	if err != nil {
		return fmt.Errorf("error selecting account: %v", err)
	}

	if selectedOpt == AddAccountOption {
		err := promptSignInNewAccount()
		if err != nil {
			return fmt.Errorf("error prompting for sign in to new account: %v", err)
		}
		return nil
	}

	var selected *shared.ClientAccount
	for i, opt := range options {
		if selectedOpt == opt {
			selected = accounts[i]
			break
		}
	}

	if selected == nil {
		return fmt.Errorf("error selecting account: account not found")
	}

	selectedAuth := *selected

	setAuth(&shared.ClientAuth{
		ClientAccount: selectedAuth,
	})

	term.StartSpinner("")
	orgs, apiErr := apiClient.ListOrgs()
	term.StopSpinner()

	if apiErr != nil {
		return fmt.Errorf("error listing orgs: %v", apiErr.Msg)
	}

	org, err := resolveOrgAuth(orgs, selectedAuth.IsLocalMode)

	if err != nil {
		return fmt.Errorf("error resolving org: %v", err)
	}

	err = setAuth(&shared.ClientAuth{
		ClientAccount:        *selected,
		OrgId:                org.Id,
		OrgName:              org.Name,
		OrgIsTrial:           org.IsTrial,
		IntegratedModelsMode: org.IntegratedModelsMode,
	})

	if err != nil {
		return fmt.Errorf("error setting auth: %v", err)
	}

	_, apiErr = apiClient.GetOrgSession()

	if apiErr != nil {
		return fmt.Errorf("error getting org session: %v", apiErr.Msg)
	}

	fmt.Printf("✅ Signed in as %s | Org: %s\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("<%s> %s", Current.UserName, Current.Email), color.New(term.ColorHiCyan).Sprint(Current.OrgName))
	fmt.Println()

	if !term.IsRepl {
		term.PrintCmds("", "")
	}

	return nil
}

func SignInWithCode(code, host string) error {
	term.StartSpinner("")
	res, apiErr := apiClient.SignIn(shared.SignInRequest{
		Pin:          code,
		IsSignInCode: true,
	}, host)
	term.StopSpinner()

	if apiErr != nil {
		return fmt.Errorf("error signing in: %v", apiErr.Msg)
	}

	return handleSignInResponse(res, host)
}

func promptInitialAuth() error {
	fmt.Println("👋 Hey there!\nIt looks like this is your first time using Plandex on this computer.")

	err := SelectOrSignInOrCreate()

	if err != nil {
		return fmt.Errorf("error selecting or signing in to account: %v", err)
	}

	return nil
}

const (
	// SignInCloudOption = "Plandex Cloud"
	SignInLocalOption = "Local mode host"
	SignInOtherOption = "Another host"
)

func promptSignInNewAccount() error {
	selected, err := term.SelectFromList("Use local mode or another host?", []string{SignInLocalOption, SignInOtherOption})

	if err != nil {
		return fmt.Errorf("error selecting sign in option: %v", err)
	}

	var host string
	var email string

	if selected == SignInLocalOption {
		host, err = term.GetRequiredUserStringInputWithDefault("Host:", "http://localhost:8099")
	} else {
		host, err = term.GetRequiredUserStringInput("Host:")
	}

	if err != nil {
		return fmt.Errorf("error prompting host: %v", err)
	}

	if selected == SignInLocalOption {
		email = "local-admin@plandex.ai"
	} else {
		email, err = term.GetRequiredUserStringInput("Your email:")
	}

	if err != nil {
		return fmt.Errorf("error prompting email: %v", err)
	}

	res, err := verifyEmail(email, host)

	if err != nil {
		return fmt.Errorf("error verifying email: %v", err)
	}

	if res.hasAccount {
		err := signIn(email, res.pin, host)
		if err != nil {
			return fmt.Errorf("error signing in: %v", err)
		}
	} else {
		err := createAccount(email, res.pin, host, res.isLocalMode)
		if err != nil {
			return fmt.Errorf("error creating account: %v", err)
		}
	}

	if !term.IsRepl {
		term.PrintCmds("", "")
	}

	return nil
}

type verifyEmailRes struct {
	hasAccount  bool
	isLocalMode bool
	pin         string
}

func verifyEmail(email, host string) (*verifyEmailRes, error) {
	term.StartSpinner("")
	res, apiErr := apiClient.CreateEmailVerification(email, host, "")
	term.StopSpinner()

	if apiErr != nil {
		return nil, fmt.Errorf("error creating email verification: %v", apiErr.Msg)
	}

	if res.IsLocalMode {
		return &verifyEmailRes{
			hasAccount:  res.HasAccount,
			isLocalMode: true,
			pin:         "",
		}, nil
	}

	fmt.Println("✉️  You'll now receive a 6 character pin by email. It will be valid for 5 minutes.")

	pin, err := term.GetUserPasswordInput("Please enter your pin:")

	if err != nil {
		return nil, fmt.Errorf("error prompting pin: %v", err)
	}

	return &verifyEmailRes{
		hasAccount:  res.HasAccount,
		isLocalMode: false,
		pin:         pin,
	}, nil
}

func signIn(email, pin, host string) error {
	term.StartSpinner("")
	res, apiErr := apiClient.SignIn(shared.SignInRequest{
		Email: email,
		Pin:   pin,
	}, host)
	term.StopSpinner()

	if apiErr != nil {
		return fmt.Errorf("error signing in: %v", apiErr.Msg)
	}

	return handleSignInResponse(res, host)
}

func handleSignInResponse(res *shared.SessionResponse, host string) error {
	isLocalMode := host != "" && res.IsLocalMode

	err := setAuth(&shared.ClientAuth{
		ClientAccount: shared.ClientAccount{
			Email:       res.Email,
			UserId:      res.UserId,
			UserName:    res.UserName,
			Token:       res.Token,
			IsTrial:     false,
			IsCloud:     host == "",
			Host:        host,
			IsLocalMode: isLocalMode,
		},
	})

	if err != nil {
		return fmt.Errorf("error setting auth: %v", err)
	}

	org, err := resolveOrgAuth(res.Orgs, isLocalMode)

	if err != nil {
		return fmt.Errorf("error resolving org: %v", err)
	}

	Current.OrgId = org.Id
	Current.OrgName = org.Name
	Current.IntegratedModelsMode = org.IntegratedModelsMode

	err = writeCurrentAuth()

	if err != nil {
		return fmt.Errorf("error writing auth: %v", err)
	}

	fmt.Printf("✅ Signed in as %s | Org: %s\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("<%s> %s", Current.UserName, Current.Email), color.New(term.ColorHiCyan).Sprint(Current.OrgName))
	fmt.Println()

	return nil
}

func createAccount(email, pin, host string, isLocalMode bool) error {
	var name string

	if isLocalMode {
		name = "Local Admin"
	} else {
		var err error
		name, err = term.GetUserStringInput("Your name:")

		if err != nil {
			return fmt.Errorf("error prompting name: %v", err)
		}
	}

	term.StartSpinner("🌟 Creating account...")
	res, apiErr := apiClient.CreateAccount(shared.CreateAccountRequest{
		Email:    email,
		UserName: name,
		Pin:      pin,
	}, host)
	term.StopSpinner()

	if apiErr != nil {
		return fmt.Errorf("error creating account: %v", apiErr.Msg)
	}

	if res.IsLocalMode {
		isLocalMode = true
	}

	err := setAuth(&shared.ClientAuth{
		ClientAccount: shared.ClientAccount{
			Email:       res.Email,
			UserId:      res.UserId,
			UserName:    res.UserName,
			Token:       res.Token,
			IsTrial:     false,
			IsCloud:     host == "",
			Host:        host,
			IsLocalMode: isLocalMode,
		},
	})

	if err != nil {
		return fmt.Errorf("error setting auth: %v", err)
	}

	org, err := resolveOrgAuth(res.Orgs, isLocalMode)

	if err != nil {
		return fmt.Errorf("error resolving org: %v", err)
	}

	if org == nil {
		return fmt.Errorf("no org selected")
	}

	Current.OrgId = org.Id
	Current.OrgName = org.Name
	Current.IntegratedModelsMode = org.IntegratedModelsMode

	err = writeCurrentAuth()

	if err != nil {
		return fmt.Errorf("error writing auth: %v", err)
	}

	fmt.Printf("✅ Signed in as %s | Org: %s\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("<%s> %s", Current.UserName, Current.Email), color.New(term.ColorHiCyan).Sprint(Current.OrgName))
	fmt.Println()

	return nil
}


================================================
FILE: app/cli/auth/api.go
================================================
package auth

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"plandex-cli/types"
	"plandex-cli/version"

	shared "plandex-shared"
)

var apiClient types.ApiClient

func SetApiClient(client types.ApiClient) {
	apiClient = client
}

func SetAuthHeader(req *http.Request) error {
	if Current == nil {
		return fmt.Errorf("error setting auth header: auth not loaded")
	}
	hash := Current.ToHash()

	authHeader := shared.AuthHeader{
		Token: Current.Token,
		OrgId: Current.OrgId,
		Hash:  hash,
	}

	bytes, err := json.Marshal(authHeader)

	if err != nil {
		return fmt.Errorf("error marshalling auth header: %v", err)
	}

	// base64 encode
	token := base64.URLEncoding.EncodeToString(bytes)

	req.Header.Set("Authorization", "Bearer "+token)

	return nil
}

func SetVersionHeader(req *http.Request) {
	req.Header.Set("X-Client-Version", version.Version)
}


================================================
FILE: app/cli/auth/auth.go
================================================
package auth

import (
	"encoding/json"
	"fmt"
	"os"
	"plandex-cli/fs"
	"plandex-cli/term"

	shared "plandex-shared"
)

var openUnauthenticatedCloudURL func(msg, path string)
var openAuthenticatedURL func(msg, path string)

func SetOpenUnauthenticatedCloudURLFn(fn func(msg, path string)) {
	openUnauthenticatedCloudURL = fn
}

func SetOpenAuthenticatedURLFn(fn func(msg, path string)) {
	openAuthenticatedURL = fn
}

func MustResolveAuthWithOrg() {
	MustResolveAuth(true)
}

func MustResolveAuth(requireOrg bool) {
	if apiClient == nil {
		term.OutputErrorAndExit("error resolving auth: api client not set")
	}

	// load HomeAuthPath file into ClientAuth struct
	bytes, err := os.ReadFile(fs.HomeAuthPath)

	if err != nil {
		if os.IsNotExist(err) {
			err = promptInitialAuth()

			if err != nil {
				term.OutputErrorAndExit("error resolving auth: %v", err)
			}

			return
		} else {
			term.OutputErrorAndExit("error reading auth.json: %v", err)
		}
	}

	var auth shared.ClientAuth
	err = json.Unmarshal(bytes, &auth)
	if err != nil {
		term.OutputErrorAndExit("error unmarshalling auth.json: %v", err)
	}

	Current = &auth

	if requireOrg && Current.OrgId == "" {
		term.StartSpinner("")
		orgs, apiErr := apiClient.ListOrgs()
		term.StopSpinner()

		if apiErr != nil {
			term.OutputErrorAndExit("Error listing orgs: %v", apiErr.Msg)
		}

		org, err := resolveOrgAuth(orgs, Current.IsLocalMode)

		if err != nil {
			term.OutputErrorAndExit("Error resolving org: %v", err)
		}

		if org.Id == "" {
			// still no org--exit now
			term.OutputErrorAndExit("No org")
		}

		Current.OrgId = org.Id
		Current.OrgName = org.Name
		Current.IntegratedModelsMode = org.IntegratedModelsMode

		err = writeCurrentAuth()

		if err != nil {
			term.OutputErrorAndExit("Error writing auth: %v", err)
		}
	}
}

func RefreshInvalidToken() error {
	if Current == nil {
		return fmt.Errorf("error refreshing token: auth not loaded")
	}
	res, err := verifyEmail(Current.Email, Current.Host)

	if err != nil {
		return fmt.Errorf("error verifying email: %v", err)
	}

	if res.hasAccount {
		return signIn(Current.Email, res.pin, Current.Host)
	} else {
		host := Current.Host
		if host == "" {
			host = "Plandex Cloud"
		}

		term.OutputErrorAndExit("Account %s not found on %s", Current.Email, host)
	}

	return nil
}

func RefreshAuth() error {
	if Current == nil {
		return fmt.Errorf("error refreshing auth: auth not loaded")
	}

	org, apiErr := apiClient.GetOrgSession()

	if apiErr != nil {
		return fmt.Errorf("error getting org session: %v", apiErr.Msg)
	}

	Current.OrgName = org.Name
	Current.OrgIsTrial = org.IsTrial
	Current.IntegratedModelsMode = org.IntegratedModelsMode

	err := writeCurrentAuth()

	if err != nil {
		return fmt.Errorf("error writing auth: %v", err)
	}

	return nil
}


================================================
FILE: app/cli/auth/org.go
================================================
package auth

import (
	"fmt"
	"plandex-cli/term"
	"strings"

	shared "plandex-shared"
)

func resolveOrgAuth(orgs []*shared.Org, isLocalMode bool) (*shared.Org, error) {
	var org *shared.Org
	var err error

	if len(orgs) == 0 {
		if isLocalMode {
			org, err = createOrg(isLocalMode)
		} else {
			org, err = promptNoOrgs()
		}

		if err != nil {
			return nil, fmt.Errorf("error prompting no orgs: %v", err)
		}

	} else if len(orgs) == 1 {
		org = orgs[0]
	} else {
		org, err = selectOrg(orgs, isLocalMode)

		if err != nil {
			return nil, fmt.Errorf("error selecting org: %v", err)
		}
	}

	return org, nil
}

func promptNoOrgs() (*shared.Org, error) {
	fmt.Println("🧐 You don't have access to any orgs yet.\n\nTo join an existing org, ask an admin to either invite you directly or give your whole email domain access.\n\nOtherwise, you can go ahead and create a new org.")

	shouldCreate, err := term.ConfirmYesNo("Create a new org now?")

	if err != nil {
		return nil, fmt.Errorf("error prompting create org: %v", err)
	}

	if shouldCreate {
		return createOrg(false)
	}

	return nil, nil
}

func createOrg(isLocalMode bool) (*shared.Org, error) {
	var err error
	var name string
	var autoAddDomainUsers bool

	if isLocalMode {
		name = "Local Org"
	} else {
		name, err = term.GetRequiredUserStringInput("Org name:")
	}
	if err != nil {
		return nil, fmt.Errorf("error prompting org name: %v", err)
	}

	if !isLocalMode {
		autoAddDomainUsers, err = promptAutoAddUsersIfValid(Current.Email)
		if err != nil {
			return nil, fmt.Errorf("error prompting auto add domain users: %v", err)
		}
	}

	term.StartSpinner("")
	res, apiErr := apiClient.CreateOrg(shared.CreateOrgRequest{
		Name:               name,
		AutoAddDomainUsers: autoAddDomainUsers,
	})
	term.StopSpinner()

	if apiErr != nil {
		return nil, fmt.Errorf("error creating org: %v", apiErr.Msg)
	}

	return &shared.Org{Id: res.Id, Name: name}, nil
}

func promptAutoAddUsersIfValid(email string) (bool, error) {
	userDomain := strings.Split(email, "@")[1]
	var autoAddDomainUsers bool
	var err error
	if !shared.IsEmailServiceDomain(userDomain) {
		fmt.Println("With domain auto-join, you can allow any user with an email ending in @"+userDomain, "to auto-join this org.")
		autoAddDomainUsers, err = term.ConfirmYesNo(fmt.Sprintf("Enable auto-join for %s?", userDomain))

		if err != nil {
			return false, err
		}
	}
	return autoAddDomainUsers, nil
}

const CreateOrgOption = "Create a new org"

func selectOrg(orgs []*shared.Org, isLocalMode bool) (*shared.Org, error) {
	var options []string
	for _, org := range orgs {
		options = append(options, org.Name)
	}
	options = append(options, CreateOrgOption)

	selected, err := term.SelectFromList("Select an org:", options)

	if err != nil {
		return nil, fmt.Errorf("error selecting org: %v", err)
	}

	if selected == CreateOrgOption {
		return createOrg(isLocalMode)
	}

	var selectedOrg *shared.Org
	for _, org := range orgs {
		if org.Name == selected {
			selectedOrg = org
			break
		}
	}

	if selectedOrg == nil {
		return nil, fmt.Errorf("error selecting org: org not found")
	}

	return selectedOrg, nil
}


================================================
FILE: app/cli/auth/state.go
================================================
package auth

import (
	"encoding/json"
	"fmt"
	"os"
	"plandex-cli/fs"

	shared "plandex-shared"
)

var Current *shared.ClientAuth

func loadAccounts() ([]*shared.ClientAccount, error) {
	bytes, err := os.ReadFile(fs.HomeAccountsPath)

	if err != nil {
		if os.IsNotExist(err) {
			// no accounts
			return []*shared.ClientAccount{}, nil
		} else {
			return nil, fmt.Errorf("error reading accounts.json: %v", err)
		}
	}

	var accounts []*shared.ClientAccount
	err = json.Unmarshal(bytes, &accounts)

	if err != nil {
		return nil, fmt.Errorf("error unmarshalling accounts.json: %v", err)
	}

	return accounts, nil
}

func setAuth(auth *shared.ClientAuth) error {
	err := storeAccount(&auth.ClientAccount)

	if err != nil {
		return fmt.Errorf("error storing account: %v", err)
	}

	Current = auth

	err = writeCurrentAuth()

	if err != nil {
		return fmt.Errorf("error writing auth: %v", err)
	}

	return nil
}

func storeAccount(toStore *shared.ClientAccount) error {
	accounts, err := loadAccounts()

	if err != nil {
		return fmt.Errorf("error loading accounts: %v", err)
	}

	found := false
	for i, account := range accounts {
		if account.UserId == toStore.UserId {
			accounts[i] = toStore
			found = true
			break
		}
	}

	if !found {
		accounts = append(accounts, toStore)
	}

	bytes, err := json.Marshal(accounts)

	if err != nil {
		return fmt.Errorf("error marshalling accounts: %v", err)
	}

	err = os.WriteFile(fs.HomeAccountsPath, bytes, os.ModePerm)

	if err != nil {
		return fmt.Errorf("error writing accounts: %v", err)
	}

	return nil
}

func writeCurrentAuth() error {
	if Current == nil {
		return fmt.Errorf("error writing auth: auth not loaded")
	}

	bytes, err := json.Marshal(Current)

	if err != nil {
		return fmt.Errorf("error marshalling auth: %v", err)
	}

	err = os.WriteFile(fs.HomeAuthPath, bytes, os.ModePerm)

	if err != nil {
		return fmt.Errorf("error writing auth: %v", err)
	}

	return nil
}


================================================
FILE: app/cli/auth/trial.go
================================================
package auth

import (
	"fmt"
	"plandex-cli/term"
	"time"
)

func ConvertTrial() {
	openAuthenticatedURL("Opening Plandex Cloud upgrade flow in your browser.", "/settings/billing?upgrade=1&cliUpgrade=1")

	fmt.Println("\nCommand will continue automatically once you've upgraded...")
	fmt.Println()
	term.StartSpinner("")

	startTime := time.Now()
	expirationTime := startTime.Add(1 * time.Hour)

	for time.Now().Before(expirationTime) {
		org, apiErr := apiClient.GetOrgSession()

		if apiErr != nil {
			term.StopSpinner()
			term.OutputErrorAndExit("error getting org session: %s", apiErr.Msg)
		}

		if org != nil && !org.IsTrial {
			term.StopSpinner()
			fmt.Println("🚀 Trial upgraded")
			fmt.Println()
			return
		}

		time.Sleep(1500 * time.Millisecond)
	}

	term.StopSpinner()
	term.OutputErrorAndExit("Timed out waiting for upgrade. Please try again. Email support@plandex.ai if the problem persists.")
}

func startTrial() {
	term.StartSpinner("")
	cliTrialToken, apiErr := apiClient.CreateCliTrialSession()
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("error starting trial: %s", apiErr.Msg)
	}

	openUnauthenticatedCloudURL(
		"Opening Plandex Cloud trial flow in your browser.",
		fmt.Sprintf("/start?cliTrialToken=%s", cliTrialToken),
	)

	fmt.Println("\nCommand will continue automatically once you've started your trial...")
	fmt.Println()
	term.StartSpinner("")

	startTime := time.Now()
	expirationTime := startTime.Add(1 * time.Hour)

	for time.Now().Before(expirationTime) {
		cliTrialSession, apiErr := apiClient.GetCliTrialSession(cliTrialToken)

		if apiErr != nil {
			term.StopSpinner()
			term.OutputErrorAndExit("error getting cli trial session: %s", apiErr.Msg)
		}

		if cliTrialSession != nil {
			// Trial session is valid, break the loop and sign in
			term.StopSpinner()
			fmt.Println("🚀 Trial started")
			fmt.Println()
			err := handleSignInResponse(cliTrialSession, "")
			if err != nil {
				term.OutputErrorAndExit("error signing in after trial started: %s", err)
			}
			return
		}

		time.Sleep(1500 * time.Millisecond)
	}

	term.StopSpinner()
	term.OutputErrorAndExit("Timed out waiting for trial to start. Please try again. Email support@plandex.ai if the problem persists.")
}


================================================
FILE: app/cli/cmd/apply.go
================================================
package cmd

import (
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/plan_exec"
	"plandex-cli/term"
	"plandex-cli/types"

	"github.com/spf13/cobra"
)

var autoCommit, skipCommit, autoExec bool

func init() {
	initApplyFlags(applyCmd, false)
	initExecScriptFlags(applyCmd)
	RootCmd.AddCommand(applyCmd)

	applyCmd.Flags().BoolVar(&fullAuto, "full", false, "Apply the plan and debug in full auto mode")
}

var applyCmd = &cobra.Command{
	Use:     "apply",
	Aliases: []string{"ap"},
	Short:   "Apply a plan to the project",
	Run:     apply,
}

func apply(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if fullAuto {
		term.StartSpinner("")
		config := lib.MustGetCurrentPlanConfig()
		_, updatedConfig, printFn := resolveAutoModeSilent(config)
		lib.SetCachedPlanConfig(updatedConfig)
		term.StopSpinner()
		printFn()
	}

	mustSetPlanExecFlags(cmd, true)

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	applyFlags := types.ApplyFlags{
		AutoConfirm: true,
		AutoCommit:  autoCommit,
		NoCommit:    skipCommit,
		AutoExec:    autoExec,
		NoExec:      noExec,
		AutoDebug:   autoDebug,
	}

	tellFlags := types.TellFlags{
		TellBg:      tellBg,
		TellStop:    tellStop,
		TellNoBuild: tellNoBuild,
		AutoContext: tellAutoContext,
		ExecEnabled: !noExec,
		AutoApply:   tellAutoApply,
	}

	lib.MustApplyPlan(lib.ApplyPlanParams{
		PlanId:     lib.CurrentPlanId,
		Branch:     lib.CurrentBranch,
		ApplyFlags: applyFlags,
		TellFlags:  tellFlags,
		OnExecFail: plan_exec.GetOnApplyExecFail(applyFlags, tellFlags),
	})
}


================================================
FILE: app/cli/cmd/archive.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"
	"strings"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var archiveCmd = &cobra.Command{
	Use:     "archive [name-or-index]",
	Aliases: []string{"arc"},
	Short:   "Archive a plan",
	Args:    cobra.MaximumNArgs(1),
	Run:     archive,
}

func init() {
	RootCmd.AddCommand(archiveCmd)
}

func archive(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	var nameOrIdx string
	if len(args) > 0 {
		nameOrIdx = strings.TrimSpace(args[0])
	}

	var plan *shared.Plan

	term.StartSpinner("")
	plans, apiErr := api.Client.ListPlans([]string{lib.CurrentProjectId})
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting plans: %v", apiErr)
	}

	if len(plans) == 0 {
		fmt.Println("🤷‍♂️ No plans available to archive")
		return
	}

	if nameOrIdx == "" {
		opts := make([]string, len(plans))
		for i, p := range plans {
			opts[i] = p.Name
		}

		selected, err := term.SelectFromList("Select a plan to archive", opts)
		if err != nil {
			term.OutputErrorAndExit("Error selecting plan: %v", err)
		}

		for _, p := range plans {
			if p.Name == selected {
				plan = p
				break
			}
		}
	} else {
		idx, err := strconv.Atoi(nameOrIdx)
		if err == nil && idx > 0 && idx <= len(plans) {
			plan = plans[idx-1]
		} else {
			for _, p := range plans {
				if p.Name == nameOrIdx {
					plan = p
					break
				}
			}
		}
	}

	if plan == nil {
		term.OutputErrorAndExit("Plan not found")
	}

	err := api.Client.ArchivePlan(plan.Id)
	if err != nil {
		term.OutputErrorAndExit("Error archiving plan: %v", err)
	}

	fmt.Printf("✅ Plan %s archived\n", color.New(color.Bold, term.ColorHiYellow).Sprint(plan.Name))

	fmt.Println()

	term.PrintCmds("", "plans --archived", "unarchive")
}


================================================
FILE: app/cli/cmd/billing.go
================================================
package cmd

import (
	"plandex-cli/auth"
	"plandex-cli/term"
	"plandex-cli/ui"

	"github.com/spf13/cobra"
)

var billingCmd = &cobra.Command{
	Use:   "billing",
	Short: "Open the billing page in the browser",
	Run:   billing,
}

func init() {
	RootCmd.AddCommand(billingCmd)
}

func billing(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()

	if !auth.Current.IsCloud {
		term.OutputErrorAndExit("This command is only available for Plandex Cloud accounts.")
	}

	ui.OpenAuthenticatedURL("Opening billing page in your default browser...", "/settings/billing")
}


================================================
FILE: app/cli/cmd/branches.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/format"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

var branchesCmd = &cobra.Command{
	Use:     "branches",
	Aliases: []string{"br"},
	Short:   "List plan branches",
	Run:     branches,
}

func init() {
	RootCmd.AddCommand(branchesCmd)
}

func branches(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")

	branches, apiErr := api.Client.ListBranches(lib.CurrentPlanId)

	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting branches: %v", apiErr)
		return
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetAutoWrapText(false)
	table.SetHeader([]string{"#", "Name", "Updated" /* "Created",*/, "Context", "Convo"})

	for i, b := range branches {
		num := strconv.Itoa(i + 1)
		if b.Name == lib.CurrentBranch {
			num = color.New(color.Bold, term.ColorHiGreen).Sprint(num)
		}

		var name string
		if b.Name == lib.CurrentBranch {
			name = color.New(color.Bold, term.ColorHiGreen).Sprint(b.Name) + " 👈"
		} else {
			name = b.Name
		}

		row := []string{
			num,
			name,
			format.Time(b.UpdatedAt),
			// format.Time(b.CreatedAt),
			strconv.Itoa(b.ContextTokens) + " 🪙",
			strconv.Itoa(b.ConvoTokens) + " 🪙",
		}

		var style []tablewriter.Colors
		if b.Name == lib.CurrentPlanId {
			style = []tablewriter.Colors{
				{tablewriter.FgGreenColor, tablewriter.Bold},
			}
		} else {
			style = []tablewriter.Colors{
				{tablewriter.Bold},
			}
		}

		table.Rich(row, style)

	}
	table.Render()
	fmt.Println()
	term.PrintCmds("", "checkout", "delete-branch")

}


================================================
FILE: app/cli/cmd/browser.go
================================================
package cmd

import (
	"context"
	"errors"
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	chrome_log "github.com/chromedp/cdproto/log"
	chrome_runtime "github.com/chromedp/cdproto/runtime"
	"github.com/chromedp/cdproto/target"
	"github.com/chromedp/chromedp"
	"github.com/spf13/cobra"
)

var timeoutSeconds int

// browserCmd is our cobra command
var browserCmd = &cobra.Command{
	Use:   "browser [urls...]",
	Short: "Open browser windows with given URLs, capturing console logs and exiting on JS errors",
	RunE:  browser,
}

func init() {
	RootCmd.AddCommand(browserCmd)
	browserCmd.Flags().IntVar(&timeoutSeconds, "timeout", 10, "Timeout in seconds for browser to load")
}

// browser is the main function for our command.
func browser(cmd *cobra.Command, args []string) error {
	if len(args) == 0 {
		return errors.New("no URLs provided")
	}

	// See if we can find Chrome or Firefox in PATH:
	chromePath, _ := findChrome()

	if chromePath != "" {
		fmt.Println("Using Chrome (not default browser, but found in PATH).")
		return openChromeWithLogs(args)
	}

	// Fallback: open with OS default tool (open/xdg-open)
	fmt.Println("No Chrome or Firefox found; falling back to OS default opener.")
	return openWithOSDefault(args)
}

// findChrome returns the path to Chrome/Chromium if found, or "" if not found.
func findChrome() (string, error) {
	switch runtime.GOOS {
	case "darwin":
		// macOS standard installation paths
		macPaths := []string{
			"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
			"/Applications/Chromium.app/Contents/MacOS/Chromium",
		}
		for _, p := range macPaths {
			if _, err := os.Stat(p); err == nil {
				return p, nil
			}
		}
	case "linux", "freebsd":
		// Linux/FreeBSD (usually in PATH)
		candidates := []string{
			"google-chrome",
			"google-chrome-stable",
			"chromium",
			"chromium-browser",
		}
		for _, c := range candidates {
			if path, err := exec.LookPath(c); err == nil {
				return path, nil
			}
		}
	}
	return "", errors.New("Chrome/Chromium not found")
}

var pages = map[target.ID]string{}

// openChromeWithLogs uses chromedp to open each URL in a visible Chrome browser,
// logs JS console messages, and exits on the first JS error (or if user presses Ctrl+C).
func openChromeWithLogs(urls []string) error {
	if len(urls) == 0 {
		return errors.New("no URLs provided")
	}

	fmt.Println("Launching Chrome with console log capture...")
	// 1) Create a cancellable context that sets up a Chrome ExecAllocator
	rootCtx, cancelAllocator := chromedp.NewExecAllocator(context.Background(),
		chromedp.Flag("headless", false), // Visible, not headless
		chromedp.Flag("disable-gpu", false),
		chromedp.Flag("no-first-run", true),             // Avoid "Welcome" dialog
		chromedp.Flag("no-default-browser-check", true), // Avoid default browser dialog
		chromedp.Flag("disable-default-apps", true),     // Prevent default apps/extensions from loading
		chromedp.Flag("remote-debugging-port", "0"),     // Ensures separate debug session
	)
	defer cancelAllocator()

	// 2) Create a new browser context from the allocator
	browserCtx, cancelBrowser := chromedp.NewContext(rootCtx)
	defer cancelBrowser()

	// Add this to get the initial target
	var initialTargetID target.ID
	chromedp.ListenTarget(browserCtx, func(ev interface{}) {
		if e, ok := ev.(*target.EventTargetCreated); ok {
			// fmt.Printf("[DEBUG] Got event: %#v\n", e)
			if e.TargetInfo.Type == "page" {
				initialTargetID = e.TargetInfo.TargetID
			}
		}
	})

	if err := chromedp.Run(
		browserCtx,
		chrome_runtime.Enable(),
		chrome_log.Enable(),
	); err != nil {
		log.Fatal(err)
	}

	// Listen for console API calls & JS exceptions
	chromedp.ListenBrowser(browserCtx, func(ev interface{}) {
		// fmt.Printf("[DEBUG] Got event: %#v\n", ev)
		switch e := ev.(type) {

		case *target.EventTargetCreated:
		case *target.EventAttachedToTarget:
			// This sometimes also includes target info
			info := e.TargetInfo
			if info.Type == "page" {
				url := info.URL
				if url == "about:blank" {
					url = urls[0]
				}
				pages[info.TargetID] = url
			}

		case *target.EventTargetDestroyed:
			// Something was destroyed
			destroyedID := e.TargetID
			// Check if it was a top-level page
			if url, ok := pages[destroyedID]; ok {
				fmt.Printf("[CHROME] Closed page: %s\n", url)
				// remove from map
				delete(pages, destroyedID)
				// If that was your last page, do something:
				if len(pages) == 0 {
					cancelBrowser()
					cancelAllocator()
					os.Exit(0)
				} else {
					fmt.Printf("num pages left: %d\n", len(pages))
				}
			}
		}
	})

	// Channels to handle signals & error detection
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	errChan := make(chan bool, 1)

	// 3) Open all URLs in new tabs
	for i, url := range urls {
		// Reuse the initial browser tab for the first URL
		var ctx context.Context
		if i == 0 {
			ctx, _ = chromedp.NewContext(browserCtx, chromedp.WithTargetID(initialTargetID))
		} else {
			// Create a new tab for each additional URL
			ctx, _ = chromedp.NewContext(browserCtx)
		}
		tabCtx, _ := context.WithTimeout(ctx, time.Duration(timeoutSeconds)*time.Second)

		chromedp.ListenTarget(tabCtx, func(ev interface{}) {
			switch e := ev.(type) {
			case *chrome_runtime.EventConsoleAPICalled:
				logType := e.Type.String()
				for _, arg := range e.Args {
					val := arg.Value
					fmt.Printf("[CHROME:%s] %v\n", logType, val)
					if logType == "error" {
						fmt.Println("❌ Chrome console error")
						errChan <- true
					}
				}
			case *chrome_log.EventEntryAdded:
				fmt.Printf("[CHROME:Log:%s] %s\n", e.Entry.Level, e.Entry.Text)
			case *chrome_runtime.EventExceptionThrown:
				fmt.Printf("[CHROME:Exception] %s\n", e.ExceptionDetails.Error())
				fmt.Println("❌ JavaScript exception")
				errChan <- true
			}
		})

		if err := chromedp.Run(
			tabCtx,
			chrome_runtime.Enable(),
			chrome_log.Enable(),
			chromedp.Navigate(url),
			chromedp.WaitReady("body", chromedp.ByQuery),
		); err != nil {
			fmt.Printf("Failed to load url %s: %v", url, err)
			cancelBrowser()
			cancelAllocator()
			os.Exit(1)
		} else {
			fmt.Printf("Opened (%d/%d): %s\n", i+1, len(urls), url)
		}
	}

	fmt.Println("Chrome is running, waiting for error or interrupt...")

	// 4) Wait forever, or until an error or signal
	select {
	case <-sigChan:
		fmt.Println("\n⚠️  Plandex browser process interrupted")
		return nil
	case <-rootCtx.Done():
		fmt.Println("\n⚠️  Plandex browser process closed")
		return nil
	case <-errChan:
		fmt.Println("\n❌ Plandex browser process exited due to JavaScript error")
		cancelBrowser()
		cancelAllocator()
		os.Exit(1)
	}
	return nil
}

func openWithOSDefault(urls []string) error {
	var openCmd string
	switch runtime.GOOS {
	case "darwin":
		openCmd = "open"
	case "linux", "freebsd":
		openCmd = "xdg-open"
	default:
		return errors.New("unsupported OS for fallback")
	}

	for _, url := range urls {
		cmd := exec.Command(openCmd, url)
		if err := cmd.Start(); err != nil {
			log.Printf("Failed to open %s with %s: %v", url, openCmd, err)
		}
	}
	return nil
}


================================================
FILE: app/cli/cmd/build.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/plan_exec"
	"plandex-cli/term"
	"plandex-cli/types"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var buildCmd = &cobra.Command{
	Use:     "build",
	Aliases: []string{"b"},
	Short:   "Build pending changes",
	// Long:  ``,
	Args: cobra.NoArgs,
	Run:  build,
}

func init() {
	RootCmd.AddCommand(buildCmd)

	initExecFlags(buildCmd, initExecFlagsParams{
		omitFile:         true,
		omitNoBuild:      true,
		omitEditor:       true,
		omitStop:         true,
		omitAutoContext:  true,
		omitSmartContext: true,
	})
}

func build(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	mustSetPlanExecFlags(cmd, false)

	didBuild, err := plan_exec.Build(plan_exec.ExecParams{
		CurrentPlanId: lib.CurrentPlanId,
		CurrentBranch: lib.CurrentBranch,
		AuthVars:      lib.MustVerifyAuthVars(auth.Current.IntegratedModelsMode),
		CheckOutdatedContext: func(maybeContexts []*shared.Context, projectPaths *types.ProjectPaths) (bool, bool, error) {
			auto := autoConfirm || tellAutoApply || tellAutoContext
			return lib.CheckOutdatedContextWithOutput(auto, auto, maybeContexts, projectPaths)
		},
	}, types.BuildFlags{
		BuildBg:   tellBg,
		AutoApply: tellAutoApply,
	})

	if err != nil {
		term.OutputErrorAndExit("Error building plan: %v", err)
	}

	if !didBuild {
		fmt.Println()
		term.PrintCmds("", "log", "tell", "continue")
		return
	}

	if tellBg {
		fmt.Println("🏗️ Building plan in the background")
		fmt.Println()
		term.PrintCmds("", "ps", "connect", "stop")
	} else if tellAutoApply {
		applyFlags := types.ApplyFlags{
			AutoConfirm: true,
			AutoCommit:  autoCommit,
			NoCommit:    !autoCommit,
			NoExec:      noExec,
			AutoExec:    autoExec,
			AutoDebug:   autoDebug,
		}

		tellFlags := types.TellFlags{
			AutoContext: tellAutoContext,
			ExecEnabled: !noExec,
			AutoApply:   tellAutoApply,
		}

		lib.MustApplyPlan(lib.ApplyPlanParams{
			PlanId:     lib.CurrentPlanId,
			Branch:     lib.CurrentBranch,
			ApplyFlags: applyFlags,
			TellFlags:  tellFlags,
			OnExecFail: plan_exec.GetOnApplyExecFail(applyFlags, tellFlags),
		})
	} else {
		fmt.Println()
		term.PrintCmds("", "diff", "diff --ui", "apply", "reject", "log")
	}
}


================================================
FILE: app/cli/cmd/cd.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"
	"strings"
	"time"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

func init() {
	RootCmd.AddCommand(cdCmd)
}

var cdCmd = &cobra.Command{
	Use:     "cd [name-or-index]",
	Aliases: []string{"set-plan"},
	Short:   "Set current plan by name or index",
	Args:    cobra.MaximumNArgs(1),
	Run:     cd,
}

func cd(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	var nameOrIdx string
	if len(args) > 0 {
		nameOrIdx = strings.TrimSpace(args[0])
	}

	var plan *shared.Plan

	term.StartSpinner("")
	plans, apiErr := api.Client.ListPlans([]string{lib.CurrentProjectId})
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting plans: %v", apiErr)
	}

	if len(plans) == 0 {
		fmt.Println("🤷‍♂️ No plans")
		fmt.Println()
		term.PrintCmds("", "new")
		return
	}

	if nameOrIdx == "" {

		opts := make([]string, len(plans))
		for i, plan := range plans {
			opts[i] = plan.Name
		}

		selected, err := term.SelectFromList("Select a plan", opts)

		if err != nil {
			term.OutputErrorAndExit("Error selecting plan: %v", err)
		}

		for _, p := range plans {
			if p.Name == selected {
				plan = p
				break
			}
		}
	} else {
		// see if it's an index
		idx, err := strconv.Atoi(nameOrIdx)

		if err == nil {
			if idx > 0 && idx <= len(plans) {
				plan = plans[idx-1]
			} else {
				term.OutputErrorAndExit("Plan index out of range")
			}
		} else {
			for _, p := range plans {
				if p.Name == nameOrIdx {
					plan = p
					break
				}
			}
		}
	}

	if plan == nil {
		term.OutputErrorAndExit("Plan not found")
	}

	err := lib.WriteCurrentPlan(plan.Id)
	if err != nil {
		term.OutputErrorAndExit("Error setting current plan: %v", err)
	}

	// reload current plan, which will also handle setting the right branch
	lib.MustLoadCurrentPlan()

	// fire and forget SetProjectPlan request (we don't care about the response or errors)
	// this only matters for setting the current plan on a new device (i.e. when the current plan is not set)
	go api.Client.SetProjectPlan(lib.CurrentProjectId, shared.SetProjectPlanRequest{PlanId: plan.Id})

	// give the SetProjectPlan request some time to be sent before exiting
	time.Sleep(50 * time.Millisecond)

	fmt.Println("✅ Changed current plan to " + color.New(term.ColorHiGreen, color.Bold).Sprint(plan.Name))

	fmt.Println()
	term.PrintCmds("", "current")
}


================================================
FILE: app/cli/cmd/chat.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/plan_exec"
	"plandex-cli/types"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var chatCmd = &cobra.Command{
	Use:     "chat [prompt]",
	Aliases: []string{"c"},
	Short:   "Chat without making changes",
	// Long:  ``,
	Args: cobra.RangeArgs(0, 1),
	Run:  doChat,
}

func init() {
	RootCmd.AddCommand(chatCmd)

	initExecFlags(chatCmd, initExecFlagsParams{
		omitNoBuild:      true,
		omitStop:         true,
		omitBg:           true,
		omitApply:        true,
		omitExec:         true,
		omitSmartContext: true,
		omitSkipMenu:     true,
	})

}

func doChat(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()
	mustSetPlanExecFlags(cmd, false)

	prompt := getTellPrompt(args)

	if prompt == "" {
		fmt.Println("🤷‍♂️ No prompt to send")
		return
	}

	plan_exec.TellPlan(plan_exec.ExecParams{
		CurrentPlanId: lib.CurrentPlanId,
		CurrentBranch: lib.CurrentBranch,
		AuthVars:      lib.MustVerifyAuthVars(auth.Current.IntegratedModelsMode),
		CheckOutdatedContext: func(maybeContexts []*shared.Context, projectPaths *types.ProjectPaths) (bool, bool, error) {
			auto := autoConfirm || tellAutoApply || tellAutoContext
			return lib.CheckOutdatedContextWithOutput(auto, auto, maybeContexts, projectPaths)
		},
	}, prompt, types.TellFlags{
		IsChatOnly:      true,
		AutoContext:     tellAutoContext,
		SkipChangesMenu: tellSkipMenu,
	})
}


================================================
FILE: app/cli/cmd/checkout.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"
	"strings"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

const (
	OptCreateNewBranch = "Create a new branch"
)

var confirmCreateBranch bool

var checkoutCmd = &cobra.Command{
	Use:     "checkout [name-or-index]",
	Aliases: []string{"co"},
	Short:   "Checkout an existing plan branch or create a new one",
	Run:     checkout,
	Args:    cobra.MaximumNArgs(1),
}

func init() {
	RootCmd.AddCommand(checkoutCmd)
	checkoutCmd.Flags().BoolVarP(&confirmCreateBranch, "yes", "y", false, "Confirm creating a new branch")
}

func checkout(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	branchName := ""
	willCreate := false

	var nameOrIdx string
	if len(args) > 0 {
		nameOrIdx = strings.TrimSpace(args[0])
	}

	term.StartSpinner("")
	branches, apiErr := api.Client.ListBranches(lib.CurrentPlanId)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting branches: %v", apiErr)
		return
	}

	if nameOrIdx != "" {
		idx, err := strconv.Atoi(nameOrIdx)

		if err == nil {
			if idx > 0 && idx <= len(branches) {
				branchName = branches[idx-1].Name
			} else {
				term.OutputErrorAndExit("Branch %d not found", idx)
			}
		} else {
			for _, b := range branches {
				if b.Name == nameOrIdx {
					branchName = b.Name
					break
				}
			}
		}

		if branchName == "" {
			fmt.Printf("🌱 Branch %s not found\n", color.New(color.Bold, term.ColorHiCyan).Sprint(nameOrIdx))

			if confirmCreateBranch {
				fmt.Println("✅ --yes flag set, will create branch")
				branchName = nameOrIdx
				willCreate = true
			} else {
				res, err := term.ConfirmYesNo("Create it now?")

				if err != nil {
					term.OutputErrorAndExit("Error getting user input: %v", err)
				}

				if res {
					branchName = nameOrIdx
					willCreate = true
				} else {
					return
				}
			}
		}

	}

	if nameOrIdx == "" {
		opts := make([]string, len(branches))
		for i, branch := range branches {
			opts[i] = branch.Name
		}
		opts = append(opts, OptCreateNewBranch)

		selected, err := term.SelectFromList("Select a branch", opts)

		if err != nil {
			term.OutputErrorAndExit("Error selecting branch: %v", err)
			return
		}

		if selected == OptCreateNewBranch {
			branchName, err = term.GetRequiredUserStringInput("Branch name")
			if err != nil {
				term.OutputErrorAndExit("Error getting branch name: %v", err)
				return
			}
			willCreate = true
		} else {
			branchName = selected
		}
	}

	if branchName == "" {
		term.OutputErrorAndExit("Branch not found")
	}

	term.StartSpinner("")
	if willCreate {
		err := api.Client.CreateBranch(lib.CurrentPlanId, lib.CurrentBranch, shared.CreateBranchRequest{Name: branchName})

		if err != nil {
			term.OutputErrorAndExit("Error creating branch: %v", err)
			return
		}

		// fmt.Printf("✅ Created branch %s\n", color.New(color.Bold, term.ColorHiGreen).Sprint(branchName))
	}

	err := lib.WriteCurrentBranch(branchName)

	if err != nil {
		term.OutputErrorAndExit("Error setting current branch: %v", err)
		return
	}

	updatedModelSettings, err := lib.SaveLatestPlanModelSettingsIfNeeded()
	term.StopSpinner()
	if err != nil {
		term.OutputErrorAndExit("Error saving model settings: %v", err)
	}

	term.StopSpinner()

	fmt.Printf("✅ Checked out branch %s\n", color.New(color.Bold, term.ColorHiGreen).Sprint(branchName))

	if updatedModelSettings {
		fmt.Println()
		fmt.Println("🧠 Model settings file updated → ", lib.GetPlanModelSettingsPath(lib.CurrentPlanId))
	}

	fmt.Println()
	term.PrintCmds("", "load", "tell", "branches", "delete-branch")

}


================================================
FILE: app/cli/cmd/claude_max.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var connectClaudeCmd = &cobra.Command{
	Use:   "connect-claude",
	Short: "Connect your Claude Pro or Max subscription",
	Run:   connectClaude,
}

var disconnectClaudeCmd = &cobra.Command{
	Use:   "disconnect-claude",
	Short: "Disconnect your Claude Pro or Max subscription",
	Run:   disconnectClaude,
}

var claudeStatusCmd = &cobra.Command{
	Use:   "claude-status",
	Short: "Check the status of your Claude Pro or Max subscription",
	Run:   claudeStatus,
}

func connectClaude(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.ConnectClaudeMax()
}

func disconnectClaude(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.DisconnectClaudeMax()
}

func claudeStatus(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()

	creds, err := lib.GetAccountCredentials()
	if err != nil {
		term.OutputErrorAndExit("Error getting account credentials: %v", err)
	}

	orgUserConfig := lib.MustGetOrgUserConfig()

	connected := creds.ClaudeMax != nil && orgUserConfig.UseClaudeSubscription

	if connected {
		fmt.Println("✅ Claude Pro or Max subscription is connected")

		// if orgUserConfig.IsClaudeSubscriptionCooldownActive() {
		if true {
			fmt.Println()
			color.New(term.ColorHiYellow, color.Bold).Println("⏳ You've reached your Claude Pro or Max subscription quota")
			fmt.Println("The next provider with valid credentials will be used for Anthropic models until the quota resets")
			fmt.Println()
		}

		term.PrintCmds("", "disconnect-claude")
	} else {
		fmt.Println("❌ No Claude Pro or Max subscription is connected")
		term.PrintCmds("", "connect-claude")
	}
}

func init() {
	RootCmd.AddCommand(connectClaudeCmd)
	RootCmd.AddCommand(disconnectClaudeCmd)
	RootCmd.AddCommand(claudeStatusCmd)
}


================================================
FILE: app/cli/cmd/clear.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var clearCmd = &cobra.Command{
	Use:   "clear",
	Short: "Clear all context",
	Long:  `Clear all context.`,
	Run:   clearAllContext,
}

func clearAllContext(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")
	contexts, err := api.Client.ListContext(lib.CurrentPlanId, lib.CurrentBranch)
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Error retrieving context: %v", err)
	}

	deleteIds := map[string]bool{}

	for _, context := range contexts {
		deleteIds[context.Id] = true
	}

	if len(deleteIds) > 0 {
		res, err := api.Client.DeleteContext(lib.CurrentPlanId, lib.CurrentBranch, shared.DeleteContextRequest{
			Ids: deleteIds,
		})

		if err != nil {
			term.OutputErrorAndExit("Error deleting context: %v", err)
		}

		fmt.Println("✅ " + res.Msg)
	} else {
		fmt.Println("🤷‍♂️ No context removed")
	}

}

func init() {
	RootCmd.AddCommand(clearCmd)
}


================================================
FILE: app/cli/cmd/config.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

func init() {
	RootCmd.AddCommand(configCmd)
	configCmd.AddCommand(defaultConfigCmd)
}

var configCmd = &cobra.Command{
	Use:   "config",
	Short: "Show plan config",
	Run:   config,
}

var defaultConfigCmd = &cobra.Command{
	Use:   "default",
	Short: "Show default config for new plans",
	Run:   defaultConfig,
}

func config(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")

	config, apiErr := api.Client.GetPlanConfig(lib.CurrentPlanId)
	if apiErr != nil {
		term.StopSpinner()
		term.OutputErrorAndExit("Error getting config: %v", apiErr.Msg)
		return
	}

	term.StopSpinner()

	color.New(color.Bold, term.ColorHiCyan).Println("⚙️  Plan Config")
	lib.ShowPlanConfig(config, "")
	fmt.Println()

	term.PrintCmds("", "set-config", "config default", "set-config default")
}

func defaultConfig(cmd *cobra.Command, args []string) {
	auth.MustResolveAuth(false)

	term.StartSpinner("")
	config, err := api.Client.GetDefaultPlanConfig()
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Error getting default config: %v", err)
		return
	}

	color.New(color.Bold, term.ColorHiCyan).Println("⚙️  Default Config")
	lib.ShowPlanConfig(config, "")
	fmt.Println()

	term.PrintCmds("", "set-config default", "config", "set-config")
}


================================================
FILE: app/cli/cmd/connect.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/stream"
	streamtui "plandex-cli/stream_tui"
	"plandex-cli/term"

	"github.com/spf13/cobra"
)

var connectCmd = &cobra.Command{
	Use:     "connect [stream-id-or-plan] [branch]",
	Aliases: []string{"conn"},
	Short:   "Connect to an active stream",
	// Long:  ``,
	Args: cobra.MaximumNArgs(2),
	Run:  connect,
}

func init() {
	RootCmd.AddCommand(connectCmd)

}

func connect(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	planId, branch, shouldContinue := lib.SelectActiveStream(args)

	if !shouldContinue {
		return
	}

	term.StartSpinner("")
	apiErr := api.Client.ConnectPlan(planId, branch, stream.OnStreamPlan)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error connecting to stream: %v", apiErr)
	}

	go func() {
		err := streamtui.StartStreamUI("", false, true)

		if err != nil {
			term.OutputErrorAndExit("Error starting stream UI", err)
		}

		fmt.Println()
		term.PrintCmds("", "diff", "diff --ui", "apply", "reject", "log")

		os.Exit(0)
	}()

	// Wait for the stream to finish
	select {}
}


================================================
FILE: app/cli/cmd/context_show.go
================================================
package cmd

import (
	"fmt"
	"log"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"strconv"

	"github.com/spf13/cobra"
)

func init() {
	RootCmd.AddCommand(contextShowCmd)
}

var contextShowCmd = &cobra.Command{
	Use:   "show [name-or-index]",
	Short: "Show the body of a context by name or list index",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		auth.MustResolveAuthWithOrg()
		lib.MustResolveProject()

		nameOrIndex := args[0]

		// Get list of contexts first
		contexts, err := api.Client.ListContext(lib.CurrentPlanId, lib.CurrentBranch)
		if err != nil {
			log.Printf("Error listing contexts: %v\n", err)
			return fmt.Errorf("error listing contexts: %v", err)
		}

		var contextId string

		// Try parsing as index first
		if idx, err := strconv.Atoi(nameOrIndex); err == nil {
			// Convert to 0-based index
			idx--
			if idx < 0 || idx >= len(contexts) {
				return fmt.Errorf("invalid context index: %s", nameOrIndex)
			}
			contextId = contexts[idx].Id
		} else {
			// Try finding by name
			found := false
			for _, ctx := range contexts {
				if ctx.Name == nameOrIndex || ctx.FilePath == nameOrIndex {
					contextId = ctx.Id
					found = true
					break
				}
			}
			if !found {
				return fmt.Errorf("no context found with name: %s", nameOrIndex)
			}
		}

		res, apiErr := api.Client.GetContextBody(lib.CurrentPlanId, lib.CurrentBranch, contextId)
		if apiErr != nil {
			log.Printf("Error getting context body: %v\n", apiErr)
			return fmt.Errorf("error getting context body: %v", apiErr)
		}

		fmt.Println(res.Body)
		return nil
	},
}


================================================
FILE: app/cli/cmd/continue.go
================================================
package cmd

import (
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/plan_exec"
	"plandex-cli/types"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var (
	chatOnly bool
)

var continueCmd = &cobra.Command{
	Use:     "continue",
	Aliases: []string{"c"},
	Short:   "Continue the plan",
	Run:     doContinue,
}

func init() {
	RootCmd.AddCommand(continueCmd)

	continueCmd.Flags().BoolVar(&chatOnly, "chat", false, "Continue in chat mode (no file changes)")

	initExecFlags(continueCmd, initExecFlagsParams{
		omitFile:   true,
		omitEditor: true,
	})
}

func doContinue(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()
	mustSetPlanExecFlags(cmd, false)

	tellFlags := types.TellFlags{
		TellBg:          tellBg,
		TellStop:        tellStop,
		TellNoBuild:     tellNoBuild,
		IsUserContinue:  true,
		ExecEnabled:     !noExec,
		AutoContext:     tellAutoContext,
		SmartContext:    tellSmartContext,
		AutoApply:       tellAutoApply,
		IsChatOnly:      chatOnly,
		SkipChangesMenu: tellSkipMenu,
	}

	plan_exec.TellPlan(plan_exec.ExecParams{
		CurrentPlanId: lib.CurrentPlanId,
		CurrentBranch: lib.CurrentBranch,
		AuthVars:      lib.MustVerifyAuthVars(auth.Current.IntegratedModelsMode),
		CheckOutdatedContext: func(maybeContexts []*shared.Context, projectPaths *types.ProjectPaths) (bool, bool, error) {
			auto := autoConfirm || tellAutoApply || tellAutoContext

			return lib.CheckOutdatedContextWithOutput(auto, auto, maybeContexts, projectPaths)
		},
	}, "", tellFlags)

	if tellAutoApply {
		applyFlags := types.ApplyFlags{
			AutoConfirm: true,
			AutoCommit:  autoCommit,
			NoCommit:    !autoCommit,
			AutoExec:    autoExec,
			NoExec:      noExec,
			AutoDebug:   autoDebug,
		}

		lib.MustApplyPlan(lib.ApplyPlanParams{
			PlanId:     lib.CurrentPlanId,
			Branch:     lib.CurrentBranch,
			ApplyFlags: applyFlags,
			TellFlags:  tellFlags,
			OnExecFail: plan_exec.GetOnApplyExecFail(applyFlags, tellFlags),
		})
	}
}


================================================
FILE: app/cli/cmd/convo.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"regexp"
	"strings"
	"time"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var plainTextOutput bool
var convoRaw bool

// convoCmd represents the convo command
var convoCmd = &cobra.Command{
	Use:   "convo [msg-range]",
	Short: "Display complete conversation history",
	Long:  `Display complete conversation history. Optionally specify a message number or range of messages (e.g. '1' or '5' or '1-5' or '5-')`,
	Run:   convo,
}

func init() {
	RootCmd.AddCommand(convoCmd)

	convoCmd.Flags().BoolVarP(&plainTextOutput, "plain", "p", false, "Output conversation in plain text with no ANSI codes")

	// for debugging output
	convoCmd.Flags().BoolVar(&convoRaw, "raw", false, "Output conversation in raw format")
	convoCmd.Flags().MarkHidden("raw")
}

const stoppedEarlyMsg = "You stopped the reply early"

func convo(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	term.StartSpinner("")
	conversation, apiErr := api.Client.ListConvo(lib.CurrentPlanId, lib.CurrentBranch)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error loading conversation: %v", apiErr.Msg)
	}

	if len(conversation) == 0 {
		fmt.Println("🤷‍♂️ No conversation history")
		return
	}

	var msgRange string
	var msgRangeStart, msgRangeEnd int
	if len(args) > 0 {
		msgRange = args[0]
	}
	if msgRange != "" {
		// validate either a number or a range of numbers
		if strings.Contains(msgRange, "-") {
			_, err := fmt.Sscanf(msgRange, "%d-%d", &msgRangeStart, &msgRangeEnd)
			if err != nil {
				_, err := fmt.Sscanf(msgRange, "%d-", &msgRangeStart)

				if err != nil {
					term.OutputErrorAndExit("Invalid message range: %s", msgRange)
				}

				msgRangeEnd = len(conversation)
			}
		} else {
			_, err := fmt.Sscanf(msgRange, "%d", &msgRangeStart)
			if err != nil {
				term.OutputErrorAndExit("Invalid message number: %s", msgRange)
			}
			msgRangeEnd = msgRangeStart
		}
	}

	var convo string
	var totalTokens int
	var didCut bool
	for i, msg := range conversation {
		if msgRangeStart > 0 && msg.Num < msgRangeStart {
			didCut = true
			continue
		}
		if msgRangeEnd > 0 && msg.Num > msgRangeEnd {
			didCut = true
			break
		}

		var author string
		if msg.Role == "assistant" {
			author = "🤖 Plandex"
		} else if msg.Role == "user" {
			author = "💬 You"
		} else {
			author = msg.Role
		}

		replyTags := msg.Flags.GetReplyTags()

		// format as above but start with day of week
		formattedTs := msg.CreatedAt.Local().Format("Mon Jan 2, 2006 | 3:04pm MST")

		// if it's today then use 'Today' instead of the date
		if msg.CreatedAt.Day() == time.Now().Day() {
			formattedTs = msg.CreatedAt.Local().Format("Today | 3:04pm MST")
		}

		// if it's yesterday then use 'Yesterday' instead of the date
		if msg.CreatedAt.Day() == time.Now().AddDate(0, 0, -1).Day() {
			formattedTs = msg.CreatedAt.Local().Format("Yesterday | 3:04pm MST")
		}

		var header string
		if len(replyTags) > 0 {
			header = fmt.Sprintf("#### %d | %s | %s | %s | %d 🪙 ", i+1,
				author, strings.Join(replyTags, " | "), formattedTs, msg.Tokens)
		} else {
			header = fmt.Sprintf("#### %d | %s | %s | %d 🪙 ", i+1,
				author, formattedTs, msg.Tokens)
		}

		txt := msg.Message
		if !convoRaw {
			txt = convertCodeBlocks(msg.Message)
		}

		if plainTextOutput {
			convo += header + "\n" + txt + "\n\n"
		} else {
			md, err := term.GetMarkdown(header + "\n" + txt + "\n\n")
			if err != nil {
				term.OutputErrorAndExit("Error creating markdown representation: %v", err)
			}
			convo += md
		}

		if !didCut && msg.Stopped {
			if plainTextOutput {
				convo += fmt.Sprintf(" 🛑 %s\n\n", stoppedEarlyMsg)
			} else {
				convo += fmt.Sprintf(" 🛑 %s\n\n", color.New(color.Bold).Sprint(stoppedEarlyMsg))
			}
		}

		totalTokens += msg.Tokens
	}

	if !plainTextOutput {
		convo = strings.ReplaceAll(convo, stoppedEarlyMsg, color.New(term.ColorHiRed).Sprint(stoppedEarlyMsg))
	}

	output :=
		fmt.Sprintf("\n%s", convo)

	if !plainTextOutput && !didCut {
		output += term.GetDivisionLine() +
			color.New(color.Bold, term.ColorHiCyan).Sprint("  Conversation size →") + fmt.Sprintf(" %d 🪙", totalTokens) + "\n\n"
	}

	if plainTextOutput {
		fmt.Println(output)
	} else {
		term.PageOutput(output)

		fmt.Println()
		term.PrintCmds("", "convo 1", "convo 2-5", "convo --plain", "log")
	}
}

var codeBlockPattern = regexp.MustCompile(`<PlandexBlock\s+lang="(.+?)".*?>([\s\S]+?)</PlandexBlock>`)

func convertCodeBlocks(msg string) string {
	return codeBlockPattern.ReplaceAllStringFunc(msg, func(match string) string {
		// Extract language and content from the match
		submatches := codeBlockPattern.FindStringSubmatch(match)
		lang := submatches[1]
		content := submatches[2]

		// Escape any backticks in the content
		content = strings.ReplaceAll(content, "```", "\\`\\`\\`")

		// Return markdown code block format
		return fmt.Sprintf("```%s%s```", lang, content)
	})
}


================================================
FILE: app/cli/cmd/current.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var currentCmd = &cobra.Command{
	Use:     "current",
	Aliases: []string{"cu"},
	Short:   "Get the current plan",
	Run:     current,
}

func init() {
	RootCmd.AddCommand(currentCmd)
}

func current(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MaybeResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")
	plan, err := api.Client.GetPlan(lib.CurrentPlanId)
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Error getting plan: %v", err)
		return
	}

	currentBranchesByPlanId, err := api.Client.GetCurrentBranchByPlanId(lib.CurrentProjectId, shared.GetCurrentBranchByPlanIdRequest{
		CurrentBranchByPlanId: map[string]string{
			lib.CurrentPlanId: lib.CurrentBranch,
		},
	})

	if err != nil {
		term.OutputErrorAndExit("Error getting current branches: %v", err)
	}

	table := lib.GetCurrentPlanTable(plan, currentBranchesByPlanId, nil)
	fmt.Println(table)

	term.PrintCmds("", "tell", "ls", "plans")

}


================================================
FILE: app/cli/cmd/debug.go
================================================
package cmd

import (
	"bufio"
	"context"
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/plan_exec"
	"plandex-cli/term"
	"plandex-cli/types"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

const DebugDefaultTries = 5

var debugCmd = &cobra.Command{
	Use:     "debug [tries] <cmd>",
	Aliases: []string{"db"},
	Short:   "Debug a failing command with Plandex",
	Args:    cobra.MinimumNArgs(1),
	Run:     doDebug,
}

func init() {
	RootCmd.AddCommand(debugCmd)
	debugCmd.Flags().BoolVarP(&autoCommit, "commit", "c", false, "Commit changes after successful execution")
}

func doDebug(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()
	mustSetPlanExecFlags(cmd, false)

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	// Parse tries and command
	tries := DebugDefaultTries
	cmdArgs := args

	// Check if first arg is tries count
	if val, err := strconv.Atoi(args[0]); err == nil {
		if val <= 0 {
			term.OutputErrorAndExit("Tries must be greater than 0")
		}
		tries = val
		cmdArgs = args[1:]
		if len(cmdArgs) == 0 {
			term.OutputErrorAndExit("No command specified")
		}
	}

	// Get current working directory
	cwd, err := os.Getwd()
	if err != nil {
		term.OutputErrorAndExit("Failed to get working directory: %v", err)
	}

	cmdStr := strings.Join(cmdArgs, " ")

	// Execute command and handle retries
	for attempt := 0; attempt < tries; attempt++ {
		// Use shell to handle operators like && and |
		shellCmdStr := "set -euo pipefail; " + cmdStr
		execCmd := exec.Command("sh", "-c", shellCmdStr)
		execCmd.Dir = cwd
		execCmd.Env = os.Environ()
		lib.SetPlatformSpecificAttrs(execCmd)

		pipe, err := execCmd.StdoutPipe()
		if err != nil {
			term.StopSpinner()
			term.OutputErrorAndExit("Failed to create pipe: %v", err)
		}
		execCmd.Stderr = execCmd.Stdout

		if err := execCmd.Start(); err != nil {
			term.StopSpinner()
			term.OutputErrorAndExit("Failed to start command: %v", err)
		}

		maybeDeleteCgroup := lib.MaybeIsolateCgroup(execCmd)

		ctx, cancel := context.WithCancel(context.Background())
		var interrupted atomic.Bool
		var interruptHandled atomic.Bool
		var interruptWG sync.WaitGroup

		sigChan := make(chan os.Signal, 1)
		signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)

		interruptWG.Add(1)
		go func() {
			defer interruptWG.Done()
			for {
				select {
				case sig := <-sigChan:
					if interruptHandled.CompareAndSwap(false, true) {
						fmt.Println()
						color.New(term.ColorHiYellow, color.Bold).Println("\n👉 Caught interrupt. Exiting gracefully...")
						interrupted.Store(true)

						var sysSig syscall.Signal

						switch sig {
						case os.Interrupt:
							// user pressed Ctrl+C
							sysSig = syscall.SIGINT
						case syscall.SIGTERM:
							// a polite "kill" request
							sysSig = syscall.SIGTERM
						case syscall.SIGHUP:
							sysSig = syscall.SIGHUP
						case syscall.SIGQUIT:
							sysSig = syscall.SIGQUIT
						default:
							sysSig = syscall.SIGINT
						}

						if err := lib.KillProcessGroup(execCmd, sysSig); err != nil {
							log.Printf("Failed to send signal %s to process group: %v", sysSig, err)
						}

						select {
						case <-time.After(2 * time.Second):
							color.New(term.ColorHiYellow, color.Bold).Println("👉 Commands didn't exit after 2 seconds. Sending SIGKILL.")
							if err := lib.KillProcessGroup(execCmd, syscall.SIGKILL); err != nil {
								log.Printf("Failed to send SIGKILL to process group: %v", err)
							}
							maybeDeleteCgroup()
						case <-ctx.Done():
							maybeDeleteCgroup()
							return
						}
					}
				case <-ctx.Done():
					maybeDeleteCgroup()
					return
				}
			}
		}()

		var outputBuilder strings.Builder
		scanner := bufio.NewScanner(pipe)
		go func() {
			for scanner.Scan() {
				line := scanner.Text()
				fmt.Println(line)
				outputBuilder.WriteString(line + "\n")
			}
		}()

		waitErr := execCmd.Wait()

		cancel()
		interruptWG.Wait()
		signal.Stop(sigChan)
		close(sigChan)

		if scanErr := scanner.Err(); scanErr != nil {
			log.Printf("⚠️ Scanner error reading subprocess output: %v", scanErr)
		}

		term.StopSpinner()

		outputStr := outputBuilder.String()
		if outputStr == "" && waitErr != nil {
			outputStr = waitErr.Error()
		}

		if outputStr != "" {
			fmt.Println(outputStr)
		}

		didSucceed := waitErr == nil

		if interrupted.Load() {
			color.New(term.ColorHiYellow, color.Bold).Println("👉  Execution interrupted")

			res, canceled, err := term.ConfirmYesNoCancel("Did the command succeed?")

			if err != nil {
				term.OutputErrorAndExit("Failed to get confirmation user input: %s", err)
			}

			didSucceed = res

			if canceled {
				os.Exit(0)
			}
		}

		if didSucceed {
			if attempt == 0 {
				fmt.Printf("✅ Command %s succeeded on first try\n", color.New(color.Bold, term.ColorHiCyan).Sprintf(cmdStr))
			} else {
				lbl := "attempts"
				if attempt == 1 {
					lbl = "attempt"
				}
				fmt.Printf("✅ Command %s succeeded after %d fix %s\n", color.New(color.Bold, term.ColorHiCyan).Sprintf(cmdStr), attempt, lbl)
			}
			return
		}

		if attempt == tries-1 {
			fmt.Printf("Command failed after %d tries\n", tries)
			os.Exit(1)
		}

		// Prepare prompt for TellPlan
		exitErr, ok := waitErr.(*exec.ExitError)
		status := -1
		if ok {
			status = exitErr.ExitCode()
		}

		prompt := fmt.Sprintf("'%s' failed with exit status %d. Output:\n\n%s\n\n--\n\n",
			strings.Join(cmdArgs, " "), status, outputStr)

		tellFlags := types.TellFlags{
			AutoContext: tellAutoContext,
			ExecEnabled: false,
			IsUserDebug: true,
		}

		plan_exec.TellPlan(plan_exec.ExecParams{
			CurrentPlanId: lib.CurrentPlanId,
			CurrentBranch: lib.CurrentBranch,
			AuthVars:      lib.MustVerifyAuthVars(auth.Current.IntegratedModelsMode),
			CheckOutdatedContext: func(maybeContexts []*shared.Context, projectPaths *types.ProjectPaths) (bool, bool, error) {
				return lib.CheckOutdatedContextWithOutput(true, true, maybeContexts, projectPaths)
			},
		}, prompt, tellFlags)

		applyFlags := types.ApplyFlags{
			AutoConfirm: true,
			AutoCommit:  autoCommit,
			NoCommit:    !autoCommit,
			NoExec:      false,
			AutoExec:    true,
		}

		lib.MustApplyPlan(lib.ApplyPlanParams{
			PlanId:      lib.CurrentPlanId,
			Branch:      lib.CurrentBranch,
			ApplyFlags:  applyFlags,
			TellFlags:   tellFlags,
			OnExecFail:  plan_exec.GetOnApplyExecFailWithCommand(applyFlags, tellFlags, cmdStr),
			ExecCommand: cmdStr,
		})
	}
}


================================================
FILE: app/cli/cmd/delete_branch.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"
	"strings"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var deleteBranchCmd = &cobra.Command{
	Use:     "delete-branch",
	Aliases: []string{"dlb"},
	Short:   "Delete a plan branch by name or index",
	Run:     deleteBranch,
	Args:    cobra.MaximumNArgs(1),
}

func init() {
	RootCmd.AddCommand(deleteBranchCmd)
}

func deleteBranch(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	var branch string
	var nameOrIdx string

	if len(args) > 0 {
		nameOrIdx = strings.TrimSpace(args[0])
	}

	if nameOrIdx == "main" {
		fmt.Println("🚨 Cannot delete main branch")
		return
	}

	term.StartSpinner("")
	branches, apiErr := api.Client.ListBranches(lib.CurrentPlanId)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting branches: %v", apiErr)
		return
	}

	if nameOrIdx == "" {
		opts := make([]string, len(branches))
		for i, branch := range branches {
			if branch.Name == "main" {
				continue
			}
			opts[i] = branch.Name
		}

		if len(opts) == 0 {
			fmt.Println("🤷‍♂️ No branches to delete")
			return
		}

		sel, err := term.SelectFromList("Select a branch to delete", opts)

		if err != nil {
			term.OutputErrorAndExit("Error selecting branch: %v", err)
			return
		}

		branch = sel
	}

	// see if it's an index
	idx, err := strconv.Atoi(nameOrIdx)

	if err == nil {
		if idx > 0 && idx <= len(branches) {
			branch = branches[idx-1].Name
		} else {
			term.OutputErrorAndExit("Branch index out of range")
		}
	} else {
		for _, b := range branches {
			if b.Name == nameOrIdx {
				branch = b.Name
				break
			}
		}

		if branch == "" {
			term.OutputErrorAndExit("Branch not found")
		}
	}

	found := false
	for _, b := range branches {
		if b.Name == branch {
			found = true
			break
		}
	}

	if !found {
		fmt.Printf("🤷‍♂️ Branch %s does not exist\n", color.New(color.Bold, term.ColorHiCyan).Sprint(branch))
		return
	}

	term.StartSpinner("")
	apiErr = api.Client.DeleteBranch(lib.CurrentPlanId, branch)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error deleting branch: %v", apiErr)
		return
	}

	fmt.Printf("✅ Deleted branch %s\n", color.New(color.Bold, term.ColorHiCyan).Sprint(branch))

	fmt.Println()
	term.PrintCmds("", "branches")
}


================================================
FILE: app/cli/cmd/delete_plan.go
================================================
package cmd

import (
	"fmt"
	"path"
	"strconv"
	"strings"

	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var all bool

func init() {
	rmCmd.Flags().BoolVar(&all, "all", false, "Delete all plans")
	RootCmd.AddCommand(rmCmd)
}

// rmCmd represents the rm command
var rmCmd = &cobra.Command{
	Use:     "delete-plan [name-or-index]",
	Aliases: []string{"dp"},
	Short:   "Delete a plan by name, index, range, or pattern, or select from a list. Delete all plans with --all flag.",
	Args:    cobra.RangeArgs(0, 1),
	Run:     del,
}

func matchPlansByPattern(pattern string, plans []*shared.Plan) []*shared.Plan {
	var matched []*shared.Plan
	for _, plan := range plans {
		if isMatched, err := path.Match(pattern, plan.Name); err == nil && isMatched {
			matched = append(matched, plan)
		}
	}
	return matched
}

func del(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if all {
		delAll()
		return
	}

	term.StartSpinner("")
	plans, apiErr := api.Client.ListPlans([]string{lib.CurrentProjectId})
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting plans: %v", apiErr)
	}

	if len(plans) == 0 {
		fmt.Println("🤷‍♂️ No plans")
		fmt.Println()
		term.PrintCmds("", "new")
		return
	}

	var plansToDelete []*shared.Plan

	if len(args) == 0 {
		// Interactive selection
		opts := make([]string, len(plans))
		for i, plan := range plans {
			opts[i] = plan.Name
		}

		selected, err := term.SelectFromList("Select a plan:", opts)
		if err != nil {
			term.OutputErrorAndExit("Error selecting plan: %v", err)
		}

		for _, p := range plans {
			if p.Name == selected {
				plansToDelete = append(plansToDelete, p)
				break
			}
		}
	} else {
		nameOrPattern := strings.TrimSpace(args[0])

		// Check if it's a range of indices
		if strings.Contains(nameOrPattern, "-") {
			// Create single-element slice with the range pattern
			rangeArgs := []string{nameOrPattern}
			indices := parseIndices(rangeArgs)
			for idx := range indices {
				if idx >= 0 && idx < len(plans) {
					plansToDelete = append(plansToDelete, plans[idx])
				}
			}
		} else if strings.Contains(nameOrPattern, "*") {
			// Wildcard pattern matching
			plansToDelete = matchPlansByPattern(nameOrPattern, plans)
		} else {
			// Try as index first
			idx, err := strconv.Atoi(nameOrPattern)
			if err == nil {
				if idx > 0 && idx <= len(plans) {
					plansToDelete = append(plansToDelete, plans[idx-1])
				} else {
					term.OutputErrorAndExit("Plan index out of range")
				}
			} else {
				// Try exact name match
				for _, p := range plans {
					if p.Name == nameOrPattern {
						plansToDelete = append(plansToDelete, p)
						break
					}
				}
			}
		}
	}

	if len(plansToDelete) == 0 {
		term.OutputErrorAndExit("No matching plans found")
	}

	// Show confirmation with list of plans to be deleted
	fmt.Printf("\nThe following %d plan(s) will be deleted:\n", len(plansToDelete))
	for _, p := range plansToDelete {
		fmt.Printf("  - %s\n", color.New(color.Bold, term.ColorHiCyan).Sprint(p.Name))
	}
	fmt.Println()

	confirmed, err := term.ConfirmYesNo("Are you sure you want to delete these plans?")
	if err != nil {
		term.OutputErrorAndExit("Error getting confirmation: %v", err)
	}
	if !confirmed {
		fmt.Println("Operation cancelled")
		return
	}

	// Delete the plans
	term.StartSpinner("")
	for _, p := range plansToDelete {
		apiErr = api.Client.DeletePlan(p.Id)
		if apiErr != nil {
			term.StopSpinner()
			term.OutputErrorAndExit("Error deleting plan %s: %s", p.Name, apiErr.Msg)
		}

		if lib.CurrentPlanId == p.Id {
			err := lib.ClearCurrentPlan()
			if err != nil {
				term.OutputErrorAndExit("Error clearing current plan: %v", err)
			}
		}
	}
	term.StopSpinner()

	if len(plansToDelete) == 1 {
		fmt.Printf("✅ Deleted plan '%s'\n", plansToDelete[0].Name)
	} else {
		fmt.Printf("✅ Deleted %d plans\n", len(plansToDelete))
	}
}

func delAll() {
	term.StartSpinner("")
	err := api.Client.DeleteAllPlans(lib.CurrentProjectId)
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Error deleting all  plans: %v", err)
	}

	fmt.Println("✅ Deleted all plans")
}


================================================
FILE: app/cli/cmd/diffs.go
================================================
package cmd

import (
	"encoding/json"
	"fmt"
	"html/template"
	"net"
	"net/http"
	"os"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"plandex-cli/ui"

	"github.com/eiannone/keyboard"
	"github.com/fatih/color"
	"github.com/spf13/cobra"
)

var showDiffUi bool = true
var diffUiSideBySide = true
var diffUiLineByLine bool
var diffGit bool

var fromTellMenu bool

var diffsCmd = &cobra.Command{
	Use:     "diff",
	Aliases: []string{"diffs"},
	Short:   "Review pending changes",
	Run:     diffs,
}

func init() {
	RootCmd.AddCommand(diffsCmd)

	diffsCmd.Flags().BoolVarP(&plainTextOutput, "plain", "p", false, "Output diffs in plain text with no ANSI codes")
	diffsCmd.Flags().BoolVar(&showDiffUi, "ui", false, "Show diffs in a browser UI")
	diffsCmd.Flags().BoolVar(&diffGit, "git", true, "Show diffs in git diff format")
	diffsCmd.Flags().BoolVarP(&diffUiSideBySide, "side", "s", true, "Show diffs UI in side-by-side view")
	diffsCmd.Flags().BoolVarP(&diffUiLineByLine, "line", "l", false, "Show diffs UI in line-by-line view")

	diffsCmd.Flags().BoolVar(&fromTellMenu, "from-tell-menu", false, "Show diffs from the tell menu")
	diffsCmd.Flags().MarkHidden("from-tell-menu")

}

func diffs(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MaybeResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")

	if showDiffUi {
		diffGit = false
	} else if diffGit || plainTextOutput {
		showDiffUi = false
	} else {
		diffGit = true
	}

	diffs, err := api.Client.GetPlanDiffs(lib.CurrentPlanId, lib.CurrentBranch, plainTextOutput || showDiffUi)
	term.StopSpinner()
	if err != nil {
		term.OutputErrorAndExit("Error getting plan diffs: %v", err)
		return
	}

	if len(diffs) == 0 {
		fmt.Println("🤷‍♂️ No pending changes")
		return
	}

	if showDiffUi {
		getNewListener := func() net.Listener {
			outputFormat := "line-by-line"
			if diffUiSideBySide {
				outputFormat = "side-by-side"
			} else if diffUiLineByLine {
				outputFormat = "line-by-line"
			}

			// Properly escape the diff content for JavaScript
			diffJSON, err := json.Marshal(diffs)
			if err != nil {
				term.OutputErrorAndExit("Error encoding diff content: %v", err)
			}

			// Create template data
			data := struct {
				DiffContent  template.JS
				OutputFormat string
			}{
				DiffContent:  template.JS(diffJSON),
				OutputFormat: outputFormat,
			}

			// Parse and execute the template
			tmpl, err := template.New("diff").Parse(htmlTemplate)
			if err != nil {
				term.OutputErrorAndExit("Error parsing template: %v", err)
			}

			// Use :0 to let the OS pick an available port
			listener, err := net.Listen("tcp", ":0")
			if err != nil {
				term.OutputErrorAndExit("Error starting server: %v", err)
			}

			// Get the actual port chosen
			port := listener.Addr().(*net.TCPAddr).Port

			// Start web server
			go func() {
				http.HandleFunc("/"+outputFormat, func(w http.ResponseWriter, r *http.Request) {
					w.Header().Set("Content-Type", "text/html; charset=utf-8")
					err := tmpl.Execute(w, data)
					if err != nil {
						http.Error(w, err.Error(), http.StatusInternalServerError)
					}
				})
				http.Serve(listener, nil)
			}()

			ui.OpenURL("Showing "+outputFormat+" diffs in your default browser...", fmt.Sprintf("http://localhost:%d/%s", port, outputFormat))

			fmt.Println()

			return listener
		}

		listener := getNewListener()
		defer listener.Close()

		var relaunch bool

		for {
			if relaunch {
				listener.Close()
				listener = getNewListener()
				defer listener.Close()
				relaunch = false
			}

			if diffUiLineByLine {
				fmt.Printf("%s for side-by-side view\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("(s)"))
			} else {
				fmt.Printf("%s for line-by-line view\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("(l)"))
			}

			fmt.Printf("%s for git diff format\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("(g)"))
			// fmt.Printf("%s to quit\n", color.New(color.Bold, term.ColorHiGreen).Sprintf("(q)"))

			s := "to exit menu/continue"
			if fromTellMenu {
				s = "to go back"
			}

			fmt.Printf("%s %s %s %s %s",
				color.New(term.ColorHiMagenta, color.Bold).Sprint("Press a hotkey,"),
				color.New(color.FgHiWhite, color.Bold).Sprintf("↓"),
				color.New(term.ColorHiMagenta, color.Bold).Sprintf("to select, or"),
				color.New(color.FgHiWhite, color.Bold).Sprintf("enter"),
				color.New(term.ColorHiMagenta, color.Bold).Sprintf("%s>", s),
			)

			char, key, err := term.GetUserKeyInput()
			if err != nil {
				term.OutputErrorAndExit("Error getting key: %v", err)
				return
			}
			fmt.Println()

			if key == keyboard.KeyArrowDown {
				options := []string{}
				if diffUiLineByLine {
					options = append(options, "side-by-side")
				} else {
					options = append(options, "line-by-line")
				}

				options = append(options, "git diff")
				options = append(options, "exit menu")

				selected, err := term.SelectFromList(
					"Select an action",
					options,
				)
				if err != nil {
					term.OutputErrorAndExit("Error selecting action: %v", err)
					return
				}

				if selected == "side-by-side" {
					diffUiSideBySide = true
					diffUiLineByLine = false
					relaunch = true
				} else if selected == "line-by-line" {
					diffUiSideBySide = false
					diffUiLineByLine = true
					relaunch = true
				} else if selected == "git diff" {
					showGitDiff()
				} else if selected == "exit menu" {
					fmt.Println()
					break
				}
			} else if string(char) == "g" {
				showGitDiff()
			} else if string(char) == "s" {
				diffUiSideBySide = true
				diffUiLineByLine = false
				relaunch = true
			} else if string(char) == "l" {
				diffUiSideBySide = false
				diffUiLineByLine = true
				relaunch = true
			} else if key == 13 || key == 10 || string(char) == "q" { // Check raw key codes for Enter/Return
				if term.IsRepl {
					fmt.Println()
					break
				} else {
					fmt.Println()
					break
				}
			} else if string(char) == "\x03" { // Ctrl+C
				os.Exit(0)
			} else {
				fmt.Println()
				term.OutputSimpleError("Invalid hotkey")
				fmt.Println()
			}
		}
	} else {
		if plainTextOutput {
			fmt.Println(diffs)
		} else {
			term.PageOutput(diffs)
		}
		fmt.Println()
	}
}

func showGitDiff() {
	_, err := lib.ExecPlandexCommandWithParams([]string{"diff", "--git"}, lib.ExecPlandexCommandParams{
		DisableSuggestions: true,
	})
	if err != nil {
		term.OutputErrorAndExit("Error showing git diff: %v", err)
	}
}

var htmlTemplate = `<!doctype html>
<html lang="en-us">
  <head>
    <meta charset="utf-8" />
    <!-- Make sure to load the highlight.js CSS file before the Diff2Html CSS file -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/vs.min.css" />
    <link
      rel="stylesheet"
      type="text/css"
      href="https://cdn.jsdelivr.net/npm/diff2html/bundles/css/diff2html.min.css"
    />
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/diff2html/bundles/js/diff2html-ui.min.js"></script>
  </head>
  <script>
    // Parse the JSON-encoded diff content
    const diffString = {{.DiffContent}};

    document.addEventListener('DOMContentLoaded', function () {
      var targetElement = document.getElementById('myDiffElement');
      var configuration = {
        outputFormat: '{{.OutputFormat}}'
      };
      var diff2htmlUi = new Diff2HtmlUI(targetElement, diffString, configuration);
      diff2htmlUi.draw();
      diff2htmlUi.highlightCode();
    });
  </script>
  <body>
    <div id="myDiffElement"></div>
  </body>
</html>`


================================================
FILE: app/cli/cmd/invite.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/spf13/cobra"
)

var inviteCmd = &cobra.Command{
	Use:   "invite [email] [name] [org-role]",
	Short: "Invite a new user to the org",
	Run:   invite,
	Args:  cobra.MaximumNArgs(3),
}

func init() {
	RootCmd.AddCommand(inviteCmd)
}

func invite(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()

	email, name, orgRoleName := "", "", ""
	if len(args) >= 1 {
		email = args[0]
	}
	if len(args) >= 2 {
		name = args[1]
	}
	if len(args) == 3 {
		orgRoleName = args[2]
	}

	term.StartSpinner("")
	orgRoles, err := api.Client.ListOrgRoles()
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Failed to list org roles: %v", err)
	}

	if email == "" {
		var err error
		email, err = term.GetRequiredUserStringInput("Email:")
		if err != nil {
			term.OutputErrorAndExit("Failed to get email: %v", err)
		}
	}
	if name == "" {
		var err error
		name, err = term.GetRequiredUserStringInput("Name:")
		if err != nil {
			term.OutputErrorAndExit("Failed to get name: %v", err)
		}
	}

	if orgRoleName == "" {
		var orgRoleNames []string
		for _, orgRole := range orgRoles {
			orgRoleNames = append(orgRoleNames, orgRole.Label)
		}

		var err error
		orgRoleName, err = term.SelectFromList("Org role:", orgRoleNames)

		if err != nil {
			term.OutputErrorAndExit("Failed to select org role: %v", err)
		}
	}

	var orgRoleId string
	for _, orgRole := range orgRoles {
		if orgRole.Label == orgRoleName {
			orgRoleId = orgRole.Id
			break
		}
	}

	if orgRoleId == "" {
		term.OutputErrorAndExit("Org role '%s' not found", orgRoleName)
	}

	inviteRequest := shared.InviteRequest{
		Email:     email,
		Name:      name,
		OrgRoleId: orgRoleId,
	}

	term.StartSpinner("")
	apiErr := api.Client.InviteUser(inviteRequest)
	term.StopSpinner()
	if apiErr != nil {
		term.OutputErrorAndExit("Failed to invite user: %s", apiErr.Msg)
	}

	fmt.Println("✅ Invite sent")
}


================================================
FILE: app/cli/cmd/load.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"plandex-cli/types"

	"github.com/sashabaranov/go-openai"
	"github.com/spf13/cobra"
)

var (
	recursive       bool
	namesOnly       bool
	note            string
	forceSkipIgnore bool
	imageDetail     string
	defsOnly        bool
)

var contextLoadCmd = &cobra.Command{
	Use:     "load [files-or-urls...]",
	Aliases: []string{"l", "add"},
	Short:   "Load context from various inputs",
	Long:    `Load context from a file path, a directory, a URL, an image, a note, or piped data.`,
	Run:     contextLoad,
}

func init() {
	contextLoadCmd.Flags().StringVarP(&note, "note", "n", "", "Add a note to the context")
	contextLoadCmd.Flags().BoolVarP(&recursive, "recursive", "r", false, "Search directories recursively")
	contextLoadCmd.Flags().BoolVar(&namesOnly, "tree", false, "Load directory tree with file names only")
	contextLoadCmd.Flags().BoolVarP(&forceSkipIgnore, "force", "f", false, "Load files even when ignored by .gitignore or .plandexignore")
	contextLoadCmd.Flags().StringVarP(&imageDetail, "detail", "d", "high", "Image detail level (high or low)")
	contextLoadCmd.Flags().BoolVar(&defsOnly, "map", false, "Load file maps (function/method/class signatures, variable names, types, etc.)")
	RootCmd.AddCommand(contextLoadCmd)
}

func contextLoad(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
		return
	}

	lib.MustLoadContext(args, &types.LoadContextParams{
		Note:            note,
		Recursive:       recursive,
		NamesOnly:       namesOnly,
		ForceSkipIgnore: forceSkipIgnore,
		ImageDetail:     openai.ImageURLDetail(imageDetail),
		DefsOnly:        defsOnly,
		SessionId:       os.Getenv("PLANDEX_REPL_SESSION_ID"),
	})

	fmt.Println()
	term.PrintCmds("", "ls", "tell", "debug")
}


================================================
FILE: app/cli/cmd/log.go
================================================
package cmd

import (
	"fmt"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/lib"
	"plandex-cli/term"
	"time"

	"github.com/spf13/cobra"
)

// logCmd represents the log command
var logCmd = &cobra.Command{
	Use:     "log",
	Aliases: []string{"history", "logs"},
	Short:   "Show plan history",
	Long:    `Show plan history`,
	Args:    cobra.NoArgs,
	Run:     runLog,
}

func init() {
	// Add log command
	RootCmd.AddCommand(logCmd)
}

func runLog(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	if lib.CurrentPlanId == "" {
		term.OutputNoCurrentPlanErrorAndExit()
	}

	term.StartSpinner("")
	res, apiErr := api.Client.ListLogs(lib.CurrentPlanId, lib.CurrentBranch)
	term.StopSpinner()

	if apiErr != nil {
		term.OutputErrorAndExit("Error getting logs: %v", apiErr)
	}

	withLocalTimestamps, err := convertTimestampsToLocal(res.Body)

	if err != nil {
		term.OutputErrorAndExit("Error converting timestamps: %v", err)
	}

	term.PageOutput(withLocalTimestamps)

	fmt.Println()
	term.PrintCmds("", "rewind", "continue", "convo", "convo 1", "convo 2-5")

}

func convertTimestampsToLocal(input string) (string, error) {
	t := time.Now()
	zone, _ := t.Zone()
	re := lib.GitLogTimestampRegex

	// Function to convert matched timestamps assuming they are in UTC to local time.
	replaceFunc := func(match string) string {
		t, err := time.Parse(lib.GitLogTimestampFormat, match)
		if err != nil {
			// In case of an error, return the original match.
			return match
		}

		localDt := t.Local()
		formattedTs := localDt.Format("Mon Jan 2, 2006 | 3:04:05pm")

		if localDt.Day() == time.Now().Day() {
			formattedTs = localDt.Format("Today | 3:04:05pm")
		} else if localDt.Day() == time.Now().AddDate(0, 0, -1).Day() {
			formattedTs = localDt.Format("Yesterday | 3:04:05pm")
		}

		// Convert to local time and format back to a string without the timezone to match the original format.
		return formattedTs + " " + zone
	}

	// Find all matches and replace them.
	result := re.ReplaceAllStringFunc(input, replaceFunc)

	return result, nil
}


================================================
FILE: app/cli/cmd/ls.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/format"
	"plandex-cli/lib"
	"plandex-cli/term"
	"strconv"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

var contextCmd = &cobra.Command{
	Use:     "ls",
	Aliases: []string{"list-context"},
	Short:   "List everything in context",
	Run:     listContext,
}

func listContext(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()
	lib.MustResolveProject()

	term.StartSpinner("")
	contexts, err := api.Client.ListContext(lib.CurrentPlanId, lib.CurrentBranch)

	if err != nil {
		term.OutputErrorAndExit("Error listing context: %v", err)
	}

	planConfig, err := api.Client.GetPlanConfig(lib.CurrentPlanId)
	if err != nil {
		term.OutputErrorAndExit("Error getting plan config: %v", err)
	}
	term.StopSpinner()

	totalTokens := 0
	totalPlannerTokens := 0
	totalMapTokens := 0
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"#", "Name", "Type", "🪙", "Added", "Updated"})
	table.SetAutoWrapText(false)

	if len(contexts) == 0 {
		fmt.Println("🤷‍♂️ No context")
		fmt.Println()
		term.PrintCmds("", "load")
		return
	}

	for i, context := range contexts {
		totalTokens += context.NumTokens

		if context.ContextType == shared.ContextMapType {
			totalMapTokens += context.NumTokens
		} else {
			totalPlannerTokens += context.NumTokens
		}

		t, icon := context.TypeAndIcon()

		name := context.Name
		if name == "" {
			name = context.FilePath
		}
		if len(name) > 40 {
			name = name[:20] + "⋯" + name[len(name)-20:]
		}

		row := []string{
			strconv.Itoa(i + 1),
			" " + icon + " " + name,
			t,
			strconv.Itoa(context.NumTokens), //+ " 🪙",
			format.Time(context.CreatedAt),
			format.Time(context.UpdatedAt),
		}
		table.Rich(row, []tablewriter.Colors{
			{tablewriter.Bold},
			{tablewriter.FgHiGreenColor, tablewriter.Bold},
		})
	}

	table.Render()

	tokensTbl := tablewriter.NewWriter(os.Stdout)
	tokensTbl.SetAutoWrapText(false)

	if planConfig.AutoLoadContext {
		tokensTbl.Append([]string{
			color.New(term.ColorHiCyan, color.Bold).Sprintf("Map tokens →") + color.New(color.Bold).Sprintf(" %d 🪙", totalMapTokens),
			color.New(term.ColorHiCyan, color.Bold).Sprintf("Context tokens →") + color.New(color.Bold).Sprintf(" %d 🪙", totalPlannerTokens),
		})
	} else {

		tokensTbl.Append([]string{color.New(term.ColorHiCyan, color.Bold).Sprintf("Total tokens →") + color.New(color.Bold).Sprintf(" %d 🪙", totalTokens)})
	}
	tokensTbl.Render()

	fmt.Println()
	term.PrintCmds("", "load", "rm", "clear")

}

func init() {
	RootCmd.AddCommand(contextCmd)

}


================================================
FILE: app/cli/cmd/model_helpers.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/lib"
	"plandex-cli/term"
	shared "plandex-shared"

	"github.com/fatih/color"
)

func warnModelsFileLocalChanges(path, cmd string) (bool, error) {
	cmdPrefix := "\\"
	if !term.IsRepl {
		cmdPrefix = "plandex "
	}

	color.New(color.Bold, term.ColorHiYellow).Println("⚠️  The models file has local changes")

	fmt.Println()
	fmt.Println("Path → " + path)
	fmt.Println()

	fmt.Println("If you continue, local changes will be dropped in favor of the latest server state")

	fmt.Println()
	fmt.Printf("To keep the local version instead, quit and run %s\n", color.New(color.Bold, color.BgCyan, color.FgHiWhite).
		Sprintf(" %s%s --save ", cmdPrefix, cmd))
	fmt.Println()
	return term.ConfirmYesNo("Drop local changes and continue?")

}

type maybePromptAndOpenModelsFileResult struct {
	shouldReturn bool
	jsonData     []byte
}

func maybePromptAndOpenModelsFile(filePath, pathArg, cmd string, defaultConfig *shared.PlanConfig, planConfig *shared.PlanConfig) maybePromptAndOpenModelsFileResult {

	printManual := func() {
		cmdPrefix := "\\"
		if !term.IsRepl {
			cmdPrefix = "plandex "
		}
		fmt.Println("To save changes, run " +
			fmt.Sprintf(" %s ", color.New(color.Bold, color.BgCyan, color.FgHiWhite).
				Sprintf(" %s%s --save%s ", cmdPrefix, cmd, pathArg)))
	}

	selectedEditor := lib.MaybePromptAndOpen(filePath, defaultConfig, planConfig)

	if selectedEditor {
		fmt.Println("📝 Opened in editor")
		fmt.Println()

		confirmed, err := term.ConfirmYesNo("Ready to save?")
		if err != nil {
			term.OutputErrorAndExit("Error confirming: %v", err)
			return maybePromptAndOpenModelsFileResult{shouldReturn: true}
		}

		if !confirmed {
			fmt.Println("🙅‍♂️ Update canceled")
			fmt.Println()

			printManual()
			return maybePromptAndOpenModelsFileResult{shouldReturn: true}
		}

		// get updated file state
		jsonData, err := os.ReadFile(filePath)
		if err != nil {
			term.OutputErrorAndExit("Error reading JSON file: %v", err)
			return maybePromptAndOpenModelsFileResult{shouldReturn: true}
		}

		return maybePromptAndOpenModelsFileResult{shouldReturn: false, jsonData: jsonData}
	} else {
		// No editor available or user chose manual
		fmt.Println("👨‍💻 Edit the file in your JSON editor of choice")
		fmt.Println()

		printManual()
		return maybePromptAndOpenModelsFileResult{shouldReturn: true}
	}
}


================================================
FILE: app/cli/cmd/model_packs.go
================================================
package cmd

import (
	"fmt"
	"os"
	"plandex-cli/api"
	"plandex-cli/auth"
	"plandex-cli/term"

	shared "plandex-shared"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	"github.com/spf13/cobra"
)

var customModelPacksOnly bool

var modelPacksCmd = &cobra.Command{
	Use:   "model-packs",
	Short: "List all model packs",
	Run:   listModelPacks,
}

var createModelPackCmd = &cobra.Command{
	Use:   "create",
	Short: "Create a model pack",
	Run:   customModelsNotImplemented,
}

var deleteModelPackCmd = &cobra.Command{
	Use:     "delete",
	Aliases: []string{"rm"},
	Short:   "Delete a model pack by name or index",
	Run:     customModelsNotImplemented,
}

var updateModelPackCmd = &cobra.Command{
	Use:   "update",
	Short: "Update a model pack by name",
	Run:   customModelsNotImplemented,
}

var showModelPackCmd = &cobra.Command{
	Use:   "show [name]",
	Short: "Show a model pack by name",
	Args:  cobra.MaximumNArgs(1),
	Run:   showModelPack,
}

func init() {
	RootCmd.AddCommand(modelPacksCmd)
	modelPacksCmd.AddCommand(createModelPackCmd)
	modelPacksCmd.AddCommand(deleteModelPackCmd)
	modelPacksCmd.AddCommand(updateModelPackCmd)
	modelPacksCmd.AddCommand(showModelPackCmd)
	modelPacksCmd.Flags().BoolVarP(&customModelPacksOnly, "custom", "c", false, "Only show custom model packs")
	modelPacksCmd.Flags().BoolVarP(&allProperties, "all", "a", false, "Show all properties")
}

func listModelPacks(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()

	term.StartSpinner("")
	builtInModelPacks := shared.BuiltInModelPacks

	if auth.Current.IsCloud {
		filtered := []*shared.ModelPack{}
		for _, mp := range builtInModelPacks {
			if mp.LocalProvider == "" {
				filtered = append(filtered, mp)
			}
		}
		builtInModelPacks = filtered
	}

	customModelPacks, err := api.Client.ListModelPacks()
	term.StopSpinner()

	if err != nil {
		term.OutputErrorAndExit("Error fetching model packs: %v", err)
		return
	}

	if !customModelPacksOnly {
		color.New(color.Bold, term.ColorHiCyan).Println("🏠 Built-in Model Packs")
		table := tablewriter.NewWriter(os.Stdout)
		table.SetAutoWrapText(true)
		table.SetRowLine(true)
		table.SetHeader([]string{"Name", "Description"})
		for _, set := range builtInModelPacks {
			table.Append([]string{set.Name, set.Description})
		}
		table.Render()
		fmt.Println()
	}

	if len(customModelPacks) > 0 {
		color.New(color.Bold, term.ColorHiCyan).Println("🛠️  Custom Model Packs")
		table := tablewriter.NewWriter(os.Stdout)
		table.SetAutoWrapText(true)
		table.SetRowLine(true)
		table.SetHeader([]string{"#", "Name", "Description"})
		for i, set := range customModelPacks {
			table.Append([]string{fmt.Sprintf("%d", i+1), set.Name, set.Description})
		}
		table.Render()

		fmt.Println()
	} else if customModelPacksOnly {
		fmt.Println("🤷‍♂️ No custom model packs")
		fmt.Println()
	}

	if customModelPacksOnly && len(customModelPacks) > 0 {
		term.PrintCmds("", "model-packs show", "models custom")
	} else if len(customModelPacks) > 0 {
		term.PrintCmds("", "model-packs --custom", "model-packs show", "models custom")
	} else {
		term.PrintCmds("", "model-packs show", "models custom")
	}

}

func showModelPack(cmd *cobra.Command, args []string) {
	auth.MustResolveAuthWithOrg()

	term.StartSpinner("")
	customModelPacks, apiErr := api.Client.ListModelPacks()
	if apiErr != nil {
		term.OutputErrorAndExit("Error fetching models: %v", apiErr)
	}
	customModels, err := api.Client.ListCustomModels()
	if err != nil {
		term.OutputErrorAndExit("Error fetching custom models: %v", err)
	}
	customModelsById := make(map[shared.ModelId]*shared.CustomModel)
	for _, m := range customModels {
		customModelsById[m.ModelId] = m
	}

	term.StopSpinner()

	modelPacks := []*shared.ModelPack{}
	modelPacks = append(modelPacks, customModelPacks...)

	builtInModelPacks := shared.BuiltInModelPacks
	if auth.Current.IsCloud {
		filtered := []*shared.ModelPack{}
		for _, mp := range builtInModelPacks {
			if mp.LocalProvider == "" {
				filtered = append(filtered, mp)
			}
		}
		builtInModelPacks = filtered
	}
	modelPacks = append(modelPacks, builtInModelPacks...)

	var name string
	if len(args) > 0 {
		name = args[0]
	}

	var modelPack *shared.ModelPack

	if name == "" {
		opts :
Download .txt
gitextract_skjdl2ff/

├── .dockerignore
├── .gitattributes
├── .github/
│   └── workflows/
│       └── docker-publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── app/
│   ├── .dockerignore
│   ├── .gitignore
│   ├── clear_local.sh
│   ├── cli/
│   │   ├── api/
│   │   │   ├── clients.go
│   │   │   ├── errors.go
│   │   │   ├── methods.go
│   │   │   └── stream.go
│   │   ├── auth/
│   │   │   ├── account.go
│   │   │   ├── api.go
│   │   │   ├── auth.go
│   │   │   ├── org.go
│   │   │   ├── state.go
│   │   │   └── trial.go
│   │   ├── cmd/
│   │   │   ├── apply.go
│   │   │   ├── archive.go
│   │   │   ├── billing.go
│   │   │   ├── branches.go
│   │   │   ├── browser.go
│   │   │   ├── build.go
│   │   │   ├── cd.go
│   │   │   ├── chat.go
│   │   │   ├── checkout.go
│   │   │   ├── claude_max.go
│   │   │   ├── clear.go
│   │   │   ├── config.go
│   │   │   ├── connect.go
│   │   │   ├── context_show.go
│   │   │   ├── continue.go
│   │   │   ├── convo.go
│   │   │   ├── current.go
│   │   │   ├── debug.go
│   │   │   ├── delete_branch.go
│   │   │   ├── delete_plan.go
│   │   │   ├── diffs.go
│   │   │   ├── invite.go
│   │   │   ├── load.go
│   │   │   ├── log.go
│   │   │   ├── ls.go
│   │   │   ├── model_helpers.go
│   │   │   ├── model_packs.go
│   │   │   ├── model_providers.go
│   │   │   ├── models.go
│   │   │   ├── new.go
│   │   │   ├── plan_exec_helpers.go
│   │   │   ├── plan_start_helpers.go
│   │   │   ├── plans.go
│   │   │   ├── ps.go
│   │   │   ├── reject.go
│   │   │   ├── rename.go
│   │   │   ├── repl.go
│   │   │   ├── revoke.go
│   │   │   ├── rewind.go
│   │   │   ├── rm.go
│   │   │   ├── root.go
│   │   │   ├── set_config.go
│   │   │   ├── set_model.go
│   │   │   ├── sign_in.go
│   │   │   ├── stop.go
│   │   │   ├── summary.go
│   │   │   ├── tell.go
│   │   │   ├── unarchive.go
│   │   │   ├── update.go
│   │   │   ├── usage.go
│   │   │   ├── users.go
│   │   │   └── version.go
│   │   ├── dev.sh
│   │   ├── format/
│   │   │   ├── file.go
│   │   │   └── time.go
│   │   ├── fs/
│   │   │   ├── fs.go
│   │   │   ├── paths.go
│   │   │   ├── projects.go
│   │   │   └── utils.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── install.sh
│   │   ├── lib/
│   │   │   ├── active_stream.go
│   │   │   ├── apply.go
│   │   │   ├── apply_cgroup_linux.go
│   │   │   ├── apply_cgroup_other.go
│   │   │   ├── apply_proc.go
│   │   │   ├── build.go
│   │   │   ├── claude_max.go
│   │   │   ├── context_auto_load.go
│   │   │   ├── context_conflict.go
│   │   │   ├── context_display.go
│   │   │   ├── context_load.go
│   │   │   ├── context_paths.go
│   │   │   ├── context_shared.go
│   │   │   ├── context_update.go
│   │   │   ├── current.go
│   │   │   ├── custom_models.go
│   │   │   ├── editor.go
│   │   │   ├── git.go
│   │   │   ├── legacy_files.go
│   │   │   ├── log_format.go
│   │   │   ├── model_credentials.go
│   │   │   ├── model_settings.go
│   │   │   ├── models_sync.go
│   │   │   ├── org_user_config.go
│   │   │   ├── plan_config.go
│   │   │   ├── plans.go
│   │   │   ├── repl.go
│   │   │   └── rewind.go
│   │   ├── main.go
│   │   ├── nodemon.json
│   │   ├── plan.json
│   │   ├── plan_exec/
│   │   │   ├── action_menu.go
│   │   │   ├── apply_exec.go
│   │   │   ├── build.go
│   │   │   ├── params.go
│   │   │   └── tell.go
│   │   ├── schema/
│   │   │   ├── json-schemas/
│   │   │   │   ├── definitions/
│   │   │   │   │   ├── auto-modes.schema.json
│   │   │   │   │   ├── local-providers.schema.json
│   │   │   │   │   └── model-providers.schema.json
│   │   │   │   ├── model-config.schema.json
│   │   │   │   ├── model-pack-base-config.schema.json
│   │   │   │   ├── model-pack-config.schema.json
│   │   │   │   ├── model-pack-inline.schema.json
│   │   │   │   ├── model-pack-roles.schema.json
│   │   │   │   ├── model-provider-config.schema.json
│   │   │   │   ├── model-role-config.schema.json
│   │   │   │   ├── models-input.schema.json
│   │   │   │   └── plan-config.schema.json
│   │   │   └── schemas.go
│   │   ├── stream/
│   │   │   └── stream.go
│   │   ├── stream_tui/
│   │   │   ├── debouncer.go
│   │   │   ├── model.go
│   │   │   ├── run.go
│   │   │   ├── update.go
│   │   │   └── view.go
│   │   ├── term/
│   │   │   ├── color.go
│   │   │   ├── errors.go
│   │   │   ├── format.go
│   │   │   ├── help.go
│   │   │   ├── os.go
│   │   │   ├── prompt.go
│   │   │   ├── repl.go
│   │   │   ├── select.go
│   │   │   ├── spinner.go
│   │   │   └── utils.go
│   │   ├── types/
│   │   │   ├── api.go
│   │   │   ├── apply.go
│   │   │   ├── exec.go
│   │   │   ├── fs.go
│   │   │   └── types.go
│   │   ├── ui/
│   │   │   └── ui.go
│   │   ├── upgrade.go
│   │   ├── url/
│   │   │   └── url.go
│   │   ├── utils/
│   │   │   └── utils.go
│   │   ├── version/
│   │   │   └── version.go
│   │   └── version.txt
│   ├── docker-compose.yml
│   ├── plans/
│   │   ├── credits-cmd.txt
│   │   ├── credits-log-cmd.txt
│   │   ├── json-prompts-to-xml.md
│   │   └── plan-config.md
│   ├── reset_local.sh
│   ├── scripts/
│   │   ├── cmd/
│   │   │   ├── gen/
│   │   │   │   └── gen.go
│   │   │   └── provider/
│   │   │       └── gen_provider.go
│   │   ├── dev.sh
│   │   ├── litellm_deps.sh
│   │   └── wait-for-it.sh
│   ├── server/
│   │   ├── .gitignore
│   │   ├── Dockerfile
│   │   ├── db/
│   │   │   ├── account_helpers.go
│   │   │   ├── ai_model_helpers.go
│   │   │   ├── auth_helpers.go
│   │   │   ├── branch_helpers.go
│   │   │   ├── build_helpers.go
│   │   │   ├── context_helpers_conflicts.go
│   │   │   ├── context_helpers_get.go
│   │   │   ├── context_helpers_load.go
│   │   │   ├── context_helpers_map.go
│   │   │   ├── context_helpers_remove.go
│   │   │   ├── context_helpers_store.go
│   │   │   ├── context_helpers_update.go
│   │   │   ├── convo_helpers.go
│   │   │   ├── data_models.go
│   │   │   ├── db.go
│   │   │   ├── diff_helpers.go
│   │   │   ├── fs.go
│   │   │   ├── git.go
│   │   │   ├── invite_helpers.go
│   │   │   ├── locks.go
│   │   │   ├── models.go
│   │   │   ├── org_helpers.go
│   │   │   ├── plan_config_helpers.go
│   │   │   ├── plan_helpers.go
│   │   │   ├── project_helpers.go
│   │   │   ├── queue.go
│   │   │   ├── rbac_helpers.go
│   │   │   ├── result_helpers.go
│   │   │   ├── settings_helpers.go
│   │   │   ├── stream_helpers.go
│   │   │   ├── subtask_helpers.go
│   │   │   ├── summary_helpers.go
│   │   │   ├── transactions.go
│   │   │   ├── user_helpers.go
│   │   │   └── utils.go
│   │   ├── diff/
│   │   │   └── diff.go
│   │   ├── email/
│   │   │   ├── email.go
│   │   │   ├── invite.go
│   │   │   └── verification.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── handlers/
│   │   │   ├── accounts.go
│   │   │   ├── auth_helpers.go
│   │   │   ├── branches.go
│   │   │   ├── client_helper.go
│   │   │   ├── context_helper.go
│   │   │   ├── err_helper.go
│   │   │   ├── file_maps.go
│   │   │   ├── file_maps_queue.go
│   │   │   ├── invites.go
│   │   │   ├── models.go
│   │   │   ├── org_helpers.go
│   │   │   ├── orgs.go
│   │   │   ├── plan_config.go
│   │   │   ├── plans_changes.go
│   │   │   ├── plans_context.go
│   │   │   ├── plans_convo.go
│   │   │   ├── plans_crud.go
│   │   │   ├── plans_exec.go
│   │   │   ├── plans_versions.go
│   │   │   ├── projects.go
│   │   │   ├── proxy_helper.go
│   │   │   ├── sessions.go
│   │   │   ├── settings.go
│   │   │   ├── stream_helper.go
│   │   │   └── users.go
│   │   ├── hooks/
│   │   │   └── hooks.go
│   │   ├── host/
│   │   │   └── ip.go
│   │   ├── litellm_proxy.py
│   │   ├── main.go
│   │   ├── migrations/
│   │   │   ├── 2023120500_init.down.sql
│   │   │   ├── 2023120500_init.up.sql
│   │   │   ├── 2024011700_rbac.down.sql
│   │   │   ├── 2024011700_rbac.up.sql
│   │   │   ├── 2024012400_streams.down.sql
│   │   │   ├── 2024012400_streams.up.sql
│   │   │   ├── 2024012500_locks.down.sql
│   │   │   ├── 2024012500_locks.up.sql
│   │   │   ├── 2024013000_plan_build_convo_ids.down.sql
│   │   │   ├── 2024013000_plan_build_convo_ids.up.sql
│   │   │   ├── 2024020800_heartbeats.down.sql
│   │   │   ├── 2024020800_heartbeats.up.sql
│   │   │   ├── 2024022000_revert_plan_build_convo_ids.down.sql
│   │   │   ├── 2024022000_revert_plan_build_convo_ids.up.sql
│   │   │   ├── 2024032700_remove_billing_admin.down.sql
│   │   │   ├── 2024032700_remove_billing_admin.up.sql
│   │   │   ├── 2024032701_drop_users_projects.down.sql
│   │   │   ├── 2024032701_drop_users_projects.up.sql
│   │   │   ├── 2024040400_add_orgs_users_unique.down.sql
│   │   │   ├── 2024040400_add_orgs_users_unique.up.sql
│   │   │   ├── 2024041500_model_sets_models.down.sql
│   │   │   ├── 2024041500_model_sets_models.up.sql
│   │   │   ├── 2024042600_default_plan_settings.down.sql
│   │   │   ├── 2024042600_default_plan_settings.up.sql
│   │   │   ├── 2024091800_sign_in_codes.down.sql
│   │   │   ├── 2024091800_sign_in_codes.up.sql
│   │   │   ├── 2024092100_remove_trial_fields.down.sql
│   │   │   ├── 2024092100_remove_trial_fields.up.sql
│   │   │   ├── 2024100900_update_locks.down.sql
│   │   │   ├── 2024100900_update_locks.up.sql
│   │   │   ├── 2024121400_plan_config.down.sql
│   │   │   ├── 2024121400_plan_config.up.sql
│   │   │   ├── 2025012600_update_custom_models.down.sql
│   │   │   ├── 2025012600_update_custom_models.up.sql
│   │   │   ├── 2025021101_locks_unique.down.sql
│   │   │   ├── 2025021101_locks_unique.up.sql
│   │   │   ├── 2025022700_remove_models_col.down.sql
│   │   │   ├── 2025022700_remove_models_col.up.sql
│   │   │   ├── 2025031300_add_model_roles.down.sql
│   │   │   ├── 2025031300_add_model_roles.up.sql
│   │   │   ├── 2025031900_add_custom_model_cols.down.sql
│   │   │   ├── 2025031900_add_custom_model_cols.up.sql
│   │   │   ├── 2025032400_sign_in_codes_on_delete.down.sql
│   │   │   ├── 2025032400_sign_in_codes_on_delete.up.sql
│   │   │   ├── 2025051600_custom_models_refactor.down.sql
│   │   │   ├── 2025051600_custom_models_refactor.up.sql
│   │   │   ├── 2025052200_model_pack_cols.down.sql
│   │   │   ├── 2025052200_model_pack_cols.up.sql
│   │   │   ├── 2025070200_add_org_user_config.down.sql
│   │   │   └── 2025070200_add_org_user_config.up.sql
│   │   ├── model/
│   │   │   ├── client.go
│   │   │   ├── client_stream.go
│   │   │   ├── litellm.go
│   │   │   ├── model_error.go
│   │   │   ├── model_request.go
│   │   │   ├── name.go
│   │   │   ├── parse/
│   │   │   │   ├── subtasks.go
│   │   │   │   └── subtasks_test.go
│   │   │   ├── plan/
│   │   │   │   ├── activate.go
│   │   │   │   ├── build_exec.go
│   │   │   │   ├── build_finish.go
│   │   │   │   ├── build_load.go
│   │   │   │   ├── build_race.go
│   │   │   │   ├── build_state.go
│   │   │   │   ├── build_structured_edits.go
│   │   │   │   ├── build_validate_and_fix.go
│   │   │   │   ├── build_whole_file.go
│   │   │   │   ├── commit_msg.go
│   │   │   │   ├── exec_status.go
│   │   │   │   ├── shutdown.go
│   │   │   │   ├── state.go
│   │   │   │   ├── stop.go
│   │   │   │   ├── tell_build_pending.go
│   │   │   │   ├── tell_context.go
│   │   │   │   ├── tell_exec.go
│   │   │   │   ├── tell_load.go
│   │   │   │   ├── tell_missing_file.go
│   │   │   │   ├── tell_prompt_message.go
│   │   │   │   ├── tell_stage.go
│   │   │   │   ├── tell_state.go
│   │   │   │   ├── tell_stream_error.go
│   │   │   │   ├── tell_stream_finish.go
│   │   │   │   ├── tell_stream_main.go
│   │   │   │   ├── tell_stream_processor.go
│   │   │   │   ├── tell_stream_processor_test.go
│   │   │   │   ├── tell_stream_status.go
│   │   │   │   ├── tell_stream_store.go
│   │   │   │   ├── tell_stream_usage.go
│   │   │   │   ├── tell_subtasks.go
│   │   │   │   ├── tell_summary.go
│   │   │   │   ├── tell_sys_prompt.go
│   │   │   │   └── utils.go
│   │   │   ├── prompts/
│   │   │   │   ├── apply_exec.go
│   │   │   │   ├── architect_context.go
│   │   │   │   ├── build_helpers.go
│   │   │   │   ├── build_validation_replacements.go
│   │   │   │   ├── build_whole_file.go
│   │   │   │   ├── chat.go
│   │   │   │   ├── code_block_langs.go
│   │   │   │   ├── describe.go
│   │   │   │   ├── exec_status.go
│   │   │   │   ├── explanation_format.go
│   │   │   │   ├── file_ops.go
│   │   │   │   ├── implement.go
│   │   │   │   ├── missing_file.go
│   │   │   │   ├── name.go
│   │   │   │   ├── planning.go
│   │   │   │   ├── shared.go
│   │   │   │   ├── summary.go
│   │   │   │   ├── update_format.go
│   │   │   │   └── user_prompt.go
│   │   │   ├── summarize.go
│   │   │   └── tokens.go
│   │   ├── notify/
│   │   │   └── errors.go
│   │   ├── routes/
│   │   │   └── routes.go
│   │   ├── setup/
│   │   │   └── setup.go
│   │   ├── shutdown/
│   │   │   └── shutdown.go
│   │   ├── syntax/
│   │   │   ├── comments.go
│   │   │   ├── file_map/
│   │   │   │   ├── cli/
│   │   │   │   │   ├── .gitignore
│   │   │   │   │   ├── go.mod
│   │   │   │   │   ├── go.sum
│   │   │   │   │   └── main.go
│   │   │   │   ├── examples/
│   │   │   │   │   ├── bash_example.sh
│   │   │   │   │   ├── c_example.c
│   │   │   │   │   ├── cpp_example.cpp
│   │   │   │   │   ├── csharp_example.cs
│   │   │   │   │   ├── css_example.css
│   │   │   │   │   ├── cue_example.cue
│   │   │   │   │   ├── dockerfile_example
│   │   │   │   │   ├── elixir_example.ex
│   │   │   │   │   ├── elm_example.elm
│   │   │   │   │   ├── go_example.go
│   │   │   │   │   ├── groovy_example.groovy
│   │   │   │   │   ├── hcl_example.hcl
│   │   │   │   │   ├── html_example.html
│   │   │   │   │   ├── java_example.java
│   │   │   │   │   ├── javascript_example.js
│   │   │   │   │   ├── kotlin_example.kt
│   │   │   │   │   ├── lua_example.lua
│   │   │   │   │   ├── markdown_example.md
│   │   │   │   │   ├── ocaml_example.ml
│   │   │   │   │   ├── php_example.php
│   │   │   │   │   ├── protobuf_example.proto
│   │   │   │   │   ├── python_example.py
│   │   │   │   │   ├── ruby_example.rb
│   │   │   │   │   ├── rust_example.rs
│   │   │   │   │   ├── scala_example.scala
│   │   │   │   │   ├── svelte_example.svelte
│   │   │   │   │   ├── swift_example.swift
│   │   │   │   │   ├── toml_example.toml
│   │   │   │   │   ├── tsx_example.tsx
│   │   │   │   │   ├── typescript_example.ts
│   │   │   │   │   └── yaml_example.yaml
│   │   │   │   ├── map.go
│   │   │   │   ├── markup.go
│   │   │   │   ├── multi.go
│   │   │   │   ├── nodes_config.go
│   │   │   │   ├── nodes_find.go
│   │   │   │   └── svelte.go
│   │   │   ├── map.txt
│   │   │   ├── parsers.go
│   │   │   ├── structured_edits_apply.go
│   │   │   ├── structured_edits_generic.go
│   │   │   ├── structured_edits_sections.go
│   │   │   ├── structured_edits_test.go
│   │   │   ├── structured_edits_tree_sitter.go
│   │   │   ├── unique_replacement.go
│   │   │   ├── unique_replacement_test.go
│   │   │   └── validate.go
│   │   ├── types/
│   │   │   ├── active_plan.go
│   │   │   ├── active_plan_pending_builds.go
│   │   │   ├── auth.go
│   │   │   ├── convo_message_desc.go
│   │   │   ├── exec_status.go
│   │   │   ├── message.go
│   │   │   ├── model.go
│   │   │   ├── reply.go
│   │   │   ├── reply_test.go
│   │   │   ├── reply_test_examples/
│   │   │   │   ├── 1.md
│   │   │   │   ├── 10.md
│   │   │   │   ├── 2.md
│   │   │   │   ├── 3.md
│   │   │   │   ├── 4.md
│   │   │   │   ├── 5.md
│   │   │   │   ├── 6.md
│   │   │   │   ├── 7.md
│   │   │   │   ├── 8.md
│   │   │   │   └── 9.md
│   │   │   ├── safe_map.go
│   │   │   └── trial.go
│   │   ├── utils/
│   │   │   ├── whitespace.go
│   │   │   ├── whitespace_test.go
│   │   │   └── xml.go
│   │   └── version.txt
│   ├── shared/
│   │   ├── ai_models_available.go
│   │   ├── ai_models_compatibility.go
│   │   ├── ai_models_config.go
│   │   ├── ai_models_credentials.go
│   │   ├── ai_models_custom.go
│   │   ├── ai_models_data_models.go
│   │   ├── ai_models_errors.go
│   │   ├── ai_models_large_context.go
│   │   ├── ai_models_openrouter.go
│   │   ├── ai_models_packs.go
│   │   ├── ai_models_providers.go
│   │   ├── ai_models_roles.go
│   │   ├── auth.go
│   │   ├── context.go
│   │   ├── convo_message.go
│   │   ├── data_models.go
│   │   ├── email.go
│   │   ├── file_maps.go
│   │   ├── go.mod
│   │   ├── go.sum
│   │   ├── images.go
│   │   ├── org_user_config.go
│   │   ├── plan_config.go
│   │   ├── plan_model_settings.go
│   │   ├── plan_result.go
│   │   ├── plan_result_exec_history.go
│   │   ├── plan_result_pending_summary.go
│   │   ├── plan_result_replacements.go
│   │   ├── plan_status.go
│   │   ├── rbac.go
│   │   ├── req_res.go
│   │   ├── stream.go
│   │   ├── streamed_change.go
│   │   ├── syntax.go
│   │   ├── tokens.go
│   │   ├── tygo.yaml
│   │   ├── utils.go
│   │   └── utils_struct.go
│   └── start_local.sh
├── docs/
│   ├── .gitignore
│   ├── README.md
│   ├── babel.config.js
│   ├── blog/
│   │   ├── 2019-05-28-first-blog-post.md
│   │   ├── 2019-05-29-long-blog-post.md
│   │   ├── 2021-08-01-mdx-blog-post.mdx
│   │   ├── 2021-08-26-welcome/
│   │   │   └── index.md
│   │   ├── authors.yml
│   │   └── tags.yml
│   ├── docs/
│   │   ├── cli-reference.md
│   │   ├── core-concepts/
│   │   │   ├── _category_.json
│   │   │   ├── autonomy.md
│   │   │   ├── background-tasks.md
│   │   │   ├── branches.md
│   │   │   ├── configuration.md
│   │   │   ├── context-management.md
│   │   │   ├── conversations.md
│   │   │   ├── execution-and-debugging.md
│   │   │   ├── orgs.md
│   │   │   ├── plans.md
│   │   │   ├── prompts.md
│   │   │   ├── reviewing-changes.md
│   │   │   └── version-control.md
│   │   ├── development.md
│   │   ├── environment-variables.md
│   │   ├── hosting/
│   │   │   ├── _category_.json
│   │   │   ├── cloud.md
│   │   │   └── self-hosting/
│   │   │       ├── _category_.json
│   │   │       ├── advanced-self-hosting.md
│   │   │       └── local-mode-quickstart.md
│   │   ├── install.md
│   │   ├── models/
│   │   │   ├── _category_.json
│   │   │   ├── built-in/
│   │   │   │   ├── _category_.json
│   │   │   │   ├── built-in-models.md
│   │   │   │   └── built-in-packs.md
│   │   │   ├── claude-subscription.md
│   │   │   ├── custom-models.md
│   │   │   ├── model-providers.md
│   │   │   ├── model-settings.md
│   │   │   ├── models-overview.md
│   │   │   ├── ollama.md
│   │   │   └── roles.md
│   │   ├── quick-start.md
│   │   ├── repl.md
│   │   └── security.md
│   ├── docusaurus.config.ts
│   ├── package.json
│   ├── sidebars.ts
│   ├── src/
│   │   └── css/
│   │       └── custom.css
│   ├── static/
│   │   ├── .nojekyll
│   │   └── _redirects
│   └── tsconfig.json
├── plans/
│   ├── invite-commands.txt
│   ├── model-sets-custom-models-crud.txt
│   ├── pdx-file.md
│   └── race_cond_chatgpt.txt
├── releases/
│   ├── cli/
│   │   ├── CHANGELOG.md
│   │   └── versions/
│   │       ├── 0.7.1.md
│   │       ├── 0.7.2.md
│   │       ├── 0.7.3.md
│   │       ├── 0.8.0.md
│   │       ├── 0.8.1.md
│   │       ├── 0.8.2.md
│   │       ├── 0.8.3.md
│   │       ├── 0.9.0.md
│   │       ├── 0.9.1.md
│   │       ├── 1.0.0.md
│   │       ├── 1.1.0.md
│   │       ├── 1.1.1.md
│   │       ├── 1.1.2.md
│   │       ├── 2.0.0.md
│   │       ├── 2.0.1.md
│   │       ├── 2.0.2.md
│   │       ├── 2.0.3.md
│   │       ├── 2.0.4.md
│   │       ├── 2.0.5.md
│   │       ├── 2.0.6.md
│   │       ├── 2.0.7+1.md
│   │       ├── 2.0.7.md
│   │       ├── 2.0.8.md
│   │       ├── 2.1.0+1.md
│   │       ├── 2.1.0.md
│   │       ├── 2.1.1.md
│   │       ├── 2.1.2.md
│   │       ├── 2.1.3.md
│   │       ├── 2.1.5.md
│   │       ├── 2.1.6+1.md
│   │       ├── 2.1.6.md
│   │       ├── 2.2.0.md
│   │       └── 2.2.1.md
│   └── server/
│       ├── CHANGELOG.md
│       └── versions/
│           ├── 0.7.0.md
│           ├── 0.7.1.md
│           ├── 0.8.0.md
│           ├── 0.8.1.md
│           ├── 0.8.2.md
│           ├── 0.8.3.md
│           ├── 0.8.4.md
│           ├── 0.9.0.md
│           ├── 0.9.1.md
│           ├── 1.0.0.md
│           ├── 1.0.1.md
│           ├── 1.1.0.md
│           ├── 1.1.1.md
│           ├── 2.0.0+1.md
│           ├── 2.0.0+2.md
│           ├── 2.0.0.md
│           ├── 2.0.2.md
│           ├── 2.0.3.md
│           ├── 2.0.4.md
│           ├── 2.0.5.md
│           ├── 2.0.6.md
│           ├── 2.1.0+1.md
│           ├── 2.1.0.md
│           ├── 2.1.1+1.md
│           ├── 2.1.1.md
│           ├── 2.1.2.md
│           ├── 2.1.3.md
│           ├── 2.1.4.md
│           ├── 2.1.5.md
│           ├── 2.1.6+1.md
│           ├── 2.1.6.md
│           ├── 2.1.7.md
│           ├── 2.1.8.md
│           ├── 2.2.0.md
│           └── 2.2.1.md
├── scripts/
│   └── merge_from_reflog.sh
└── test/
    ├── _test_apply.sh
    ├── error-test.html
    ├── evals/
    │   └── promptfoo-poc/
    │       ├── README.md
    │       ├── build/
    │       │   ├── assets/
    │       │   │   ├── build/
    │       │   │   │   ├── changes.md
    │       │   │   │   └── post_build.go
    │       │   │   └── shared/
    │       │   │       └── pre_build.go
    │       │   ├── build.config.properties
    │       │   ├── build.parameters.json
    │       │   ├── build.prompt.txt
    │       │   ├── build.provider.yml
    │       │   ├── promptfooconfig.yaml
    │       │   └── tests/
    │       │       └── build.test.yml
    │       ├── evals.md
    │       ├── fix/
    │       │   ├── assets/
    │       │   │   ├── removal/
    │       │   │   │   ├── changes.md
    │       │   │   │   ├── post_build.go
    │       │   │   │   └── problems.txt
    │       │   │   └── shared/
    │       │   │       └── pre_build.go
    │       │   ├── fix.config.properties
    │       │   ├── fix.parameters.json
    │       │   ├── fix.prompt.txt
    │       │   ├── fix.provider.yml
    │       │   ├── promptfooconfig.yaml
    │       │   └── tests/
    │       │       └── fix.test.yml
    │       ├── templates/
    │       │   └── provider.template.yml
    │       └── verify/
    │           ├── assets/
    │           │   ├── removal/
    │           │   │   ├── changes.md
    │           │   │   ├── diff.txt
    │           │   │   └── post_build.go
    │           │   ├── shared/
    │           │   │   └── pre_build.go
    │           │   └── valid/
    │           │       ├── changes.md
    │           │       ├── diff.txt
    │           │       └── post_build.go
    │           ├── promptfooconfig.yaml
    │           ├── tests/
    │           │   ├── removal.test.yml
    │           │   └── validate.test.yml
    │           ├── verify.config.properties
    │           ├── verify.parameters.json
    │           ├── verify.prompt.txt
    │           └── verify.provider.yml
    ├── plan_deletion_test.sh
    ├── project/
    │   └── react-redux-foobar/
    │       ├── action.ts
    │       ├── component.ts
    │       ├── lib/
    │       │   ├── constants.ts
    │       │   └── utils.ts
    │       ├── package.json
    │       ├── reducer.ts
    │       ├── tests/
    │       │   ├── action.test.ts
    │       │   └── component.test.ts
    │       └── tsconfig.json
    ├── smoke_test.sh
    ├── test_custom_models.sh
    ├── test_prompts/
    │   ├── aws-infra.txt
    │   ├── pong.txt
    │   ├── robust-logging.txt
    │   ├── stripe-plan.txt
    │   └── tic-tac-toe.txt
    └── test_utils.sh
Download .txt
Showing preview only (231K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2489 symbols across 359 files)

FILE: app/cli/api/clients.go
  constant dialTimeout (line 14) | dialTimeout = 10 * time.Second
  constant fastReqTimeout (line 15) | fastReqTimeout = 30 * time.Second
  constant slowReqTimeout (line 16) | slowReqTimeout = 5 * time.Minute
  type Api (line 18) | type Api struct
  function init (line 23) | func init() {
  function GetApiHost (line 34) | func GetApiHost() string {
  type authenticatedTransport (line 44) | type authenticatedTransport struct
    method RoundTrip (line 48) | func (t *authenticatedTransport) RoundTrip(req *http.Request) (*http.R...
  type unauthenticatedTransport (line 57) | type unauthenticatedTransport struct
    method RoundTrip (line 61) | func (t *unauthenticatedTransport) RoundTrip(req *http.Request) (*http...
  type retryTransport (line 66) | type retryTransport struct
    method RoundTrip (line 75) | func (t *retryTransport) RoundTrip(req *http.Request) (*http.Response,...

FILE: app/cli/api/errors.go
  function HandleApiError (line 14) | func HandleApiError(r *http.Response, errBody []byte) *shared.ApiError {
  function refreshAuthIfNeeded (line 44) | func refreshAuthIfNeeded(apiErr *shared.ApiError) (bool, *shared.ApiErro...

FILE: app/cli/api/methods.go
  method CreateCliTrialSession (line 19) | func (a *Api) CreateCliTrialSession() (string, *shared.ApiError) {
  method GetCliTrialSession (line 45) | func (a *Api) GetCliTrialSession(token string) (*shared.SessionResponse,...
  method CreateProject (line 75) | func (a *Api) CreateProject(req shared.CreateProjectRequest) (*shared.Cr...
  method ListProjects (line 108) | func (a *Api) ListProjects() ([]*shared.Project, *shared.ApiError) {
  method SetProjectPlan (line 135) | func (a *Api) SetProjectPlan(projectId string, req shared.SetProjectPlan...
  method RenameProject (line 167) | func (a *Api) RenameProject(projectId string, req shared.RenameProjectRe...
  method ListPlans (line 199) | func (a *Api) ListPlans(projectIds []string) ([]*shared.Plan, *shared.Ap...
  method ListArchivedPlans (line 234) | func (a *Api) ListArchivedPlans(projectIds []string) ([]*shared.Plan, *s...
  method ListPlansRunning (line 267) | func (a *Api) ListPlansRunning(projectIds []string, includeRecent bool) ...
  method GetCurrentBranchByPlanId (line 303) | func (a *Api) GetCurrentBranchByPlanId(projectId string, req shared.GetC...
  method CreatePlan (line 347) | func (a *Api) CreatePlan(projectId string, req shared.CreatePlanRequest)...
  method GetPlan (line 379) | func (a *Api) GetPlan(planId string) (*shared.Plan, *shared.ApiError) {
  method DeletePlan (line 408) | func (a *Api) DeletePlan(planId string) *shared.ApiError {
  method DeleteAllPlans (line 436) | func (a *Api) DeleteAllPlans(projectId string) *shared.ApiError {
  method TellPlan (line 465) | func (a *Api) TellPlan(planId, branch string, req shared.TellPlanRequest...
  method BuildPlan (line 514) | func (a *Api) BuildPlan(planId, branch string, req shared.BuildPlanReque...
  method RespondMissingFile (line 567) | func (a *Api) RespondMissingFile(planId, branch string, req shared.Respo...
  method ConnectPlan (line 602) | func (a *Api) ConnectPlan(planId, branch string, onStream types.OnStream...
  method StopPlan (line 633) | func (a *Api) StopPlan(ctx context.Context, planId, branch string) *shar...
  method GetCurrentPlanState (line 660) | func (a *Api) GetCurrentPlanState(planId, branch string) (*shared.Curren...
  method GetCurrentPlanStateAtSha (line 664) | func (a *Api) GetCurrentPlanStateAtSha(planId, sha string) (*shared.Curr...
  method getCurrentPlanState (line 668) | func (a *Api) getCurrentPlanState(planId, branch, sha string) (*shared.C...
  method ApplyPlan (line 701) | func (a *Api) ApplyPlan(planId, branch string, req shared.ApplyPlanReque...
  method ArchivePlan (line 741) | func (a *Api) ArchivePlan(planId string) *shared.ApiError {
  method UnarchivePlan (line 769) | func (a *Api) UnarchivePlan(planId string) *shared.ApiError {
  method RenamePlan (line 797) | func (a *Api) RenamePlan(planId string, name string) *shared.ApiError {
  method RejectAllChanges (line 836) | func (a *Api) RejectAllChanges(planId, branch string) *shared.ApiError {
  method RejectFile (line 864) | func (a *Api) RejectFile(planId, branch, filePath string) *shared.ApiErr...
  method RejectFiles (line 898) | func (a *Api) RejectFiles(planId, branch string, paths []string) *shared...
  method LoadContext (line 932) | func (a *Api) LoadContext(planId, branch string, req shared.LoadContextR...
  method UpdateContext (line 965) | func (a *Api) UpdateContext(planId, branch string, req shared.UpdateCont...
  method DeleteContext (line 1007) | func (a *Api) DeleteContext(planId, branch string, req shared.DeleteCont...
  method ListContext (line 1045) | func (a *Api) ListContext(planId, branch string) ([]*shared.Context, *sh...
  method LoadCachedFileMap (line 1073) | func (a *Api) LoadCachedFileMap(planId, branch string, req shared.LoadCa...
  method ListConvo (line 1101) | func (a *Api) ListConvo(planId, branch string) ([]*shared.ConvoMessage, ...
  method GetPlanStatus (line 1129) | func (a *Api) GetPlanStatus(planId, branch string) (string, *shared.ApiE...
  method GetPlanDiffs (line 1157) | func (a *Api) GetPlanDiffs(planId, branch string, plain bool) (string, *...
  method ListLogs (line 1189) | func (a *Api) ListLogs(planId, branch string) (*shared.LogResponse, *sha...
  method RewindPlan (line 1218) | func (a *Api) RewindPlan(planId, branch string, req shared.RewindPlanReq...
  method SignIn (line 1257) | func (a *Api) SignIn(req shared.SignInRequest, customHost string) (*shar...
  method CreateAccount (line 1289) | func (a *Api) CreateAccount(req shared.CreateAccountRequest, customHost ...
  method CreateOrg (line 1321) | func (a *Api) CreateOrg(req shared.CreateOrgRequest) (*shared.CreateOrgR...
  method GetOrgSession (line 1353) | func (a *Api) GetOrgSession() (*shared.Org, *shared.ApiError) {
  method ListOrgs (line 1382) | func (a *Api) ListOrgs() ([]*shared.Org, *shared.ApiError) {
  method GetOrgUserConfig (line 1409) | func (a *Api) GetOrgUserConfig() (*shared.OrgUserConfig, *shared.ApiErro...
  method UpdateOrgUserConfig (line 1436) | func (a *Api) UpdateOrgUserConfig(c shared.OrgUserConfig) *shared.ApiErr...
  method DeleteUser (line 1471) | func (a *Api) DeleteUser(userId string) *shared.ApiError {
  method ListOrgRoles (line 1497) | func (a *Api) ListOrgRoles() ([]*shared.OrgRole, *shared.ApiError) {
  method InviteUser (line 1525) | func (a *Api) InviteUser(req shared.InviteRequest) *shared.ApiError {
  method ListPendingInvites (line 1552) | func (a *Api) ListPendingInvites() ([]*shared.Invite, *shared.ApiError) {
  method ListAcceptedInvites (line 1579) | func (a *Api) ListAcceptedInvites() ([]*shared.Invite, *shared.ApiError) {
  method ListAllInvites (line 1606) | func (a *Api) ListAllInvites() ([]*shared.Invite, *shared.ApiError) {
  method DeleteInvite (line 1633) | func (a *Api) DeleteInvite(inviteId string) *shared.ApiError {
  method CreateEmailVerification (line 1660) | func (a *Api) CreateEmailVerification(email, customHost, userId string) ...
  method CreateSignInCode (line 1692) | func (a *Api) CreateSignInCode() (string, *shared.ApiError) {
  method SignOut (line 1720) | func (a *Api) SignOut() *shared.ApiError {
  method ListUsers (line 1742) | func (a *Api) ListUsers() (*shared.ListUsersResponse, *shared.ApiError) {
  method ListBranches (line 1769) | func (a *Api) ListBranches(planId string) ([]*shared.Branch, *shared.Api...
  method CreateBranch (line 1798) | func (a *Api) CreateBranch(planId, branch string, req shared.CreateBranc...
  method DeleteBranch (line 1826) | func (a *Api) DeleteBranch(planId, branch string) *shared.ApiError {
  method GetSettings (line 1854) | func (a *Api) GetSettings(planId, branch string) (*shared.PlanSettings, ...
  method UpdateSettings (line 1883) | func (a *Api) UpdateSettings(planId, branch string, req shared.UpdateSet...
  method GetOrgDefaultSettings (line 1926) | func (a *Api) GetOrgDefaultSettings() (*shared.PlanSettings, *shared.Api...
  method UpdateOrgDefaultSettings (line 1955) | func (a *Api) UpdateOrgDefaultSettings(req shared.UpdateSettingsRequest)...
  method GetPlanConfig (line 1997) | func (a *Api) GetPlanConfig(planId string) (*shared.PlanConfig, *shared....
  method UpdatePlanConfig (line 2025) | func (a *Api) UpdatePlanConfig(planId string, req shared.UpdatePlanConfi...
  method GetDefaultPlanConfig (line 2058) | func (a *Api) GetDefaultPlanConfig() (*shared.PlanConfig, *shared.ApiErr...
  method UpdateDefaultPlanConfig (line 2086) | func (a *Api) UpdateDefaultPlanConfig(req shared.UpdateDefaultPlanConfig...
  method CreateCustomModels (line 2119) | func (a *Api) CreateCustomModels(input *shared.ModelsInput) *shared.ApiE...
  method ListCustomModels (line 2146) | func (a *Api) ListCustomModels() ([]*shared.CustomModel, *shared.ApiErro...
  method ListCustomProviders (line 2174) | func (a *Api) ListCustomProviders() ([]*shared.CustomProvider, *shared.A...
  method ListModelPacks (line 2201) | func (a *Api) ListModelPacks() ([]*shared.ModelPack, *shared.ApiError) {
  method GetCreditsTransactions (line 2231) | func (a *Api) GetCreditsTransactions(pageSize, pageNum int, req shared.C...
  method GetCreditsSummary (line 2265) | func (a *Api) GetCreditsSummary(req shared.CreditsLogRequest) (*shared.C...
  method GetBalance (line 2298) | func (a *Api) GetBalance() (decimal.Decimal, *shared.ApiError) {
  method GetFileMap (line 2326) | func (a *Api) GetFileMap(req shared.GetFileMapRequest) (*shared.GetFileM...
  method GetContextBody (line 2358) | func (a *Api) GetContextBody(planId, branch, contextId string) (*shared....
  method AutoLoadContext (line 2386) | func (a *Api) AutoLoadContext(ctx context.Context, planId, branch string...
  method GetBuildStatus (line 2428) | func (a *Api) GetBuildStatus(planId, branch string) (*shared.GetBuildSta...

FILE: app/cli/api/stream.go
  constant HeartbeatTimeout (line 17) | HeartbeatTimeout = 16 * time.Second
  function connectPlanRespStream (line 19) | func connectPlanRespStream(body io.ReadCloser, onStream types.OnStreamPl...
  function readUntilSeparator (line 72) | func readUntilSeparator(reader *bufio.Reader, separator string) (string,...

FILE: app/cli/auth/account.go
  constant AddAccountOption (line 12) | AddAccountOption = "Add another account"
  function SelectOrSignInOrCreate (line 14) | func SelectOrSignInOrCreate() error {
  function SignInWithCode (line 113) | func SignInWithCode(code, host string) error {
  function promptInitialAuth (line 128) | func promptInitialAuth() error {
  constant SignInLocalOption (line 142) | SignInLocalOption = "Local mode host"
  constant SignInOtherOption (line 143) | SignInOtherOption = "Another host"
  function promptSignInNewAccount (line 146) | func promptSignInNewAccount() error {
  type verifyEmailRes (line 201) | type verifyEmailRes struct
  function verifyEmail (line 207) | func verifyEmail(email, host string) (*verifyEmailRes, error) {
  function signIn (line 239) | func signIn(email, pin, host string) error {
  function handleSignInResponse (line 254) | func handleSignInResponse(res *shared.SessionResponse, host string) error {
  function createAccount (line 296) | func createAccount(email, pin, host string, isLocalMode bool) error {

FILE: app/cli/auth/api.go
  function SetApiClient (line 16) | func SetApiClient(client types.ApiClient) {
  function SetAuthHeader (line 20) | func SetAuthHeader(req *http.Request) error {
  function SetVersionHeader (line 46) | func SetVersionHeader(req *http.Request) {

FILE: app/cli/auth/auth.go
  function SetOpenUnauthenticatedCloudURLFn (line 16) | func SetOpenUnauthenticatedCloudURLFn(fn func(msg, path string)) {
  function SetOpenAuthenticatedURLFn (line 20) | func SetOpenAuthenticatedURLFn(fn func(msg, path string)) {
  function MustResolveAuthWithOrg (line 24) | func MustResolveAuthWithOrg() {
  function MustResolveAuth (line 28) | func MustResolveAuth(requireOrg bool) {
  function RefreshInvalidToken (line 90) | func RefreshInvalidToken() error {
  function RefreshAuth (line 114) | func RefreshAuth() error {

FILE: app/cli/auth/org.go
  function resolveOrgAuth (line 11) | func resolveOrgAuth(orgs []*shared.Org, isLocalMode bool) (*shared.Org, ...
  function promptNoOrgs (line 39) | func promptNoOrgs() (*shared.Org, error) {
  function createOrg (line 55) | func createOrg(isLocalMode bool) (*shared.Org, error) {
  function promptAutoAddUsersIfValid (line 90) | func promptAutoAddUsersIfValid(email string) (bool, error) {
  constant CreateOrgOption (line 105) | CreateOrgOption = "Create a new org"
  function selectOrg (line 107) | func selectOrg(orgs []*shared.Org, isLocalMode bool) (*shared.Org, error) {

FILE: app/cli/auth/state.go
  function loadAccounts (line 14) | func loadAccounts() ([]*shared.ClientAccount, error) {
  function setAuth (line 36) | func setAuth(auth *shared.ClientAuth) error {
  function storeAccount (line 54) | func storeAccount(toStore *shared.ClientAccount) error {
  function writeCurrentAuth (line 89) | func writeCurrentAuth() error {

FILE: app/cli/auth/trial.go
  function ConvertTrial (line 9) | func ConvertTrial() {
  function startTrial (line 41) | func startTrial() {

FILE: app/cli/cmd/apply.go
  function init (line 15) | func init() {
  function apply (line 30) | func apply(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/archive.go
  function init (line 26) | func init() {
  function archive (line 30) | func archive(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/billing.go
  function init (line 17) | func init() {
  function billing (line 21) | func billing(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/branches.go
  function init (line 25) | func init() {
  function branches (line 29) | func branches(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/browser.go
  function init (line 31) | func init() {
  function browser (line 37) | func browser(cmd *cobra.Command, args []string) error {
  function findChrome (line 56) | func findChrome() (string, error) {
  function openChromeWithLogs (line 90) | func openChromeWithLogs(urls []string) error {
  function openWithOSDefault (line 241) | func openWithOSDefault(urls []string) error {

FILE: app/cli/cmd/build.go
  function init (line 25) | func init() {
  function build (line 38) | func build(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/cd.go
  function init (line 19) | func init() {
  function cd (line 31) | func cd(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/chat.go
  function init (line 24) | func init() {
  function doChat (line 39) | func doChat(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/checkout.go
  constant OptCreateNewBranch (line 19) | OptCreateNewBranch = "Create a new branch"
  function init (line 32) | func init() {
  function checkout (line 37) | func checkout(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/claude_max.go
  function connectClaude (line 31) | func connectClaude(cmd *cobra.Command, args []string) {
  function disconnectClaude (line 36) | func disconnectClaude(cmd *cobra.Command, args []string) {
  function claudeStatus (line 41) | func claudeStatus(cmd *cobra.Command, args []string) {
  function init (line 71) | func init() {

FILE: app/cli/cmd/clear.go
  function clearAllContext (line 22) | func clearAllContext(cmd *cobra.Command, args []string) {
  function init (line 60) | func init() {

FILE: app/cli/cmd/config.go
  function init (line 14) | func init() {
  function config (line 31) | func config(cmd *cobra.Command, args []string) {
  function defaultConfig (line 57) | func defaultConfig(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/connect.go
  function init (line 25) | func init() {
  function connect (line 30) | func connect(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/context_show.go
  function init (line 14) | func init() {

FILE: app/cli/cmd/continue.go
  function init (line 25) | func init() {
  function doContinue (line 36) | func doContinue(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/convo.go
  function init (line 28) | func init() {
  constant stoppedEarlyMsg (line 38) | stoppedEarlyMsg = "You stopped the reply early"
  function convo (line 40) | func convo(cmd *cobra.Command, args []string) {
  function convertCodeBlocks (line 180) | func convertCodeBlocks(msg string) string {

FILE: app/cli/cmd/current.go
  function init (line 22) | func init() {
  function current (line 26) | func current(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/debug.go
  constant DebugDefaultTries (line 29) | DebugDefaultTries = 5
  function init (line 39) | func init() {
  function doDebug (line 44) | func doDebug(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/delete_branch.go
  function init (line 24) | func init() {
  function deleteBranch (line 28) | func deleteBranch(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/delete_plan.go
  function init (line 22) | func init() {
  function matchPlansByPattern (line 36) | func matchPlansByPattern(pattern string, plans []*shared.Plan) []*shared...
  function del (line 46) | func del(cmd *cobra.Command, args []string) {
  function delAll (line 172) | func delAll() {

FILE: app/cli/cmd/diffs.go
  function init (line 35) | func init() {
  function diffs (line 49) | func diffs(cmd *cobra.Command, args []string) {
  function showGitDiff (line 249) | func showGitDiff() {

FILE: app/cli/cmd/invite.go
  function init (line 21) | func init() {
  function invite (line 25) | func invite(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/load.go
  function init (line 32) | func init() {
  function contextLoad (line 42) | func contextLoad(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/log.go
  function init (line 24) | func init() {
  function runLog (line 29) | func runLog(cmd *cobra.Command, args []string) {
  function convertTimestampsToLocal (line 58) | func convertTimestampsToLocal(input string) (string, error) {

FILE: app/cli/cmd/ls.go
  function listContext (line 27) | func listContext(cmd *cobra.Command, args []string) {
  function init (line 112) | func init() {

FILE: app/cli/cmd/model_helpers.go
  function warnModelsFileLocalChanges (line 13) | func warnModelsFileLocalChanges(path, cmd string) (bool, error) {
  type maybePromptAndOpenModelsFileResult (line 35) | type maybePromptAndOpenModelsFileResult struct
  function maybePromptAndOpenModelsFile (line 40) | func maybePromptAndOpenModelsFile(filePath, pathArg, cmd string, default...

FILE: app/cli/cmd/model_packs.go
  function init (line 51) | func init() {
  function listModelPacks (line 61) | func listModelPacks(cmd *cobra.Command, args []string) {
  function showModelPack (line 125) | func showModelPack(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/model_providers.go
  function init (line 42) | func init() {
  function listProviders (line 49) | func listProviders(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/models.go
  function init (line 28) | func init() {
  function manageCustomModels (line 93) | func manageCustomModels(cmd *cobra.Command, args []string) {
  function models (line 240) | func models(cmd *cobra.Command, args []string) {
  function defaultModels (line 279) | func defaultModels(cmd *cobra.Command, args []string) {
  function listAvailableModels (line 304) | func listAvailableModels(cmd *cobra.Command, args []string) {
  function renderSettings (line 364) | func renderSettings(settings *shared.PlanSettings, allProperties bool) {
  function renderModelPack (line 384) | func renderModelPack(modelPack *shared.ModelPack, customModelsById map[s...
  function customModelsNotImplemented (line 509) | func customModelsNotImplemented(cmd *cobra.Command, args []string) {
  function getExampleTemplate (line 516) | func getExampleTemplate(isCloud, isCloudIntegratedModels bool) shared.Cl...

FILE: app/cli/cmd/new.go
  function init (line 31) | func init() {
  function new (line 39) | func new(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/plan_exec_helpers.go
  constant EditorTypeVim (line 16) | EditorTypeVim  string = "vim"
  constant EditorTypeNano (line 17) | EditorTypeNano string = "nano"
  constant defaultAutoDebugTries (line 22) | defaultAutoDebugTries = 5
  function init (line 40) | func init() {
  type initExecFlagsParams (line 51) | type initExecFlagsParams struct
  function initExecFlags (line 64) | func initExecFlags(cmd *cobra.Command, params initExecFlagsParams) {
  function initApplyFlags (line 110) | func initApplyFlags(cmd *cobra.Command, applyFlag bool) {
  function initExecScriptFlags (line 124) | func initExecScriptFlags(cmd *cobra.Command) {
  function validatePlanExecFlags (line 131) | func validatePlanExecFlags(isApply bool) {
  function mustSetPlanExecFlags (line 158) | func mustSetPlanExecFlags(cmd *cobra.Command, isApply bool) {
  type autoDebugValue (line 222) | type autoDebugValue struct
    method Set (line 231) | func (f *autoDebugValue) Set(s string) error {
    method String (line 247) | func (f *autoDebugValue) String() string {
    method Type (line 254) | func (f *autoDebugValue) Type() string {
  function newAutoDebugValue (line 226) | func newAutoDebugValue(p *int) *autoDebugValue {
  type editorValue (line 259) | type editorValue struct
    method Set (line 268) | func (f *editorValue) Set(s string) error {
    method String (line 278) | func (f *editorValue) String() string {
    method Type (line 285) | func (f *editorValue) Type() string {
  function newEditorValue (line 263) | func newEditorValue(p *string) *editorValue {

FILE: app/cli/cmd/plan_start_helpers.go
  function AddNewPlanFlags (line 36) | func AddNewPlanFlags(cmd *cobra.Command) {
  function resolveAutoMode (line 58) | func resolveAutoMode(config *shared.PlanConfig) (bool, *shared.PlanConfi...
  function resolveAutoModeSilent (line 63) | func resolveAutoModeSilent(config *shared.PlanConfig) (bool, *shared.Pla...
  function resolveAutoModeWithArgs (line 67) | func resolveAutoModeWithArgs(config *shared.PlanConfig, silent bool) (bo...
  function resolveModelPack (line 114) | func resolveModelPack() {
  function resolveModelPackSilent (line 118) | func resolveModelPackSilent(settings *shared.PlanSettings) (*shared.Plan...
  function resolveModelPackWithArgs (line 122) | func resolveModelPackWithArgs(settings *shared.PlanSettings, silent bool...
  function printModelPackTable (line 209) | func printModelPackTable(packName string) {
  function printAutoModeTable (line 216) | func printAutoModeTable(config *shared.PlanConfig) {

FILE: app/cli/cmd/plans.go
  function init (line 31) | func init() {
  function plans (line 44) | func plans(cmd *cobra.Command, args []string) {
  function listActive (line 55) | func listActive() {
  function listArchived (line 355) | func listArchived() {

FILE: app/cli/cmd/ps.go
  function init (line 24) | func init() {
  function ps (line 28) | func ps(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/reject.go
  function init (line 17) | func init() {
  function reject (line 30) | func reject(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/rename.go
  function init (line 21) | func init() {
  function rename (line 25) | func rename(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/repl.go
  function init (line 45) | func init() {
  function setReplConfig (line 64) | func setReplConfig() {
  function runRepl (line 68) | func runRepl(cmd *cobra.Command, args []string) {
  function getSuggestions (line 224) | func getSuggestions() []prompt.Suggest {
  function executeOnEnter (line 296) | func executeOnEnter(p *prompt.Prompt, indentSize int) (int, bool) {
  constant cancelOpt (line 311) | cancelOpt = "Cancel"
  function executor (line 313) | func executor(in string, p *prompt.Prompt) {
  function completer (line 526) | func completer(in prompt.Document) ([]prompt.Suggest, pstrings.RuneNumbe...
  type replWelcomeParams (line 769) | type replWelcomeParams struct
  function replWelcome (line 778) | func replWelcome(params replWelcomeParams) {
  function replHelp (line 886) | func replHelp() {
  function showReplMode (line 894) | func showReplMode() {
  function showMultiLineMode (line 906) | func showMultiLineMode() {
  function parseCommand (line 919) | func parseCommand(in string) (string, string) {
  function isFileInProjectPaths (line 1042) | func isFileInProjectPaths(filePath string) bool {
  function handleRunCommand (line 1062) | func handleRunCommand(args []string) error {
  function getPromptOpt (line 1091) | func getPromptOpt(cmd string) string {
  type suggestCmdsResult (line 1099) | type suggestCmdsResult struct
  function suggestCmds (line 1104) | func suggestCmds(cmds []string, promptOpt string) suggestCmdsResult {
  type execWithInputParams (line 1127) | type execWithInputParams struct
  type execWithInputResult (line 1140) | type execWithInputResult struct
  function execWithInput (line 1146) | func execWithInput(params execWithInputParams) execWithInputResult {
  function findSimilarCommands (line 1367) | func findSimilarCommands(input string, commands []string) []string {

FILE: app/cli/cmd/revoke.go
  function init (line 21) | func init() {
  function revoke (line 25) | func revoke(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/rewind.go
  function init (line 44) | func init() {
  function rewind (line 53) | func rewind(cmd *cobra.Command, args []string) {
  function formatLogMessage (line 495) | func formatLogMessage(msg string) string {

FILE: app/cli/cmd/rm.go
  function contextRm (line 33) | func contextRm(cmd *cobra.Command, args []string) {
  function init (line 102) | func init() {
  function parseIndices (line 106) | func parseIndices(args []string) map[int]bool {

FILE: app/cli/cmd/root.go
  function Execute (line 28) | func Execute() {
  function run (line 72) | func run(cmd *cobra.Command, args []string) {
  function init (line 76) | func init() {

FILE: app/cli/cmd/set_config.go
  function init (line 19) | func init() {
  function setAuto (line 54) | func setAuto(cmd *cobra.Command, args []string) {
  function setAutoDefault (line 58) | func setAutoDefault(cmd *cobra.Command, args []string) {
  function setConfig (line 62) | func setConfig(cmd *cobra.Command, args []string) {
  function defaultSetConfig (line 123) | func defaultSetConfig(cmd *cobra.Command, args []string) {
  type sortableSetting (line 161) | type sortableSetting struct
  function updateConfig (line 166) | func updateConfig(args []string, originalConfig *shared.PlanConfig) (str...
  function parseBooleanArg (line 320) | func parseBooleanArg(value string) (bool, error) {
  function loadMapIfNeeded (line 332) | func loadMapIfNeeded(originalConfig, updatedConfig *shared.PlanConfig) {
  function removeMapIfNeeded (line 355) | func removeMapIfNeeded(originalConfig, updatedConfig *shared.PlanConfig) {

FILE: app/cli/cmd/set_model.go
  function init (line 23) | func init() {
  function modelsSet (line 52) | func modelsSet(cmd *cobra.Command, args []string) {
  function defaultModelsSet (line 95) | func defaultModelsSet(cmd *cobra.Command, args []string) {
  function updateModelSettings (line 137) | func updateModelSettings(args []string, originalSettings *shared.PlanSet...

FILE: app/cli/cmd/sign_in.go
  function init (line 19) | func init() {
  function signIn (line 25) | func signIn(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/stop.go
  function init (line 22) | func init() {
  function stop (line 26) | func stop(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/summary.go
  function init (line 21) | func init() {
  function status (line 27) | func status(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/tell.go
  function init (line 33) | func init() {
  function doTell (line 41) | func doTell(cmd *cobra.Command, args []string) {
  function getTellPrompt (line 102) | func getTellPrompt(args []string) string {
  function prepareEditorCommand (line 144) | func prepareEditorCommand(editor string, filename string) *exec.Cmd {
  function getEditorInstructions (line 155) | func getEditorInstructions() string {
  function getEditorPrompt (line 167) | func getEditorPrompt() string {

FILE: app/cli/cmd/unarchive.go
  function init (line 26) | func init() {
  function unarchive (line 30) | func unarchive(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/update.go
  function init (line 22) | func init() {
  function update (line 27) | func update(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/usage.go
  constant MaxCreditsLogPageSize (line 24) | MaxCreditsLogPageSize = 500
  function init (line 45) | func init() {
  function usage (line 59) | func usage(cmd *cobra.Command, args []string) {
  function showUsage (line 67) | func showUsage() {
  function showLog (line 236) | func showLog(cmd *cobra.Command, args []string) {
  function formatSpend (line 542) | func formatSpend(spend decimal.Decimal) string {

FILE: app/cli/cmd/users.go
  function init (line 22) | func init() {
  function listUsersAndInvites (line 26) | func listUsersAndInvites(cmd *cobra.Command, args []string) {

FILE: app/cli/cmd/version.go
  function init (line 20) | func init() {

FILE: app/cli/format/file.go
  function GetFileNameWithoutExt (line 8) | func GetFileNameWithoutExt(path string) string {

FILE: app/cli/format/time.go
  constant Day (line 13) | Day      = 24 * time.Hour
  constant Week (line 14) | Week     = 7 * Day
  constant Month (line 15) | Month    = 30 * Day
  constant Year (line 16) | Year     = 12 * Month
  constant LongTime (line 17) | LongTime = 37 * Year
  function Time (line 23) | func Time(then time.Time) string {
  type relTimeMagnitude (line 42) | type relTimeMagnitude struct
  function relTime (line 63) | func relTime(a, b time.Time, albl, blbl string) string {
  function customRelTime (line 67) | func customRelTime(a, b time.Time, albl, blbl string, magnitudes []relTi...

FILE: app/cli/fs/fs.go
  function init (line 20) | func init() {
  function FindOrCreatePlandex (line 64) | func FindOrCreatePlandex() (string, bool, error) {
  function ProjectRootIsGitRepo (line 89) | func ProjectRootIsGitRepo() bool {
  function IsGitRepo (line 97) | func IsGitRepo(dir string) bool {
  function FindPlandexDir (line 116) | func FindPlandexDir() {
  function findPlandex (line 120) | func findPlandex(baseDir string) string {
  function isCommandAvailable (line 134) | func isCommandAvailable(name string) bool {

FILE: app/cli/fs/paths.go
  function GetProjectPaths (line 17) | func GetProjectPaths(baseDir string) (*types.ProjectPaths, error) {
  function GetPaths (line 25) | func GetPaths(baseDir, currentDir string) (*types.ProjectPaths, error) {
  function GetPlandexIgnore (line 352) | func GetPlandexIgnore(dir string) (*ignore.GitIgnore, error) {
  function GetBaseDirForContexts (line 370) | func GetBaseDirForContexts(contexts []*shared.Context) string {
  function GetBaseDirForFilePaths (line 382) | func GetBaseDirForFilePaths(paths []string) string {
  function IsSubpathOf (line 413) | func IsSubpathOf(parent, child, baseDir string) (bool, error) {
  function IsIgnored (line 448) | func IsIgnored(paths *types.ProjectPaths, path, baseDir string) (bool, s...
  function ShouldSkipDir (line 506) | func ShouldSkipDir(path string) bool {
  function IsInSkippedDir (line 523) | func IsInSkippedDir(path string) bool {

FILE: app/cli/fs/projects.go
  function GetParentProjectIdsWithPaths (line 14) | func GetParentProjectIdsWithPaths(currentUserId string) ([][2]string, er...
  function GetChildProjectIdsWithPaths (line 49) | func GetChildProjectIdsWithPaths(ctx context.Context, currentUserId stri...

FILE: app/cli/fs/utils.go
  function FileExists (line 8) | func FileExists(path string) (bool, error) {

FILE: app/cli/lib/active_stream.go
  function SelectActiveStream (line 11) | func SelectActiveStream(args []string) (string, string, bool) {

FILE: app/cli/lib/apply.go
  type ApplyPlanParams (line 28) | type ApplyPlanParams struct
  function MustApplyPlan (line 37) | func MustApplyPlan(
  function MustApplyPlanAttempt (line 43) | func MustApplyPlanAttempt(
  function handleApplyScript (line 254) | func handleApplyScript(
  function execApplyScript (line 332) | func execApplyScript(
  function apiApplyPlan (line 576) | func apiApplyPlan(planId, branch string) (string, error) {
  function commitApplied (line 594) | func commitApplied(autoCommit bool, commitSummary string, updatedFiles [...
  function ApplyFiles (line 622) | func ApplyFiles(toApply map[string]string, toRemove map[string]bool, pro...
  function Rollback (line 752) | func Rollback(rollbackPlan *types.ApplyRollbackPlan, msg bool) error {

FILE: app/cli/lib/apply_cgroup_linux.go
  constant cgroupCallTimeout (line 18) | cgroupCallTimeout = 1 * time.Second
  function MaybeIsolateCgroup (line 20) | func MaybeIsolateCgroup(cmd *exec.Cmd) (deleteFn func()) {

FILE: app/cli/lib/apply_cgroup_other.go
  function MaybeIsolateCgroup (line 8) | func MaybeIsolateCgroup(cmd *exec.Cmd) (deleteFn func()) {

FILE: app/cli/lib/apply_proc.go
  function SetPlatformSpecificAttrs (line 8) | func SetPlatformSpecificAttrs(cmd *exec.Cmd) {
  function KillProcessGroup (line 14) | func KillProcessGroup(cmd *exec.Cmd, signal syscall.Signal) error {

FILE: app/cli/lib/build.go
  function SetBuildPlanInlineFn (line 7) | func SetBuildPlanInlineFn(fn func(autoConfirm bool, maybeContexts []*sha...

FILE: app/cli/lib/claude_max.go
  constant claudeMaxClientId (line 23) | claudeMaxClientId = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
  constant claudeMaxScopes (line 24) | claudeMaxScopes = "org:create_api_key user:profile user:inference"
  constant claudeMaxRedirect (line 25) | claudeMaxRedirect = "https://console.anthropic.com/oauth/code/callback"
  constant claudeMaxTokenUrl (line 26) | claudeMaxTokenUrl = "https://console.anthropic.com/v1/oauth/token"
  function hasAnthropicModels (line 28) | func hasAnthropicModels(opts shared.ModelProviderOptions) bool {
  function promptClaudeMaxIfNeeded (line 37) | func promptClaudeMaxIfNeeded() bool {
  function connectClaudeMaxIfNeeded (line 67) | func connectClaudeMaxIfNeeded() bool {
  function refreshClaudeMaxCredsIfNeeded (line 92) | func refreshClaudeMaxCredsIfNeeded() {
  function ConnectClaudeMax (line 128) | func ConnectClaudeMax() {
  function DisconnectClaudeMax (line 145) | func DisconnectClaudeMax() {
  function connectClaudeMaxOauth (line 172) | func connectClaudeMaxOauth() {
  function exchangeCode (line 231) | func exchangeCode(code, verifier, state string) (*types.OauthResponse, e...
  function genCodeVerifier (line 267) | func genCodeVerifier() (string, error) {
  function sha256Base64 (line 275) | func sha256Base64(verifier string) string {
  function needsRefresh (line 280) | func needsRefresh(creds *types.OauthCreds) bool {
  function refreshCreds (line 285) | func refreshCreds(accountCreds *types.AccountCredentials) (*types.OauthC...

FILE: app/cli/lib/context_auto_load.go
  function AutoLoadContextFiles (line 17) | func AutoLoadContextFiles(ctx context.Context, files []string) (string, ...
  function MustLoadAutoContextMap (line 154) | func MustLoadAutoContextMap() {

FILE: app/cli/lib/context_conflict.go
  function checkContextConflicts (line 12) | func checkContextConflicts(filesByPath map[string]string) (bool, error) {

FILE: app/cli/lib/context_display.go
  function GetContextLabelAndIcon (line 5) | func GetContextLabelAndIcon(contextType shared.ContextType) (string, str...
  function FindContextByIndex (line 35) | func FindContextByIndex(contexts []*shared.Context, index int) *shared.C...
  function FindContextByName (line 44) | func FindContextByName(contexts []*shared.Context, name string) *shared....

FILE: app/cli/lib/context_load.go
  constant maxSkippedFileList (line 24) | maxSkippedFileList = 20
  function MustLoadContext (line 26) | func MustLoadContext(resources []string, params *types.LoadContextParams) {
  function printAlreadyLoadedMsg (line 759) | func printAlreadyLoadedMsg(alreadyLoadedByComposite map[string]*shared.C...
  function printIgnoredMsg (line 773) | func printIgnoredMsg() {

FILE: app/cli/lib/context_paths.go
  type ParseInputPathsParams (line 9) | type ParseInputPathsParams struct
  function ParseInputPaths (line 16) | func ParseInputPaths(params ParseInputPathsParams) ([]string, error) {

FILE: app/cli/lib/context_shared.go
  constant ContextMapMaxClientConcurrency (line 18) | ContextMapMaxClientConcurrency = 250
  type filePathWithSize (line 20) | type filePathWithSize struct
  type mapFileDetails (line 25) | type mapFileDetails struct
  function getMapFileDetails (line 34) | func getMapFileDetails(path string, size, mapSize int64) (mapFileDetails...
  type mapFileContent (line 103) | type mapFileContent struct
  function getMapFileContent (line 110) | func getMapFileContent(path string) (mapFileContent, error) {
  function processMapBatches (line 138) | func processMapBatches(mapInputBatches []shared.FileMapInputs) (shared.F...
  function readImageTokensForDefsOnly (line 177) | func readImageTokensForDefsOnly(path string, size int64, detail openai.I...
  function printSkippedFilesMsg (line 191) | func printSkippedFilesMsg(
  function getSkippedFilesMsg (line 201) | func getSkippedFilesMsg(

FILE: app/cli/lib/context_update.go
  function CheckOutdatedContextWithOutput (line 24) | func CheckOutdatedContextWithOutput(quiet, autoConfirm bool, maybeContex...
  type UpdateContextParams (line 198) | type UpdateContextParams struct
  type UpdateContextResult (line 204) | type UpdateContextResult struct
  function UpdateContextWithOutput (line 209) | func UpdateContextWithOutput(params UpdateContextParams) (UpdateContextR...
  function UpdateContext (line 224) | func UpdateContext(params UpdateContextParams) (UpdateContextResult, err...
  function CheckOutdatedContext (line 291) | func CheckOutdatedContext(maybeContexts []*shared.Context, projectPaths ...
  type mapState (line 295) | type mapState struct
  function checkOutdatedAndMaybeUpdateContext (line 305) | func checkOutdatedAndMaybeUpdateContext(doUpdate bool, maybeContexts []*...
  function tableForContextOutdated (line 1027) | func tableForContextOutdated(updatedContexts []*shared.Context, tokenDif...

FILE: app/cli/lib/current.go
  function MustResolveOrCreateProject (line 30) | func MustResolveOrCreateProject() {
  function MustResolveProject (line 34) | func MustResolveProject() {
  function MaybeResolveProject (line 38) | func MaybeResolveProject() {
  function resolveProject (line 42) | func resolveProject(mustResolve, shouldCreate bool) {
  function MustLoadCurrentPlan (line 124) | func MustLoadCurrentPlan() {
  function loadCurrentBranch (line 173) | func loadCurrentBranch() error {
  function GetCurrentPlanTable (line 211) | func GetCurrentPlanTable(plan *shared.Plan, currentBranchesByPlanId map[...
  function mustInitProject (line 258) | func mustInitProject(existingSettings *types.CurrentProjectSettingsByAcc...

FILE: app/cli/lib/custom_models.go
  type CustomModelsCheckLocalChangesResult (line 19) | type CustomModelsCheckLocalChangesResult struct
  function GetCustomModelsPath (line 24) | func GetCustomModelsPath(userId string) string {
  function GetServerModelsInput (line 28) | func GetServerModelsInput() (*shared.ModelsInput, error) {
  function CustomModelsCheckLocalChanges (line 93) | func CustomModelsCheckLocalChanges(path string) (CustomModelsCheckLocalC...
  function WriteCustomModelsFile (line 135) | func WriteCustomModelsFile(path string, modelsInput *shared.ModelsInput)...
  function SaveCustomModelsHash (line 162) | func SaveCustomModelsHash(basePath string, modelsInput *shared.ModelsInp...
  function MustSyncCustomModels (line 178) | func MustSyncCustomModels(path string, serverModelsInput *shared.ModelsI...
  function SyncCustomModels (line 330) | func SyncCustomModels() error {

FILE: app/cli/lib/editor.go
  function MaybePromptAndOpen (line 14) | func MaybePromptAndOpen(path string, defaultConfig *shared.PlanConfig, p...
  type SelectEditorResult (line 83) | type SelectEditorResult struct
  function SelectEditor (line 90) | func SelectEditor(includeOpenManuallyOpt bool) SelectEditorResult {
  type editorCandidate (line 155) | type editorCandidate struct
  constant maxEditorOpts (line 162) | maxEditorOpts = 5
  function detectEditors (line 164) | func detectEditors() []editorCandidate {

FILE: app/cli/lib/git.go
  function GitAddAndCommit (line 15) | func GitAddAndCommit(dir, message string, lockMutex bool) error {
  function GitAddAndCommitPaths (line 34) | func GitAddAndCommitPaths(dir, message string, paths []string, lockMutex...
  function GitAdd (line 59) | func GitAdd(repoDir, path string, lockMutex bool) error {
  function GitCommit (line 73) | func GitCommit(repoDir, commitMsg string, paths []string, lockMutex bool...
  function CheckUncommittedChanges (line 93) | func CheckUncommittedChanges() (bool, error) {
  function GitStashCreate (line 107) | func GitStashCreate(message string) error {
  constant PopStashConflictMsg (line 122) | PopStashConflictMsg = "overwritten by merge"
  constant ConflictMsgFilesEnd (line 123) | ConflictMsgFilesEnd = "commit your changes"
  function GitStashPop (line 125) | func GitStashPop(forceOverwrite bool) error {
  function GitClearUncommittedChanges (line 172) | func GitClearUncommittedChanges() error {
  function GitFileHasUncommittedChanges (line 191) | func GitFileHasUncommittedChanges(path string) (bool, error) {
  function GitCheckoutFile (line 203) | func GitCheckoutFile(path string) error {
  constant GitLogTimestampFormat (line 217) | GitLogTimestampFormat = "Mon Jan 2, 2006 | 3:04:05pm"
  function GetGitLogTimestamp (line 221) | func GetGitLogTimestamp(log string) (time.Time, error) {
  function parseConflictFiles (line 230) | func parseConflictFiles(gitOutput string) []string {

FILE: app/cli/lib/legacy_files.go
  function MigrateLegacyProjectFile (line 13) | func MigrateLegacyProjectFile(currentUserId string) {
  function MigrateLegacyCurrentPlanFile (line 62) | func MigrateLegacyCurrentPlanFile(currentUserId string) {
  function MigrateLegacyPlanSettingsFile (line 114) | func MigrateLegacyPlanSettingsFile(currentUserId string) {

FILE: app/cli/lib/log_format.go
  type LogEntry (line 25) | type LogEntry struct
  function ParseLogEntry (line 33) | func ParseLogEntry(raw string) LogEntry {
  function FormatCompactSummary (line 58) | func FormatCompactSummary(entry LogEntry) string {
  function parseTimestamp (line 99) | func parseTimestamp(ts string) string {
  function cleanType (line 111) | func cleanType(t string) string {
  function extractFirstLine (line 117) | func extractFirstLine(s string) string {

FILE: app/cli/lib/model_credentials.go
  type ProviderAuthStatus (line 23) | type ProviderAuthStatus
  constant FullySatisfied (line 26) | FullySatisfied ProviderAuthStatus = iota
  constant PartiallySatisfied (line 27) | PartiallySatisfied
  constant FullyMissing (line 28) | FullyMissing
  type ProviderCredentialStatus (line 31) | type ProviderCredentialStatus struct
  type PublisherCredentialStatus (line 37) | type PublisherCredentialStatus struct
  type CredentialCheckResult (line 43) | type CredentialCheckResult struct
  function CheckCredentialStatus (line 49) | func CheckCredentialStatus(opts shared.ModelProviderOptions, claudeMaxEn...
  function groupProvidersByPublisher (line 108) | func groupProvidersByPublisher(opts shared.ModelProviderOptions) map[sha...
  function checkProviderCredentialStatus (line 124) | func checkProviderCredentialStatus(cfg *shared.ModelProviderConfigSchema...
  function MustVerifyAuthVars (line 171) | func MustVerifyAuthVars(integratedModels bool) map[string]string {
  function MustVerifyAuthVarsSilent (line 175) | func MustVerifyAuthVarsSilent(integratedModels bool) map[string]string {
  function mustVerifyAuthVars (line 179) | func mustVerifyAuthVars(integratedModels, silent bool) map[string]string {
  function ResolveProviderAuthVars (line 237) | func ResolveProviderAuthVars(cfg *shared.ModelProviderConfigSchema) (map...
  function maybeLoadFile (line 301) | func maybeLoadFile(pathOrJson string) (string, error) {
  function loadAWSVars (line 324) | func loadAWSVars(vars map[string]string) error {
  function mergeAuthVars (line 348) | func mergeAuthVars(dest, src map[string]string) {
  function showCredentialErrorMessage (line 354) | func showCredentialErrorMessage(res CredentialCheckResult, opts shared.M...
  function requiredVars (line 506) | func requiredVars(cfg *shared.ModelProviderConfigSchema) []string {
  function providersByPublisher (line 519) | func providersByPublisher(opts shared.ModelProviderOptions) map[shared.M...
  function allPublishersHaveProvider (line 536) | func allPublishersHaveProvider(byPub map[shared.ModelPublisher][]shared....
  function mark (line 558) | func mark(ok bool) string {
  function SetAccountCredentials (line 567) | func SetAccountCredentials(creds *types.AccountCredentials) error {
  function GetAccountCredentials (line 591) | func GetAccountCredentials() (*types.AccountCredentials, error) {

FILE: app/cli/lib/model_settings.go
  function init (line 19) | func init() {
  function GetPlanModelSettingsPath (line 23) | func GetPlanModelSettingsPath(planId string) string {
  type ModelSettingsCheckLocalChangesResult (line 27) | type ModelSettingsCheckLocalChangesResult struct
  function ModelSettingsCheckLocalChanges (line 32) | func ModelSettingsCheckLocalChanges(path string) (ModelSettingsCheckLoca...
  function WriteModelSettingsFile (line 73) | func WriteModelSettingsFile(path string, originalSettings *shared.PlanSe...
  function SaveModelPackRolesHash (line 101) | func SaveModelPackRolesHash(basePath string, serverModelPack *shared.Mod...
  function ApplyModelSettings (line 117) | func ApplyModelSettings(path string, originalSettings *shared.PlanSettin...
  function SaveLatestPlanModelSettingsIfNeeded (line 153) | func SaveLatestPlanModelSettingsIfNeeded() (bool, error) {
  function SyncPlanModelSettings (line 199) | func SyncPlanModelSettings() error {
  function SyncDefaultModelSettings (line 228) | func SyncDefaultModelSettings() error {

FILE: app/cli/lib/models_sync.go
  function PromptSyncModelsIfNeeded (line 11) | func PromptSyncModelsIfNeeded() error {

FILE: app/cli/lib/org_user_config.go
  function MustGetOrgUserConfig (line 12) | func MustGetOrgUserConfig() *shared.OrgUserConfig {
  function MustUpdateOrgUserConfig (line 25) | func MustUpdateOrgUserConfig(orgUserConfig shared.OrgUserConfig) {
  function SetCachedOrgUserConfig (line 33) | func SetCachedOrgUserConfig(orgUserConfig *shared.OrgUserConfig) {

FILE: app/cli/lib/plan_config.go
  function MustGetCurrentPlanConfig (line 16) | func MustGetCurrentPlanConfig() *shared.PlanConfig {
  function SetCachedPlanConfig (line 29) | func SetCachedPlanConfig(planConfig *shared.PlanConfig) {
  function ShowPlanConfig (line 33) | func ShowPlanConfig(config *shared.PlanConfig, key string) {

FILE: app/cli/lib/plans.go
  function WriteCurrentPlan (line 14) | func WriteCurrentPlan(id string) error {
  function ClearCurrentPlan (line 60) | func ClearCurrentPlan() error {
  function WriteCurrentBranch (line 100) | func WriteCurrentBranch(branch string) error {
  function GetCurrentBranchNamesByPlanId (line 164) | func GetCurrentBranchNamesByPlanId(planIds []string) (map[string]string,...
  function getPlanCurrentBranch (line 200) | func getPlanCurrentBranch(planId string) (string, error) {

FILE: app/cli/lib/repl.go
  type ReplMode (line 17) | type ReplMode
  constant ReplModeTell (line 20) | ReplModeTell ReplMode = "tell"
  constant ReplModeChat (line 21) | ReplModeChat ReplMode = "chat"
  type ReplState (line 24) | type ReplState struct
  type ReplSettings (line 34) | type ReplSettings struct
  function init (line 49) | func init() {
  function EnsureReplSettingsFile (line 53) | func EnsureReplSettingsFile() {
  function writeSettings (line 80) | func writeSettings(settings *ReplSettings) {
  function getSettings (line 92) | func getSettings() *ReplSettings {
  function LoadState (line 112) | func LoadState() {
  function WriteState (line 123) | func WriteState() {
  function WriteHistory (line 129) | func WriteHistory(input string) {
  function GetHistory (line 136) | func GetHistory() []string {
  function ExecPlandexCommand (line 143) | func ExecPlandexCommand(args []string) (string, error) {
  type ExecPlandexCommandParams (line 147) | type ExecPlandexCommandParams struct
  function ExecPlandexCommandWithParams (line 152) | func ExecPlandexCommandWithParams(args []string, params ExecPlandexComma...

FILE: app/cli/lib/rewind.go
  function GetUndonePlanApplies (line 17) | func GetUndonePlanApplies(currentState *shared.CurrentPlanState, timesta...
  function GetAffectedFilePaths (line 40) | func GetAffectedFilePaths(currentState *shared.CurrentPlanState, applies...
  type RewindAnalysis (line 97) | type RewindAnalysis struct
  function AnalyzeRewind (line 107) | func AnalyzeRewind(targetState, currentState *shared.CurrentPlanState) (...
  function RemoveEmptyDirs (line 217) | func RemoveEmptyDirs(path string, baseDir string) error {
  function ApplyRewindChanges (line 258) | func ApplyRewindChanges(requiredChanges map[string]string) error {

FILE: app/cli/main.go
  function init (line 22) | func init() {
  function main (line 63) | func main() {

FILE: app/cli/plan_exec/action_menu.go
  type hotkeyOption (line 17) | type hotkeyOption struct
  function showHotkeyMenu (line 77) | func showHotkeyMenu(diffs []string) {
  function handleHotkey (line 152) | func handleHotkey(diffs []string, params ExecParams) {
  function handleHotkeyOption (line 200) | func handleHotkeyOption(option hotkeyOption, diffs []string, params Exec...
  function getDiffs (line 276) | func getDiffs(params ExecParams) ([]string, *shared.ApiError) {

FILE: app/cli/plan_exec/apply_exec.go
  function GetOnApplyExecFail (line 18) | func GetOnApplyExecFail(applyFlags types.ApplyFlags, tellFlags types.Tel...
  function GetOnApplyExecFailWithCommand (line 22) | func GetOnApplyExecFailWithCommand(applyFlags types.ApplyFlags, tellFlag...
  function getOnApplyExecFail (line 26) | func getOnApplyExecFail(applyFlags types.ApplyFlags, tellFlags types.Tel...

FILE: app/cli/plan_exec/build.go
  function Build (line 16) | func Build(params ExecParams, flags types.BuildFlags) (bool, error) {

FILE: app/cli/plan_exec/params.go
  type ExecParams (line 8) | type ExecParams struct
  function SetPromptSyncModelsIfNeeded (line 17) | func SetPromptSyncModelsIfNeeded(fn func() error) {

FILE: app/cli/plan_exec/tell.go
  constant CloudTrialBalanceWarningThreshold (line 24) | CloudTrialBalanceWarningThreshold = 1
  function TellPlan (line 26) | func TellPlan(

FILE: app/cli/schema/schemas.go
  constant scheme (line 18) | scheme = "embed://"
  type SchemaPath (line 20) | type SchemaPath
  constant SchemaPathInputConfig (line 23) | SchemaPathInputConfig     SchemaPath = "json-schemas/models-input.schema...
  constant SchemaPathPlanConfig (line 24) | SchemaPathPlanConfig      SchemaPath = "json-schemas/plan-config.schema....
  constant SchemaPathModelPackInline (line 25) | SchemaPathModelPackInline SchemaPath = "json-schemas/model-pack-inline.s...
  type embeddedSchemaLoader (line 31) | type embeddedSchemaLoader struct
    method JsonSource (line 90) | func (l *embeddedSchemaLoader) JsonSource() interface{} {
    method LoadJSON (line 94) | func (l *embeddedSchemaLoader) LoadJSON() (interface{}, error) {
    method JsonReference (line 133) | func (l *embeddedSchemaLoader) JsonReference() (gojsonreference.JsonRe...
    method LoaderFactory (line 144) | func (l *embeddedSchemaLoader) LoaderFactory() gojsonschema.JSONLoader...
  function ValidateModelsInputJSON (line 36) | func ValidateModelsInputJSON(jsonData []byte) (shared.ClientModelsInput,...
  function ValidateModelPackInlineJSON (line 40) | func ValidateModelPackInlineJSON(jsonData []byte) (shared.ClientModelPac...
  function validateJSON (line 44) | func validateJSON[T any](jsonData []byte, schemaPath SchemaPath) (T, err...
  function newEmbeddedSchemaLoader (line 83) | func newEmbeddedSchemaLoader(source SchemaPath) *embeddedSchemaLoader {
  type embeddedLoaderFactory (line 137) | type embeddedLoaderFactory struct
    method New (line 139) | func (embeddedLoaderFactory) New(source string) gojsonschema.JSONLoader {

FILE: app/cli/stream/stream.go
  function init (line 17) | func init() {

FILE: app/cli/stream_tui/debouncer.go
  type UpdateDebouncer (line 9) | type UpdateDebouncer struct
    method ShouldUpdate (line 23) | func (d *UpdateDebouncer) ShouldUpdate() bool {
  function NewUpdateDebouncer (line 16) | func NewUpdateDebouncer(minInterval time.Duration) *UpdateDebouncer {

FILE: app/cli/stream_tui/model.go
  constant MissingFileLoadLabel (line 19) | MissingFileLoadLabel      = "Load the file into context"
  constant MissingFileSkipLabel (line 20) | MissingFileSkipLabel      = "Skip generating this file"
  constant MissingFileOverwriteLabel (line 21) | MissingFileOverwriteLabel = "Allow Plandex to overwrite this file"
  type streamUIModel (line 38) | type streamUIModel struct
    method Init (line 105) | func (m streamUIModel) Init() tea.Cmd {
    method pollBuildStatus (line 116) | func (m streamUIModel) pollBuildStatus() tea.Cmd {
    method Tick (line 214) | func (m streamUIModel) Tick() tea.Cmd {
    method cleanup (line 221) | func (m *streamUIModel) cleanup() {
    method readState (line 228) | func (m *streamUIModel) readState() streamUIModel {
    method updateState (line 234) | func (m *streamUIModel) updateState(updateFn func()) {
  type buildStatusPollMsg (line 114) | type buildStatusPollMsg
  function initialModel (line 122) | func initialModel(prestartReply, prompt string, buildOnly bool, canSendT...

FILE: app/cli/stream_tui/run.go
  function StartStreamUI (line 24) | func StartStreamUI(prompt string, buildOnly, canSendToBg bool) error {
  function Quit (line 113) | func Quit() {
  function Send (line 127) | func Send(msg shared.StreamMessage) {
  function ToggleVisibility (line 145) | func ToggleVisibility(hide bool) {

FILE: app/cli/stream_tui/update.go
  method Update (line 25) | func (m streamUIModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  method windowResized (line 171) | func (m *streamUIModel) windowResized(w, h int) {
  method updateReplyDisplay (line 197) | func (m *streamUIModel) updateReplyDisplay() {
  method updateViewportDimensions (line 235) | func (m *streamUIModel) updateViewportDimensions() {
  method getViewportDimensions (line 245) | func (m *streamUIModel) getViewportDimensions() (int, int) {
  method replyScrollable (line 275) | func (m streamUIModel) replyScrollable() bool {
  method scrollDown (line 279) | func (m *streamUIModel) scrollDown() {
  method scrollUp (line 295) | func (m *streamUIModel) scrollUp() {
  method pageDown (line 306) | func (m *streamUIModel) pageDown() {
  method pageUp (line 322) | func (m *streamUIModel) pageUp() {
  method scrollStart (line 333) | func (m *streamUIModel) scrollStart() {
  method scrollEnd (line 344) | func (m *streamUIModel) scrollEnd() {
  method streamUpdate (line 355) | func (m *streamUIModel) streamUpdate(msg *shared.StreamMessage, deferUIU...
  type delayFileRestartMsg (line 551) | type delayFileRestartMsg struct
  function startDelay (line 555) | func startDelay(path string, delay time.Duration) tea.Cmd {
  method resolveEscapeSequence (line 565) | func (m *streamUIModel) resolveEscapeSequence(val string) {
  method up (line 594) | func (m *streamUIModel) up() {
  method down (line 608) | func (m *streamUIModel) down() {
  method selectedMissingFileOpt (line 622) | func (m *streamUIModel) selectedMissingFileOpt() (tea.Model, tea.Cmd) {
  method checkMissingFile (line 668) | func (m *streamUIModel) checkMissingFile(msg *shared.StreamMessage) (tea...
  type contextLoadDoneMsg (line 744) | type contextLoadDoneMsg struct
  function loadContextCmd (line 749) | func loadContextCmd(loadContextFiles []string) tea.Cmd {

FILE: app/cli/stream_tui/view.go
  method View (line 17) | func (m streamUIModel) View() string {
  method renderMainView (line 38) | func (m streamUIModel) renderMainView() string {
  method renderHelp (line 42) | func (m streamUIModel) renderHelp() string {
  method renderProcessing (line 61) | func (m streamUIModel) renderProcessing() string {
  method renderBuild (line 69) | func (m streamUIModel) renderBuild() string {
  method renderStaticBuild (line 73) | func (m streamUIModel) renderStaticBuild() string {
  method doRenderBuild (line 77) | func (m streamUIModel) doRenderBuild(outputStatic bool) string {
  method didBuild (line 143) | func (m streamUIModel) didBuild() bool {
  method getBuildHeader (line 147) | func (m streamUIModel) getBuildHeader(static bool) string {
  method getRows (line 177) | func (m streamUIModel) getRows(static bool) []string {
  method renderMissingFilePrompt (line 279) | func (m streamUIModel) renderMissingFilePrompt() string {

FILE: app/cli/term/color.go
  function init (line 17) | func init() {

FILE: app/cli/term/errors.go
  function SetOpenUnauthenticatedCloudURLFn (line 18) | func SetOpenUnauthenticatedCloudURLFn(fn func(msg, path string)) {
  function SetOpenAuthenticatedURLFn (line 21) | func SetOpenAuthenticatedURLFn(fn func(msg, path string)) {
  function SetConvertTrialFn (line 24) | func SetConvertTrialFn(fn func()) {
  function OutputSimpleError (line 28) | func OutputSimpleError(msg string, args ...interface{}) {
  function OutputErrorAndExit (line 33) | func OutputErrorAndExit(msg string, args ...interface{}) {
  function OutputUnformattedErrorAndExit (line 107) | func OutputUnformattedErrorAndExit(msg string) {
  function OutputNoCurrentPlanErrorAndExit (line 113) | func OutputNoCurrentPlanErrorAndExit() {
  function HandleApiError (line 120) | func HandleApiError(apiError *shared.ApiError) {
  function maybeJSON (line 218) | func maybeJSON(s string) bool {
  function prettyJSON (line 229) | func prettyJSON(s string) string {

FILE: app/cli/term/format.go
  function init (line 14) | func init() {
  function getGlamourRenderer (line 24) | func getGlamourRenderer() (*glamour.TermRenderer, error) {
  function GetMarkdown (line 58) | func GetMarkdown(input string) (string, error) {
  function GetPlain (line 74) | func GetPlain(input string) string {

FILE: app/cli/term/help.go
  type CmdConfig (line 12) | type CmdConfig struct
  function init (line 165) | func init() {
  function PrintCmds (line 171) | func PrintCmds(prefix string, cmds ...string) {
  function PrintCmdsWithColors (line 175) | func PrintCmdsWithColors(prefix string, colors []color.Attribute, cmds ....
  function printCmds (line 179) | func printCmds(w io.Writer, prefix string, colors []color.Attribute, cmd...
  function PrintCustomCmd (line 227) | func PrintCustomCmd(prefix, cmd, alias, desc string) {
  function PrintCustomHelp (line 235) | func PrintCustomHelp(all bool) {
  function PrintHelpAllCommands (line 296) | func PrintHelpAllCommands() {
  function ShowCmd (line 367) | func ShowCmd(cmd string) string {

FILE: app/cli/term/os.go
  function GetOsDetails (line 9) | func GetOsDetails() string {

FILE: app/cli/term/prompt.go
  function GetRequiredUserStringInput (line 13) | func GetRequiredUserStringInput(msg string) (string, error) {
  function GetUserStringInput (line 27) | func GetUserStringInput(msg string) (string, error) {
  function GetUserStringInputWithDefault (line 31) | func GetUserStringInputWithDefault(msg, def string) (string, error) {
  function GetRequiredUserStringInputWithDefault (line 44) | func GetRequiredUserStringInputWithDefault(msg, def string) (string, err...
  function GetUserPasswordInput (line 58) | func GetUserPasswordInput(msg string) (string, error) {
  function GetUserKeyInput (line 71) | func GetUserKeyInput() (rune, keyboard.Key, error) {
  function ConfirmYesNo (line 87) | func ConfirmYesNo(fmtStr string, fmtArgs ...interface{}) (bool, error) {
  function ConfirmYesNoCancel (line 113) | func ConfirmYesNoCancel(fmtStr string, fmtArgs ...interface{}) (bool, bo...
  function disableBracketedPaste (line 141) | func disableBracketedPaste() {
  function enableBracketedPaste (line 145) | func enableBracketedPaste() {

FILE: app/cli/term/repl.go
  function SetIsRepl (line 7) | func SetIsRepl(value bool) {

FILE: app/cli/term/select.go
  function SelectFromList (line 11) | func SelectFromList(msg string, options []string) (string, error) {
  function convertToStringSlice (line 30) | func convertToStringSlice[T any](input []T) []string {

FILE: app/cli/term/spinner.go
  constant withMessageMinDuration (line 10) | withMessageMinDuration = 700 * time.Millisecond
  constant withoutMessageMinDuration (line 11) | withoutMessageMinDuration = 350 * time.Millisecond
  function StartSpinner (line 20) | func StartSpinner(msg string) {
  function StopSpinner (line 36) | func StopSpinner() {
  function ResumeSpinner (line 51) | func ResumeSpinner() {
  function LongSpinnerWithWarning (line 57) | func LongSpinnerWithWarning(msg, warning string) {

FILE: app/cli/term/utils.go
  function init (line 14) | func init() {
  function AlternateScreen (line 22) | func AlternateScreen() {
  function ClearScreen (line 27) | func ClearScreen() {
  function MoveCursorToTopLeft (line 31) | func MoveCursorToTopLeft() {
  function ClearCurrentLine (line 35) | func ClearCurrentLine() {
  function MoveUpLines (line 39) | func MoveUpLines(numLines int) {
  function BackToMain (line 43) | func BackToMain() {
  function PageOutput (line 48) | func PageOutput(output string) {
  function PageOutputReverse (line 60) | func PageOutputReverse(output string) {
  function GetDivisionLine (line 74) | func GetDivisionLine() string {
  function GetTerminalWidth (line 83) | func GetTerminalWidth() int {
  function GetStreamForegroundColor (line 120) | func GetStreamForegroundColor() termenv.Color {
  function HasDarkBackground (line 141) | func HasDarkBackground() bool {
  function IsTerminal (line 153) | func IsTerminal() bool {

FILE: app/cli/types/api.go
  type OnStreamPlanParams (line 10) | type OnStreamPlanParams struct
  type OnStreamPlan (line 15) | type OnStreamPlan
  type ApiClient (line 17) | type ApiClient interface

FILE: app/cli/types/apply.go
  type ApplyFlags (line 7) | type ApplyFlags struct
  type ApplyRollbackOption (line 16) | type ApplyRollbackOption
  constant ApplyRollbackOptionKeep (line 19) | ApplyRollbackOptionKeep     ApplyRollbackOption = "Apply file changes"
  constant ApplyRollbackOptionRollback (line 20) | ApplyRollbackOptionRollback ApplyRollbackOption = "Roll back file changes"
  type OnApplyExecFailFn (line 23) | type OnApplyExecFailFn
  type ApplyReversion (line 25) | type ApplyReversion struct
  type ApplyRollbackPlan (line 30) | type ApplyRollbackPlan struct
    method HasChanges (line 36) | func (r *ApplyRollbackPlan) HasChanges() bool {

FILE: app/cli/types/exec.go
  type TellFlags (line 3) | type TellFlags struct
  type BuildFlags (line 19) | type BuildFlags struct

FILE: app/cli/types/fs.go
  type ProjectPaths (line 5) | type ProjectPaths struct

FILE: app/cli/types/types.go
  type LoadContextParams (line 10) | type LoadContextParams struct
  type ContextOutdatedResult (line 22) | type ContextOutdatedResult struct
  constant PlanOutdatedStrategyOverwrite (line 37) | PlanOutdatedStrategyOverwrite        string = "Clear the modifications a...
  constant PlanOutdatedStrategyApplyUnmodified (line 38) | PlanOutdatedStrategyApplyUnmodified  string = "Apply only new and unmodi...
  constant PlanOutdatedStrategyApplyNoConflicts (line 39) | PlanOutdatedStrategyApplyNoConflicts string = "Apply anyway since there ...
  constant PlanOutdatedStrategyRebuild (line 40) | PlanOutdatedStrategyRebuild          string = "Rebuild the plan with upd...
  constant PlanOutdatedStrategyCancel (line 41) | PlanOutdatedStrategyCancel           string = "Cancel"
  type CurrentPlanSettings (line 44) | type CurrentPlanSettings struct
  type PlanSettings (line 48) | type PlanSettings struct
  type CurrentProjectSettings (line 52) | type CurrentProjectSettings struct
  type CurrentPlanSettingsByAccount (line 56) | type CurrentPlanSettingsByAccount
  type PlanSettingsByAccount (line 57) | type PlanSettingsByAccount
  type CurrentProjectSettingsByAccount (line 58) | type CurrentProjectSettingsByAccount
  type ChangesUIScrollReplacement (line 60) | type ChangesUIScrollReplacement struct
  type ChangesUIViewportsUpdate (line 66) | type ChangesUIViewportsUpdate struct
  type OnErrFn (line 70) | type OnErrFn
  type OauthResponse (line 72) | type OauthResponse struct
  type OauthCreds (line 78) | type OauthCreds struct
  type AccountCredentials (line 83) | type AccountCredentials struct

FILE: app/cli/ui/ui.go
  function OpenAuthenticatedURL (line 18) | func OpenAuthenticatedURL(msg, path string) {
  function OpenUnauthenticatedCloudURL (line 45) | func OpenUnauthenticatedCloudURL(msg, path string) {
  function OpenURL (line 54) | func OpenURL(msg, url string) {

FILE: app/cli/upgrade.go
  function checkForUpgrade (line 27) | func checkForUpgrade() {
  function doUpgrade (line 99) | func doUpgrade(version string) error {
  function restartPlandex (line 161) | func restartPlandex() {

FILE: app/cli/url/url.go
  constant maxRedirections (line 18) | maxRedirections    = 10
  constant httpTimeout (line 19) | httpTimeout        = 30 * time.Second
  constant maxContentSizeInMB (line 20) | maxContentSizeInMB = 10
  function FetchURLContent (line 23) | func FetchURLContent(url string) (string, error) {
  function ExtractTextualContent (line 60) | func ExtractTextualContent(htmlContent string) string {
  function SanitizeURL (line 70) | func SanitizeURL(url string) string {
  function IsValidURL (line 88) | func IsValidURL(str string) bool {

FILE: app/cli/utils/utils.go
  function EnsureMinDuration (line 7) | func EnsureMinDuration(start time.Time, minDuration time.Duration) {

FILE: app/scripts/cmd/gen/gen.go
  function main (line 11) | func main() {

FILE: app/scripts/cmd/provider/gen_provider.go
  function main (line 15) | func main() {

FILE: app/server/db/account_helpers.go
  type CreateAccountResult (line 10) | type CreateAccountResult struct
  function CreateAccount (line 16) | func CreateAccount(name, email, emailVerificationId string, tx *sqlx.Tx)...

FILE: app/server/db/auth_helpers.go
  constant tokenExpirationDays (line 16) | tokenExpirationDays = 90
  function CreateAuthToken (line 18) | func CreateAuthToken(userId string, tx *sqlx.Tx) (token, id string, err ...
  function ValidateAuthToken (line 33) | func ValidateAuthToken(token string) (*AuthToken, error) {
  function CreateEmailVerification (line 60) | func CreateEmailVerification(email string, userId, pinHash string) error {
  constant emailVerificationExpirationMinutes (line 76) | emailVerificationExpirationMinutes = 5
  constant InvalidOrExpiredPinError (line 78) | InvalidOrExpiredPinError = "invalid or expired pin"
  function ValidateEmailVerification (line 80) | func ValidateEmailVerification(email, pin string) (id string, err error) {
  function ValidateEmailPreviouslyVerified (line 84) | func ValidateEmailPreviouslyVerified(email, pin string) (id string, err ...
  function validateEmailVerification (line 88) | func validateEmailVerification(email, pin string, enforceExpiration bool...
  function CreateSignInCode (line 122) | func CreateSignInCode(userId, orgId, pinHash string) error {
  constant signInCodeExpirationMinutes (line 132) | signInCodeExpirationMinutes = 5
  type ValidateSignInCodeRes (line 134) | type ValidateSignInCodeRes struct
  function ValidateSignInCode (line 140) | func ValidateSignInCode(pin string) (*ValidateSignInCodeRes, error) {
  function GetUserPermissions (line 160) | func GetUserPermissions(userId, orgId string) ([]string, error) {

FILE: app/server/db/branch_helpers.go
  function CreateBranch (line 14) | func CreateBranch(repo *GitRepo, plan *Plan, parentBranch *Branch, name ...
  function GetDbBranch (line 105) | func GetDbBranch(planId, name string) (*Branch, error) {
  function ListPlanBranches (line 120) | func ListPlanBranches(repo *GitRepo, planId string) ([]*Branch, error) {
  function ListBranchesForPlans (line 153) | func ListBranchesForPlans(orgId string, planIds []string) ([]*Branch, er...
  function DeleteBranch (line 164) | func DeleteBranch(ctx context.Context, repo *GitRepo, planId, branch str...

FILE: app/server/db/build_helpers.go
  function StorePlanBuild (line 8) | func StorePlanBuild(build *PlanBuild) error {
  function SetBuildError (line 40) | func SetBuildError(build *PlanBuild) error {

FILE: app/server/db/context_helpers_conflicts.go
  type invalidateConflictedResultsParams (line 11) | type invalidateConflictedResultsParams struct
  function invalidateConflictedResults (line 19) | func invalidateConflictedResults(params invalidateConflictedResultsParam...

FILE: app/server/db/context_helpers_get.go
  function GetPlanContexts (line 16) | func GetPlanContexts(orgId, planId string, includeBody, includeMapParts ...
  function GetContext (line 78) | func GetContext(orgId, planId, contextId string, includeBody, includeMap...

FILE: app/server/db/context_helpers_load.go
  type Ctx (line 19) | type Ctx
  type LoadContextsParams (line 21) | type LoadContextsParams struct
  function LoadContexts (line 32) | func LoadContexts(ctx Ctx, params LoadContextsParams) (*shared.LoadConte...

FILE: app/server/db/context_helpers_map.go
  function GetCachedMap (line 14) | func GetCachedMap(orgId, projectId, filePath string) (*Context, error) {
  type CachedMap (line 42) | type CachedMap struct

FILE: app/server/db/context_helpers_remove.go
  function ContextRemove (line 13) | func ContextRemove(orgId, planId string, contexts []*Context) error {
  type contextRemoveParams (line 21) | type contextRemoveParams struct
  function contextRemove (line 29) | func contextRemove(params contextRemoveParams) error {
  type ClearContextParams (line 79) | type ClearContextParams struct
  function ClearContext (line 86) | func ClearContext(params ClearContextParams) error {

FILE: app/server/db/context_helpers_store.go
  function StoreContext (line 19) | func StoreContext(context *Context, skipMapCache bool) error {

FILE: app/server/db/context_helpers_update.go
  type UpdateContextsParams (line 14) | type UpdateContextsParams struct
  function UpdateContexts (line 23) | func UpdateContexts(params UpdateContextsParams) (*shared.UpdateContextR...

FILE: app/server/db/convo_helpers.go
  function GetPlanConvo (line 22) | func GetPlanConvo(orgId, planId string) ([]*ConvoMessage, error) {
  function GetConvoMessage (line 83) | func GetConvoMessage(orgId, planId, messageId string) (*ConvoMessage, er...
  function StoreConvoMessage (line 102) | func StoreConvoMessage(repo *GitRepo, message *ConvoMessage, currentUser...

FILE: app/server/db/data_models.go
  type AuthToken (line 19) | type AuthToken struct
  type Org (line 27) | type Org struct
    method ToApi (line 39) | func (org *Org) ToApi() *shared.Org {
  type User (line 48) | type User struct
    method ToApi (line 59) | func (user *User) ToApi() *shared.User {
  type Invite (line 70) | type Invite struct
    method ToApi (line 83) | func (invite *Invite) ToApi() *shared.Invite {
  type OrgUser (line 97) | type OrgUser struct
    method ToApi (line 107) | func (orgUser *OrgUser) ToApi() *shared.OrgUser {
  type Project (line 116) | type Project struct
    method ToApi (line 124) | func (project *Project) ToApi() *shared.Project {
  type Plan (line 131) | type Plan struct
    method ToApi (line 146) | func (plan *Plan) ToApi() *shared.Plan {
  type Branch (line 162) | type Branch struct
    method ToApi (line 180) | func (branch *Branch) ToApi() *shared.Branch {
  type ConvoSummary (line 197) | type ConvoSummary struct
    method ToApi (line 209) | func (summary *ConvoSummary) ToApi() *shared.ConvoSummary {
  type PlanBuild (line 221) | type PlanBuild struct
    method ToApi (line 232) | func (build *PlanBuild) ToApi() *shared.PlanBuild {
  type OrgRole (line 243) | type OrgRole struct
    method ToApi (line 253) | func (role *OrgRole) ToApi() *shared.OrgRole {
  type ModelStream (line 262) | type ModelStream struct
  type LockScope (line 284) | type LockScope
  constant LockScopeRead (line 287) | LockScopeRead  LockScope = "r"
  constant LockScopeWrite (line 288) | LockScopeWrite LockScope = "w"
  type repoLock (line 291) | type repoLock struct
  type ModelPack (line 303) | type ModelPack struct
    method ToApi (line 337) | func (modelPack *ModelPack) ToApi() *shared.ModelPack {
  function ModelPackFromApi (line 321) | func ModelPackFromApi(apiModelPack *shared.ModelPack) *ModelPack {
  type CustomModel (line 354) | type CustomModel struct
    method ToApi (line 425) | func (model *CustomModel) ToApi() *shared.CustomModel {
  function CustomModelFromApi (line 388) | func CustomModelFromApi(apiModel *shared.CustomModel) *CustomModel {
  type ExtraAuthVars (line 463) | type ExtraAuthVars
    method Scan (line 465) | func (e *ExtraAuthVars) Scan(src interface{}) error {
    method Value (line 480) | func (e ExtraAuthVars) Value() (driver.Value, error) {
  type CustomProvider (line 484) | type CustomProvider struct
    method ToApi (line 507) | func (provider *CustomProvider) ToApi() *shared.CustomProvider {
  function CustomProviderFromApi (line 496) | func CustomProviderFromApi(apiProvider *shared.CustomProvider) *CustomPr...
  type CustomModelUsesProvider (line 518) | type CustomModelUsesProvider struct
    method ToApi (line 524) | func (usesProvider *CustomModelUsesProvider) ToApi() *shared.BaseModel...
  type CustomModelProviders (line 532) | type CustomModelProviders
    method Scan (line 534) | func (providers *CustomModelProviders) Scan(src interface{}) error {
    method Value (line 549) | func (providers CustomModelProviders) Value() (driver.Value, error) {
  type DefaultPlanSettings (line 553) | type DefaultPlanSettings struct
  type Context (line 564) | type Context struct
    method ToMeta (line 589) | func (context *Context) ToMeta() *Context {
    method ToApi (line 615) | func (context *Context) ToApi() *shared.Context {
  type ConvoMessage (line 639) | type ConvoMessage struct
    method ToApi (line 658) | func (msg *ConvoMessage) ToApi() *shared.ConvoMessage {
  type ConvoMessageDescription (line 679) | type ConvoMessageDescription struct
    method ToApi (line 697) | func (desc *ConvoMessageDescription) ToApi() *shared.ConvoMessageDescr...
  type PlanFileResult (line 715) | type PlanFileResult struct
    method ToApi (line 741) | func (res *PlanFileResult) ToApi() *shared.PlanFileResult {
  type PlanApply (line 760) | type PlanApply struct
    method ToApi (line 772) | func (apply *PlanApply) ToApi() *shared.PlanApply {
  type Subtask (line 784) | type Subtask struct
    method ToApi (line 792) | func (subtask *Subtask) ToApi() *shared.Subtask {

FILE: app/server/db/db.go
  constant LockTimeout (line 20) | LockTimeout = 4000
  constant IdleInTransactionSessionTimeout (line 21) | IdleInTransactionSessionTimeout = 90000
  constant StatementTimeout (line 22) | StatementTimeout = 30000
  function Connect (line 24) | func Connect() error {
  function MigrationsUp (line 96) | func MigrationsUp() error {
  function MigrationsUpWithDir (line 105) | func MigrationsUpWithDir(dir string) error {
  function migrationsUp (line 109) | func migrationsUp(dir string) error {

FILE: app/server/db/diff_helpers.go
  function GetPlanDiffs (line 15) | func GetPlanDiffs(orgId, planId string, plain bool) (string, error) {

FILE: app/server/db/fs.go
  function init (line 12) | func init() {
  function InitPlan (line 38) | func InitPlan(orgId, planId string) error {
  function DeletePlanDir (line 67) | func DeletePlanDir(orgId, planId string) error {
  function getOrgDir (line 78) | func getOrgDir(orgId string) string {
  function getProjectDir (line 82) | func getProjectDir(orgId, projectId string) string {
  function getProjectMapCacheDir (line 86) | func getProjectMapCacheDir(orgId, projectId string) string {
  function getPlanDir (line 90) | func getPlanDir(orgId, planId string) string {
  function getPlanContextDir (line 94) | func getPlanContextDir(orgId, planId string) string {
  function getPlanConversationDir (line 98) | func getPlanConversationDir(orgId, planId string) string {
  function getPlanResultsDir (line 102) | func getPlanResultsDir(orgId, planId string) string {
  function getPlanAppliesDir (line 106) | func getPlanAppliesDir(orgId, planId string) string {
  function getPlanDescriptionsDir (line 110) | func getPlanDescriptionsDir(orgId, planId string) string {

FILE: app/server/db/git.go
  constant maxGitRetries (line 20) | maxGitRetries     = 5
  constant baseGitRetryDelay (line 21) | baseGitRetryDelay = 100 * time.Millisecond
  function init (line 24) | func init() {
  type GitRepo (line 32) | type GitRepo struct
    method GitAddAndCommit (line 67) | func (repo *GitRepo) GitAddAndCommit(branch, message string) error {
    method GitRewindToSha (line 95) | func (repo *GitRepo) GitRewindToSha(branch, sha string) error {
    method GetCurrentCommitSha (line 111) | func (repo *GitRepo) GetCurrentCommitSha() (sha string, err error) {
    method GetCommitTime (line 127) | func (repo *GitRepo) GetCommitTime(branch, ref string) (time.Time, err...
    method GitResetToSha (line 151) | func (repo *GitRepo) GitResetToSha(sha string) error {
    method GitCheckoutSha (line 174) | func (repo *GitRepo) GitCheckoutSha(sha string) error {
    method GetGitCommitHistory (line 197) | func (repo *GitRepo) GetGitCommitHistory(branch string) (body string, ...
    method GetLatestCommit (line 211) | func (repo *GitRepo) GetLatestCommit(branch string) (sha, body string,...
    method GetLatestCommitShaBeforeTime (line 225) | func (repo *GitRepo) GetLatestCommitShaBeforeTime(branch string, befor...
    method GitListBranches (line 265) | func (repo *GitRepo) GitListBranches() ([]string, error) {
    method GitCreateBranch (line 289) | func (repo *GitRepo) GitCreateBranch(newBranch string) error {
    method GitDeleteBranch (line 311) | func (repo *GitRepo) GitDeleteBranch(branchName string) error {
    method GitClearUncommittedChanges (line 333) | func (repo *GitRepo) GitClearUncommittedChanges(branch string) error {
    method GitCheckoutBranch (line 385) | func (repo *GitRepo) GitCheckoutBranch(branch string) error {
    method LogGitRepoState (line 692) | func (repo *GitRepo) LogGitRepoState() {
  function InitGitRepo (line 37) | func InitGitRepo(orgId, planId string) error {
  function initGitRepo (line 42) | func initGitRepo(dir string) error {
  function getGitRepo (line 60) | func getGitRepo(orgId, planId string) *GitRepo {
  function gitAdd (line 402) | func gitAdd(repoDir, path string) error {
  function gitCommit (line 415) | func gitCommit(repoDir, commitMsg string) error {
  function gitCheckoutBranch (line 428) | func gitCheckoutBranch(repoDir, branch string) error {
  function gitRewindToSha (line 460) | func gitRewindToSha(repoDir, sha string) error {
  function getLatestCommit (line 469) | func getLatestCommit(dir string) (sha, body string, err error) {
  function getGitCommitHistory (line 490) | func getGitCommitHistory(dir string) (body string, shas []string, err er...
  function processGitHistoryOutput (line 513) | func processGitHistoryOutput(raw string) [][2]string {
  function removeLockFile (line 557) | func removeLockFile(lockFilePath string) error {
  function gitRemoveIndexLockFileIfExists (line 604) | func gitRemoveIndexLockFileIfExists(repoDir string) error {
  function setGitConfig (line 647) | func setGitConfig(repoDir, key, value string) error {
  function gitWriteOperation (line 655) | func gitWriteOperation(operation func() error, repoDir, label string) er...

FILE: app/server/db/invite_helpers.go
  function CreateInvite (line 12) | func CreateInvite(invite *Invite, tx *sqlx.Tx) error {
  function GetInvite (line 22) | func GetInvite(id string) (*Invite, error) {
  function GetActiveInviteByEmail (line 37) | func GetActiveInviteByEmail(orgId, email string) (*Invite, error) {
  function ListPendingInvites (line 52) | func ListPendingInvites(orgId string) ([]*Invite, error) {
  function ListAllInvites (line 63) | func ListAllInvites(orgId string) ([]*Invite, error) {
  function ListAcceptedInvites (line 74) | func ListAcceptedInvites(orgId string) ([]*Invite, error) {
  function GetPendingInvitesForEmail (line 85) | func GetPendingInvitesForEmail(email string) ([]*Invite, error) {
  function DeleteInvite (line 100) | func DeleteInvite(id string, tx *sqlx.Tx) error {
  function AcceptInvite (line 117) | func AcceptInvite(ctx context.Context, invite *Invite, inviteeId string)...

FILE: app/server/db/locks.go
  constant locksVerboseLogging (line 25) | locksVerboseLogging = false
  constant lockHeartbeatInterval (line 27) | lockHeartbeatInterval = 3 * time.Second
  constant lockHeartbeatTimeout (line 28) | lockHeartbeatTimeout = 60 * time.Second
  constant maxLockRetries (line 29) | maxLockRetries = 6
  constant initialLockRetryDelay (line 30) | initialLockRetryDelay = 300 * time.Millisecond
  constant backoffFactor (line 31) | backoffFactor = 2
  constant jitterFraction (line 32) | jitterFraction = 0.3
  constant maxDeleteRetries (line 35) | maxDeleteRetries = 60
  constant deleteRetryDelay (line 36) | deleteRetryDelay = 50 * time.Millisecond
  type LockRepoParams (line 42) | type LockRepoParams struct
  function lockRepoDB (line 54) | func lockRepoDB(params LockRepoParams, numRetry int) (string, error) {
  function deleteRepoLockDB (line 480) | func deleteRepoLockDB(id, planId, reason string, numRetry int) error {
  function formatStackTrace (line 523) | func formatStackTrace(stack []byte) string {
  function formatStackTraceLong (line 531) | func formatStackTraceLong(stack []byte) string {
  function formatStackTraceWithNumLines (line 535) | func formatStackTraceWithNumLines(stack []byte, numLines int) string {
  function getGoroutineID (line 543) | func getGoroutineID() uint64 {
  function isDeadlockError (line 552) | func isDeadlockError(err error) bool {
  function retryWithExponentialBackoff (line 564) | func retryWithExponentialBackoff(
  function retryDeleteLock (line 600) | func retryDeleteLock(ctx context.Context, cause error, attempt int, next...
  function CleanupActiveLocks (line 613) | func CleanupActiveLocks(ctx context.Context) error {

FILE: app/server/db/models.go
  function UpsertCustomModel (line 11) | func UpsertCustomModel(tx *sqlx.Tx, model *CustomModel) error {
  function ListCustomModels (line 90) | func ListCustomModels(orgId string) ([]*CustomModel, error) {
  function ListCustomModelsForModelIds (line 96) | func ListCustomModelsForModelIds(orgId string, modelIds []string) ([]*Cu...
  function GetCustomModel (line 103) | func GetCustomModel(orgId, id string) (*CustomModel, error) {
  function DeleteCustomModels (line 115) | func DeleteCustomModels(tx *sqlx.Tx, orgId string, ids []string) error {
  function UpsertCustomProvider (line 126) | func UpsertCustomProvider(tx *sqlx.Tx, p *CustomProvider) error {
  function GetCustomProvider (line 158) | func GetCustomProvider(orgId, id string) (*CustomProvider, error) {
  function ListCustomProviders (line 170) | func ListCustomProviders(orgId string) ([]*CustomProvider, error) {
  function ListCustomProvidersForNames (line 176) | func ListCustomProvidersForNames(orgId string, names []string) ([]*Custo...
  function DeleteCustomProviders (line 183) | func DeleteCustomProviders(tx *sqlx.Tx, orgId string, ids []string) error {
  function UpsertModelPack (line 194) | func UpsertModelPack(tx *sqlx.Tx, mp *ModelPack) error {
  function ListModelPacks (line 242) | func ListModelPacks(orgId string) ([]*ModelPack, error) {
  function ListModelPacksForNames (line 255) | func ListModelPacksForNames(orgId string, names []string) ([]*ModelPack,...
  function DeleteModelPacks (line 262) | func DeleteModelPacks(tx *sqlx.Tx, orgId string, ids []string) error {

FILE: app/server/db/org_helpers.go
  constant orgFields (line 15) | orgFields = "id, name, domain, auto_add_domain_users, owner_id, is_trial...
  function GetAccessibleOrgsForUser (line 17) | func GetAccessibleOrgsForUser(user *User) ([]*Org, error) {
  function GetOrg (line 69) | func GetOrg(orgId string) (*Org, error) {
  function ValidateOrgMembership (line 85) | func ValidateOrgMembership(userId string, orgId string) (bool, error) {
  function CreateOrg (line 96) | func CreateOrg(req *shared.CreateOrgRequest, userId string, domain *stri...
  function GetOrgForDomain (line 130) | func GetOrgForDomain(domain string) (*Org, error) {
  function AddOrgDomainUsers (line 146) | func AddOrgDomainUsers(orgId, domain string, tx *sqlx.Tx) error {
  function DeleteOrgUser (line 181) | func DeleteOrgUser(orgId, userId string, tx *sqlx.Tx) error {
  function CreateOrgUser (line 193) | func CreateOrgUser(orgId, userId, orgRoleId string, tx *sqlx.Tx) error {
  function ListOrgRoles (line 209) | func ListOrgRoles(orgId string) ([]*OrgRole, error) {
  function AddToOrgForDomain (line 220) | func AddToOrgForDomain(userId, domain string, tx *sqlx.Tx) (string, erro...

FILE: app/server/db/plan_config_helpers.go
  function GetPlanConfig (line 11) | func GetPlanConfig(planId string) (*shared.PlanConfig, error) {
  function StorePlanConfig (line 24) | func StorePlanConfig(planId string, config *shared.PlanConfig) error {
  function GetDefaultPlanConfig (line 40) | func GetDefaultPlanConfig(userId string) (*shared.PlanConfig, error) {
  function StoreDefaultPlanConfig (line 53) | func StoreDefaultPlanConfig(userId string, config *shared.PlanConfig, tx...

FILE: app/server/db/plan_helpers.go
  function CreatePlan (line 23) | func CreatePlan(ctx context.Context, orgId, projectId, userId, name stri...
  function ListOwnedPlans (line 97) | func ListOwnedPlans(projectIds []string, userId string, archived bool) (...
  function GetPlanNamesById (line 119) | func GetPlanNamesById(planIds []string) (map[string]string, error) {
  function AddPlanContextTokens (line 134) | func AddPlanContextTokens(planId, branch string, addTokens int) error {
  function AddPlanConvoMessage (line 142) | func AddPlanConvoMessage(msg *ConvoMessage, branch string) error {
  function SyncPlanTokens (line 195) | func SyncPlanTokens(orgId, planId, branch string) error {
  function GetPlan (line 252) | func GetPlan(planId string) (*Plan, error) {
  function SetPlanStatus (line 264) | func SetPlanStatus(planId, branch string, status shared.PlanStatus, errS...
  function RenamePlan (line 274) | func RenamePlan(planId string, name string, tx *sqlx.Tx) error {
  function IncActiveBranches (line 289) | func IncActiveBranches(planId string, inc int, tx *sqlx.Tx) error {
  function IncNumNonDraftPlans (line 299) | func IncNumNonDraftPlans(userId string, tx *sqlx.Tx) error {
  function StoreDescription (line 309) | func StoreDescription(description *ConvoMessageDescription) error {
  function DeleteDraftPlans (line 352) | func DeleteDraftPlans(orgId, projectId, userId string) error {
  function DeleteOwnerPlans (line 400) | func DeleteOwnerPlans(orgId, projectId, userId string) error {
  function ValidatePlanAccess (line 448) | func ValidatePlanAccess(planId, userId, orgId string) (*Plan, error) {
  function BumpPlanUpdatedAt (line 487) | func BumpPlanUpdatedAt(planId string, t time.Time) error {
  function GetPlanIdsForProject (line 497) | func GetPlanIdsForProject(projectId string) ([]string, error) {

FILE: app/server/db/project_helpers.go
  function ProjectExists (line 9) | func ProjectExists(orgId, projectId string) (bool, error) {
  function CreateProject (line 20) | func CreateProject(orgId, name string, tx *sqlx.Tx) (string, error) {

FILE: app/server/db/queue.go
  type repoOpFn (line 13) | type repoOpFn
  type repoOperation (line 15) | type repoOperation struct
  type repoQueue (line 31) | type repoQueue struct
    method add (line 70) | func (q *repoQueue) add(op *repoOperation) int {
    method nextBatch (line 95) | func (q *repoQueue) nextBatch() []*repoOperation {
    method runQueue (line 150) | func (q *repoQueue) runQueue() {
  type repoQueueMap (line 37) | type repoQueueMap
    method getQueue (line 42) | func (m repoQueueMap) getQueue(planId string) *repoQueue {
    method add (line 61) | func (m repoQueueMap) add(op *repoOperation) int {
  type ExecRepoOperationParams (line 300) | type ExecRepoOperationParams struct
  function ExecRepoOperation (line 313) | func ExecRepoOperation(

FILE: app/server/db/rbac_helpers.go
  function GetOrgOwnerRoleId (line 11) | func GetOrgOwnerRoleId() (string, error) {
  function GetOrgMemberRoleId (line 26) | func GetOrgMemberRoleId() (string, error) {
  function GetOrgOwners (line 41) | func GetOrgOwners(orgId string) ([]*User, error) {
  function CacheOrgRoleIds (line 52) | func CacheOrgRoleIds() error {
  function cacheOrgOwnerRoleId (line 75) | func cacheOrgOwnerRoleId() error {
  function cacheOrgMemberRoleId (line 88) | func cacheOrgMemberRoleId() error {

FILE: app/server/db/result_helpers.go
  function StorePlanResult (line 22) | func StorePlanResult(result *PlanFileResult) error {
  type CurrentPlanStateParams (line 56) | type CurrentPlanStateParams struct
  function GetFullCurrentPlanStateParams (line 64) | func GetFullCurrentPlanStateParams(orgId, planId string) (CurrentPlanSta...
  function GetCurrentPlanState (line 141) | func GetCurrentPlanState(params CurrentPlanStateParams) (*shared.Current...
  function GetConvoMessageDescriptions (line 309) | func GetConvoMessageDescriptions(orgId, planId string) ([]*ConvoMessageD...
  function GetPlanFileResults (line 378) | func GetPlanFileResults(orgId, planId string) ([]*PlanFileResult, error) {
  function GetPlanFileResultById (line 443) | func GetPlanFileResultById(orgId, planId, resultId string) (*PlanFileRes...
  function GetPlanResult (line 462) | func GetPlanResult(planFileResults []*shared.PlanFileResult) *shared.Pla...
  type ApplyPlanParams (line 499) | type ApplyPlanParams struct
  function ApplyPlan (line 509) | func ApplyPlan(repo *GitRepo, ctx context.Context, params ApplyPlanParam...
  function RejectAllResults (line 790) | func RejectAllResults(orgId, planId string) error {
  function DeletePendingResultsForPaths (line 838) | func DeletePendingResultsForPaths(orgId, planId string, paths map[string...
  function RejectPlanFiles (line 906) | func RejectPlanFiles(orgId, planId string, files []string, now time.Time...
  function RejectPlanFile (line 939) | func RejectPlanFile(orgId, planId, filePathOrResultId string, now time.T...
  function RejectReplacement (line 991) | func RejectReplacement(orgId, planId, resultId, replacementId string) er...
  function GetPlanApplies (line 1029) | func GetPlanApplies(orgId, planId string) ([]*PlanApply, error) {

FILE: app/server/db/settings_helpers.go
  function GetPlanSettings (line 17) | func GetPlanSettings(plan *Plan) (settings *shared.PlanSettings, err err...
  function StorePlanSettings (line 72) | func StorePlanSettings(plan *Plan, settings shared.PlanSettings) error {
  function GetOrgDefaultSettings (line 106) | func GetOrgDefaultSettings(orgId string) (settings *shared.PlanSettings,...
  function GetOrgDefaultSettingsForUpdate (line 140) | func GetOrgDefaultSettingsForUpdate(orgId string, tx *sqlx.Tx) (settings...
  function StoreOrgDefaultSettings (line 173) | func StoreOrgDefaultSettings(orgId string, settings *shared.PlanSettings...
  type GetCustomModelsResult (line 190) | type GetCustomModelsResult struct
  function GetApiCustomModels (line 196) | func GetApiCustomModels(orgId string) (result *GetCustomModelsResult, er...

FILE: app/server/db/stream_helpers.go
  constant modelStreamHeartbeatInterval (line 17) | modelStreamHeartbeatInterval = 1 * time.Second
  constant modelStreamHeartbeatTimeout (line 18) | modelStreamHeartbeatTimeout = 5 * time.Second
  function StoreModelStream (line 20) | func StoreModelStream(stream *ModelStream, ctx context.Context, cancelFn...
  function SetModelStreamFinished (line 85) | func SetModelStreamFinished(id string) error {
  function GetActiveModelStream (line 99) | func GetActiveModelStream(planId, branch string) (*ModelStream, error) {
  function GetActiveOrRecentModelStreams (line 134) | func GetActiveOrRecentModelStreams(planIds []string) ([]*ModelStream, er...
  function GetActiveModelStreams (line 145) | func GetActiveModelStreams(planIds []string) ([]*ModelStream, error) {

FILE: app/server/db/subtask_helpers.go
  function GetPlanSubtasks (line 10) | func GetPlanSubtasks(orgId, planId string) ([]*Subtask, error) {
  function StorePlanSubtasks (line 34) | func StorePlanSubtasks(orgId, planId string, subtasks []*Subtask) error {

FILE: app/server/db/summary_helpers.go
  function GetPlanSummaries (line 10) | func GetPlanSummaries(planId string, convoMessageIds []string) ([]*Convo...
  function StoreSummary (line 21) | func StoreSummary(summary *ConvoSummary) error {

FILE: app/server/db/transactions.go
  function WithTx (line 13) | func WithTx(ctx context.Context, reason string, fn func(tx *sqlx.Tx) err...
  function WithTxOpts (line 17) | func WithTxOpts(ctx context.Context, opts *sql.TxOptions, reason string,...
  function withTx (line 21) | func withTx(ctx context.Context, opts *sql.TxOptions, reason string, fn ...

FILE: app/server/db/user_helpers.go
  function GetUser (line 13) | func GetUser(userId string) (*User, error) {
  function GetUserByEmail (line 28) | func GetUserByEmail(email string) (*User, error) {
  function GetUsersForDomain (line 43) | func GetUsersForDomain(domain string) ([]*User, error) {
  function GetOrgUser (line 58) | func GetOrgUser(userId, orgId string) (*OrgUser, error) {
  function GetOrgUserConfig (line 73) | func GetOrgUserConfig(userId, orgId string) (*shared.OrgUserConfig, erro...
  function UpdateOrgUserConfig (line 88) | func UpdateOrgUserConfig(userId, orgId string, config *shared.OrgUserCon...
  function ListOrgUsers (line 98) | func ListOrgUsers(orgId string) ([]*OrgUser, error) {
  function ListUsers (line 109) | func ListUsers(orgId string) ([]*User, error) {
  function CreateUser (line 132) | func CreateUser(name, email string, tx *sqlx.Tx) (*User, error) {
  function NumUsersWithRole (line 157) | func NumUsersWithRole(orgId, roleId string) (int, error) {

FILE: app/server/db/utils.go
  function IsNonUniqueErr (line 7) | func IsNonUniqueErr(err error) bool {

FILE: app/server/diff/diff.go
  function GetDiffs (line 18) | func GetDiffs(original, updated string) (string, error) {
  type change (line 60) | type change struct
  function GetDiffReplacements (line 67) | func GetDiffReplacements(original, updated string) ([]*shared.Replacemen...
  function processHunk (line 147) | func processHunk(oldLines, newLines []string, startLine int) *change {

FILE: app/server/email/email.go
  function SendEmailViaSES (line 14) | func SendEmailViaSES(recipient, subject, htmlBody, textBody string) error {
  function sendEmailViaSMTP (line 55) | func sendEmailViaSMTP(recipient, subject, htmlBody, textBody string) err...

FILE: app/server/email/invite.go
  function SendInviteEmail (line 10) | func SendInviteEmail(email, inviteeFirstName, inviterName, orgName strin...

FILE: app/server/email/verification.go
  function SendVerificationEmail (line 12) | func SendVerificationEmail(email string, pin string) error {

FILE: app/server/handlers/accounts.go
  function CreateAccountHandler (line 20) | func CreateAccountHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/auth_helpers.go
  function Authenticate (line 22) | func Authenticate(w http.ResponseWriter, r *http.Request, requireOrg boo...
  function AuthenticateOptional (line 26) | func AuthenticateOptional(w http.ResponseWriter, r *http.Request, requir...
  function GetAuthHeader (line 30) | func GetAuthHeader(r *http.Request) (*shared.AuthHeader, error) {
  function ClearAuthCookieIfBrowser (line 80) | func ClearAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request) er...
  function ClearAccountFromCookies (line 119) | func ClearAccountFromCookies(w http.ResponseWriter, r *http.Request, use...
  function SetAuthCookieIfBrowser (line 161) | func SetAuthCookieIfBrowser(w http.ResponseWriter, r *http.Request, user...
  function GetAccountsFromCookie (line 270) | func GetAccountsFromCookie(r *http.Request) ([]*shared.ClientAccount, er...
  function ValidateAndSignIn (line 293) | func ValidateAndSignIn(w http.ResponseWriter, r *http.Request, req share...
  function requireMinClientVersion (line 442) | func requireMinClientVersion(w http.ResponseWriter, r *http.Request, min...
  function execAuthenticate (line 463) | func execAuthenticate(w http.ResponseWriter, r *http.Request, requireOrg...
  function authorizeProject (line 617) | func authorizeProject(w http.ResponseWriter, projectId string, auth *typ...
  function authorizeProjectOptional (line 621) | func authorizeProjectOptional(w http.ResponseWriter, projectId string, a...
  function authorizeProjectRename (line 641) | func authorizeProjectRename(w http.ResponseWriter, projectId string, aut...
  function authorizeProjectDelete (line 655) | func authorizeProjectDelete(w http.ResponseWriter, projectId string, aut...
  function authorizePlan (line 669) | func authorizePlan(w http.ResponseWriter, planId string, auth *types.Ser...
  function authorizePlanUpdate (line 689) | func authorizePlanUpdate(w http.ResponseWriter, planId string, auth *typ...
  function authorizePlanDelete (line 705) | func authorizePlanDelete(w http.ResponseWriter, planId string, auth *typ...
  function authorizePlanRename (line 721) | func authorizePlanRename(w http.ResponseWriter, planId string, auth *typ...
  function authorizePlanArchive (line 737) | func authorizePlanArchive(w http.ResponseWriter, planId string, auth *ty...

FILE: app/server/handlers/branches.go
  function ListBranchesHandler (line 18) | func ListBranchesHandler(w http.ResponseWriter, r *http.Request) {
  function CreateBranchHandler (line 80) | func CreateBranchHandler(w http.ResponseWriter, r *http.Request) {
  function DeleteBranchHandler (line 160) | func DeleteBranchHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/client_helper.go
  type initClientsParams (line 14) | type initClientsParams struct
  type initClientsResult (line 28) | type initClientsResult struct
  function initClients (line 33) | func initClients(params initClientsParams) initClientsResult {

FILE: app/server/handlers/context_helper.go
  type loadContextsParams (line 18) | type loadContextsParams struct
  function loadContexts (line 29) | func loadContexts(

FILE: app/server/handlers/err_helper.go
  function writeApiError (line 11) | func writeApiError(w http.ResponseWriter, apiErr shared.ApiError) {

FILE: app/server/handlers/file_maps.go
  function GetFileMapHandler (line 18) | func GetFileMapHandler(w http.ResponseWriter, r *http.Request) {
  function LoadCachedFileMapHandler (line 105) | func LoadCachedFileMapHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/file_maps_queue.go
  constant fileMapMaxQueueSize (line 18) | fileMapMaxQueueSize = 20
  constant mapJobTimeout (line 20) | mapJobTimeout = 60 * time.Second
  type projectMapJob (line 22) | type projectMapJob struct
  function init (line 32) | func init() {
  function processProjectMapQueue (line 50) | func processProjectMapQueue() {
  function queueProjectMapJob (line 72) | func queueProjectMapJob(job projectMapJob) error {
  function mapWorker (line 82) | func mapWorker(job projectMapJob) {
  function safeSend (line 133) | func safeSend(ch chan shared.FileMapBodies, v shared.FileMapBodies) {

FILE: app/server/handlers/invites.go
  function InviteUserHandler (line 19) | func InviteUserHandler(w http.ResponseWriter, r *http.Request) {
  function ListPendingInvitesHandler (line 162) | func ListPendingInvitesHandler(w http.ResponseWriter, r *http.Request) {
  function ListAcceptedInvitesHandler (line 220) | func ListAcceptedInvitesHandler(w http.ResponseWriter, r *http.Request) {
  function ListAllInvitesHandler (line 278) | func ListAllInvitesHandler(w http.ResponseWriter, r *http.Request) {
  function DeleteInviteHandler (line 336) | func DeleteInviteHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/models.go
  constant CustomModelsMinClientVersion (line 17) | CustomModelsMinClientVersion = "2.2.0"
  function UpsertCustomModelsHandler (line 19) | func UpsertCustomModelsHandler(w http.ResponseWriter, r *http.Request) {
  function GetCustomModelHandler (line 341) | func GetCustomModelHandler(w http.ResponseWriter, r *http.Request) {
  function ListCustomModelsHandler (line 373) | func ListCustomModelsHandler(w http.ResponseWriter, r *http.Request) {
  function GetCustomProviderHandler (line 407) | func GetCustomProviderHandler(w http.ResponseWriter, r *http.Request) {
  function ListCustomProvidersHandler (line 431) | func ListCustomProvidersHandler(w http.ResponseWriter, r *http.Request) {
  function CreateModelPackHandler (line 463) | func CreateModelPackHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateModelPackHandler (line 478) | func UpdateModelPackHandler(w http.ResponseWriter, r *http.Request) {
  function ListModelPacksHandler (line 493) | func ListModelPacksHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/org_helpers.go
  function toApiOrgs (line 11) | func toApiOrgs(orgs []*db.Org) ([]*shared.Org, *shared.ApiError) {
  function getApiOrg (line 39) | func getApiOrg(orgId string) (*shared.Org, *shared.ApiError) {

FILE: app/server/handlers/orgs.go
  function ListOrgsHandler (line 18) | func ListOrgsHandler(w http.ResponseWriter, r *http.Request) {
  function CreateOrgHandler (line 55) | func CreateOrgHandler(w http.ResponseWriter, r *http.Request) {
  function GetOrgSessionHandler (line 166) | func GetOrgSessionHandler(w http.ResponseWriter, r *http.Request) {
  function ListOrgRolesHandler (line 203) | func ListOrgRolesHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/plan_config.go
  function GetPlanConfigHandler (line 16) | func GetPlanConfigHandler(w http.ResponseWriter, r *http.Request) {
  function UpdatePlanConfigHandler (line 56) | func UpdatePlanConfigHandler(w http.ResponseWriter, r *http.Request) {
  function GetDefaultPlanConfigHandler (line 92) | func GetDefaultPlanConfigHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateDefaultPlanConfigHandler (line 122) | func UpdateDefaultPlanConfigHandler(w http.ResponseWriter, r *http.Reque...

FILE: app/server/handlers/plans_changes.go
  function CurrentPlanHandler (line 19) | func CurrentPlanHandler(w http.ResponseWriter, r *http.Request) {
  function ApplyPlanHandler (line 106) | func ApplyPlanHandler(w http.ResponseWriter, r *http.Request) {
  function RejectAllChangesHandler (line 251) | func RejectAllChangesHandler(w http.ResponseWriter, r *http.Request) {
  function RejectFileHandler (line 302) | func RejectFileHandler(w http.ResponseWriter, r *http.Request) {
  function RejectFilesHandler (line 362) | func RejectFilesHandler(w http.ResponseWriter, r *http.Request) {
  function ArchivePlanHandler (line 432) | func ArchivePlanHandler(w http.ResponseWriter, r *http.Request) {
  function UnarchivePlanHandler (line 480) | func UnarchivePlanHandler(w http.ResponseWriter, r *http.Request) {
  function GetPlanDiffsHandler (line 528) | func GetPlanDiffsHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/plans_context.go
  function ListContextHandler (line 17) | func ListContextHandler(w http.ResponseWriter, r *http.Request) {
  function GetContextBodyHandler (line 80) | func GetContextBodyHandler(w http.ResponseWriter, r *http.Request) {
  function LoadContextHandler (line 154) | func LoadContextHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateContextHandler (line 214) | func UpdateContextHandler(w http.ResponseWriter, r *http.Request) {
  function DeleteContextHandler (line 320) | func DeleteContextHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/plans_convo.go
  function ListConvoHandler (line 15) | func ListConvoHandler(w http.ResponseWriter, r *http.Request) {
  function GetPlanStatusHandler (line 81) | func GetPlanStatusHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/plans_crud.go
  function CreatePlanHandler (line 22) | func CreatePlanHandler(w http.ResponseWriter, r *http.Request) {
  function GetPlanHandler (line 129) | func GetPlanHandler(w http.ResponseWriter, r *http.Request) {
  function RenamePlanHandler (line 159) | func RenamePlanHandler(w http.ResponseWriter, r *http.Request) {
  function DeletePlanHandler (line 208) | func DeletePlanHandler(w http.ResponseWriter, r *http.Request) {
  function DeleteAllPlansHandler (line 265) | func DeleteAllPlansHandler(w http.ResponseWriter, r *http.Request) {
  function ListPlansHandler (line 293) | func ListPlansHandler(w http.ResponseWriter, r *http.Request) {
  function ListArchivedPlansHandler (line 350) | func ListArchivedPlansHandler(w http.ResponseWriter, r *http.Request) {
  function ListPlansRunningHandler (line 403) | func ListPlansRunningHandler(w http.ResponseWriter, r *http.Request) {
  function GetCurrentBranchByPlanIdHandler (line 576) | func GetCurrentBranchByPlanIdHandler(w http.ResponseWriter, r *http.Requ...

FILE: app/server/handlers/plans_exec.go
  function TellPlanHandler (line 23) | func TellPlanHandler(w http.ResponseWriter, r *http.Request) {
  function BuildPlanHandler (line 121) | func BuildPlanHandler(w http.ResponseWriter, r *http.Request) {
  function ConnectPlanHandler (line 216) | func ConnectPlanHandler(w http.ResponseWriter, r *http.Request) {
  function StopPlanHandler (line 258) | func StopPlanHandler(w http.ResponseWriter, r *http.Request) {
  function RespondMissingFileHandler (line 334) | func RespondMissingFileHandler(w http.ResponseWriter, r *http.Request) {
  function AutoLoadContextHandler (line 428) | func AutoLoadContextHandler(w http.ResponseWriter, r *http.Request) {
  function GetBuildStatusHandler (line 570) | func GetBuildStatusHandler(w http.ResponseWriter, r *http.Request) {
  function authorizePlanExecUpdate (line 619) | func authorizePlanExecUpdate(w http.ResponseWriter, planId string, auth ...

FILE: app/server/handlers/plans_versions.go
  function ListLogsHandler (line 16) | func ListLogsHandler(w http.ResponseWriter, r *http.Request) {
  function RewindPlanHandler (line 82) | func RewindPlanHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/projects.go
  function CreateProjectHandler (line 17) | func CreateProjectHandler(w http.ResponseWriter, r *http.Request) {
  function ListProjectsHandler (line 84) | func ListProjectsHandler(w http.ResponseWriter, r *http.Request) {
  function ProjectSetPlanHandler (line 123) | func ProjectSetPlanHandler(w http.ResponseWriter, r *http.Request) {
  function RenameProjectHandler (line 166) | func RenameProjectHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/proxy_helper.go
  function proxyActivePlanMethod (line 16) | func proxyActivePlanMethod(w http.ResponseWriter, r *http.Request, planI...
  function proxyRequest (line 57) | func proxyRequest(w http.ResponseWriter, originalRequest *http.Request, ...

FILE: app/server/handlers/sessions.go
  function CreateEmailVerificationHandler (line 18) | func CreateEmailVerificationHandler(w http.ResponseWriter, r *http.Reque...
  function CheckEmailPinHandler (line 138) | func CheckEmailPinHandler(w http.ResponseWriter, r *http.Request) {
  function CreateSignInCodeHandler (line 176) | func CreateSignInCodeHandler(w http.ResponseWriter, r *http.Request) {
  function SignInHandler (line 211) | func SignInHandler(w http.ResponseWriter, r *http.Request) {
  function SignOutHandler (line 252) | func SignOutHandler(w http.ResponseWriter, r *http.Request) {
  function GetOrgUserConfigHandler (line 287) | func GetOrgUserConfigHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateOrgUserConfigHandler (line 314) | func UpdateOrgUserConfigHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/handlers/settings.go
  function GetSettingsHandler (line 19) | func GetSettingsHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateSettingsHandler (line 80) | func UpdateSettingsHandler(w http.ResponseWriter, r *http.Request) {
  function GetDefaultSettingsHandler (line 225) | func GetDefaultSettingsHandler(w http.ResponseWriter, r *http.Request) {
  function UpdateDefaultSettingsHandler (line 254) | func UpdateDefaultSettingsHandler(w http.ResponseWriter, r *http.Request) {
  function getUpdateCommitMsg (line 344) | func getUpdateCommitMsg(settings *shared.PlanSettings, originalSettings ...
  function compareSettings (line 373) | func compareSettings(original, updated *shared.PlanSettings, changes []s...
  function compareAny (line 391) | func compareAny(a, b interface{}, path string, changes []string) []string {
  function short (line 510) | func short(v reflect.Value) string {

FILE: app/server/handlers/stream_helper.go
  constant HeartbeatInterval (line 17) | HeartbeatInterval = 5 * time.Second
  function startResponseStream (line 19) | func startResponseStream(reqCtx context.Context, w http.ResponseWriter, ...
  function sendStreamMessage (line 112) | func sendStreamMessage(w http.ResponseWriter, msg string) error {
  function initConnectActive (line 127) | func initConnectActive(auth *types.ServerAuth, planId, branch string, w ...

FILE: app/server/handlers/users.go
  function ListUsersHandler (line 18) | func ListUsersHandler(w http.ResponseWriter, r *http.Request) {
  function DeleteOrgUserHandler (line 93) | func DeleteOrgUserHandler(w http.ResponseWriter, r *http.Request) {

FILE: app/server/hooks/hooks.go
  constant HealthCheck (line 16) | HealthCheck = "health_check"
  constant CreateAccount (line 18) | CreateAccount        = "create_account"
  constant WillCreatePlan (line 19) | WillCreatePlan       = "will_create_plan"
  constant WillTellPlan (line 20) | WillTellPlan         = "will_tell_plan"
  constant WillExecPlan (line 21) | WillExecPlan         = "will_exec_plan"
  constant WillSendModelRequest (line 22) | WillSendModelRequest = "will_send_model_request"
  constant DidSendModelRequest (line 23) | DidSendModelRequest  = "did_send_model_request"
  constant DidFinishBuilderRun (line 24) | DidFinishBuilderRun  = "did_finish_builder_run"
  constant CreateOrg (line 25) | CreateOrg            = "create_org"
  constant Authenticate (line 26) | Authenticate         = "authenticate"
  constant GetIntegratedModels (line 27) | GetIntegratedModels  = "get_integrated_models"
  constant GetApiOrgs (line 28) | GetApiOrgs           = "get_api_orgs"
  constant CallFastApply (line 29) | CallFastApply        = "call_fast_apply"
  type WillSendModelRequestParams (line 32) | type WillSendModelRequestParams struct
  type DidSendModelRequestParams (line 41) | type DidSendModelRequestParams struct
  type DidFinishBuilderRunParams (line 72) | type DidFinishBuilderRunParams struct
  type CreateOrgHookRequestParams (line 120) | type CreateOrgHookRequestParams struct
  type AuthenticateHookRequestParams (line 124) | type AuthenticateHookRequestParams struct
  type FastApplyParams (line 129) | type FastApplyParams struct
  type HookParams (line 141) | type HookParams struct
  type GetIntegratedModelsResult (line 155) | type GetIntegratedModelsResult struct
  type FastApplyResult (line 160) | type FastApplyResult struct
  type HookResult (line 164) | type HookResult struct
  type Hook (line 170) | type Hook
  function RegisterHook (line 174) | func RegisterHook(name string, hook Hook) {
  function ExecHook (line 178) | func ExecHook(name string, params HookParams) (HookResult, *shared.ApiEr...
  function TestUpdate (line 186) | func TestUpdate() {

FILE: app/server/host/ip.go
  function LoadIp (line 15) | func LoadIp() error {
  type ecsMetadata (line 39) | type ecsMetadata struct
  function getAwsIp (line 47) | func getAwsIp() (string, error) {

FILE: app/server/litellm_proxy.py
  function _oauth_get_hdrs (line 6) | def _oauth_get_hdrs(
  function health (line 61) | async def health():
  function passthrough (line 65) | async def passthrough(request: Request):
  function error_response (line 158) | def error_response(exc: Exception) -> JSONResponse:
  function normalise_for_ollama (line 167) | def normalise_for_ollama(p):

FILE: app/server/main.go
  function main (line 14) | func main() {

FILE: app/server/migrations/2023120500_init.up.sql
  function update_updated_at_column (line 3) | CREATE OR REPLACE FUNCTION update_updated_at_column()
  type users (line 11) | CREATE TABLE IF NOT EXISTS users (
  type users_domain_idx (line 24) | CREATE INDEX users_domain_idx ON users(domain)
  type orgs (line 26) | CREATE TABLE IF NOT EXISTS orgs (
  type orgs_users (line 40) | CREATE TABLE IF NOT EXISTS orgs_users (
  type orgs_users_user_idx (line 49) | CREATE INDEX orgs_users_user_idx ON orgs_users(user_id)
  type orgs_users_org_idx (line 50) | CREATE INDEX orgs_users_org_idx ON orgs_users(org_id)
  type invites (line 52) | CREATE TABLE IF NOT EXISTS invites (
  type invites_pending_idx (line 65) | CREATE INDEX invites_pending_idx ON invites(org_id, (accepted_at IS NULL))
  type invites_email_idx (line 66) | CREATE INDEX invites_email_idx ON invites(email, (accepted_at IS NULL))
  type invites_org_user_idx (line 67) | CREATE INDEX invites_org_user_idx ON invites(org_id, invitee_id)
  type auth_tokens (line 69) | CREATE TABLE IF NOT EXISTS auth_tokens (
  type auth_tokens_idx (line 77) | CREATE UNIQUE INDEX auth_tokens_idx ON auth_tokens(token_hash)
  type email_verifications (line 79) | CREATE TABLE IF NOT EXISTS email_verifications (
  type email_verifications_idx (line 90) | CREATE UNIQUE INDEX email_verifications_idx ON email_verifications(pin_h...
  type projects (line 92) | CREATE TABLE IF NOT EXISTS projects (
  type plans (line 101) | CREATE TABLE IF NOT EXISTS plans (
  type plans_name_idx (line 116) | CREATE INDEX plans_name_idx ON plans(project_id, owner_id, name)
  type plans_archived_idx (line 117) | CREATE INDEX plans_archived_idx ON plans(project_id, owner_id, archived_at)
  type branches (line 119) | CREATE TABLE IF NOT EXISTS branches (
  type branches_name_idx (line 138) | CREATE UNIQUE INDEX branches_name_idx ON branches(plan_id, name, archive...
  type users_projects (line 141) | CREATE TABLE IF NOT EXISTS users_projects (
  type users_projects_idx (line 152) | CREATE INDEX users_projects_idx ON users_projects(user_id, org_id, proje...
  type convo_summaries (line 154) | CREATE TABLE IF NOT EXISTS convo_summaries (
  type plan_builds (line 166) | CREATE TABLE IF NOT EXISTS plan_builds (

FILE: app/server/migrations/2024011700_rbac.up.sql
  type org_roles (line 2) | CREATE TABLE IF NOT EXISTS org_roles (
  type org_roles_org_idx (line 13) | CREATE UNIQUE INDEX org_roles_org_idx ON org_roles(org_id, name)
  type orgs_users_org_role_idx (line 16) | CREATE INDEX orgs_users_org_role_idx ON orgs_users(org_id, org_role_id)
  type invites_org_role_idx (line 19) | CREATE INDEX invites_org_role_idx ON invites(org_id, org_role_id)
  type permissions (line 21) | CREATE TABLE IF NOT EXISTS permissions (
  type org_roles_permissions (line 29) | CREATE TABLE IF NOT EXISTS org_roles_permissions (

FILE: app/server/migrations/2024012400_streams.up.sql
  type model_streams (line 1) | CREATE TABLE IF NOT EXISTS model_streams (
  type model_streams_plan_idx (line 11) | CREATE UNIQUE INDEX model_streams_plan_idx ON model_streams(plan_id, bra...

FILE: app/server/migrations/2024012500_locks.up.sql
  type repo_locks (line 1) | CREATE UNLOGGED TABLE IF NOT EXISTS repo_locks (
  type repo_locks_plan_idx (line 12) | CREATE INDEX repo_locks_plan_idx ON repo_locks(plan_id)

FILE: app/server/migrations/2024032701_drop_users_projects.down.sql
  type users_projects (line 1) | CREATE TABLE IF NOT EXISTS users_projects (
  type users_projects_idx (line 12) | CREATE INDEX users_projects_idx ON users_projects(user_id, org_id, proje...

FILE: app/server/migrations/2024041500_model_sets_models.up.sql
  type model_sets (line 1) | CREATE TABLE IF NOT EXISTS model_sets (
  type model_sets_org_idx (line 18) | CREATE INDEX model_sets_org_idx ON model_sets(org_id)
  type custom_models (line 20) | CREATE TABLE IF NOT EXISTS custom_models (
  type custom_models_org_idx (line 47) | CREATE INDEX custom_models_org_idx ON custom_models(org_id)

FILE: app/server/migrations/2024042600_default_plan_settings.up.sql
  type default_plan_settings (line 1) | CREATE TABLE IF NOT EXISTS default_plan_settings (
  type default_plan_settings_org_idx (line 12) | CREATE UNIQUE INDEX default_plan_settings_org_idx ON default_plan_settin...

FILE: app/server/migrations/2024091800_sign_in_codes.up.sql
  type sign_in_codes (line 1) | CREATE TABLE IF NOT EXISTS sign_in_codes (
  type sign_in_codes_idx (line 12) | CREATE UNIQUE INDEX sign_in_codes_idx ON sign_in_codes(pin_hash, created...

FILE: app/server/migrations/2025021101_locks_unique.up.sql
  type repo_locks_single_write_lock (line 2) | CREATE UNIQUE INDEX repo_locks_single_write_lock
  type lockable_plan_ids (line 6) | CREATE TABLE IF NOT EXISTS lockable_plan_ids (

FILE: app/server/migrations/2025051600_custom_models_refactor.up.sql
  type custom_models (line 5) | CREATE TABLE IF NOT EXISTS custom_models (
  type cmv_org_idx (line 38) | CREATE INDEX IF NOT EXISTS cmv_org_idx ON custom_models(org_id)
  type cmv_unique_idx (line 39) | CREATE UNIQUE INDEX IF NOT EXISTS cmv_unique_idx ON custom_models(org_id...
  type custom_providers (line 44) | CREATE TABLE IF NOT EXISTS custom_providers (
  type cp_org_idx (line 58) | CREATE INDEX IF NOT EXISTS cp_org_idx ON custom_providers(org_id)
  type cp_unique_idx (line 59) | CREATE UNIQUE INDEX IF NOT EXISTS cp_unique_idx ON custom_providers(org_...

FILE: app/server/migrations/2025052200_model_pack_cols.up.sql
  type model_set_unique_idx (line 7) | CREATE UNIQUE INDEX IF NOT EXISTS model_set_unique_idx ON model_sets(org...

FILE: app/server/model/client.go
  constant ACTIVE_STREAM_CHUNK_TIMEOUT (line 30) | ACTIVE_STREAM_CHUNK_TIMEOUT          = time.Duration(60) * time.Second
  constant USAGE_CHUNK_TIMEOUT (line 31) | USAGE_CHUNK_TIMEOUT                  = time.Duration(10) * time.Second
  constant MAX_ADDITIONAL_RETRIES_WITH_FALLBACK (line 32) | MAX_ADDITIONAL_RETRIES_WITH_FALLBACK = 1
  constant MAX_RETRIES_WITHOUT_FALLBACK (line 33) | MAX_RETRIES_WITHOUT_FALLBACK         = 3
  constant MAX_RETRY_DELAY_SECONDS (line 34) | MAX_RETRY_DELAY_SECONDS              = 10
  type ClientInfo (line 39) | type ClientInfo struct
  function InitClients (line 46) | func InitClients(authVars map[string]string, settings *shared.PlanSettin...
  function newClient (line 57) | func newClient(providerConfig shared.ModelProviderConfigSchema, authVars...
  type ExtendedChatCompletionStream (line 83) | type ExtendedChatCompletionStream struct
    method Recv (line 472) | func (stream *ExtendedChatCompletionStream) Recv() (*types.ExtendedCha...
    method Close (line 495) | func (stream *ExtendedChatCompletionStream) Close() error {
  type StreamReader (line 90) | type StreamReader struct
  type ErrorAccumulator (line 99) | type ErrorAccumulator struct
    method Add (line 405) | func (ea *ErrorAccumulator) Add(err error) {
    method GetErrors (line 411) | func (ea *ErrorAccumulator) GetErrors() []error {
  type JSONUnmarshaler (line 105) | type JSONUnmarshaler struct
    method Unmarshal (line 417) | func (ju *JSONUnmarshaler) Unmarshal(data []byte, v interface{}) error {
  function CreateChatCompletionStream (line 107) | func CreateChatCompletionStream(
  function createChatCompletionStreamExtended (line 216) | func createChatCompletionStreamExtended(
  function NewErrorAccumulator (line 399) | func NewErrorAccumulator() *ErrorAccumulator {
  method Recv (line 422) | func (stream *StreamReader[T]) Recv() (*T, error) {
  method Close (line 464) | func (stream *StreamReader[T]) Close() error {
  function resolveReq (line 502) | func resolveReq(req *types.ExtendedChatCompletionRequest, modelConfig *s...
  function addOpenRouterHeaders (line 534) | func addOpenRouterHeaders(req *http.Request) {
  function handleClaudeMaxRateLimitedIfNeeded (line 543) | func handleClaudeMaxRateLimitedIfNeeded(modelErr *shared.ModelError, mod...

FILE: app/server/model/client_stream.go
  type OnStreamFn (line 17) | type OnStreamFn
  function CreateChatCompletionWithInternalStream (line 19) | func CreateChatCompletionWithInternalStream(
  function processChatCompletionStream (line 86) | func processChatCompletionStream(
  function withStreamingRetries (line 230) | func withStreamingRetries[T any](

FILE: app/server/model/litellm.go
  function EnsureLiteLLM (line 20) | func EnsureLiteLLM(numWorkers int) error {
  function ShutdownLiteLLMServer (line 63) | func ShutdownLiteLLMServer() error {
  function isLiteLLMHealthy (line 86) | func isLiteLLMHealthy() bool {
  function startLiteLLMServer (line 106) | func startLiteLLMServer(numWorkers int) error {

FILE: app/server/model/model_error.go
  type HTTPError (line 14) | type HTTPError struct
    method Error (line 20) | func (e *HTTPError) Error() string {
  function ClassifyErrMsg (line 38) | func ClassifyErrMsg(msg string) *shared.ModelError {
  function ClassifyModelError (line 90) | func ClassifyModelError(code int, message string, headers http.Header, i...
  function extractRetryAfter (line 167) | func extractRetryAfter(h http.Header, body string) (sec int) {
  function normalizeUnit (line 217) | func normalizeUnit(numStr, unit string) int {
  function classifyBasicError (line 230) | func classifyBasicError(err error, isClaudeMax bool) shared.ModelError {
  function isNonRetriableBasicErr (line 255) | func isNonRetriableBasicErr(err error) bool {

FILE: app/server/model/model_request.go
  type ModelRequestParams (line 20) | type ModelRequestParams struct
  function ModelRequest (line 52) | func ModelRequest(
  function FilterEmptyMessages (line 265) | func FilterEmptyMessages(messages []types.ExtendedChatMessage) []types.E...
  function CheckSingleSystemMessage (line 284) | func CheckSingleSystemMessage(modelConfig *shared.ModelRoleConfig, baseM...

FILE: app/server/model/name.go
  function GenPlanName (line 17) | func GenPlanName(
  type GenPipedDataNameParams (line 115) | type GenPipedDataNameParams struct
  function GenPipedDataName (line 127) | func GenPipedDataName(
  function GenNoteName (line 227) | func GenNoteName(

FILE: app/server/model/parse/subtasks.go
  function ParseSubtasks (line 10) | func ParseSubtasks(replyContent string) []*db.Subtask {
  function ParseRemoveSubtasks (line 91) | func ParseRemoveSubtasks(replyContent string) []string {

FILE: app/server/model/parse/subtasks_test.go
  function TestParseSubtasks (line 8) | func TestParseSubtasks(t *testing.T) {
  function sliceEqual (line 131) | func sliceEqual(a, b []string) bool {

FILE: app/server/model/plan/activate.go
  function activatePlan (line 15) | func activatePlan(

FILE: app/server/model/plan/build_exec.go
  type BuildParams (line 19) | type BuildParams struct
  function Build (line 30) | func Build(params BuildParams) (int, error) {
  method queueBuild (line 95) | func (state *activeBuildStreamState) queueBuild(activeBuild *types.Activ...
  method queueBuilds (line 132) | func (state *activeBuildStreamState) queueBuilds(activeBuilds []*types.A...
  method execPlanBuild (line 140) | func (buildState *activeBuildStreamState) execPlanBuild(activeBuild *typ...
  method buildFile (line 225) | func (fileState *activeBuildStreamFileState) buildFile() {
  method resolvePreBuildState (line 400) | func (fileState *activeBuildStreamFileState) resolvePreBuildState() {

FILE: app/server/model/plan/build_finish.go
  method onFinishBuild (line 18) | func (state *activeBuildStreamFileState) onFinishBuild() {
  method onFinishBuildFile (line 165) | func (fileState *activeBuildStreamFileState) onFinishBuildFile(planRes *...
  method onBuildProcessed (line 242) | func (fileState *activeBuildStreamFileState) onBuildProcessed(activeBuil...
  method onBuildFileError (line 276) | func (fileState *activeBuildStreamFileState) onBuildFileError(err error) {
  method buildNextInQueue (line 315) | func (fileState *activeBuildStreamFileState) buildNextInQueue() bool {

FILE: app/server/model/plan/build_load.go
  method loadPendingBuilds (line 17) | func (state *activeBuildStreamState) loadPendingBuilds(sessionId string)...
  method loadBuildFile (line 159) | func (state *activeBuildStreamFileState) loadBuildFile(activeBuild *type...

FILE: app/server/model/plan/build_race.go
  type raceResult (line 16) | type raceResult struct
  type buildRaceParams (line 21) | type buildRaceParams struct
  method buildRace (line 34) | func (fileState *activeBuildStreamFileState) buildRace(

FILE: app/server/model/plan/build_state.go
  constant MaxBuildErrorRetries (line 14) | MaxBuildErrorRetries = 3
  type activeBuildStreamState (line 16) | type activeBuildStreamState struct
  type activeBuildStreamFileState (line 31) | type activeBuildStreamFileState struct

FILE: app/server/model/plan/build_structured_edits.go
  method buildStructuredEdits (line 20) | func (fileState *activeBuildStreamFileState) buildStructuredEdits() {
  method validateSyntax (line 223) | func (fileState *activeBuildStreamFileState) validateSyntax(buildCtx con...

FILE: app/server/model/plan/build_validate_and_fix.go
  constant MaxValidationFixAttempts (line 22) | MaxValidationFixAttempts = 3
  type buildValidateLoopParams (line 24) | type buildValidateLoopParams struct
  type buildValidateLoopResult (line 38) | type buildValidateLoopResult struct
  method buildValidateLoop (line 44) | func (fileState *activeBuildStreamFileState) buildValidateLoop(
  type buildValidateParams (line 161) | type buildValidateParams struct
  type buildValidateResult (line 176) | type buildValidateResult struct
  method buildValidate (line 182) | func (fileState *activeBuildStreamFileState) buildValidate(
  function handleXMLResponse (line 327) | func handleXMLResponse(
  method validationRetryOrError (line 455) | func (fileState *activeBuildStreamFileState) validationRetryOrError(buil...

FILE: app/server/model/plan/build_whole_file.go
  method buildWholeFileFallback (line 20) | func (fileState *activeBuildStreamFileState) buildWholeFileFallback(buil...
  method wholeFileRetryOrError (line 143) | func (fileState *activeBuildStreamFileState) wholeFileRetryOrError(build...

FILE: app/server/model/plan/commit_msg.go
  method genPlanDescription (line 21) | func (state *activeTellStreamState) genPlanDescription() (*db.ConvoMessa...
  type GenCommitMsgForPendingResultsParams (line 176) | type GenCommitMsgForPendingResultsParams struct
  function GenCommitMsgForPendingResults (line 187) | func GenCommitMsgForPendingResults(params GenCommitMsgForPendingResultsP...

FILE: app/server/model/plan/exec_status.go
  constant MaxPreviousMessages (line 24) | MaxPreviousMessages = 4
  type execStatusShouldContinueResult (line 26) | type execStatusShouldContinueResult struct
  method execStatusShouldContinue (line 30) | func (state *activeTellStreamState) execStatusShouldContinue(currentMess...

FILE: app/server/model/plan/state.go
  function GetActivePlan (line 21) | func GetActivePlan(planId, branch string) *types.ActivePlan {
  function CreateActivePlan (line 25) | func CreateActivePlan(orgId, userId, planId, branch, prompt string, buil...
  function DeleteActivePlan (line 99) | func DeleteActivePlan(orgId, userId, planId, branch string) {
  function UpdateActivePlan (line 139) | func UpdateActivePlan(planId, branch string, fn func(*types.ActivePlan)) {
  function SubscribePlan (line 143) | func SubscribePlan(ctx context.Context, planId, branch string) (string, ...
  function UnsubscribePlan (line 160) | func UnsubscribePlan(planId, branch, subscriptionId string) {
  function NumActivePlans (line 176) | func NumActivePlans() int {

FILE: app/server/model/plan/stop.go
  function Stop (line 10) | func Stop(planId, branch, currentUserId, currentOrgId string) error {
  function StorePartialReply (line 23) | func StorePartialReply(repo *db.GitRepo, planId, branch, currentUserId, ...

FILE: app/server/model/plan/tell_build_pending.go
  method queuePendingBuilds (line 13) | func (state *activeTellStreamState) queuePendingBuilds() {

FILE: app/server/model/plan/tell_context.go
  type formatModelContextParams (line 16) | type formatModelContextParams struct
  method formatModelContext (line 29) | func (state *activeTellStreamState) formatModelContext(params formatMode...
  type checkAutoLoadContextResult (line 370) | type checkAutoLoadContextResult struct
  method checkAutoLoadContext (line 377) | func (state *activeTellStreamState) checkAutoLoadContext() checkAutoLoad...

FILE: app/server/model/plan/tell_exec.go
  type TellParams (line 23) | type TellParams struct
  function Tell (line 32) | func Tell(params TellParams) error {
  type execTellPlanParams (line 73) | type execTellPlanParams struct
  function execTellPlan (line 86) | func execTellPlan(params execTellPlanParams) {
  method doTellRequest (line 494) | func (state *activeTellStreamState) doTellRequest() {
  method dryRunCalculateTokensWithoutContext (line 584) | func (state *activeTellStreamState) dryRunCalculateTokensWithoutContext(...

FILE: app/server/model/plan/tell_load.go
  method loadTellPlan (line 20) | func (state *activeTellStreamState) loadTellPlan() error {
  method setActivePlan (line 429) | func (state *activeTellStreamState) setActivePlan() error {

FILE: app/server/model/plan/tell_missing_file.go
  method handleMissingFileResponse (line 13) | func (state *activeTellStreamState) handleMissingFileResponse(unfinished...

FILE: app/server/model/plan/tell_prompt_message.go
  method resolvePromptMessage (line 13) | func (state *activeTellStreamState) resolvePromptMessage(

FILE: app/server/model/plan/tell_stage.go
  method lastSuccessfulConvoMessage (line 11) | func (state *activeTellStreamState) lastSuccessfulConvoMessage() *db.Con...
  method resolveCurrentStage (line 22) | func (state *activeTellStreamState) resolveCurrentStage() (activatePaths...

FILE: app/server/model/plan/tell_state.go
  type activeTellStreamState (line 14) | type activeTellStreamState struct
  type chunkProcessor (line 71) | type chunkProcessor struct

FILE: app/server/model/plan/tell_stream_error.go
  type onErrorParams (line 19) | type onErrorParams struct
  type onErrorResult (line 29) | type onErrorResult struct
  method onError (line 34) | func (state *activeTellStreamState) onError(params onErrorParams) onErro...
  method onActivePlanMissingError (line 262) | func (state *activeTellStreamState) onActivePlanMissingError() {

FILE: app/server/model/plan/tell_stream_finish.go
  constant MaxAutoContinueIterations (line 18) | MaxAutoContinueIterations = 200
  type handleStreamFinishedResult (line 20) | type handleStreamFinishedResult struct
  method handleStreamFinished (line 25) | func (state *activeTellStreamState) handleStreamFinished() handleStreamF...

FILE: app/server/model/plan/tell_stream_main.go
  method listenStream (line 20) | func (state *activeTellStreamState) listenStream(stream *model.ExtendedC...
  function firstTokenTimeout (line 286) | func firstTokenTimeout(tok int, isLocalModel bool) time.Duration {

FILE: app/server/model/plan/tell_stream_processor.go
  constant verboseLogging (line 20) | verboseLogging = false
  type processChunkResult (line 24) | type processChunkResult struct
  method processChunk (line 29) | func (state *activeTellStreamState) processChunk(choice types.ExtendedCh...
  type bufferOrStreamResult (line 158) | type bufferOrStreamResult struct
  method bufferOrStream (line 165) | func (processor *chunkProcessor) bufferOrStream(content string, parserRe...
  method handleNewOperations (line 522) | func (state *activeTellStreamState) handleNewOperations(parserRes *types...
  method handleMissingFile (line 595) | func (state *activeTellStreamState) handleMissingFile(content, currentFi...
  function getCroppedChunk (line 728) | func getCroppedChunk(uncropped, cropped, chunk string) string {
  function replaceCodeBlockOpeningTag (line 737) | func replaceCodeBlockOpeningTag(content string, replaceWithFn func(lang ...

FILE: app/server/model/plan/tell_stream_processor_test.go
  function TestBufferOrStream (line 9) | func TestBufferOrStream(t *testing.T) {

FILE: app/server/model/plan/tell_stream_status.go
  type handleDescAndExecStatusResult (line 12) | type handleDescAndExecStatusResult struct
  method handleDescAndExecStatus (line 18) | func (state *activeTellStreamState) handleDescAndExecStatus() handleDesc...
  type willContinuePlanParams (line 130) | type willContinuePlanParams struct
  method willContinuePlan (line 138) | func (state *activeTellStreamState) willContinuePlan(params willContinue...

FILE: app/server/model/plan/tell_stream_store.go
  type storeOnFinishedParams (line 15) | type storeOnFinishedParams struct
  type storeOnFinishedResult (line 25) | type storeOnFinishedResult struct
  method storeOnFinished (line 30) | func (state *activeTellStreamState) storeOnFinished(params storeOnFinish...
  type storeAssistantReplyParams (line 239) | type storeAssistantReplyParams struct
  method storeAssistantReply (line 248) | func (state *activeTellStreamState) storeAssistantReply(repo *db.GitRepo...

FILE: app/server/model/plan/tell_stream_usage.go
  method handleUsageChunk (line 14) | func (state *activeTellStreamState) handleUsageChunk(usage *openai.Usage) {
  method execHookOnStop (line 76) | func (state *activeTellStreamState) execHookOnStop(sendStreamErr bool) {

FILE: app/server/model/plan/tell_subtasks.go
  method formatSubtasks (line 14) | func (state *activeTellStreamState) formatSubtasks() string {
  type checkNewSubtasksResult (line 80) | type checkNewSubtasksResult struct
  method checkNewSubtasks (line 85) | func (state *activeTellStreamState) checkNewSubtasks() checkNewSubtasksR...
  type checkRemoveSubtasksResult (line 174) | type checkRemoveSubtasksResult struct
  method checkRemoveSubtasks (line 179) | func (state *activeTellStreamState) checkRemoveSubtasks() checkRemoveSub...

FILE: app/server/model/plan/tell_summary.go
  method addConversationMessages (line 22) | func (state *activeTellStreamState) addConversationMessages() bool {
  type summarizeConvoParams (line 233) | type summarizeConvoParams struct
  function summarizeConvo (line 246) | func summarizeConvo(clients map[string]model.ClientInfo, authVars map[st...

FILE: app/server/model/plan/tell_sys_prompt.go
  constant AllTasksCompletedMsg (line 14) | AllTasksCompletedMsg = "All tasks have been completed. There is no curre...
  type getTellSysPromptParams (line 16) | type getTellSysPromptParams struct
  method getTellSysPrompt (line 24) | func (state *activeTellStreamState) getTellSysPrompt(params getTellSysPr...

FILE: app/server/model/plan/utils.go
  function StripBackticksWrapper (line 8) | func StripBackticksWrapper(s string) string {

FILE: app/server/model/prompts/apply_exec.go
  constant ApplyScriptSharedPrompt (line 3) | ApplyScriptSharedPrompt = `
  constant ApplyScriptPlanningPrompt (line 242) | ApplyScriptPlanningPrompt = ApplyScriptSharedPrompt + `
  constant ApplyScriptImplementationPrompt (line 305) | ApplyScriptImplementationPrompt = ApplyScriptSharedPrompt + `
  constant ApplyScriptResetUpdateSharedPrompt (line 531) | ApplyScriptResetUpdateSharedPrompt = `
  constant ApplyScriptResetUpdatePlanningPrompt (line 561) | ApplyScriptResetUpdatePlanningPrompt = ApplyScriptResetUpdateSharedPromp...
  constant ApplyScriptResetUpdateImplementationPrompt (line 776) | ApplyScriptResetUpdateImplementationPrompt = ApplyScriptResetUpdateShare...
  constant ApplyScriptPlanningPromptSummary (line 847) | ApplyScriptPlanningPromptSummary = `
  constant ApplyScriptImplementationPromptSummary (line 917) | ApplyScriptImplementationPromptSummary = `
  constant ApplyScriptResetUpdateSharedSummary (line 987) | ApplyScriptResetUpdateSharedSummary = `
  constant ApplyScriptResetUpdatePlanningSummary (line 1001) | ApplyScriptResetUpdatePlanningSummary = `
  constant ApplyScriptResetUpdateImplementationSummary (line 1024) | ApplyScriptResetUpdateImplementationSummary = `
  constant ApplyScriptExecutionSummary (line 1050) | ApplyScriptExecutionSummary = `
  constant SharedPlanningDebugPrompt (line 1124) | SharedPlanningDebugPrompt = `
  constant UserPlanningDebugPrompt (line 1143) | UserPlanningDebugPrompt = SharedPlanningDebugPrompt + `You are debugging...
  constant ApplyPlanningDebugPrompt (line 1152) | ApplyPlanningDebugPrompt = SharedPlanningDebugPrompt + `The _apply.sh sc...
  constant ExitCodePrompt (line 1163) | ExitCodePrompt = `
  constant ApplyScriptStartupLogic (line 1167) | ApplyScriptStartupLogic = `

FILE: app/server/model/prompts/architect_context.go
  function GetArchitectContextSummary (line 5) | func GetArchitectContextSummary(tokenLimit int) string {
  function GetAutoContextTellPrompt (line 119) | func GetAutoContextTellPrompt(params CreatePromptParams) string {
  function GetAutoContextChatPrompt (line 168) | func GetAutoContextChatPrompt(params CreatePromptParams) string {
  function GetAutoContextShared (line 202) | func GetAutoContextShared(params CreatePromptParams, tellMode bool) stri...

FILE: app/server/model/prompts/build_helpers.go
  constant ExampleReferences (line 3) | ExampleReferences = `
  constant CommentClassifierPrompt (line 27) | CommentClassifierPrompt = `

FILE: app/server/model/prompts/build_validation_replacements.go
  type ValidationPromptParams (line 11) | type ValidationPromptParams struct
  function GetValidationReplacementsXmlPrompt (line 22) | func GetValidationReplacementsXmlPrompt(params ValidationPromptParams) (...
  function getBuildPromptHead (line 220) | func getBuildPromptHead(filePath string, preBuildStateWithLineNums share...

FILE: app/server/model/prompts/build_whole_file.go
  function GetWholeFilePrompt (line 5) | func GetWholeFilePrompt(filePath string, preBuildStateWithLineNums share...
  constant WholeFilePrompt (line 23) | WholeFilePrompt = `

FILE: app/server/model/prompts/chat.go
  function GetChatSysPrompt (line 3) | func GetChatSysPrompt(params CreatePromptParams) string {

FILE: app/server/model/prompts/code_block_langs.go
  constant ValidLangIdentifiers (line 3) | ValidLangIdentifiers = `

FILE: app/server/model/prompts/describe.go
  constant SysDescribeXml (line 9) | SysDescribeXml = `You are an AI parser. You turn an AI's plan for a prog...
  constant SysDescribe (line 14) | SysDescribe = "You are an AI parser. You turn an AI's plan for a program...
  constant SysPendingResults (line 29) | SysPendingResults = "You are an AI commit message summarizer. You take a...

FILE: app/server/model/prompts/exec_status.go
  constant SysExecStatusFinishedSubtaskXml (line 10) | SysExecStatusFinishedSubtaskXml = `You are tasked with evaluating a resp...
  constant SysExecStatusFinishedSubtask (line 30) | SysExecStatusFinishedSubtask = `You are tasked with evaluating a respons...
  type GetExecStatusFinishedSubtaskParams (line 48) | type GetExecStatusFinishedSubtaskParams struct
  function GetExecStatusFinishedSubtask (line 56) | func GetExecStatusFinishedSubtask(params GetExecStatusFinishedSubtaskPar...

FILE: app/server/model/prompts/explanation_format.go
  constant ChangeExplanationPrompt (line 3) | ChangeExplanationPrompt = `

FILE: app/server/model/prompts/file_ops.go
  constant FileOpsPlanningPrompt (line 3) | FileOpsPlanningPrompt = `
  constant FileOpsImplementationPrompt (line 31) | FileOpsImplementationPrompt = `
  constant FileOpsImplementationPromptSummary (line 122) | FileOpsImplementationPromptSummary = `

FILE: app/server/model/prompts/implement.go
  function GetImplementationPrompt (line 3) | func GetImplementationPrompt(task string) string {
  constant CurrentSubtaskPrompt (line 271) | CurrentSubtaskPrompt = `
  constant MarkSubtaskDonePrompt (line 278) | MarkSubtaskDonePrompt = `

FILE: app/server/model/prompts/missing_file.go
  function GetSkipMissingFilePrompt (line 5) | func GetSkipMissingFilePrompt(path string) string {
  function GetMissingFileContinueGeneratingPrompt (line 9) | func GetMissingFileContinueGeneratingPrompt(path string) string {

FILE: app/server/model/prompts/name.go
  constant SysPlanNameXml (line 8) | SysPlanNameXml = `You are an AI namer that creates a name for the plan. ...
  constant SysPlanName (line 13) | SysPlanName = "You are an AI namer that creates a name for the plan. Mos...
  type PlanNameRes (line 28) | type PlanNameRes struct
  function GetPlanNamePrompt (line 32) | func GetPlanNamePrompt(sysPrompt, text string) string {
  type PipedDataNameRes (line 36) | type PipedDataNameRes struct
  constant SysPipedDataNameXml (line 40) | SysPipedDataNameXml = `You are an AI namer that creates a name for outpu...
  constant SysPipedDataName (line 45) | SysPipedDataName = "You are an AI namer that creates a name for output t...
  function GetPipedDataNamePrompt (line 60) | func GetPipedDataNamePrompt(sysPrompt, text string) string {
  type NoteNameRes (line 64) | type NoteNameRes struct
  constant SysNoteNameXml (line 68) | SysNoteNameXml = `You are an AI namer that creates a name for an arbitra...
  constant SysNoteName (line 73) | SysNoteName = "You are an AI namer that creates a name for an arbitrary ...
  function GetNoteNamePrompt (line 88) | func GetNoteNamePrompt(sysPrompt, text string) string {

FILE: app/server/model/prompts/planning.go
  type CreatePromptParams (line 3) | type CreatePromptParams struct
  function GetPlanningPrompt (line 12) | func GetPlanningPrompt(params CreatePromptParams) string {
  function getUsesPrompt (line 206) | func getUsesPrompt(params CreatePromptParams) string {
  constant SharedPlanningImplementationPrompt (line 254) | SharedPlanningImplementationPrompt = `
  constant ReviseSubtasksPrompt (line 311) | ReviseSubtasksPrompt = `

FILE: app/server/model/prompts/shared.go
  constant Identity (line 3) | Identity = "You are Plandex, an AI programming and system administration...

FILE: app/server/model/prompts/summary.go
  constant PlanSummary (line 3) | PlanSummary = `

FILE: app/server/model/prompts/update_format.go
  constant UpdateFormatPrompt (line 3) | UpdateFormatPrompt = `
  constant UpdateFormatAdditionalExamples (line 854) | UpdateFormatAdditionalExamples = `

FILE: app/server/model/prompts/user_prompt.go
  constant SharedPromptWrapperFormatStr (line 9) | SharedPromptWrapperFormatStr = "# The user's latest prompt:\n```\n%s\n``...
  function GetContextLoadingPromptWrapperFormatStr (line 27) | func GetContextLoadingPromptWrapperFormatStr(params CreatePromptParams) ...
  function GetPlanningPromptWrapperFormatStr (line 34) | func GetPlanningPromptWrapperFormatStr(params CreatePromptParams) string {
  function GetImplementationPromptWrapperFormatStr (line 107) | func GetImplementationPromptWrapperFormatStr(params CreatePromptParams) ...
  type UserPromptParams (line 259) | type UserPromptParams struct
  function GetWrappedPrompt (line 267) | func GetWrappedPrompt(params UserPromptParams) string {
  constant UserContinuePrompt (line 321) | UserContinuePrompt = "Continue the plan according to your instructions f...
  constant AutoContinuePlanningPrompt (line 323) | AutoContinuePlanningPrompt = UserContinuePrompt
  constant AutoContinueImplementationPrompt (line 325) | AutoContinueImplementationPrompt = `Continue the plan from where you lef...
  constant SkippedPathsPrompt (line 341) | SkippedPathsPrompt = "\n\nSome files have been skipped by the user and *...
  constant CombineSubtasksPrompt (line 343) | CombineSubtasksPrompt = `
  type ChatUserPromptParams (line 417) | type ChatUserPromptParams struct
  function GetWrappedChatOnlyPrompt (line 423) | func GetWrappedChatOnlyPrompt(params ChatUserPromptParams) string {
  function GetPlanningFlowControl (line 509) | func GetPlanningFlowControl(params CreatePromptParams) string {

FILE: app/server/model/summarize.go
  type PlanSummaryParams (line 18) | type PlanSummaryParams struct
  function PlanSummary (line 31) | func PlanSummary(clients map[string]ClientInfo, authVars map[string]stri...

FILE: app/server/model/tokens.go
  constant TokensPerMessage (line 14) | TokensPerMessage = 4
  constant TokensPerName (line 17) | TokensPerName = 1
  constant TokensPerRequest (line 20) | TokensPerRequest = 3
  constant TokensPerExtendedPart (line 22) | TokensPerExtendedPart = 6
  function GetMessagesTokenEstimate (line 25) | func GetMessagesTokenEstimate(messages ...types.ExtendedChatMessage) int {

FILE: app/server/notify/errors.go
  type Severity (line 11) | type Severity
  constant SeverityInfo (line 14) | SeverityInfo Severity = iota
  constant SeverityError (line 15) | SeverityError
  function RegisterNotifyErrFn (line 20) | func RegisterNotifyErrFn(fn func(severity Severity, data ...interface{})) {
  function NotifyErr (line 24) | func NotifyErr(severity Severity, data ...interface{}) {

FILE: app/server/routes/routes.go
  type PlandexHandler (line 15) | type PlandexHandler
  type HandlePlandex (line 16) | type HandlePlandex
  function RegisterHandlePlandex (line 20) | func RegisterHandlePlandex(fn HandlePlandex) {
  function EnsureHandlePlandex (line 24) | func EnsureHandlePlandex() {
  function AddHealthRoutes (line 30) | func AddHealthRoutes(r *mux.Router) {
  function AddApiRoutes (line 73) | func AddApiRoutes(r *mux.Router) {
  function AddApiRoutesWithPrefix (line 77) | func AddApiRoutesWithPrefix(r *mux.Router, prefix string) {
  function AddProxyableApiRoutes (line 81) | func AddProxyableApiRoutes(r *mux.Router) {
  function AddProxyableApiRoutesWithPrefix (line 85) | func AddProxyableApiRoutesWithPrefix(r *mux.Router, prefix string) {
  function addApiRoutes (line 89) | func addApiRoutes(r *mux.Router, prefix string) {
  function addProxyableApiRoutes (line 192) | func addProxyableApiRoutes(r *mux.Router, prefix string) {

FILE: app/server/setup/setup.go
  function MustLoadIp (line 20) | func MustLoadIp() {
  function MustInitDb (line 27) | func MustInitDb() {
  function RegisterShutdownHook (line 46) | func RegisterShutdownHook(hook func()) {
  function loggingMiddleware (line 50) | func loggingMiddleware(next http.Handler) http.Handler {
  function StartServer (line 66) | func StartServer(handler http.Handler, configureFn func(handler http.Han...
  function waitForActivePlans (line 187) | func waitForActivePlans() chan struct{} {
  function maxBytesMiddleware (line 206) | func maxBytesMiddleware(next http.Handler, maxBytes int64) http.Handler {

FILE: app/server/syntax/comments.go
  function GetCommentSymbols (line 91) | func GetCommentSymbols(lang shared.Language) (string, string) {

FILE: app/server/syntax/file_map/cli/main.go
  function main (line 14) | func main() {

FILE: app/server/syntax/file_map/examples/c_example.c
  type Person (line 10) | typedef struct {
  type Weekday (line 15) | typedef enum {
  function add (line 42) | int add(int a, int b) {
  function subtract (line 46) | int subtract(int a, int b) {
  function printPerson (line 50) | void printPerson(const Person* p) {
  function factorial (line 54) | int factorial(int n) {
  function main (line 60) | int main() {

FILE: app/server/syntax/file_map/examples/cpp_example.cpp
  type Color (line 13) | enum Color { RED, GREEN, BLUE }
  class Container (line 18) | class Container {
    method add (line 22) | void add(T item) { items.push_back(item); }
  class Animal (line 33) | class Animal {
  class Dog (line 42) | class Dog : virtual public Animal {
    method Dog (line 44) | Dog(const std::string& dogName) { name = dogName; }
    method makeSound (line 45) | void makeSound() const override {
  type Utils (line 51) | namespace Utils {
    function T (line 58) | T max(T a, T b) {
  class Resource (line 69) | class Resource {
    method Resource (line 71) | Resource(const std::string& data) : data_(data) {
    method Resource (line 77) | Resource(Resource&& other) noexcept : data_(std::move(other.data_)) {}
    method getData (line 78) | std::string getData() const { return data_; }
  class Counter (line 84) | class Counter {
    method getCount (line 86) | static int getCount() { return count; }
    method Counter (line 87) | Counter() { ++count; }
  class Box (line 95) | class Box {
    method Box (line 98) | Box(int w, int h) : width(w), height(h) {}
  function main (line 109) | int main() {

FILE: app/server/syntax/file_map/examples/csharp_example.cs
  type IProcessor (line 10) | public interface IProcessor<T>
    method ProcessAsync (line 12) | Task<T> ProcessAsync(T input);
    method Validate (line 13) | bool Validate(T input);
  type Status (line 17) | public enum Status
  class DataProcessor (line 29) | public class DataProcessor<T> : IProcessor<T> where T : class
    method DataProcessor (line 41) | public DataProcessor()
    method ProcessAsync (line 47) | public async Task<T> ProcessAsync(T input)
    method Validate (line 67) | public bool Validate(T input) => input != null;
    method OnStatusChanged (line 70) | protected virtual void OnStatusChanged(Status oldStatus, Status newSta...
    method GetProcessedCount (line 76) | public static int GetProcessedCount<TItem>() where TItem : class
  type Person (line 83) | public record Person(string Name, int Age)
  class StringExtensions (line 90) | public static class StringExtensions
    method WordCount (line 92) | public static int WordCount(this string str)
  class Program (line 99) | public class Program
    method Main (line 101) | public static async Task Main(string[] args)

FILE: app/server/syntax/file_map/examples/elixir_example.ex
  class ExampleApp (line 1) | defmodule ExampleApp
    method validate_email (line 36) | defp validate_email(email) do
    method handle_result (line 41) | def handle_result({:ok, value}), do: "Success: #{value}"
    method handle_result (line 42) | def handle_result({:error, reason}), do: "Error: #{reason}"
    method handle_result (line 43) | def handle_result(_), do: "Unknown result"
    method create_user (line 70) | def create_user(params) do

FILE: app/server/syntax/file_map/examples/go_example.go
  type DataProcessor (line 14) | type DataProcessor interface
  type ValidationError (line 20) | type ValidationError struct
    method Error (line 25) | func (e *ValidationError) Error() string {
  type User (line 30) | type User struct
  constant MaxRetries (line 43) | MaxRetries   = 3
  constant DefaultLimit (line 44) | DefaultLimit = 100
  constant singleLineConst (line 48) | singleLineConst string = "single line const"
  type Result (line 60) | type Result struct
  type UserProcessor (line 67) | type UserProcessor struct
    method Process (line 78) | func (p *UserProcessor) Process(ctx context.Context, data interface{})...
    method Validate (line 91) | func (p *UserProcessor) Validate(data interface{}) bool {
  function NewUserProcessor (line 72) | func NewUserProcessor() *UserProcessor {
  function processUsers (line 97) | func processUsers(ctx context.Context, users <-chan *User) <-chan *Resul...
  function createUser (line 115) | func createUser(name, email string) (user *User, err error) {
  function main (line 135) | func main() {

FILE: app/server/syntax/file_map/examples/java_example.java
  type DataProcessor (line 10) | interface DataProcessor<T extends Comparable<T>> {
    method processAsync (line 11) | CompletableFuture<T> processAsync(T input);
    method validate (line 12) | boolean validate(T input);
  type Status (line 16) | enum Status {
    method Status (line 24) | Status(String code) {
    method getCode (line 28) | public String getCode() {
  class BaseEntity (line 34) | abstract class BaseEntity<ID> {
    method validate (line 39) | public abstract void validate();
  class Example (line 56) | public class Example extends BaseEntity<UUID> implements DataProcessor<S...
    method Example (line 72) | private Example(Builder builder) {
    class Builder (line 79) | public static class Builder {
      method name (line 82) | public Builder name(String name) {
      method build (line 87) | public Example build() {
    method processAsync (line 93) | @Override
    method validate (line 105) | @Override
    method validate (line 111) | @Override
    method sort (line 119) | public <T extends Comparable<? super T>> List<T> sort(Collection<T> it...
    method processItems (line 126) | public void processItems(
    class ProcessingException (line 137) | public static class ProcessingException extends RuntimeException {
      method ProcessingException (line 138) | public ProcessingException(String message) {
    method main (line 144) | public static void main(String[] args) {

FILE: app/server/syntax/file_map/examples/javascript_example.js
  constant MAX_RETRIES (line 6) | const MAX_RETRIES = 3;
  constant DEFAULT_TIMEOUT (line 7) | const DEFAULT_TIMEOUT = 5000;
  class DataProcessor (line 13) | class DataProcessor extends EventEmitter {
    method constructor (line 21) | constructor({ maxRetries = MAX_RETRIES, timeout = DEFAULT_TIMEOUT } = ...
    method processData (line 27) | async processData(data) {
    method #validateAndTransform (line 39) | async #validateAndTransform(data) {
    method iterateCache (line 45) | *iterateCache() {
  function deprecated (line 54) | function deprecated(target, context) {
  method get (line 66) | get(target, prop) {
  class ValidationError (line 97) | class ValidationError extends Error {
    method constructor (line 98) | constructor(message, field) {
  method theme (line 108) | get theme() {
  method theme (line 111) | set theme(value) {

FILE: app/server/syntax/file_map/examples/php_example.php
  type DataProcessor (line 14) | interface DataProcessor
    method process (line 16) | public function process(mixed $data): mixed;
    method validate (line 17) | public function validate(mixed $data): bool;
  type Loggable (line 21) | trait Loggable
    method setLogger (line 25) | public function setLogger(LoggerInterface $logger): void
    method log (line 30) | protected function log(string $message, array $context = []): void
  class Entity (line 37) | abstract class Entity implements JsonSerializable
    method __construct (line 42) | public function __construct()
    method validate (line 47) | abstract public function validate(): bool;
    method jsonSerialize (line 49) | public function jsonSerialize(): mixed
  method label (line 66) | public function label(): string
  class User (line 78) | class User extends Entity implements DataProcessor
    method __construct (line 84) | public function __construct(
    method getInstanceCount (line 94) | public static function getInstanceCount(): int
    method getEmail (line 100) | public function getEmail(): string
    method setEmail (line 106) | public function setEmail(string $email): void
    method __get (line 116) | public function __get(string $name)
    method __set (line 121) | public function __set(string $name, mixed $value): void
    method process (line 127) | public function process(mixed $data): mixed
    method validate (line 143) | public function validate(mixed $data): bool
    method validate (line 149) | public function validate(): bool
    method getMetadataValues (line 155) | public function getMetadataValues(): array
    method jsonSerialize (line 164) | public function jsonSerialize(): mixed
  class ProcessingException (line 177) | class ProcessingException extends Exception
    method __construct (line 179) | public function __construct(
    method getErrorCode (line 188) | public function getErrorCode(): ?string
  method validateUser (line 196) | public function validateUser(User $user): bool

FILE: app/server/syntax/file_map/examples/python_example.py
  class Processable (line 21) | class Processable(Protocol):
    method process (line 22) | def process(self) -> None: ...
    method validate (line 23) | def validate(self) -> bool: ...
  class Status (line 26) | class Status(enum.Enum):
    method __str__ (line 32) | def __str__(self) -> str:
  class UserCredentials (line 37) | class UserCredentials:
  class BaseProcessor (line 43) | class BaseProcessor(ABC, Generic[T]):
    method __init__ (line 44) | def __init__(self) -> None:
    method process_item (line 49) | async def process_item(self, item: T) -> None:
    method processed_count (line 53) | def processed_count(self) -> int:
  function log_execution (line 57) | def log_execution(func: Callable) -> Callable:
  class DataProcessor (line 71) | class DataProcessor(BaseProcessor[UserCredentials], Processable):
    method __init__ (line 75) | def __init__(self, batch_size: Optional[int] = None) -> None:
    method status (line 82) | def status(self) -> Status:
    method status (line 86) | def status(self, value: Status) -> None:
    method __aenter__ (line 92) | async def __aenter__(self) -> DataProcessor:
    method __aexit__ (line 96) | async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
    method process_batch (line 100) | async def process_batch(self) -> AsyncIterator[List[UserCredentials]]:
    method process_item (line 108) | async def process_item(self, item: UserCredentials) -> None:
    method process (line 115) | def process(self) -> None:
    method validate (line 120) | def validate(self) -> bool:
  class ProcessingError (line 124) | class ProcessingError(Exception):
    method __init__ (line 125) | def __init__(self, message: str, item: Any) -> None:
  function main (line 130) | async def main() -> None:

FILE: app/server/syntax/file_map/examples/ruby_example.rb
  type Loggable (line 6) | module Loggable
    function log (line 7) | def log(message)
  type Utils (line 13) | module Utils
    function generate_id (line 15) | def generate_id
  class BaseProcessor (line 22) | class BaseProcessor
    method register (line 31) | def register(processor)
    method initialize (line 40) | def initialize
    method process (line 48) | def process
  class ProcessingError (line 54) | class ProcessingError < StandardError
    method initialize (line 57) | def initialize(message, item)
  function valid? (line 65) | def valid?
  type Status (line 71) | module Status
  class DataProcessor (line 81) | class DataProcessor < BaseProcessor
    method instance_count (line 89) | def self.instance_count
    method initialize (line 93) | def initialize(options = {})
    method add_item (line 101) | def add_item(item:, priority: :normal)
    method validate_item (line 109) | def validate_item(item)
    method with_retry (line 115) | def with_retry
    method process_items (line 127) | def process_items
    method process_item (line 136) | def process_item(item)
  class Configuration (line 144) | class Configuration
    method initialize (line 147) | def initialize
    method [] (line 151) | def [](key)
    method []= (line 155) | def []=(key, value)

FILE: app/server/syntax/file_map/examples/rust_example.rs
  type Result (line 11) | type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send...
  constant MAX_RETRIES (line 14) | const MAX_RETRIES: u32 = 3;
  constant DEFAULT_TIMEOUT (line 15) | const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
  type ProcessError (line 19) | pub enum ProcessError {
  type DataProcessor (line 32) | pub trait DataProcessor<T> {
    method process (line 33) | async fn process(&self, data: T) -> Result<T>;
    method validate (line 34) | fn validate(&self, data: &T) -> bool;
  type ProcessorState (line 39) | pub struct ProcessorState<'a, T> {
  type Status (line 47) | pub enum Status {
  type ItemProcessor (line 55) | pub struct ItemProcessor {
    method process (line 64) | async fn process(&self, data: String) -> Result<String> {
    method validate (line 71) | fn validate(&self, data: &String) -> bool {
  type Config (line 78) | pub struct Config {
  type Storage (line 87) | pub trait Storage {
    method store (line 91) | fn store(&mut self, item: Self::Item) -> std::result::Result<(), Self:...
    method retrieve (line 92) | fn retrieve(&self, id: &str) -> std::result::Result<Option<Self::Item>...
    type Item (line 101) | type Item = Vec<u8>;
    type Error (line 102) | type Error = std::io::Error;
    method store (line 104) | fn store(&mut self, item: Self::Item) -> std::result::Result<(), Self:...
    method retrieve (line 109) | fn retrieve(&self, id: &str) -> std::result::Result<Option<Self::Item>...
  type MemoryStorage (line 96) | pub struct MemoryStorage {
  function main (line 116) | async fn main() -> Result<()> {

FILE: app/server/syntax/file_map/examples/tsx_example.tsx
  type User (line 5) | interface User {
  type ValidationResult (line 12) | type ValidationResult = {
  type DataListProps (line 18) | interface DataListProps<T> {
  function useDebounce (line 25) | function useDebounce<T>(value: T, delay: number): T {
  function withLoading (line 42) | function withLoading<P extends object>(

FILE: app/server/syntax/file_map/examples/typescript_example.ts
  type DataProcessor (line 7) | interface DataProcessor<T> {
  type Result (line 13) | type Result<T> = {
  type Status (line 20) | enum Status {
  type ValidationResult (line 28) | type ValidationResult =
  type AdminUser (line 33) | type AdminUser = User & {
  type Readonly (line 39) | type Readonly<T> = {
  type Partial (line 44) | type Partial<T> = {
  function validate (line 51) | function validate(target: any, propertyKey: string, descriptor: Property...
  class User (line 62) | @logger
    method constructor (line 73) | constructor(name: string, email: string) {
    method updateEmail (line 81) | public updateEmail(newEmail: string): void {
    method isAdmin (line 86) | public get isAdmin(): this is AdminUser {
  method validate (line 98) | validate(data: T): boolean {
  class StringProcessor (line 104) | class StringProcessor extends BaseProcessor<string> {
    method process (line 105) | async process(data: string): Promise<string> {
    method transform (line 112) | private async transform(data: string): Promise<string> {
  function process (line 120) | function process(data: string | number): Promise<string | number> {
  function validateData (line 125) | async function validateData<T extends { id: string }>(
  function withRetry (line 135) | function withRetry<T>(
  type Middleware (line 155) | type Middleware = (
  function main (line 178) | async function main() {
  constant SOME_CONST (line 202) | const SOME_CONST: number = 123;
  constant SOME_LET (line 204) | let SOME_LET: boolean = true;
  type SOME_TYPE (line 205) | type SOME_TYPE = string;
  type SOME_INTERFACE (line 206) | interface SOME_INTERFACE {
  class SOME_CLASS (line 209) | class SOME_CLASS {
    method constructor (line 210) | constructor(public name: string) { }
  function fn (line 213) | function fn() {
  function asyncFn (line 217) | async function asyncFn() {
  type Enum (line 221) | enum Enum {
  function makeId (line 232) | function makeId<T = string>() { return '' as T }
  class DefaultCls (line 233) | class DefaultCls { }
  type Flags (line 241) | const enum Flags { None = 0, Read = 1 }
  type Ambient (line 242) | enum Ambient { X }
  function greet (line 245) | function greet() { }
  class C (line 257) | class C {
    method inc (line 259) | static get inc() { return ++this.value }
  class Modern (line 263) | class Modern {
  type Route (line 268) | type Route<T extends string> = `/api/${T}`
  type Flatten (line 269) | type Flatten<T> = T extends (infer U)[] ? U : T
  type Window (line 273) | interface Window { myLib: unknown }

FILE: app/server/syntax/file_map/map.go
  type FileMap (line 18) | type FileMap struct
    method String (line 414) | func (m *FileMap) String() string {
  type Definition (line 22) | type Definition struct
  type Node (line 32) | type Node struct
  function MapFile (line 39) | func MapFile(ctx context.Context, filename string, content []byte) (*Fil...
  function mapNode (line 135) | func mapNode(node *tree_sitter.Node, content []byte, lang shared.Languag...
  function mapTraditional (line 151) | func mapTraditional(baseNode Node, parentNode *Node) []Definition {
  function mapMarkdownSimple (line 465) | func mapMarkdownSimple(content []byte) []Definition {

FILE: app/server/syntax/file_map/markup.go
  function mapMarkup (line 11) | func mapMarkup(content []byte) []Definition {
  function areMarkupDefinitionsEqual (line 69) | func areMarkupDefinitionsEqual(a, b Definition) bool {
  function consolidateRepeatedTags (line 85) | func consolidateRepeatedTags(defs []Definition) []Definition {
  function isSignificantTag (line 155) | func isSignificantTag(tag string) bool {

FILE: app/server/syntax/file_map/multi.go
  function ProcessMapFiles (line 21) | func ProcessMapFiles(ctx context.Context, inputs map[string]string) (sha...
  type MapTrees (line 77) | type MapTrees
    method CombinedTrees (line 127) | func (m MapTrees) CombinedTrees() string {
  function ProcessMapTrees (line 79) | func ProcessMapTrees(ctx context.Context, inputs map[string]string) (Map...

FILE: app/server/syntax/file_map/nodes_config.go
  type nodeType (line 5) | type nodeType
  type matchType (line 7) | type matchType
  constant matchTypeEqual (line 10) | matchTypeEqual  matchType = "equal"
  constant matchTypePrefix (line 11) | matchTypePrefix matchType = "prefix"
  constant matchTypeSuffix (line 12) | matchTypeSuffix matchType = "suffix"
  type langSet (line 15) | type langSet
  type nodeConfig (line 17) | type nodeConfig struct
  type nodeMap (line 27) | type nodeMap

FILE: app/server/syntax/file_map/nodes_find.go
  function isDefinitionNode (line 10) | func isDefinitionNode(node Node, parentNode *Node) bool {
  function isAssignmentNode (line 39) | func isAssignmentNode(node Node) bool {
  function isParentNode (line 48) | func isParentNode(node Node) bool {
  function isImplBoundaryNode (line 57) | func isImplBoundaryNode(node Node) bool {
  function isAssignmentBoundaryNode (line 66) | func isAssignmentBoundaryNode(node Node) bool {
  function isIdentifierNode (line 75) | func isIdentifierNode(node Node) bool {
  function isPassThroughParentNode (line 84) | func isPassThroughParentNode(node Node) bool {
  function isIncludeAndContinueNode (line 93) | func isIncludeAndContinueNode(node Node) bool {
  method getConfig (line 102) | func (m nodeMap) getConfig(t string, lang shared.Language) *nodeConfig {
  function findImplementationBoundary (line 153) | func findImplementationBoundary(node Node) *Node {
  function findIdentifier (line 184) | func findIdentifier(node Node) []Node {
  function firstDefinitionChild (line 211) | func firstDefinitionChild(node Node) *Node {
  function findAssignmentBoundary (line 233) | func findAssignmentBoundary(node Node) *Node {
  function findAssignmentBoundaryOnly (line 237) | func findAssignmentBoundaryOnly(node Node, only map[nodeType]bool) *Node {
  function skipForwardIfNeeded (line 268) | func skipForwardIfNeeded(node Node) *Node {
  function setNodeType (line 295) | func setNodeType(node *Node) {

FILE: app/server/syntax/file_map/svelte.go
  function mapSvelte (line 16) | func mapSvelte(content []byte) []Definition {
  function getSvelteScriptAndStyle (line 74) | func getSvelteScriptAndStyle(content []byte) (scriptContent, scriptLang,...

FILE: app/server/syntax/parsers.go
  function GetLanguageForPath (line 42) | func GetLanguageForPath(path string) shared.Language {
  function GetParserForPath (line 74) | func GetParserForPath(path string) (*tree_sitter.Parser, shared.Language...
  function GetParserForLanguage (line 92) | func GetParserForLanguage(lang shared.Language) *tree_sitter.Parser {

FILE: app/server/syntax/structured_edits_apply.go
  type Reference (line 19) | type Reference
  type Removal (line 20) | type Removal
  type Anchor (line 22) | type Anchor
  type NeedsVerifyReason (line 24) | type NeedsVerifyReason
  constant NeedsVerifyReasonCodeRemoved (line 27) | NeedsVerifyReasonCodeRemoved       NeedsVerifyReason = "code_removed"
  constant NeedsVerifyReasonCodeDuplicated (line 28) | NeedsVerifyReasonCodeDuplicated    NeedsVerifyReason = "code_duplicated"
  constant NeedsVerifyReasonAmbiguousLocation (line 29) | NeedsVerifyReasonAmbiguousLocation NeedsVerifyReason = "ambiguous_location"
  type ApplyChangesResult (line 32) | type ApplyChangesResult struct
  type ReferenceBlock (line 46) | type ReferenceBlock struct
  type Comment (line 51) | type Comment struct
  type RemovalRange (line 56) | type RemovalRange struct
    method Overlaps (line 61) | func (r RemovalRange) Overlaps(other RemovalRange) bool {
  constant verboseLogging (line 67) | verboseLogging = false
  function isRef (line 69) | func isRef(content string) bool {
  function isRemoval (line 78) | func isRemoval(content string) bool {
  type ApplyChangesParams (line 82) | type ApplyChangesParams struct
  function ApplyChanges (line 91) | func ApplyChanges(

FILE: app/server/syntax/structured_edits_generic.go
  type execApplyGenericParams (line 11) | type execApplyGenericParams struct
  function ExecApplyGeneric (line 22) | func ExecApplyGeneric(
  function buildAnchorMap (line 464) | func buildAnchorMap(

FILE: app/server/syntax/structured_edits_sections.go
  type TreeSitterSection (line 12) | type TreeSitterSection
    method String (line 296) | func (s TreeSitterSection) String(sourceLines []string, bytes []byte) ...
  type NodeIndex (line 14) | type NodeIndex struct
  function getSections (line 19) | func getSections(parent *tree_sitter.Node, bytes []byte, numSections, fr...
  function isStructuralNode (line 185) | func isStructuralNode(node *tree_sitter.Node) bool {
  function BuildNodeIndex (line 212) | func BuildNodeIndex(tree *tree_sitter.Tree) *NodeIndex {
  function getNodeDepth (line 286) | func getNodeDepth(node *tree_sitter.Node) int {

FILE: app/server/syntax/structured_edits_test.go
  function TestStructuredReplacements (line 12) | func TestStructuredReplacements(t *testing.T) {

FILE: app/server/syntax/structured_edits_tree_sitter.go
  type tsAnchor (line 13) | type tsAnchor struct
  type execApplyTreeSitterParams (line 18) | type execApplyTreeSitterParams struct
  function ExecApplyTreeSitter (line 29) | func ExecApplyTreeSitter(

FILE: app/server/syntax/unique_replacement.go
  function FindUniqueReplacement (line 5) | func FindUniqueReplacement(originalFile, old string) string {

FILE: app/server/syntax/unique_replacement_test.go
  function TestFindUniqueReplacement (line 7) | func TestFindUniqueReplacement(t *testing.T) {

FILE: app/server/syntax/validate.go
  constant parserTimeout (line 15) | parserTimeout = 500 * time.Millisecond
  function ValidateFile (line 25) | func ValidateFile(ctx context.Context, path string, file string) (*Valid...
  function ValidateWithParsers (line 35) | func ValidateWithParsers(ctx context.Context, lang shared.Language, pars...
  function insertErrorMarkers (line 93) | func insertErrorMarkers(source string, node *tree_sitter.Node) []string {
  function visitNodes (line 139) | func visitNodes(n *tree_sitter.Node, f func(node *tree_sitter.Node)) {

FILE: app/server/types/active_plan.go
  constant MaxStreamRate (line 21) | MaxStreamRate = 70 * time.Millisecond
  constant ActivePlanTimeout (line 22) | ActivePlanTimeout = 2 * time.Hour
  type ActiveBuild (line 24) | type ActiveBuild struct
    method BuildFinished (line 386) | func (b *ActiveBuild) BuildFinished() bool {
    method IsFileOperation (line 444) | func (ab *ActiveBuild) IsFileOperation() bool {
  type subscription (line 39) | type subscription struct
    method processMessages (line 404) | func (sub *subscription) processMessages() {
    method enqueueMessage (line 430) | func (sub *subscription) enqueueMessage(msg string) {
  type ActivePlan (line 48) | type ActivePlan struct
    method FlushStreamBuffer (line 161) | func (ap *ActivePlan) FlushStreamBuffer() {
    method Stream (line 186) | func (ap *ActivePlan) Stream(msg shared.StreamMessage) {
    method ResetModelCtx (line 313) | func (ap *ActivePlan) ResetModelCtx() {
    method BuildFinished (line 317) | func (ap *ActivePlan) BuildFinished() bool {
    method PathQueueEmpty (line 327) | func (ap *ActivePlan) PathQueueEmpty(path string) bool {
    method Subscribe (line 339) | func (ap *ActivePlan) Subscribe(reqCtx context.Context) (string, chan ...
    method Unsubscribe (line 367) | func (ap *ActivePlan) Unsubscribe(id string) {
    method NumSubscribers (line 380) | func (ap *ActivePlan) NumSubscribers() int {
    method Finish (line 438) | func (ap *ActivePlan) Finish() {
  function NewActivePlan (line 95) | func NewActivePlan(orgId, userId, planId, branch, prompt string, buildOn...
  constant verboseStreamLogging (line 184) | verboseStreamLogging = false
  function newSubscription (line 390) | func newSubscription(ctx context.Context) *subscription {

FILE: app/server/types/active_plan_pending_builds.go
  method PendingBuildsByPath (line 11) | func (ap *ActivePlan) PendingBuildsByPath(orgId, userId string, convoMes...

FILE: app/server/types/auth.go
  type ServerAuth (line 9) | type ServerAuth struct
    method HasPermission (line 16) | func (a *ServerAuth) HasPermission(permission shared.Permission) bool {
    method HasPermissionForResource (line 20) | func (a *ServerAuth) HasPermissionForResource(permission shared.Permis...

FILE: app/server/types/convo_message_desc.go
  function HasPendingBuilds (line 9) | func HasPendingBuilds(planDescs []*db.ConvoMessageDescription) bool {

FILE: app/server/types/exec_status.go
  type ExecStatusResponse (line 3) | type ExecStatusResponse struct

FILE: app/server/types/message.go
  type CacheControlType (line 12) | type CacheControlType
  constant CacheControlTypeEphemeral (line 15) | CacheControlTypeEphemeral CacheControlType = "ephemeral"
  type CacheControlSpec (line 18) | type CacheControlSpec struct
  type ExtendedChatMessagePart (line 22) | type ExtendedChatMessagePart struct
  type ExtendedChatMessage (line 29) | type ExtendedChatMessage struct
    method ToOpenAI (line 34) | func (msg *ExtendedChatMessage) ToOpenAI() *openai.ChatCompletionMessa...
  type OpenAIPrediction (line 59) | type OpenAIPrediction struct
  type ReasoningConfig (line 64) | type ReasoningConfig struct
  type OpenRouterProviderConfig (line 70) | type OpenRouterProviderConfig struct
  type ExtendedChatCompletionRequest (line 79) | type ExtendedChatCompletionRequest struct
    method ToOpenAI (line 169) | func (req *ExtendedChatCompletionRequest) ToOpenAI() *ExtendedOpenAICh...
  type ExtendedOpenAIChatCompletionRequest (line 162) | type ExtendedOpenAIChatCompletionRequest struct
  type ExtendedChatCompletionStreamChoiceDelta (line 213) | type ExtendedChatCompletionStreamChoiceDelta struct
  type ExtendedChatCompletionStreamChoice (line 222) | type ExtendedChatCompletionStreamChoice struct
  type ExtendedChatCompletionStreamError (line 230) | type ExtendedChatCompletionStreamError struct
  type ExtendedChatCompletionStreamResponse (line 239) | type ExtendedChatCompletionStreamResponse struct
  type ModelResponse (line 256) | type ModelResponse struct
  type StreamCompletionAccumulator (line 266) | type StreamCompletionAccumulator struct
    method AddContent (line 282) | func (a *StreamCompletionAccumulator) AddContent(content string) {
    method SetUsage (line 287) | func (a *StreamCompletionAccumulator) SetUsage(usage *openai.Usage) {
    method SetGenerationId (line 291) | func (a *StreamCompletionAccumulator) SetGenerationId(generationId str...
    method SetFirstTokenAt (line 295) | func (a *StreamCompletionAccumulator) SetFirstTokenAt(firstTokenAt tim...
    method Content (line 299) | func (a *StreamCompletionAccumulator) Content() string {
    method Result (line 304) | func (a *StreamCompletionAccumulator) Result(stopped bool, err error) ...
  function NewStreamCompletionAccumulator (line 274) | func NewStreamCompletionAccumulator() *StreamCompletionAccumulator {

FILE: app/server/types/model.go
  type ChangesWithLineNums (line 7) | type ChangesWithLineNums struct

FILE: app/server/types/reply.go
  constant verboseLogging (line 13) | verboseLogging = false
  type ReplyParserRes (line 15) | type ReplyParserRes struct
    method FileOperationBlockOpen (line 385) | func (r *ReplyParserRes) FileOperationBlockOpen() bool {
  type ReplyParser (line 25) | type ReplyParser struct
    method AddChunk (line 54) | func (r *ReplyParser) AddChunk(chunk string, addToTotal bool) {
    method Read (line 322) | func (r *ReplyParser) Read() ReplyParserRes {
    method FinishAndRead (line 334) | func (r *ReplyParser) FinishAndRead() ReplyParserRes {
    method GetReplyBeforeCurrentPath (line 339) | func (r *ReplyParser) GetReplyBeforeCurrentPath() string {
    method GetReplyBeforePath (line 343) | func (r *ReplyParser) GetReplyBeforePath(path string) string {
    method GetReplyForMissingFile (line 360) | func (r *ReplyParser) GetReplyForMissingFile() string {
  function NewReplyParser (line 43) | func NewReplyParser() *ReplyParser {
  function LineHasXmlPath (line 389) | func LineHasXmlPath(line string) bool {
  function LineMaybeHasFilePath (line 393) | func LineMaybeHasFilePath(line string) bool {
  function extractFilePath (line 412) | func extractFilePath(line string) string {
  function extractMoveFile (line 458) | func extractMoveFile(line string) *shared.Operation {
  function extractRemoveOrResetFile (line 487) | func extractRemoveOrResetFile(opType shared.OperationType, line string) ...

FILE: app/server/types/reply_test.go
  type TestExample (line 12) | type TestExample struct
  function TestReplyParser (line 148) | func TestReplyParser(t *testing.T) {

FILE: app/server/types/safe_map.go
  type SafeMap (line 5) | type SafeMap struct
  function NewSafeMap (line 10) | func NewSafeMap[V any]() *SafeMap[V] {
  method Get (line 14) | func (sm *SafeMap[V]) Get(key string) V {
  method Set (line 20) | func (sm *SafeMap[V]) Set(key string, value V) {
  method Delete (line 26) | func (sm *SafeMap[V]) Delete(key string) {
  method Update (line 32) | func (sm *SafeMap[V]) Update(key string, fn func(V)) {
  method Items (line 41) | func (sm *SafeMap[V]) Items() map[string]V {
  method Keys (line 47) | func (sm *SafeMap[V]) Keys() []string {
  method Len (line 59) | func (sm *SafeMap[V]) Len() int {

FILE: app/server/types/trial.go
  constant TrialMaxReplies (line 3) | TrialMaxReplies = 20
  constant TrialMaxPlans (line 4) | TrialMaxPlans = 10

FILE: app/server/utils/whitespace.go
  function StripAddedBlankLines (line 5) | func StripAddedBlankLines(orig, upd string) string {

FILE: app/server/utils/whitespace_test.go
  function TestStripAddedBlankLines (line 5) | func TestStripAddedBlankLines(t *testing.T) {

FILE: app/server/utils/xml.go
  function EscapeInvalidXMLAttributeCharacters (line 8) | func EscapeInvalidXMLAttributeCharacters(xmlString string) string {
  function EscapeCdata (line 27) | func EscapeCdata(xmlString string) string {
  function UnescapeCdata (line 32) | func UnescapeCdata(xmlString string) string {
  function StripCdata (line 37) | func StripCdata(xmlString, tagName string) string {
  function WrapCdata (line 45) | func WrapCdata(xmlString, tagName string) string {
  function GetXMLTag (line 56) | func GetXMLTag(xmlString, tagName string, wrapCdata bool) string {
  function GetXMLContent (line 82) | func GetXMLContent(xmlString, tagName string) string {
  function GetAllXMLContent (line 104) | func GetAllXMLContent(xmlString, tagName string) []string {

FILE: app/shared/ai_models_available.go
  function init (line 597) | func init() {
  function GetAvailableModel (line 719) | func GetAvailableModel(provider ModelProvider, modelId ModelId) *Availab...

FILE: app/shared/ai_models_compatibility.go
  function FilterBuiltInCompatibleModels (line 19) | func FilterBuiltInCompatibleModels(models []*BaseModelConfigSchema, role...
  function FilterCustomCompatibleModels (line 32) | func FilterCustomCompatibleModels(models []*CustomModel, role ModelRole)...

FILE: app/shared/ai_models_credentials.go
  type ModelProviderOption (line 3) | type ModelProviderOption struct
  type ModelProviderOptions (line 9) | type ModelProviderOptions
    method Condense (line 93) | func (m ModelProviderOptions) Condense(opts ...ModelProviderOptions) M...
  method GetModelProviderOptions (line 11) | func (m ModelRoleConfig) GetModelProviderOptions(settings *PlanSettings)...
  function copyPublishersMap (line 123) | func copyPublishersMap(src map[ModelPublisher]bool) map[ModelPublisher]b...

FILE: app/shared/ai_models_custom.go
  type SchemaUrl (line 15) | type SchemaUrl
  constant SchemaUrlInputConfig (line 18) | SchemaUrlInputConfig     SchemaUrl = "https://plandex.ai/schemas/models-...
  constant SchemaUrlPlanConfig (line 19) | SchemaUrlPlanConfig      SchemaUrl = "https://plandex.ai/schemas/plan-co...
  constant SchemaUrlInlineModelPack (line 20) | SchemaUrlInlineModelPack SchemaUrl = "https://plandex.ai/schemas/model-p...
  type CustomModel (line 25) | type CustomModel struct
    method ToBaseModelConfig (line 275) | func (input *CustomModel) ToBaseModelConfig(authVars map[string]string...
    method ToBaseModelConfigForProvider (line 286) | func (input *CustomModel) ToBaseModelConfigForProvider(authVars map[st...
  type CustomProvider (line 39) | type CustomProvider struct
    method ToModelProviderConfigSchema (line 263) | func (cp *CustomProvider) ToModelProviderConfigSchema() ModelProviderC...
  type ModelsInput (line 57) | type ModelsInput struct
    method FilterUnchanged (line 63) | func (input ModelsInput) FilterUnchanged(existing *ModelsInput) Models...
    method Equals (line 100) | func (input ModelsInput) Equals(other ModelsInput) bool {
    method CheckNoDuplicates (line 107) | func (input ModelsInput) CheckNoDuplicates() (bool, string) {
    method IsEmpty (line 140) | func (input ModelsInput) IsEmpty() bool {
    method Hash (line 181) | func (input ModelsInput) Hash() (string, error) {
    method ToClientModelsInput (line 249) | func (input ModelsInput) ToClientModelsInput() ClientModelsInput {
  function modelsEqual (line 144) | func modelsEqual(a, b *CustomModel) bool {
  function providersEqual (line 152) | func providersEqual(a, b *CustomProvider) bool {
  function packsEqual (line 161) | func packsEqual(a, b *ModelPackSchema) bool {
  method Equals (line 170) | func (s *ModelPackSchema) Equals(other *ModelPackSchema) bool {
  method Equals (line 174) | func (mp *ModelPack) Equals(other *ModelPack) bool {
  type ClientModelPackSchema (line 191) | type ClientModelPackSchema struct
    method ToModelPackSchema (line 198) | func (input *ClientModelPackSchema) ToModelPackSchema() *ModelPackSche...
  method ToClientModelPackSchema (line 206) | func (input *ModelPackSchema) ToClientModelPackSchema() *ClientModelPack...
  type ClientModelsInput (line 214) | type ClientModelsInput struct
    method ToModelsInput (line 222) | func (input ClientModelsInput) ToModelsInput() ModelsInput {
    method PrepareUpdate (line 235) | func (input *ClientModelsInput) PrepareUpdate() {

FILE: app/shared/ai_models_data_models.go
  type ModelCompatibility (line 14) | type ModelCompatibility struct
  type ModelOutputFormat (line 18) | type ModelOutputFormat
  constant ModelOutputFormatToolCallJson (line 21) | ModelOutputFormatToolCallJson ModelOutputFormat = "tool-call-json"
  constant ModelOutputFormatXml (line 22) | ModelOutputFormatXml          ModelOutputFormat = "xml"
  type ModelName (line 26) | type ModelName
  type ModelId (line 27) | type ModelId
  type ModelTag (line 28) | type ModelTag
  type VariantTag (line 29) | type VariantTag
  type BaseModelShared (line 31) | type BaseModelShared struct
  type BaseModelProviderConfig (line 52) | type BaseModelProviderConfig struct
  type BaseModelConfig (line 57) | type BaseModelConfig struct
  type BaseModelUsesProvider (line 65) | type BaseModelUsesProvider struct
    method ToComposite (line 71) | func (b BaseModelUsesProvider) ToComposite() string {
  type BaseModelConfigSchema (line 78) | type BaseModelConfigSchema struct
    method IsLocalOnly (line 102) | func (b *BaseModelConfigSchema) IsLocalOnly() bool {
    method ToAvailableModels (line 122) | func (b *BaseModelConfigSchema) ToAvailableModels() []*AvailableModel {
  type BaseModelConfigVariant (line 92) | type BaseModelConfigVariant struct
  type AvailableModel (line 256) | type AvailableModel struct
    method ModelString (line 265) | func (m *AvailableModel) ModelString() string {
  type PlannerModelConfig (line 274) | type PlannerModelConfig struct
  type ReasoningEffort (line 278) | type ReasoningEffort
  constant ReasoningEffortLow (line 281) | ReasoningEffortLow    ReasoningEffort = "low"
  constant ReasoningEffortMedium (line 282) | ReasoningEffortMedium ReasoningEffort = "medium"
  constant ReasoningEffortHigh (line 283) | ReasoningEffortHigh   ReasoningEffort = "high"
  type ModelRoleConfig (line 286) | type ModelRoleConfig struct
    method ToModelRoleConfigSchema (line 515) | func (m *ModelRoleConfig) ToModelRoleConfigSchema() ModelRoleConfigSch...
    method GetModelId (line 578) | func (m ModelRoleConfig) GetModelId() ModelId {
    method GetBaseModelConfig (line 586) | func (m ModelRoleConfig) GetBaseModelConfig(authVars map[string]string...
    method GetBaseModelConfigForProvider (line 595) | func (m ModelRoleConfig) GetBaseModelConfigForProvider(authVars map[st...
    method GetProviderComposite (line 618) | func (m ModelRoleConfig) GetProviderComposite(authVars map[string]stri...
    method GetReservedOutputTokens (line 628) | func (m ModelRoleConfig) GetReservedOutputTokens(customModelsById map[...
    method GetSharedBaseConfig (line 637) | func (m ModelRoleConfig) GetSharedBaseConfig(settings *PlanSettings) *...
    method GetSharedBaseConfigWithCustomModels (line 641) | func (m ModelRoleConfig) GetSharedBaseConfigWithCustomModels(customMod...
    method Scan (line 659) | func (m *ModelRoleConfig) Scan(src interface{}) error {
    method Value (line 673) | func (m ModelRoleConfig) Value() (driver.Value, error) {
  type ModelRoleModelConfig (line 305) | type ModelRoleModelConfig struct
  type ModelRoleConfigSchema (line 311) | type ModelRoleConfigSchema struct
    method ToClientVal (line 329) | func (m *ModelRoleConfigSchema) ToClientVal() RoleJSON {
    method bareRole (line 373) | func (m *ModelRoleConfigSchema) bareRole() bool {
    method AllModelIds (line 403) | func (m *ModelRoleConfigSchema) AllModelIds() []ModelId {
    method ToModelRoleConfig (line 429) | func (m *ModelRoleConfigSchema) ToModelRoleConfig(role ModelRole) Mode...
    method toModelRoleConfig (line 433) | func (m *ModelRoleConfigSchema) toModelRoleConfig(role ModelRole) Mode...
    method MarshalJSON (line 488) | func (m *ModelRoleConfigSchema) MarshalJSON() ([]byte, error) {
    method UnmarshalJSON (line 503) | func (m *ModelRoleConfigSchema) UnmarshalJSON(data []byte) error {
  type PlannerRoleConfig (line 677) | type PlannerRoleConfig struct
    method ToModelRoleConfigSchema (line 566) | func (p PlannerRoleConfig) ToModelRoleConfigSchema() ModelRoleConfigSc...
    method Scan (line 682) | func (p *PlannerRoleConfig) Scan(src interface{}) error {
    method Value (line 696) | func (p PlannerRoleConfig) Value() (driver.Value, error) {
    method GetMaxConvoTokens (line 700) | func (p PlannerRoleConfig) GetMaxConvoTokens(settings *PlanSettings) i...
  type RoleJSON (line 708) | type RoleJSON
  type ClientModelPackSchemaRoles (line 710) | type ClientModelPackSchemaRoles struct
    method ToModelPackSchemaRoles (line 727) | func (c *ClientModelPackSchemaRoles) ToModelPackSchemaRoles() ModelPac...
  type ModelPackSchemaRoles (line 797) | type ModelPackSchemaRoles struct
    method ToClientModelPackSchemaRoles (line 810) | func (m *ModelPackSchemaRoles) ToClientModelPackSchemaRoles() ClientMo...
    method Hash (line 992) | func (m ModelPackSchemaRoles) Hash() (string, error) {
  type ModelPackSchema (line 838) | type ModelPackSchema struct
    method AllModelIds (line 845) | func (m *ModelPackSchema) AllModelIds() []ModelId {
    method ToModelPack (line 872) | func (m *ModelPackSchema) ToModelPack() ModelPack {
  type ModelPack (line 920) | type ModelPack struct
    method GetCoder (line 936) | func (m *ModelPack) GetCoder() ModelRoleConfig {
    method GetWholeFileBuilder (line 943) | func (m *ModelPack) GetWholeFileBuilder() ModelRoleConfig {
    method GetArchitect (line 950) | func (m *ModelPack) GetArchitect() ModelRoleConfig {
    method ToModelPackSchema (line 957) | func (m *ModelPack) ToModelPackSchema() *ModelPackSchema {

FILE: app/shared/ai_models_errors.go
  type ModelErrKind (line 10) | type ModelErrKind
  constant ErrOverloaded (line 13) | ErrOverloaded                 ModelErrKind = "ErrOverloaded"
  constant ErrContextTooLong (line 14) | ErrContextTooLong             ModelErrKind = "ErrContextTooLong"
  constant ErrRateLimited (line 15) | ErrRateLimited                ModelErrKind = "ErrRateLimited"
  constant ErrSubscriptionQuotaExhausted (line 16) | ErrSubscriptionQuotaExhausted ModelErrKind = "ErrSubscriptionQuotaExhaus...
  constant ErrOther (line 17) | ErrOther                      ModelErrKind = "ErrOther"
  constant ErrCacheSupport (line 18) | ErrCacheSupport               ModelErrKind = "ErrCacheSupport"
  type ModelError (line 21) | type ModelError struct
    method ShouldIncrementRetry (line 27) | func (m ModelError) ShouldIncrementRetry() bool {
  type FallbackType (line 32) | type FallbackType
  constant FallbackTypeError (line 35) | FallbackTypeError    FallbackType = "error"
  constant FallbackTypeContext (line 36) | FallbackTypeContext  FallbackType = "context"
  constant FallbackTypeProvider (line 37) | FallbackTypeProvider FallbackType = "provider"
  type FallbackResult (line 40) | type FallbackResult struct
  constant MAX_RETRIES_BEFORE_FALLBACK (line 47) | MAX_RETRIES_BEFORE_FALLBACK = 1
  method GetFallbackForModelError (line 49) | func (m *ModelRoleConfig) GetFallbackForModelError(
  method GetProviderFallback (line 111) | func (m ModelRoleConfig) GetProviderFallback(authVars map[string]string,...

FILE: app/shared/ai_models_large_context.go
  constant maxFallbackDepth (line 3) | maxFallbackDepth = 10
  method GetFinalLargeContextFallback (line 5) | func (m ModelRoleConfig) GetFinalLargeContextFallback() ModelRoleConfig {
  method GetFinalLargeOutputFallback (line 24) | func (m ModelRoleConfig) GetFinalLargeOutputFallback() ModelRoleConfig {
  method GetRoleForInputTokens (line 49) | func (m ModelRoleConfig) GetRoleForInputTokens(inputTokens int, settings...
  method GetRoleForOutputTokens (line 78) | func (m ModelRoleConfig) GetRoleForOutputTokens(outputTokens int, settin...

FILE: app/shared/ai_models_openrouter.go
  type OpenRouterFamily (line 3) | type OpenRouterFamily
  constant OpenRouterFamilyAnthropic (line 6) | OpenRouterFamilyAnthropic OpenRouterFamily = "anthropic"
  constant OpenRouterFamilyGoogle (line 7) | OpenRouterFamilyGoogle    OpenRouterFamily = "google"
  constant OpenRouterFamilyOpenAI (line 8) | OpenRouterFamilyOpenAI    OpenRouterFamily = "openai"
  constant OpenRouterFamilyQwen (line 9) | OpenRouterFamilyQwen      OpenRouterFamily = "qwen"
  constant OpenRouterFamilyDeepSeek (line 10) | OpenRouterFamilyDeepSeek  OpenRouterFamily = "deepseek"

FILE: app/shared/ai_models_packs.go
  function getModelRoleConfig (line 47) | func getModelRoleConfig(role ModelRole, modelId ModelId, fns ...func(*Mo...
  function getLargeContextFallback (line 57) | func getLargeContextFallback(role ModelRole, modelId ModelId, fns ...fun...
  function getErrorFallback (line 67) | func getErrorFallback(role ModelRole, modelId ModelId, fns ...func(*Mode...
  function getStrongModelFallback (line 77) | func getStrongModelFallback(role ModelRole, modelId ModelId, fns ...func...
  function init (line 124) | func init() {
  function cloneSchema (line 454) | func cloneSchema(schema ModelPackSchema) ModelPackSchema {

FILE: app/shared/ai_models_providers.go
  constant OpenAIV1BaseUrl (line 7) | OpenAIV1BaseUrl = "https://api.openai.com/v1"
  constant OpenRouterBaseUrl (line 8) | OpenRouterBaseUrl = "https://openrouter.ai/api/v1"
  constant LiteLLMBaseUrl (line 9) | LiteLLMBaseUrl = "http://localhost:4000/v1"
  constant OpenAIEnvVar (line 11) | OpenAIEnvVar = "OPENAI_API_KEY"
  constant OpenRouterApiKeyEnvVar (line 12) | OpenRouterApiKeyEnvVar = "OPENROUTER_API_KEY"
  constant AnthropicApiKeyEnvVar (line 13) | AnthropicApiKeyEnvVar = "ANTHROPIC_API_KEY"
  constant GoogleAIStudioApiKeyEnvVar (line 14) | GoogleAIStudioApiKeyEnvVar = "GEMINI_API_KEY"
  constant AzureOpenAIEnvVar (line 15) | AzureOpenAIEnvVar = "AZURE_OPENAI_API_KEY"
  constant DeepSeekApiKeyEnvVar (line 16) | DeepSeekApiKeyEnvVar = "DEEPSEEK_API_KEY"
  constant PerplexityApiKeyEnvVar (line 17) | PerplexityApiKeyEnvVar = "PERPLEXITY_API_KEY"
  constant AnthropicClaudeMaxTokenEnvVar (line 20) | AnthropicClaudeMaxTokenEnvVar = "ANTHROPIC_CLAUDE_MAX_TOKEN"
  constant AnthropicClaudeMaxBetaHeader (line 21) | AnthropicClaudeMaxBetaHeader = "oauth-2025-04-20"
  constant LiteLLMAnthropicBaseUrl (line 22) | LiteLLMAnthropicBaseUrl = "https://api.anthropic.com"
  type ModelPublisher (line 24) | type ModelPublisher
  constant ModelPublisherOpenAI (line 27) | ModelPublisherOpenAI     ModelPublisher = "OpenAI"
  constant ModelPublisherAnthropic (line 28) | ModelPublisherAnthropic  ModelPublisher = "Anthropic"
  constant ModelPublisherGoogle (line 29) | ModelPublisherGoogle     ModelPublisher = "Google"
  constant ModelPublisherDeepSeek (line 30) | ModelPublisherDeepSeek   ModelPublisher = "DeepSeek"
  constant ModelPublisherPerplexity (line 31) | ModelPublisherPerplexity ModelPublisher = "Perplexity"
  constant ModelPublisherQwen (line 32) | ModelPublisherQwen       ModelPublisher = "Qwen"
  constant ModelPublisherMistral (line 33) | ModelPublisherMistral    ModelPublisher = "Mistral"
  type ModelProvider (line 36) | type ModelProvider
  constant ModelProviderOpenRouter (line 39) | ModelProviderOpenRouter ModelProvider = "openrouter"
  constant ModelProviderOpenAI (line 40) | ModelProviderOpenAI     ModelProvider = "openai"
  constant ModelProviderAnthropic (line 42) | ModelProviderAnthropic          ModelProvider = "anthropic"
  constant ModelProviderAnthropicClaudeMax (line 43) | ModelProviderAnthropicClaudeMax ModelProvider = "anthropic-pro"
  constant ModelProviderGoogleAIStudio (line 44) | ModelProviderGoogleAIStudio     ModelProvider = "google-ai-studio"
  constant ModelProviderGoogleVertex (line 45) | ModelProviderGoogleVertex       ModelProvider = "google-vertex"
  constant ModelProviderAzureOpenAI (line 46) | ModelProviderAzureOpenAI        ModelProvider = "azure-openai"
  constant ModelProviderDeepSeek (line 47) | ModelProviderDeepSeek           ModelProvider = "deepseek"
  constant ModelProviderPerplexity (line 48) | ModelProviderPerplexity         ModelProvider = "perplexity"
  constant ModelProviderAmazonBedrock (line 50) | ModelProviderAmazonBedrock ModelProvider = "aws-bedrock"
  constant ModelProviderOllama (line 52) | ModelProviderOllama ModelProvider = "ollama"
  constant ModelProviderCustom (line 54) | ModelProviderCustom ModelProvider = "custom"
  type ModelProviderExtraAuthVars (line 79) | type ModelProviderExtraAuthVars struct
  type ModelProviderConfigSchema (line 86) | type ModelProviderConfigSchema struct
    method ToComposite (line 105) | func (m *ModelProviderConfigSchema) ToComposite() string {
  constant DefaultAzureApiVersion (line 112) | DefaultAzureApiVersion = "2025-04-01-preview"
  constant AnthropicMaxReasoningBudget (line 113) | AnthropicMaxReasoningBudget = 32000
  constant GoogleMaxReasoningBudget (line 114) | GoogleMaxReasoningBudget = 32000
  function init (line 223) | func init() {
  function GetProvidersForAuthVars (line 229) | func GetProvidersForAuthVars(authVars map[string]string, settings *PlanS...
  function GetProvidersForAuthVarsWithModelId (line 290) | func GetProvidersForAuthVarsWithModelId(authVars map[string]string, sett...
  method GetProvidersForAuthVars (line 337) | func (m ModelRoleConfig) GetProvidersForAuthVars(authVars map[string]str...
  method GetFirstProviderForAuthVars (line 341) | func (m ModelRoleConfig) GetFirstProviderForAuthVars(authVars map[string...

FILE: app/shared/ai_models_roles.go
  type ModelRole (line 3) | type ModelRole
  constant ModelRolePlanner (line 6) | ModelRolePlanner          ModelRole = "planner"
  constant ModelRoleCoder (line 7) | ModelRoleCoder            ModelRole = "coder"
  constant ModelRoleArchitect (line 8) | ModelRoleArchitect        ModelRole = "architect"
  constant ModelRolePlanSummary (line 9) | ModelRolePlanSummary      ModelRole = "summarizer"
  constant ModelRoleBuilder (line 10) | ModelRoleBuilder          ModelRole = "builder"
  constant ModelRoleWholeFileBuilder (line 11) | ModelRoleWholeFileBuilder ModelRole = "whole-file-builder"
  constant ModelRoleName (line 12) | ModelRoleName             ModelRole = "names"
  constant ModelRoleCommitMsg (line 13) | ModelRoleCommitMsg        ModelRole = "commit-messages"
  constant ModelRoleExecStatus (line 14) | ModelRoleExecStatus       ModelRole = "auto-continue"

FILE: app/shared/auth.go
  type AuthHeader (line 11) | type AuthHeader struct
  type ApiErrorType (line 17) | type ApiErrorType
  constant ApiErrorTypeInvalidToken (line 20) | ApiErrorTypeInvalidToken          ApiErrorType = "invalid_token"
  constant ApiErrorTypeAuthOutdated (line 21) | ApiErrorTypeAuthOutdated          ApiErrorType = "auth_outdated"
  constant ApiErrorTypeTrialPlansExceeded (line 22) | ApiErrorTypeTrialPlansExceeded    ApiErrorType = "trial_plans_exceeded"
  constant ApiErrorTypeTrialMessagesExceeded (line 23) | ApiErrorTypeTrialMessagesExceeded ApiErrorType = "trial_messages_exceeded"
  constant ApiErrorTypeTrialActionNotAllowed (line 24) | ApiErrorTypeTrialActionNotAllowed ApiErrorType = "trial_action_not_allowed"
  constant ApiErrorTypeContinueNoMessages (line 26) | ApiErrorTypeContinueNoMessages ApiErrorType = "continue_no_messages"
  constant ApiErrorTypeCloudInsufficientCredits (line 28) | ApiErrorTypeCloudInsufficientCredits ApiErrorType = "cloud_insufficient_...
  constant ApiErrorTypeCloudMonthlyMaxReached (line 29) | ApiErrorTypeCloudMonthlyMaxReached   ApiErrorType = "cloud_monthly_max_r...
  constant ApiErrorTypeCloudSubscriptionPaused (line 30) | ApiErrorTypeCloudSubscriptionPaused  ApiErrorType = "cloud_subscription_...
  constant ApiErrorTypeCloudSubscriptionOverdue (line 31) | ApiErrorTypeCloudSubscriptionOverdue ApiErrorType = "cloud_subscription_...
  constant ApiErrorTypeOther (line 33) | ApiErrorTypeOther ApiErrorType = "other"
  type TrialPlansExceededError (line 36) | type TrialPlansExceededError struct
  type TrialMessagesExceededError (line 40) | type TrialMessagesExceededError struct
  type BillingError (line 44) | type BillingError struct
  type ApiError (line 49) | type ApiError struct
    method Error (line 64) | func (e *ApiError) Error() string {
  type ClientAccount (line 68) | type ClientAccount struct
  type ClientAuth (line 80) | type ClientAuth struct
    method ToHash (line 89) | func (c *ClientAuth) ToHash() string {

FILE: app/shared/context.go
Condensed preview — 656 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,477K chars).
[
  {
    "path": ".dockerignore",
    "chars": 61,
    "preview": "dist-server/\ncli/\nnode_modules/\nplandex-server\nplandex-cloud\n"
  },
  {
    "path": ".gitattributes",
    "chars": 17,
    "preview": "*.sh\t\ttext eol=lf"
  },
  {
    "path": ".github/workflows/docker-publish.yml",
    "chars": 3982,
    "preview": "name: Build and publish Docker Image\n\non:\n  release:\n    types: [created]\n  workflow_dispatch: # enable manual triggerin"
  },
  {
    "path": ".gitignore",
    "chars": 274,
    "preview": ".plandex/\n.plandex-dev/\n.plandex-v2/\n.plandex-dev-v2/\n.envkey\n.env\n.env.*\nplandex\nplandex-dev\nplandex-server\n*.exe\nnode_"
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2025 PlandexAI Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "README.md",
    "chars": 10697,
    "preview": "<h1 align=\"center\">\r\n <a href=\"https://plandex.ai\">\r\n  <picture>\r\n    <source media=\"(prefers-color-scheme: dark)\" srcse"
  },
  {
    "path": "app/.dockerignore",
    "chars": 19,
    "preview": "cli/\nplandex-server"
  },
  {
    "path": "app/.gitignore",
    "chars": 5,
    "preview": ".env\n"
  },
  {
    "path": "app/clear_local.sh",
    "chars": 722,
    "preview": "#!/usr/bin/env bash\n\n# Get the absolute path to the script's directory, regardless of where it's run from\nSCRIPT_DIR=\"$("
  },
  {
    "path": "app/cli/api/clients.go",
    "chars": 3676,
    "preview": "package api\n\nimport (\n\t\"math\"\n\t\"math/rand\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/types\"\n\t\"time\"\n)\n\n"
  },
  {
    "path": "app/cli/api/errors.go",
    "chars": 1531,
    "preview": "package api\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"net/http\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\t\"strings\"\n\n\tshared \"p"
  },
  {
    "path": "app/cli/api/methods.go",
    "chars": 76044,
    "preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"plandex-cli/types\"\n\t\"string"
  },
  {
    "path": "app/cli/api/stream.go",
    "chars": 1987,
    "preview": "package api\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"plandex-cli/types\"\n\t\"time\"\n\n\tshared \"plan"
  },
  {
    "path": "app/cli/auth/account.go",
    "chars": 8160,
    "preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/fatih/color\"\n)\n\nconst AddAccou"
  },
  {
    "path": "app/cli/auth/api.go",
    "chars": 871,
    "preview": "package auth\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"plandex-cli/types\"\n\t\"plandex-cli/version"
  },
  {
    "path": "app/cli/auth/auth.go",
    "chars": 2788,
    "preview": "package auth\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n)\n\n"
  },
  {
    "path": "app/cli/auth/org.go",
    "chars": 3136,
    "preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/term\"\n\t\"strings\"\n\n\tshared \"plandex-shared\"\n)\n\nfunc resolveOrgAuth(orgs []*sh"
  },
  {
    "path": "app/cli/auth/state.go",
    "chars": 1933,
    "preview": "package auth\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/fs\"\n\n\tshared \"plandex-shared\"\n)\n\nvar Current *shared."
  },
  {
    "path": "app/cli/auth/trial.go",
    "chars": 2244,
    "preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/term\"\n\t\"time\"\n)\n\nfunc ConvertTrial() {\n\topenAuthenticatedURL(\"Opening Plande"
  },
  {
    "path": "app/cli/cmd/apply.go",
    "chars": 1596,
    "preview": "package cmd\n\nimport (\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/plan_exec\"\n\t\"plandex-cli/term\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/cmd/archive.go",
    "chars": 1890,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "app/cli/cmd/billing.go",
    "chars": 580,
    "preview": "package cmd\n\nimport (\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\t\"plandex-cli/ui\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar billin"
  },
  {
    "path": "app/cli/cmd/branches.go",
    "chars": 1826,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/format\"\n\t\"plandex-cli/lib\"\n\t\"pla"
  },
  {
    "path": "app/cli/cmd/browser.go",
    "chars": 7147,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"runtime\"\n\t\"syscall\"\n\t\"time\"\n\n\tc"
  },
  {
    "path": "app/cli/cmd/build.go",
    "chars": 2277,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/plan_exec\"\n\t\"plandex-cli/term\"\n\t\"pland"
  },
  {
    "path": "app/cli/cmd/cd.go",
    "chars": 2514,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "app/cli/cmd/chat.go",
    "chars": 1467,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/plan_exec\"\n\t\"plandex-cli/types\"\n\n\tshar"
  },
  {
    "path": "app/cli/cmd/checkout.go",
    "chars": 3771,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "app/cli/cmd/claude_max.go",
    "chars": 1901,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\t\"github.com/fatih/color\"\n\t\"git"
  },
  {
    "path": "app/cli/cmd/clear.go",
    "chars": 1175,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\tshared \"pla"
  },
  {
    "path": "app/cli/cmd/config.go",
    "chars": 1544,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\t\"github.com"
  },
  {
    "path": "app/cli/cmd/connect.go",
    "chars": 1255,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/stream\"\n\tstre"
  },
  {
    "path": "app/cli/cmd/context_show.go",
    "chars": 1615,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"strconv\"\n\n\t\"github.com/s"
  },
  {
    "path": "app/cli/cmd/continue.go",
    "chars": 1991,
    "preview": "package cmd\n\nimport (\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/plan_exec\"\n\t\"plandex-cli/types\"\n\n\tshared \"pla"
  },
  {
    "path": "app/cli/cmd/convo.go",
    "chars": 5011,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"regexp\"\n\t\"s"
  },
  {
    "path": "app/cli/cmd/current.go",
    "chars": 1168,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\tshared \"pla"
  },
  {
    "path": "app/cli/cmd/debug.go",
    "chars": 6628,
    "preview": "package cmd\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/cmd/delete_branch.go",
    "chars": 2452,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "app/cli/cmd/delete_plan.go",
    "chars": 4249,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"path\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\""
  },
  {
    "path": "app/cli/cmd/diffs.go",
    "chars": 7622,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"net\"\n\t\"net/http\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli"
  },
  {
    "path": "app/cli/cmd/invite.go",
    "chars": 2004,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n\n\t\"git"
  },
  {
    "path": "app/cli/cmd/load.go",
    "chars": 1909,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"plandex-cli/types\"\n\n\t\"gi"
  },
  {
    "path": "app/cli/cmd/log.go",
    "chars": 2088,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"time\"\n\n\t\"gi"
  },
  {
    "path": "app/cli/cmd/ls.go",
    "chars": 2653,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/format\"\n\t\"plandex-cli/lib\"\n\t\"pla"
  },
  {
    "path": "app/cli/cmd/model_helpers.go",
    "chars": 2357,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\tshared \"plandex-shared\"\n\n\t\"github.com/fatih/c"
  },
  {
    "path": "app/cli/cmd/model_packs.go",
    "chars": 7687,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n"
  },
  {
    "path": "app/cli/cmd/model_providers.go",
    "chars": 3916,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\ts"
  },
  {
    "path": "app/cli/cmd/models.go",
    "chars": 16863,
    "preview": "package cmd\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-c"
  },
  {
    "path": "app/cli/cmd/new.go",
    "chars": 2781,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"plandex-cl"
  },
  {
    "path": "app/cli/cmd/plan_exec_helpers.go",
    "chars": 7042,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\n\tshared \"plandex-shared\"\n\n\t\"github"
  },
  {
    "path": "app/cli/cmd/plan_start_helpers.go",
    "chars": 7237,
    "preview": "package cmd\n\nimport (\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\tshared \"plandex-shared\"\n\n\t\"github"
  },
  {
    "path": "app/cli/cmd/plans.go",
    "chars": 10101,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"plandex-c"
  },
  {
    "path": "app/cli/cmd/ps.go",
    "chars": 2022,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/format\"\n\t\"plandex-cli/lib\"\n\t\"pla"
  },
  {
    "path": "app/cli/cmd/reject.go",
    "chars": 3532,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"sort\"\n\n\t\"gi"
  },
  {
    "path": "app/cli/cmd/rename.go",
    "chars": 1130,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\t\"github.com"
  },
  {
    "path": "app/cli/cmd/repl.go",
    "chars": 39024,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-c"
  },
  {
    "path": "app/cli/cmd/revoke.go",
    "chars": 2892,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n\n\t\"git"
  },
  {
    "path": "app/cli/cmd/rewind.go",
    "chars": 12836,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/lib\"\n\t\"plandex"
  },
  {
    "path": "app/cli/cmd/rm.go",
    "chars": 2756,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/te"
  },
  {
    "path": "app/cli/cmd/root.go",
    "chars": 2912,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/term\"\n\t\"strings\"\n\n\t\"github.com/fatih/color\"\n\t\"github.com/spf13/cobra\"\n)"
  },
  {
    "path": "app/cli/cmd/set_config.go",
    "chars": 9804,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"slices\"\n\t\"s"
  },
  {
    "path": "app/cli/cmd/set_model.go",
    "chars": 9034,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/lib\"\n\t\"plandex"
  },
  {
    "path": "app/cli/cmd/sign_in.go",
    "chars": 699,
    "preview": "package cmd\n\nimport (\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar pin string\n\nvar signInCm"
  },
  {
    "path": "app/cli/cmd/stop.go",
    "chars": 946,
    "preview": "package cmd\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\t"
  },
  {
    "path": "app/cli/cmd/summary.go",
    "chars": 1040,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\n\t\"github.com"
  },
  {
    "path": "app/cli/cmd/tell.go",
    "chars": 6670,
    "preview": "package cmd\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"os/exec\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/plan_e"
  },
  {
    "path": "app/cli/cmd/unarchive.go",
    "chars": 1890,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"strconv\"\n\t\""
  },
  {
    "path": "app/cli/cmd/update.go",
    "chars": 1266,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/t"
  },
  {
    "path": "app/cli/cmd/usage.go",
    "chars": 14465,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\tshared"
  },
  {
    "path": "app/cli/cmd/users.go",
    "chars": 2005,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n"
  },
  {
    "path": "app/cli/cmd/version.go",
    "chars": 372,
    "preview": "package cmd\n\nimport (\n\t\"fmt\"\n\n\t\"plandex-cli/version\"\n\n\t\"github.com/spf13/cobra\"\n)\n\nvar versionCmd = &cobra.Command{\n\tUse"
  },
  {
    "path": "app/cli/dev.sh",
    "chars": 400,
    "preview": "#!/usr/bin/env bash\n\nOUT=\"${PLANDEX_DEV_CLI_OUT_DIR:-/usr/local/bin}\"\nNAME=\"${PLANDEX_DEV_CLI_NAME:-plandex-dev}\"\nALIAS="
  },
  {
    "path": "app/cli/format/file.go",
    "chars": 545,
    "preview": "package format\n\nimport (\n\t\"path/filepath\"\n\t\"strings\"\n)\n\nfunc GetFileNameWithoutExt(path string) string {\n\tname := path[:"
  },
  {
    "path": "app/cli/format/time.go",
    "chars": 3488,
    "preview": "// Adapted from https://raw.githubusercontent.com/dustin/go-humanize/master/times.go\n\npackage format\n\nimport (\n\t\"fmt\"\n\t\""
  },
  {
    "path": "app/cli/fs/fs.go",
    "chars": 2783,
    "preview": "package fs\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"plandex-cli/term\"\n)\n\nvar Cwd string\nvar PlandexDir string\nvar P"
  },
  {
    "path": "app/cli/fs/paths.go",
    "chars": 12169,
    "preview": "package fs\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"plandex-cli/types\"\n\t\"strings\"\n\t\"sync\"\n\n\tshared \"plandex-"
  },
  {
    "path": "app/cli/fs/projects.go",
    "chars": 2760,
    "preview": "package fs\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/term\"\n\t\"plandex-cli/types\"\n"
  },
  {
    "path": "app/cli/fs/utils.go",
    "chars": 279,
    "preview": "package fs\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc FileExists(path string) (bool, error) {\n\t_, err := os.Stat(path)\n\tif err == ni"
  },
  {
    "path": "app/cli/go.mod",
    "chars": 4794,
    "preview": "module plandex-cli\n\ngo 1.23.3\n\nrequire (\n\tgithub.com/aws/aws-sdk-go-v2/config v1.29.14\n\tgithub.com/charmbracelet/lipglos"
  },
  {
    "path": "app/cli/go.sum",
    "chars": 137162,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
  },
  {
    "path": "app/cli/install.sh",
    "chars": 5670,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nSCRIPT_DIR=$( cd -- \"$( dirname -- \"${BASH_SOURCE[0]}\" )\" &> /dev/null && pwd )\n\nPLATFORM=\n"
  },
  {
    "path": "app/cli/lib/active_stream.go",
    "chars": 2796,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n)\n\nfunc SelectActiveStream"
  },
  {
    "path": "app/cli/lib/apply.go",
    "chars": 20275,
    "preview": "package lib\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"plandex-cli/api"
  },
  {
    "path": "app/cli/lib/apply_cgroup_linux.go",
    "chars": 2288,
    "preview": "//go:build linux\n// +build linux\n\npackage lib\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os/exec\"\n\t\"time\"\n\n\tsystemdDbus \"githu"
  },
  {
    "path": "app/cli/lib/apply_cgroup_other.go",
    "chars": 146,
    "preview": "//go:build !linux\n// +build !linux\n\npackage lib\n\nimport \"os/exec\"\n\nfunc MaybeIsolateCgroup(cmd *exec.Cmd) (deleteFn func"
  },
  {
    "path": "app/cli/lib/apply_proc.go",
    "chars": 275,
    "preview": "package lib\n\nimport (\n\t\"os/exec\"\n\t\"syscall\"\n)\n\nfunc SetPlatformSpecificAttrs(cmd *exec.Cmd) {\n\tcmd.SysProcAttr = &syscal"
  },
  {
    "path": "app/cli/lib/build.go",
    "chars": 266,
    "preview": "package lib\n\nimport shared \"plandex-shared\"\n\nvar buildPlanInlineFn func(autoConfirm bool, maybeContexts []*shared.Contex"
  },
  {
    "path": "app/cli/lib/claude_max.go",
    "chars": 9762,
    "preview": "package lib\n\nimport (\n\t\"bytes\"\n\t\"crypto/rand\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/ht"
  },
  {
    "path": "app/cli/lib/context_auto_load.go",
    "chars": 4174,
    "preview": "package lib\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/types\"\n\tshared "
  },
  {
    "path": "app/cli/lib/context_conflict.go",
    "chars": 1123,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\n\t\"github.com/fatih/color\"\n)\n\nfunc checkContex"
  },
  {
    "path": "app/cli/lib/context_display.go",
    "chars": 1033,
    "preview": "package lib\n\nimport shared \"plandex-shared\"\n\nfunc GetContextLabelAndIcon(contextType shared.ContextType) (string, string"
  },
  {
    "path": "app/cli/lib/context_load.go",
    "chars": 21883,
    "preview": "package lib\n\nimport (\n\t\"bufio\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/a"
  },
  {
    "path": "app/cli/lib/context_paths.go",
    "chars": 1590,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/types\"\n)\n\ntype ParseInputPathsParams struct {\n\tFileOrDirPat"
  },
  {
    "path": "app/cli/lib/context_shared.go",
    "chars": 7559,
    "preview": "package lib\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"strings\"\n\t\"sync\"\n\n\tshared"
  },
  {
    "path": "app/cli/lib/context_update.go",
    "chars": 27705,
    "preview": "package lib\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/lib/current.go",
    "chars": 7851,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"pla"
  },
  {
    "path": "app/cli/lib/custom_models.go",
    "chars": 8919,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cl"
  },
  {
    "path": "app/cli/lib/editor.go",
    "chars": 5930,
    "preview": "package lib\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\tshared \"plandex-shared\"\n"
  },
  {
    "path": "app/cli/lib/git.go",
    "chars": 6658,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os/exec\"\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n)\n\nvar gitMutex sync.Mutex\n\nfunc Git"
  },
  {
    "path": "app/cli/lib/legacy_files.go",
    "chars": 4613,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/term\"\n\t\"plandex-cli"
  },
  {
    "path": "app/cli/lib/log_format.go",
    "chars": 3051,
    "preview": "package lib\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n)\n\n// Regular expressions for parsing log entries\nvar (\n\t// Match the"
  },
  {
    "path": "app/cli/lib/model_credentials.go",
    "chars": 17253,
    "preview": "package lib\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\""
  },
  {
    "path": "app/cli/lib/model_settings.go",
    "chars": 7023,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/lib/models_sync.go",
    "chars": 2199,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/term\"\n\n\t\"github.com/fatih/color\"\n)\n\nfunc PromptSyncModels"
  },
  {
    "path": "app/cli/lib/org_user_config.go",
    "chars": 817,
    "preview": "package lib\n\nimport (\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\n\tshared \"plandex-shared\"\n)\n\nvar cachedOrgUserConfig *share"
  },
  {
    "path": "app/cli/lib/plan_config.go",
    "chars": 1770,
    "preview": "package lib\n\nimport (\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\t\"sort\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/oleku"
  },
  {
    "path": "app/cli/lib/plans.go",
    "chars": 5792,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli"
  },
  {
    "path": "app/cli/lib/repl.go",
    "chars": 5113,
    "preview": "package lib\n\nimport (\n\t\"encoding/json\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/te"
  },
  {
    "path": "app/cli/lib/rewind.go",
    "chars": 8400,
    "preview": "package lib\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/fs\"\n\tshared \"plandex-shared\"\n\t\"sort\"\n\t\"sync\"\n\t\"time\"\n)"
  },
  {
    "path": "app/cli/main.go",
    "chars": 2282,
    "preview": "package main\n\nimport (\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/cmd\"\n\t\"plandex"
  },
  {
    "path": "app/cli/nodemon.json",
    "chars": 90,
    "preview": "{\n  \"watch\": [\n    \".\",\n    \"../shared\"\n  ],\n  \"ext\": \"go,mod,sum\",\n  \"exec\": \"./dev.sh\"\n}"
  },
  {
    "path": "app/cli/plan.json",
    "chars": 238,
    "preview": "{\n  \"name\": \"draft\",\n  \"proposalId\": \"\",\n  \"rootId\": \"\",\n  \"createdAt\": \"2023-11-04T09:44:29.147Z\",\n  \"updatedAt\": \"2023"
  },
  {
    "path": "app/cli/plan_exec/action_menu.go",
    "chars": 6569,
    "preview": "package plan_exec\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\tshared \"plandex-shar"
  },
  {
    "path": "app/cli/plan_exec/apply_exec.go",
    "chars": 4448,
    "preview": "package plan_exec\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/plan_exec/build.go",
    "chars": 1894,
    "preview": "package plan_exec\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/stream\"\n\tstreamtui \"plandex"
  },
  {
    "path": "app/cli/plan_exec/params.go",
    "chars": 445,
    "preview": "package plan_exec\n\nimport (\n\t\"plandex-cli/types\"\n\tshared \"plandex-shared\"\n)\n\ntype ExecParams struct {\n\tCurrentPlanId    "
  },
  {
    "path": "app/cli/plan_exec/tell.go",
    "chars": 7472,
    "preview": "package plan_exec\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/auth\"\n\t\"plandex-cli/fs\"\n\t\"plandex-cli/s"
  },
  {
    "path": "app/cli/schema/json-schemas/definitions/auto-modes.schema.json",
    "chars": 301,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/definitions/auto-modes.sc"
  },
  {
    "path": "app/cli/schema/json-schemas/definitions/local-providers.schema.json",
    "chars": 255,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/definitions/local-provide"
  },
  {
    "path": "app/cli/schema/json-schemas/definitions/model-providers.schema.json",
    "chars": 467,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/definitions/model-provide"
  },
  {
    "path": "app/cli/schema/json-schemas/model-config.schema.json",
    "chars": 7823,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-config.schema.json\""
  },
  {
    "path": "app/cli/schema/json-schemas/model-pack-base-config.schema.json",
    "chars": 654,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-pack-base-config.sc"
  },
  {
    "path": "app/cli/schema/json-schemas/model-pack-config.schema.json",
    "chars": 599,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-pack-config.schema."
  },
  {
    "path": "app/cli/schema/json-schemas/model-pack-inline.schema.json",
    "chars": 695,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-pack-inline.schema."
  },
  {
    "path": "app/cli/schema/json-schemas/model-pack-roles.schema.json",
    "chars": 2911,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-pack-roles.schema.j"
  },
  {
    "path": "app/cli/schema/json-schemas/model-provider-config.schema.json",
    "chars": 2853,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-provider-config.sch"
  },
  {
    "path": "app/cli/schema/json-schemas/model-role-config.schema.json",
    "chars": 1583,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/model-role-config.schema."
  },
  {
    "path": "app/cli/schema/json-schemas/models-input.schema.json",
    "chars": 1088,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/models-input.schema.json\""
  },
  {
    "path": "app/cli/schema/json-schemas/plan-config.schema.json",
    "chars": 385,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://plandex.ai/schemas/plan-config.schema.json\","
  },
  {
    "path": "app/cli/schema/schemas.go",
    "chars": 4159,
    "preview": "package schema\n\nimport (\n\t\"bytes\"\n\t\"embed\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"path\"\n\t\"strings\"\n\n\tshared \"plandex-shared"
  },
  {
    "path": "app/cli/stream/stream.go",
    "chars": 1173,
    "preview": "package stream\n\nimport (\n\t\"log\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/lib\"\n\tstreamtui \"plandex-cli/stream_tui\"\n\t\"plandex-cli/"
  },
  {
    "path": "app/cli/stream_tui/debouncer.go",
    "chars": 685,
    "preview": "package streamtui\n\nimport (\n\t\"sync\"\n\t\"time\"\n)\n\n// UpdateDebouncer helps prevent visual glitches from rapid updates\ntype "
  },
  {
    "path": "app/cli/stream_tui/model.go",
    "chars": 4976,
    "preview": "package streamtui\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"sync\"\n\t\"time\"\n\n\tshared \"plandex-shared\"\n\n\tbubbleKey \"github.com/charmbra"
  },
  {
    "path": "app/cli/stream_tui/run.go",
    "chars": 3048,
    "preview": "package streamtui\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"plandex-cli/term\"\n\t\"sync\"\n\n\tshared \"plandex-shared\"\n\n\ttea \"github.com/"
  },
  {
    "path": "app/cli/stream_tui/update.go",
    "chars": 17310,
    "preview": "package streamtui\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/lib\"\n\t\"plandex-cli/term\"\n\t\"s"
  },
  {
    "path": "app/cli/stream_tui/view.go",
    "chars": 7441,
    "preview": "package streamtui\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"plandex-cli/term\"\n\n\t\"github.com/charmbracelet/lipgloss\"\n\t\"githu"
  },
  {
    "path": "app/cli/term/color.go",
    "chars": 748,
    "preview": "package term\n\nimport (\n\t\"github.com/fatih/color\"\n\t\"github.com/muesli/termenv\"\n)\n\nvar IsDarkBg = termenv.HasDarkBackgroun"
  },
  {
    "path": "app/cli/term/errors.go",
    "chars": 5915,
    "preview": "package term\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/fatih/color\"\n)\n\n"
  },
  {
    "path": "app/cli/term/format.go",
    "chars": 1889,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/glamour\"\n\t\"github.com/charmbracelet/glow/util"
  },
  {
    "path": "app/cli/term/help.go",
    "chars": 17990,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/fatih/color\"\n)\n\ntype CmdConfig struct {\n\tCmd   string"
  },
  {
    "path": "app/cli/term/os.go",
    "chars": 232,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"runtime\"\n)\n\nfunc GetOsDetails() string {\n\treturn fmt.Sprintf(\n\t\t\"OS: %s\\nArchitect"
  },
  {
    "path": "app/cli/term/prompt.go",
    "chars": 3568,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/cqroot/prompt\"\n\t\"github.com/cqroot/prompt/input\"\n\t\"github.com/eiannone"
  },
  {
    "path": "app/cli/term/repl.go",
    "chars": 120,
    "preview": "package term\n\nimport \"os\"\n\nvar IsRepl = os.Getenv(\"PLANDEX_REPL\") != \"\"\n\nfunc SetIsRepl(value bool) {\n\tIsRepl = value\n}\n"
  },
  {
    "path": "app/cli/term/select.go",
    "chars": 678,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/fatih/color\"\n\t\"github.com/plandex-ai/survey/v2\"\n)\n\nfunc SelectFromList"
  },
  {
    "path": "app/cli/term/spinner.go",
    "chars": 1477,
    "preview": "package term\n\nimport (\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/briandowns/spinner\"\n)\n\nconst withMessageMinDuration = 700 * "
  },
  {
    "path": "app/cli/term/utils.go",
    "chars": 3282,
    "preview": "package term\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/muesli/termenv\"\n\t\"golang.org/x/term\"\n"
  },
  {
    "path": "app/cli/types/api.go",
    "chars": 6388,
    "preview": "package types\n\nimport (\n\t\"context\"\n\tshared \"plandex-shared\"\n\n\t\"github.com/shopspring/decimal\"\n)\n\ntype OnStreamPlanParams"
  },
  {
    "path": "app/cli/types/apply.go",
    "chars": 813,
    "preview": "package types\n\nimport (\n\t\"os\"\n)\n\ntype ApplyFlags struct {\n\tAutoConfirm bool\n\tAutoCommit  bool\n\tNoCommit    bool\n\tAutoExe"
  },
  {
    "path": "app/cli/types/exec.go",
    "chars": 506,
    "preview": "package types\n\ntype TellFlags struct {\n\tTellBg                 bool\n\tTellStop               bool\n\tTellNoBuild           "
  },
  {
    "path": "app/cli/types/fs.go",
    "chars": 322,
    "preview": "package types\n\nimport ignore \"github.com/sabhiram/go-gitignore\"\n\ntype ProjectPaths struct {\n\tActivePaths    map[string]b"
  },
  {
    "path": "app/cli/types/types.go",
    "chars": 2112,
    "preview": "package types\n\nimport (\n\tshared \"plandex-shared\"\n\t\"time\"\n\n\t\"github.com/sashabaranov/go-openai\"\n)\n\ntype LoadContextParams"
  },
  {
    "path": "app/cli/ui/ui.go",
    "chars": 1409,
    "preview": "package ui\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"plandex-cli/api\"\n\t\"plandex-cli/term\"\n\t\"strings\""
  },
  {
    "path": "app/cli/upgrade.go",
    "chars": 4663,
    "preview": "package main\n\nimport (\n\t\"archive/tar\"\n\t\"compress/gzip\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"log\"\n\t\"net/http\"\n\t\"n"
  },
  {
    "path": "app/cli/url/url.go",
    "chars": 2295,
    "preview": "package url\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"plandex-cli/term\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github."
  },
  {
    "path": "app/cli/utils/utils.go",
    "chars": 203,
    "preview": "package utils\n\nimport (\n\t\"time\"\n)\n\nfunc EnsureMinDuration(start time.Time, minDuration time.Duration) {\n\telapsed := time"
  },
  {
    "path": "app/cli/version/version.go",
    "chars": 97,
    "preview": "package version\n\n// Version will be set at build time using -ldflags\nvar Version = \"development\"\n"
  },
  {
    "path": "app/cli/version.txt",
    "chars": 6,
    "preview": "2.2.1\n"
  },
  {
    "path": "app/docker-compose.yml",
    "chars": 1134,
    "preview": "services:\n  plandex-postgres:\n    image: postgres:latest\n    restart: always\n    environment:\n      POSTGRES_PASSWORD: p"
  },
  {
    "path": "app/plans/credits-cmd.txt",
    "chars": 369,
    "preview": "\nAdd a cmd/credits.go file with a command that calls GetOrgSession to get the current org and then if IntegratedModelsMo"
  },
  {
    "path": "app/plans/credits-log-cmd.txt",
    "chars": 742,
    "preview": "I want to add a 'plandex credits log' command to the 'cli/cmd' directory. I want it to show all debits and credits from "
  },
  {
    "path": "app/plans/json-prompts-to-xml.md",
    "chars": 1840,
    "preview": "dI want to update a number of LLM calls to potentially use XML instead of JSON-based tool calls based on their configura"
  },
  {
    "path": "app/plans/plan-config.md",
    "chars": 2308,
    "preview": "I want to add a plan config feature. It should be loosely modeled  \non the plan model settings (often referred to also a"
  },
  {
    "path": "app/reset_local.sh",
    "chars": 354,
    "preview": "#!/usr/bin/env bash\n\n# Get the absolute path to the script's directory, regardless of where it's run from\nSCRIPT_DIR=\"$("
  },
  {
    "path": "app/scripts/cmd/gen/gen.go",
    "chars": 2774,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"text/template\"\n)\n\nfunc main() {\n\tif len(os.Args) < 2 {\n\t\tl"
  },
  {
    "path": "app/scripts/cmd/provider/gen_provider.go",
    "chars": 3180,
    "preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"text/template\"\n)\n\nvar testDir = \"test"
  },
  {
    "path": "app/scripts/dev.sh",
    "chars": 1405,
    "preview": "#!/usr/bin/env bash\n\n# Detect zsh and trigger it if its the shell\nif [ -n \"$ZSH_VERSION\" ]; then\n  # shell is zsh\n  echo"
  },
  {
    "path": "app/scripts/litellm_deps.sh",
    "chars": 943,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nVENV_DIR=\"$SCRIPT_DIR/../litellm"
  },
  {
    "path": "app/scripts/wait-for-it.sh",
    "chars": 5227,
    "preview": "#!/usr/bin/env bash\n# Use this script to test if a given TCP host/port are available\n\nWAITFORIT_cmdname=${0##*/}\n\nechoer"
  },
  {
    "path": "app/server/.gitignore",
    "chars": 6,
    "preview": "cloud/"
  },
  {
    "path": "app/server/Dockerfile",
    "chars": 1222,
    "preview": "FROM golang:1.23.3\n\n# Update and install necessary packages including build tools for Tree-sitter\nRUN apt-get update && "
  },
  {
    "path": "app/server/db/account_helpers.go",
    "chars": 1372,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\ntype CreateAccountResult struct {\n\tUser  *User\n\tOrgId s"
  },
  {
    "path": "app/server/db/ai_model_helpers.go",
    "chars": 11,
    "preview": "package db\n"
  },
  {
    "path": "app/server/db/auth_helpers.go",
    "chars": 5314,
    "preview": "package db\n\nimport (\n\t\"crypto/sha256\"\n\t\"database/sql\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t"
  },
  {
    "path": "app/server/db/branch_helpers.go",
    "chars": 4049,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/jmoiron/sqlx\"\n\t\"github.co"
  },
  {
    "path": "app/server/db/build_helpers.go",
    "chars": 1120,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"time\"\n)\n\nfunc StorePlanBuild(build *PlanBuild) error {\n\n\tquery := `INSERT INTO plan_builds"
  },
  {
    "path": "app/server/db/context_helpers_conflicts.go",
    "chars": 2883,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\tshared \"plandex-shared\"\n\t\"runtime\"\n\t\"runtime/debug\"\n)\n\ntype invalidateConflictedResu"
  },
  {
    "path": "app/server/db/context_helpers_get.go",
    "chars": 3117,
    "preview": "package db\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"sort\"\n\t\"strings"
  },
  {
    "path": "app/server/db/context_helpers_load.go",
    "chars": 11182,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"log\"\n\tshared \"plandex-shared\"\n\t\"runtime\"\n\t\"run"
  },
  {
    "path": "app/server/db/context_helpers_map.go",
    "chars": 997,
    "preview": "package db\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\tshared \"plande"
  },
  {
    "path": "app/server/db/context_helpers_remove.go",
    "chars": 3532,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\tshared \"plandex-shared\"\n\t\"runtime\"\n\t\"runtime/debug\"\n)\n\nfunc C"
  },
  {
    "path": "app/server/db/context_helpers_store.go",
    "chars": 3664,
    "preview": "package db\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"ti"
  },
  {
    "path": "app/server/db/context_helpers_update.go",
    "chars": 10770,
    "preview": "package db\n\nimport (\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"log\"\n\tshared \"plandex-shared\"\n\t\"runtime\"\n\t\"runtime/debug\""
  },
  {
    "path": "app/server/db/convo_helpers.go",
    "chars": 5050,
    "preview": "package db\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"sort\"\n\t\"strings"
  },
  {
    "path": "app/server/db/data_models.go",
    "chars": 28934,
    "preview": "package db\n\nimport (\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"time\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/sash"
  },
  {
    "path": "app/server/db/db.go",
    "chars": 4575,
    "preview": "package db\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/url\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/golang-migrate/migrate/v4\"\n\t\"gith"
  },
  {
    "path": "app/server/db/diff_helpers.go",
    "chars": 4575,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\n\tshared \"plandex-share"
  },
  {
    "path": "app/server/db/fs.go",
    "chars": 2626,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n)\n\nvar BaseDir string\n\nfunc init() {\n\thome, err := os.UserHome"
  },
  {
    "path": "app/server/db/git.go",
    "chars": 23878,
    "preview": "package db\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"strconv\"\n\t\"s"
  },
  {
    "path": "app/server/db/invite_helpers.go",
    "chars": 3365,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\nfunc CreateInvite(invit"
  },
  {
    "path": "app/server/db/locks.go",
    "chars": 19611,
    "preview": "package db\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"math\"\n\t\"math/rand\"\n\t\"plandex-server/notify\"\n\t\"p"
  },
  {
    "path": "app/server/db/models.go",
    "chars": 7941,
    "preview": "package db\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\n\t\"github.com/jmoiron/sqlx\"\n\t\"github.com/lib/pq\"\n)\n\nfunc UpsertCustomModel(t"
  },
  {
    "path": "app/server/db/org_helpers.go",
    "chars": 6423,
    "preview": "package db\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"strings\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/jmoiron/sqlx\"\n\t\"gi"
  },
  {
    "path": "app/server/db/plan_config_helpers.go",
    "chars": 1300,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\n\tshared \"plandex-shared\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\nfunc GetPlanConfig(planId string) ("
  },
  {
    "path": "app/server/db/plan_helpers.go",
    "chars": 12078,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"strc"
  },
  {
    "path": "app/server/db/project_helpers.go",
    "chars": 686,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/jmoiron/sqlx\"\n)\n\nfunc ProjectExists(orgId, projectId string) (bool, error) {\n\t"
  },
  {
    "path": "app/server/db/queue.go",
    "chars": 9708,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"runtime/debug\"\n\t\"sync\"\n\n\t\"github.com/google/uuid\"\n)\n\ntype repoOpFn func("
  },
  {
    "path": "app/server/db/rbac_helpers.go",
    "chars": 2016,
    "preview": "package db\n\nimport (\n\t\"fmt\"\n\t\"log\"\n)\n\nvar orgOwnerRoleId string\nvar orgMemberRoleId string\n\nfunc GetOrgOwnerRoleId() (st"
  },
  {
    "path": "app/server/db/result_helpers.go",
    "chars": 28182,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"runtime/debug\"\n\t\"sort"
  },
  {
    "path": "app/server/db/settings_helpers.go",
    "chars": 6729,
    "preview": "package db\n\nimport (\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\tshared \"plandex-sha"
  },
  {
    "path": "app/server/db/stream_helpers.go",
    "chars": 5193,
    "preview": "package db\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"log\"\n\t\"plandex-server/notify\"\n\t\"runtime/debug\"\n\t\"time\"\n\n\tshared"
  }
]

// ... and 456 more files (download for full content)

About this extraction

This page contains the full source code of the plandex-ai/plandex GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 656 files (3.0 MB), approximately 828.2k tokens, and a symbol index with 2489 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!