Skip to content

feat(cli): add profile switching, bulk-import with column mapping, and fix shell completions - #404

Open
ImBIOS wants to merge 2 commits into
usemoss:mainfrom
ImBIOS:feat/cli-improvements-profile-and-bulk-import
Open

ImBIOS wants to merge 2 commits into
usemoss:mainfrom
ImBIOS:feat/cli-improvements-profile-and-bulk-import

Conversation

@ImBIOS

@ImBIOS ImBIOS commented Jul 16, 2026

Copy link
Copy Markdown

Description

This PR introduces three major, high-impact improvements to the Moss CLI to enhance developer experience, streamline multi-project workflows, and fix a critical bug in the shell completions command.


1. 🐛 Fix Shell Completions Fall-through Bug

While running the CLI tests, I discovered that the command was failing with:
Shell completion is unavailable in this Typer installation.

Upon inspection of packages/moss-cli/src/moss_cli/commands/completions.py, I identified a fall-through bug in the exception handling block:

    except Exception:  # pragma: no cover
        try:
            from typer._completion_shared import get_completion_script  # type: ignore
        except Exception:  # pragma: no cover - depends on Typer installation
            output.print_error(
                "Shell completion is unavailable in this Typer installation.",
                json_mode,
            )
            raise typer.Exit(1)
        output.print_error(
            "Shell completion is unavailable in this Typer installation.",
            json_mode,
        )
        raise typer.Exit(1)

Even when the inner import from typer._completion_shared succeeded, the code fell through to print the error and exit non-zero.

  • Fix: Removed the duplicate error print/raise block at the end of the outer except block so that successful imports correctly proceed to script generation.
  • Result: All shell completion tests are now 100% green!

2. 📁 Profile Switching Commands (Closes #176, Closes #126)

Added subcommands to make switching between named credential profiles seamless and explicit without manually editing configuration files or relying on environment variables:

  • moss profile use <profile-name> (or moss profile set-default <profile-name>): Sets the active/default profile in the config.
  • moss profile current: Displays the currently selected profile (taking into account CLI flags and env vars).

3. 📥 Bulk-Import with Column Mapping (Closes #379)

Added a powerful bulk-loading command to import documents from arbitrary CSV, JSON, or JSONL files without writing code:

  • moss doc import <index_name> -f <file_path>
  • Supports column mapping via --id-column / -i and --text-column / -t to map arbitrary column/key names to document ID and text.
  • Automatically maps all other columns/keys to the document's metadata dictionary (satisfying the Dict[str, str] constraint of DocumentInfo by converting values to strings and serializing complex objects/lists to JSON strings).
  • Supports explicit metadata filtering selection via --metadata-columns / -m and toggling with --include-all-metadata / --no-include-all-metadata.

4. 🧪 Comprehensive Test Coverage

Added robust unit and integration tests in tests/test_profiles.py covering:

  • set_active_profile success and failure paths.
  • moss profile use, set-default, and current CLI commands.
  • CSV, JSON, and JSONL document parsers with arbitrary column mapping.
  • End-to-end integration test of moss doc import with mocked API client responses.

All 42 CLI tests are now fully passing!

ImBIOS added 2 commits July 16, 2026 11:11
Upgrades esbuild, pydantic-settings, nltk, cryptography, and aiohttp to keep the build healthy and up to date.

Closes usemoss#377

Closes usemoss#366

Closes usemoss#364

Closes usemoss#363

Closes usemoss#357
Copilot AI review requested due to automatic review settings July 16, 2026 04:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the Moss CLI’s usability for multi-project workflows by adding explicit profile switching, introducing a bulk document import command with column/key mapping, and fixing a shell completions fall-through bug. It also updates several JS/Python lockfiles and overrides (notably esbuild, plus some Python deps in uv.lock snapshots).

Changes:

  • Add moss profile use|set-default|current commands and config support for setting the active profile.
  • Add moss doc import for CSV/JSON/JSONL bulk imports with ID/text/metadata column mapping.
  • Fix moss completions so it doesn’t incorrectly error/exit after a successful fallback import.

Reviewed changes

Copilot reviewed 10 out of 39 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/vitepress-plugin-moss/demo-site/package.json Bump esbuild override for the demo site.
packages/moss-md-indexer/pnpm-lock.yaml Lockfile updates reflecting esbuild override bump.
packages/moss-md-indexer/package.json Bump esbuild overrides.
packages/moss-md-indexer/example/package.json Bump esbuild override in example.
packages/moss-data-connector/moss-connector-supabase/uv.lock Update Python lock snapshot (deps + revision metadata).
packages/moss-data-connector/moss-connector-sqlite/uv.lock Update Python lock snapshot (deps + revision metadata).
packages/moss-data-connector/moss-connector-mongodb/uv.lock Update Python lock snapshot (deps + revision metadata).
packages/moss-cli/tests/test_profiles.py Add tests for profile switching and document import mapping.
packages/moss-cli/src/moss_cli/documents.py Add CSV/JSON/JSONL import helpers with mapping + metadata handling.
packages/moss-cli/src/moss_cli/config.py Add set_active_profile() to persist active profile selection.
packages/moss-cli/src/moss_cli/commands/profile.py Add profile use, set-default, and current commands.
packages/moss-cli/src/moss_cli/commands/doc.py Add doc import command wiring to new import helpers.
packages/moss-cli/src/moss_cli/commands/completions.py Remove erroneous fall-through error/exit in completion script generation.
packages/agora-moss/uv.lock Update Python lock snapshot (deps + revision metadata).
package.json Bump root esbuild override.
package-lock.json Update npm lockfile for esbuild patch bump.
moss-live-labs/python/uv.lock Update experimental Python lock snapshot (deps + revision metadata).
moss-live-labs/examples/voice-agent/uv.lock Update experimental Python lock snapshot (deps + revision metadata).
moss-live-labs/examples/semantic-cache/uv.lock Update experimental Python lock snapshot (revision metadata).
moss-live-labs/examples/image-search/setup-py/uv.lock Update experimental Python lock snapshot (deps + revision metadata).
moss-live-labs/examples/image-search/backend-py/uv.lock Update experimental Python lock snapshot (revision metadata).
examples/voice-agents/insurance-adjuster/uv.lock Update example Python lock snapshot (revision metadata).
examples/cookbook/smolagents/uv.lock Update cookbook Python lock snapshot (revision metadata).
examples/cookbook/sim/uv.lock Update cookbook Python lock snapshot (revision metadata).
apps/vapi-moss/uv.lock Update app Python lock snapshot (revision metadata).
apps/elevenlabs-moss/uv.lock Update app Python lock snapshot (deps + revision metadata).
apps/agora-moss/uv.lock Update app Python lock snapshot (deps + revision metadata).
Files not reviewed (2)
  • packages/moss-md-indexer/example/pnpm-lock.yaml: Generated file
  • packages/moss-md-indexer/pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

metadata_columns: Optional[List[str]] = None,
include_all_metadata: bool = True,
) -> List[DocumentInfo]:
reader = csv.DictReader(content.splitlines())
content: str,
id_column: str = "id",
text_column: str = "text",
metadata_columns: Optional[List[str]] = None,
source: str = "input",
id_column: str = "id",
text_column: str = "text",
metadata_columns: Optional[List[str]] = None,
source: str = "input",
id_column: str = "id",
text_column: str = "text",
metadata_columns: Optional[List[str]] = None,
index: int,
id_column: str = "id",
text_column: str = "text",
metadata_columns: Optional[List[str]] = None,
file_path: str,
id_column: str = "id",
text_column: str = "text",
metadata_columns: Optional[List[str]] = None,
raise typer.BadParameter(f"File not found: {file_path}")

suffix = path.suffix.lower()
content = path.read_text()
def import_command(
ctx: typer.Context,
index_name: str = typer.Argument(..., help="Index name", autocompletion=complete_index_name),
file: str = typer.Option(..., "--file", "-f", help="Path to JSON/CSV document file, or '-' for stdin"),

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants