Skip to content

Conversation

@devinpearson
Copy link
Owner

@devinpearson devinpearson commented Jun 9, 2025

This pull request introduces significant enhancements to the Investec programmable banking CLI tool, including new commands, improved workflows, and better error handling. The key updates focus on expanding functionality, automating CI/CD processes, and refining the codebase for maintainability.

New Commands and Features:

  • Accounts Command: Added functionality to fetch and display Investec accounts, with options for JSON output and table formatting. (src/cmds/accounts.ts)
  • Balances Command: Implemented a command to retrieve account balances, including details like current, available, and budget balances. (src/cmds/balances.ts)
  • Beneficiaries Command: Added a command to list beneficiaries associated with the user's Investec profile, with formatted table output. (src/cmds/beneficiaries.ts)
  • Bank Command: Introduced an AI-powered command to interact with banking data using natural language prompts, leveraging OpenAI's GPT models and function calls. (src/cmds/bank.ts)

Workflow Automation:

  • Node.js CI Workflow: Added a GitHub Actions workflow to automate testing and building across multiple Node.js versions. (.github/workflows/node.js.yml)
  • Publish Workflow: Implemented a workflow to publish the package to npm when a version tag is pushed. (.github/workflows/publish.yml)

Documentation Updates:

  • Project Overview: Updated documentation to describe the CLI tool's purpose, features, and structure. (.github/copilot-instructions.md)
  • README Enhancements: Expanded the README to include detailed descriptions of new commands, such as accounts, balances, transfer, and bank. (README.md) [1] [2]

Dependency and Configuration Changes:

  • Package Updates: Added new dependencies (@inquirer/prompts, investec-pb-api) and updated scripts for linting and security audits. (package.json) [1] [2]
  • Version Bump: Incremented the package version from 0.8.0 to 0.8.1. (package.json)

Codebase Refinements:

  • Error Handling: Improved error handling across commands by centralizing logic into utility functions. (src/cmds/ai.ts, src/cmds/bank.ts) [1] [2]
  • Removed Legacy Code: Cleaned up obsolete functions related to transaction handling. (published.js)

These changes collectively enhance the CLI tool's functionality, reliability, and usability while streamlining development processes.

Summary by CodeRabbit

  • New Features
    • Added CLI commands for viewing accounts, balances, transactions, beneficiaries, making payments, and transferring funds.
    • Introduced a "bank" command powered by AI for natural language banking queries.
    • Enhanced interactive prompts for missing command parameters.
    • Added mock API support for testing without real bank connections.
  • Improvements
    • Unified and simplified error handling across all commands with centralized utilities.
    • Streamlined output formatting using consistent tabular displays.
    • Modularized CLI option handling for easier command extension.
    • Improved documentation with detailed CLI command usage.
  • Automation & CI
    • Added automated CI workflows for build, test, and npm publishing.
    • Expanded test coverage and improved test output formatting.
  • Chores
    • Updated dependencies and scripts.
    • Added and updated .gitignore and documentation files.
  • Style
    • Refactored commands to use shared types and utilities for maintainability.
  • Tests
    • Updated tests to match new output formatting.

@devinpearson devinpearson requested a review from Copilot June 9, 2025 09:47
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 9, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces new CLI commands for Investec banking operations, including accounts, balances, transactions, transfers, payments, and beneficiaries. It adds a "bank" command leveraging OpenAI for natural language queries, centralizes error handling, refactors option handling via shared types, and improves modularity with mock/test support. CI/CD workflows and documentation are added.

Changes

File(s) / Group Change Summary
.github/copilot-instructions.md, README.md Added/updated documentation for new CLI commands and project usage.
.github/workflows/node.js.yml, .github/workflows/publish.yml Added CI workflow for Node.js and npm publishing.
.gitignore Added published.js to ignored files.
package.json Version bump, new dependencies, lint script, and updated CI script.
published.js Deleted transaction lifecycle function file.
scripts/tapes.sh Added commands to generate new tape assets for CLI demos.
test/cmds/cards.test.ts Updated tests for new table-based card output formatting.
tapes/*.tape Added new tapes for accounts, balances, beneficiaries, pay, transactions, transfer; reduced sleep durations in others.
src/cmds/accounts.ts, balances.ts, transactions.ts, transfer.ts, pay.ts, beneficiaries.ts, bank.ts Added new CLI commands for banking operations and LLM-powered queries.
src/cmds/cards.ts, countries.ts, currencies.ts, merchants.ts Refactored output to use shared printTable utility and centralized error handling.
src/cmds/deploy.ts, disable.ts, env.ts, fetch.ts, logs.ts, publish.ts, published.ts, upload-env.ts, upload.ts, toggle.ts Refactored to use shared CommonOptions interface and centralized error handler.
src/cmds/login.ts, register.ts, run.ts, new.ts, set.ts, simulate.ts Improved interactive prompts, error handling, and credential file management.
src/cmds/index.ts Exported new bankCommand.
src/cmds/types.ts Added shared TypeScript interfaces for CLI options and credentials.
src/function-calls.ts Added OpenAI-compatible function call specs and implementations for banking and weather APIs.
src/index.ts Major CLI refactor: modularized API init, added new commands, unified options, improved error handling.
src/mock-pb.ts Added mock programmable banking API client for testing.
src/utils.ts Added utilities for error handling, table printing, version checking, and credential loading.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant InvestecAPI
    participant OpenAI

    User->>CLI: Run "ipb bank <prompt>"
    CLI->>OpenAI: Send prompt + system instructions
    OpenAI-->>CLI: Responds (may include tool calls)
    alt Tool call present
        CLI->>InvestecAPI: Execute requested function (e.g., getAccounts)
        InvestecAPI-->>CLI: Return data
        CLI->>OpenAI: Send tool response for final answer
        OpenAI-->>CLI: Final natural language response
    end
    CLI->>User: Output result
Loading
sequenceDiagram
    participant User
    participant CLI
    participant InvestecAPI

    User->>CLI: Run "ipb <accounts|balances|transactions|transfer|pay|beneficiaries> ..."
    CLI->>InvestecAPI: Authenticate and call respective API method
    InvestecAPI-->>CLI: Return data/result
    CLI->>User: Display formatted output or error
Loading

Possibly related PRs

  • devinpearson/ipb#32: Deletes the published.js file, which this PR also removes, indicating a direct inverse relationship.
  • devinpearson/ipb#22: Refactors CLI commands and API initialization, similar to this PR's modularization and new command additions.
  • devinpearson/ipb#14: Both PRs update CLI credential handling and configuration, affecting how credentials are managed and passed to commands.

Poem

🐇
A hop, a skip, new commands in tow,
To check your bank, just say "hello!"
With tables neat and errors tamed,
A bunny's dream of code well-named.
Now tape and test, the CLI's bright—
Hooray for banking done just right!
🌱💸


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d0a30f and 50a780b.

📒 Files selected for processing (15)
  • .github/copilot-instructions.md (1 hunks)
  • .github/workflows/node.js.yml (1 hunks)
  • .github/workflows/publish.yml (1 hunks)
  • src/cmds/ai.ts (4 hunks)
  • src/cmds/balances.ts (1 hunks)
  • src/cmds/bank.ts (1 hunks)
  • src/cmds/login.ts (3 hunks)
  • src/cmds/pay.ts (1 hunks)
  • src/cmds/register.ts (2 hunks)
  • src/cmds/run.ts (2 hunks)
  • src/cmds/transfer.ts (1 hunks)
  • src/function-calls.ts (1 hunks)
  • src/mock-pb.ts (1 hunks)
  • src/utils.ts (1 hunks)
  • test/cmds/cards.test.ts (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds and refactors core CLI commands for Investec programmable banking, centralizing error handling and introducing table output utilities

  • Registers the new bank AI-driven command in the command index
  • Refactors existing commands (fetch, env, disable, deploy, currencies, countries, cards) to use handleCliError and printTable
  • Introduces new commands: accounts, balances, and beneficiaries, plus CI/CD workflows, docs, and dependency updates

Reviewed Changes

Copilot reviewed 79 out of 79 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/cmds/index.ts Imported and exported bankCommand
src/cmds/fetch.ts Replaced manual error logging with handleCliError
src/cmds/env.ts Ditto for envCommand
src/cmds/disable.ts Ditto for disableCommand
src/cmds/deploy.ts Wrapped deploy logic in try/catch and centralized errors
src/cmds/currencies.ts Switched to printTable for output
src/cmds/countries.ts Switched to printTable for output
src/cmds/cards.ts Switched to printTable for output
src/cmds/beneficiaries.ts Added new beneficiariesCommand
src/cmds/bank.ts Added new AI-driven bankCommand
src/cmds/balances.ts Added new balancesCommand
src/cmds/accounts.ts Added new accountsCommand
scripts/tapes.sh Added tapes for new commands
published.js Removed legacy transaction hooks
package.json Bumped version, added dependencies & scripts
README.md Documented new commands
.github/workflows/publish.yml New npm publish workflow
.github/workflows/node.js.yml New Node.js CI workflow
.github/copilot-instructions.md Added project overview doc
Comments suppressed due to low confidence (1)

src/cmds/fetch.ts:27

  • [nitpick] Avoid using synchronous fs.writeFileSync inside an async function; consider using fs.promises.writeFile to prevent blocking the event loop.
await fs.writeFileSync(options.filename, code);

console.log("🎉 code deployed");
}
} catch (error: any) {
handleCliError(error, { verbose: (options as any).verbose }, "deploy code");
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

Passing only the verbose flag to handleCliError may omit other common options; pass the full options object to preserve context.

Suggested change
handleCliError(error, { verbose: (options as any).verbose }, "deploy code");
handleCliError(error, options, "deploy code");

Copilot uses AI. Check for mistakes.
if (options.cardKey === undefined) {
if (credentials.cardKey === "") {
throw new Error("cardkey is required");
throw new Error("card-key is required");
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

The error message refers to 'card-key' but the code and CLI flag use 'cardKey'; align the message to match the flag name for clarity.

Suggested change
throw new Error("card-key is required");
throw new Error("cardKey is required");

Copilot uses AI. Check for mistakes.
}
throw new Error("Invalid response format from OpenAI");
} catch (error) {
console.error("Error generating code:", error);
Copy link

Copilot AI Jun 9, 2025

Choose a reason for hiding this comment

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

[nitpick] This standalone console.error bypasses the centralized handleCliError; consider routing all errors through the same handler for consistency.

Suggested change
console.error("Error generating code:", error);
handleCliError(error, "Error generating code");

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 29

🔭 Outside diff range comments (2)
src/cmds/set.ts (1)

5-13: 🛠️ Refactor suggestion

Consider extending CommonOptions for consistency.

Unlike env.ts, this Options interface doesn't extend CommonOptions, creating inconsistency in the codebase. The interface contains several properties (verbose, clientId, clientSecret, apiKey) that are already defined in CommonOptions.

Consider refactoring to extend CommonOptions:

+import type { CommonOptions } from "./types.js";
+
-interface Options {
-  clientId: string;
-  clientSecret: string;
-  apiKey: string;
+interface Options extends CommonOptions {
   cardKey: string;
   openaiKey: string;
   sandboxKey: string;
-  verbose: boolean;
 }
src/cmds/run.ts (1)

7-18: ⚠️ Potential issue

Fix Options interface to extend CommonOptions

The Options interface should extend CommonOptions to maintain consistency with other commands and ensure the verbose property is available.

Apply this diff:

+import type { CommonOptions } from "./types.js";
-interface Options {
+interface Options extends CommonOptions {
   filename: string;
   env: string;
   currency: string;
   amount: number;
   mcc: string;
   merchant: string;
   city: string;
   country: string;
-  // verbose: boolean;
 }
♻️ Duplicate comments (5)
src/cmds/logs.ts (1)

13-21: Same validation behavior change as in simulate.ts.

Moving validation inside the try block changes error handling behavior consistently with other commands. Ensure this standardization provides the desired user experience.

.github/copilot-instructions.md (1)

1-1: Fix grammar: Use singular form and proper capitalization.

Based on the past review comment, this issue was already identified. The line should read: "This project is a command line tool for managing and interacting with Investec Bank's API services."

🧰 Tools
🪛 LanguageTool

[grammar] ~1-~1: Consider using the singular form after the singular determiner “This”.
Context: This projects is a command line tool for managing and...

(AGREEMENT_SENT_START)

src/cmds/deploy.ts (1)

48-48: ⚠️ Potential issue

Remove unnecessary type cast and pass full options object

The type cast to any is unnecessary since Options extends CommonOptions which already includes the verbose property. Additionally, passing the full options object preserves context for error handling.

Apply this diff:

-    handleCliError(error, { verbose: (options as any).verbose }, "deploy code");
+    handleCliError(error, options, "deploy code");
src/cmds/bank.ts (2)

10-12: ⚠️ Potential issue

Security: Enable SSL certificate verification

Disabling SSL certificate verification exposes the CLI to man-in-the-middle attacks.

Consider using a proper certificate for sandbox environments:

 const agent = new https.Agent({
-  rejectUnauthorized: false,
+  ca: fs.readFileSync(process.env.CA_CERT_PATH || "./sandbox-ca.pem"),
 });

123-124: ⚠️ Potential issue

Use centralized error handling

This console.error bypasses the centralized error handling pattern used throughout the codebase.

Apply this diff:

   } catch (error) {
-    console.error("Error generating code:", error);
-    return null;
+    throw error;
   }
🧹 Nitpick comments (22)
src/cmds/types.ts (1)

21-27: DRY up BasicOptions by reusing CommonOptions
The BasicOptions interface duplicates all fields of CommonOptions except verbose. Consider leveraging TypeScript utility types to avoid repetition:

-export interface BasicOptions {
-  host: string;
-  apiKey: string;
-  clientId: string;
-  clientSecret: string;
-  credentialsFile: string;
-}
+// BasicOptions reuses CommonOptions without the verbose flag
+export type BasicOptions = Omit<CommonOptions, 'verbose'>;
tapes/accounts.tape (2)

4-4: Normalize spacing around the Enter action.
There are two spaces before Enter, which is inconsistent with other tapes.

-Type "ipb accounts" Sleep 500ms  Enter
+Type "ipb accounts" Sleep 500ms Enter

6-6: Consider dynamic waits to avoid flakiness.
A fixed Sleep 2s may lead to brittle tests on slower CI runners. Consider waiting on a specific prompt or output marker instead.

tapes/beneficiaries.tape (2)

4-4: Align spacing before Enter.
Ensure single-space separation before Enter to match style across tapes.

-Type "ipb beneficiaries" Sleep 500ms Enter
+Type "ipb beneficiaries" Sleep 500ms Enter

(This line has one space—verify consistency with other tape files.)


6-6: Replace static sleep with conditional wait.
Static Sleep 2s can be flaky; consider waiting for a CLI-ready prompt or a successful output signal.

tapes/transactions.tape (2)

4-4: Uniform spacing around the Enter key.
Remove any extra spaces before/after Enter to keep tape scripts consistent.

-Type "ipb transactions mock-account-id" Sleep 500ms Enter
+Type "ipb transactions mock-account-id" Sleep 500ms Enter

6-6: Avoid fixed-delay sleeps.
Consider a targeted wait (e.g., wait for a prompt) rather than a constant Sleep 2s to improve robustness.

tapes/balances.tape (2)

4-4: Consistent Enter formatting.
Ensure a single space before Enter to align with other tape files.

-Type "ipb balances mock-account-id" Sleep 500ms Enter
+Type "ipb balances mock-account-id" Sleep 500ms Enter

6-6: Robust test timing.
Static Sleep 2s can fail under variable latency; replace with a conditional wait or polling for expected output.

package.json (2)

14-14: Add explicit linting step.
Introducing "lint": "tsc" is useful for type-checks. You may also consider adding ESLint for broader code-quality enforcement.


17-17: CI script omission of check-exports.
The ci script no longer includes npm run check-exports. If export integrity checks are still needed, re-add it; otherwise remove the unused script entry.

src/cmds/accounts.ts (1)

9-12: Enhance JSDoc documentation.

Consider adding parameter and return type documentation for better developer experience.

/**
 * Fetch and display Investec accounts.
- * @param options CLI options
+ * @param options CLI options including verbosity and output format
+ * @returns Promise<void>
 */
.github/workflows/publish.yml (1)

13-17: Consider Node.js version consistency.

Using Node.js 20.x for publishing is reasonable, but consider if this should match the minimum supported version from the CI workflow or use the same matrix approach for consistency.

src/cmds/beneficiaries.ts (2)

4-4: Simplify the empty Options interface.

Since the Options interface doesn't add any additional fields beyond CommonOptions, you can use CommonOptions directly in the function signature.

-interface Options extends CommonOptions {}

And update the function signature:

-export async function beneficiariesCommand(options: Options) {
+export async function beneficiariesCommand(options: CommonOptions) {

18-34: Remove redundant mapping operation.

The mapping operation extracts fields and immediately returns them with the same names and structure. This is redundant and can be simplified.

-    const simpleBeneficiaries = beneficiaries.map(
-      ({
-        beneficiaryId,
-        accountNumber,
-        beneficiaryName,
-        lastPaymentDate,
-        lastPaymentAmount,
-        referenceName,
-      }) => ({
-        beneficiaryId,
-        accountNumber,
-        beneficiaryName,
-        lastPaymentDate,
-        lastPaymentAmount,
-        referenceName,
-      }),
-    );
-    printTable(simpleBeneficiaries);
+    printTable(beneficiaries);

If you need to filter specific fields, consider using a more explicit approach or adding comments explaining why the mapping is necessary.

src/cmds/balances.ts (2)

14-14: Remove commented code.

The commented console.table(accounts) line should be removed to keep the codebase clean.

-    //console.table(accounts)

24-26: Improve error message specificity.

The current error handling assumes that any "Bad Request" means "Account not found", which may not always be accurate. Consider making this more specific or providing additional context.

-    if (error.message && error.message === "Bad Request") {
+    if (error.message && error.message.includes("Bad Request")) {
       console.log("");
-      console.error(`Account with ID ${accountId} not found.`);
+      console.error(`Account with ID ${accountId} not found or invalid request.`);

Alternatively, check for more specific error properties if available from the API response.

src/cmds/transactions.ts (1)

9-15: Consider extending the Transaction type for future needs.

The minimal Transaction type is appropriate for current display needs, but consider if additional fields like balance, category, or status might be useful for future enhancements.

.github/copilot-instructions.md (1)

1-12: Improve documentation formatting and structure.

Consider enhancing the documentation with:

  • Proper markdown formatting (headers, bullet points, code blocks)
  • More structured sections (Overview, Features, Usage, etc.)
  • Consistent capitalization ("JavaScript" instead of "js")

Example improvement:

-This projects is a command line tool for managing and interacting with investec banks api services. It provides various commands to perform operations such as getting a list of bank accounts, balances, and transactions.
+# Investec Programmable Banking CLI
+
+This project is a command line tool for managing and interacting with Investec Bank's API services. It provides various commands to perform operations such as:
+
+- Getting a list of bank accounts
+- Retrieving balances and transactions  
+- Managing beneficiaries and payments
🧰 Tools
🪛 LanguageTool

[grammar] ~1-~1: Consider using the singular form after the singular determiner “This”.
Context: This projects is a command line tool for managing and...

(AGREEMENT_SENT_START)


[style] ~3-~3: ‘make a payment’ might be wordy. Consider a shorter alternative.
Context: ...bank card account and executed when you make a payment. This allows you to automate certain ac...

(EN_WORDINESS_PREMIUM_MAKE_A_PAYMENT)

src/cmds/bank.ts (2)

108-113: Use optional chaining for cleaner code

Simplify the nested conditional checks using optional chaining.

Apply this diff:

-    const message =
-      completion.choices &&
-      completion.choices[0] &&
-      completion.choices[0].message
-        ? completion.choices[0].message
-        : undefined;
+    const message = completion.choices?.[0]?.message;
🧰 Tools
🪛 Biome (1.9.4)

[error] 108-110: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


165-168: Use optional chaining for consistency

Apply the same optional chaining pattern here for consistency.

Apply this diff:

-  const message =
-    response2.choices && response2.choices[0] && response2.choices[0].message
-      ? response2.choices[0].message
-      : undefined;
+  const message = response2.choices?.[0]?.message;
🧰 Tools
🪛 Biome (1.9.4)

[error] 166-166: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/index.ts (1)

368-393: Consider adding printTitleBox() for consistency.

The initializePbApi function doesn't call printTitleBox() while initializeApi does (line 335). For consistency across API initialization functions, consider adding it.

 export async function initializePbApi(
   credentials: Credentials,
   options: BasicOptions,
 ) {
+  printTitleBox();
   credentials = await optionCredentials(options, credentials);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 859ef49 and 4d0a30f.

⛔ Files ignored due to path filters (20)
  • assets/accounts.gif is excluded by !**/*.gif
  • assets/balances.gif is excluded by !**/*.gif
  • assets/beneficiaries.gif is excluded by !**/*.gif
  • assets/cards.gif is excluded by !**/*.gif
  • assets/deploy.gif is excluded by !**/*.gif
  • assets/env.gif is excluded by !**/*.gif
  • assets/fetch.gif is excluded by !**/*.gif
  • assets/logs.gif is excluded by !**/*.gif
  • assets/new.gif is excluded by !**/*.gif
  • assets/pay.gif is excluded by !**/*.gif
  • assets/publish.gif is excluded by !**/*.gif
  • assets/published.gif is excluded by !**/*.gif
  • assets/run.gif is excluded by !**/*.gif
  • assets/simulate.gif is excluded by !**/*.gif
  • assets/toggle.gif is excluded by !**/*.gif
  • assets/transactions.gif is excluded by !**/*.gif
  • assets/transfer.gif is excluded by !**/*.gif
  • assets/upload-env.gif is excluded by !**/*.gif
  • assets/upload.gif is excluded by !**/*.gif
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (60)
  • .github/copilot-instructions.md (1 hunks)
  • .github/workflows/node.js.yml (1 hunks)
  • .github/workflows/publish.yml (1 hunks)
  • .gitignore (1 hunks)
  • README.md (2 hunks)
  • package.json (3 hunks)
  • published.js (0 hunks)
  • scripts/tapes.sh (1 hunks)
  • src/cmds/accounts.ts (1 hunks)
  • src/cmds/ai.ts (4 hunks)
  • src/cmds/balances.ts (1 hunks)
  • src/cmds/bank.ts (1 hunks)
  • src/cmds/beneficiaries.ts (1 hunks)
  • src/cmds/cards.ts (2 hunks)
  • src/cmds/countries.ts (2 hunks)
  • src/cmds/currencies.ts (2 hunks)
  • src/cmds/deploy.ts (1 hunks)
  • src/cmds/disable.ts (2 hunks)
  • src/cmds/env.ts (2 hunks)
  • src/cmds/fetch.ts (2 hunks)
  • src/cmds/index.ts (2 hunks)
  • src/cmds/login.ts (3 hunks)
  • src/cmds/logs.ts (2 hunks)
  • src/cmds/merchants.ts (2 hunks)
  • src/cmds/new.ts (2 hunks)
  • src/cmds/pay.ts (1 hunks)
  • src/cmds/publish.ts (2 hunks)
  • src/cmds/published.ts (2 hunks)
  • src/cmds/register.ts (2 hunks)
  • src/cmds/run.ts (2 hunks)
  • src/cmds/set.ts (2 hunks)
  • src/cmds/simulate.ts (3 hunks)
  • src/cmds/toggle.ts (2 hunks)
  • src/cmds/transactions.ts (1 hunks)
  • src/cmds/transfer.ts (1 hunks)
  • src/cmds/types.ts (1 hunks)
  • src/cmds/upload-env.ts (2 hunks)
  • src/cmds/upload.ts (2 hunks)
  • src/function-calls.ts (1 hunks)
  • src/index.ts (10 hunks)
  • src/mock-pb.ts (1 hunks)
  • src/utils.ts (1 hunks)
  • tapes/accounts.tape (1 hunks)
  • tapes/balances.tape (1 hunks)
  • tapes/beneficiaries.tape (1 hunks)
  • tapes/deploy.tape (1 hunks)
  • tapes/env.tape (1 hunks)
  • tapes/fetch.tape (1 hunks)
  • tapes/pay.tape (1 hunks)
  • tapes/publish.tape (1 hunks)
  • tapes/published.tape (1 hunks)
  • tapes/run.tape (1 hunks)
  • tapes/set.tape (1 hunks)
  • tapes/simulate.tape (1 hunks)
  • tapes/toggle.tape (1 hunks)
  • tapes/transactions.tape (1 hunks)
  • tapes/transfer.tape (1 hunks)
  • tapes/upload-env.tape (1 hunks)
  • tapes/upload.tape (1 hunks)
  • test/cmds/cards.test.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • published.js
🧰 Additional context used
🧬 Code Graph Analysis (26)
src/cmds/beneficiaries.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/new.ts (1)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/merchants.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/accounts.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/simulate.ts (2)
src/index.ts (1)
  • credentials (90-98)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/cards.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/transactions.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/env.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/published.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/currencies.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/publish.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (1)
  • credentials (90-98)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/set.ts (1)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/fetch.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/upload-env.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/countries.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (2)
  • printTable (36-62)
  • handleCliError (4-14)
src/cmds/login.ts (2)
src/index.ts (2)
  • printTitleBox (56-62)
  • credentialLocation (50-53)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/transfer.ts (4)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
src/mock-pb.ts (1)
  • transfer (148-167)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/deploy.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • credentials (90-98)
  • initializeApi (331-366)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/balances.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/toggle.ts (2)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/register.ts (2)
src/index.ts (1)
  • printTitleBox (56-62)
src/utils.ts (1)
  • handleCliError (4-14)
src/cmds/bank.ts (4)
src/cmds/index.ts (1)
  • bankCommand (40-40)
src/index.ts (2)
  • printTitleBox (56-62)
  • credentials (90-98)
src/utils.ts (1)
  • handleCliError (4-14)
src/function-calls.ts (2)
  • tools (192-198)
  • availableFunctions (200-206)
src/utils.ts (2)
src/index.ts (1)
  • credentials (90-98)
src/cmds/types.ts (1)
  • Credentials (11-19)
src/cmds/disable.ts (3)
src/cmds/types.ts (1)
  • CommonOptions (2-9)
src/index.ts (1)
  • credentials (90-98)
src/utils.ts (1)
  • handleCliError (4-14)
src/index.ts (22)
src/cmds/cards.ts (1)
  • cardsCommand (6-30)
src/cmds/deploy.ts (1)
  • deployCommand (12-50)
src/cmds/fetch.ts (1)
  • fetchCommand (10-32)
src/cmds/upload.ts (1)
  • uploadCommand (10-32)
src/cmds/env.ts (1)
  • envCommand (10-32)
src/cmds/upload-env.ts (1)
  • uploadEnvCommand (10-32)
src/cmds/published.ts (1)
  • publishedCommand (10-29)
src/cmds/toggle.ts (1)
  • enableCommand (8-28)
src/cmds/disable.ts (1)
  • disableCommand (8-28)
src/cmds/countries.ts (1)
  • countriesCommand (5-23)
src/cmds/merchants.ts (1)
  • merchantsCommand (6-24)
src/cmds/accounts.ts (1)
  • accountsCommand (13-40)
src/cmds/balances.ts (1)
  • balancesCommand (8-31)
src/cmds/transfer.ts (1)
  • transferCommand (8-52)
src/cmds/pay.ts (1)
  • payCommand (8-50)
src/cmds/transactions.ts (1)
  • transactionsCommand (22-57)
src/cmds/beneficiaries.ts (1)
  • beneficiariesCommand (6-39)
src/cmds/bank.ts (1)
  • bankCommand (25-80)
src/utils.ts (2)
  • handleCliError (4-14)
  • loadCredentialsFile (64-92)
src/cmds/types.ts (2)
  • Credentials (11-19)
  • BasicOptions (21-27)
src/mock-card.ts (1)
  • CardApi (46-333)
src/mock-pb.ts (1)
  • PbApi (37-208)
src/function-calls.ts (2)
src/mock-pb.ts (6)
  • getAccounts (82-98)
  • getAccountBalances (68-81)
  • getAccountTransactions (99-123)
  • getBeneficiaries (124-147)
  • transferMultiple (187-207)
  • transfer (148-167)
src/index.ts (2)
  • initializePbApi (368-393)
  • credentials (90-98)
🪛 LanguageTool
.github/copilot-instructions.md

[grammar] ~1-~1: Consider using the singular form after the singular determiner “This”.
Context: This projects is a command line tool for managing and...

(AGREEMENT_SENT_START)


[style] ~3-~3: ‘make a payment’ might be wordy. Consider a shorter alternative.
Context: ...bank card account and executed when you make a payment. This allows you to automate certain ac...

(EN_WORDINESS_PREMIUM_MAKE_A_PAYMENT)

🪛 Biome (1.9.4)
src/cmds/bank.ts

[error] 108-110: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 166-166: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

src/function-calls.ts

[error] 30-35: This code is unreachable

... because this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (75)
tapes/fetch.tape (1)

6-6: Standardize sleep duration to 5 seconds
Reduced the post-command wait from 10s to 5s to match other tape scripts and speed up automated playbacks.

tapes/upload.tape (1)

6-6: Standardize sleep duration to 5 seconds
Reduced the post-command wait from 10s to 5s to match other tape scripts and speed up automated playbacks.

tapes/run.tape (1)

6-6: Standardize sleep duration to 5 seconds
Reduced the post-command wait from 10s to 5s to match other tape scripts and speed up automated playbacks.

tapes/publish.tape (1)

6-6: Standardize sleep duration to 5 seconds
Reduced the post-command wait from 10s to 5s to match other tape scripts and speed up automated playbacks.

tapes/upload-env.tape (1)

6-6: Standardize sleep duration to 5 seconds
Reduced the post-command wait from 10s to 5s to match other tape scripts and speed up automated playbacks.

tapes/env.tape (1)

6-6: Reduce demo sleep duration to 5 seconds
Shortens the wait time after the ipb env command for faster tape execution, consistent with other scripts.

tapes/simulate.tape (1)

6-6: Shorten post-command sleep to 5 seconds
Aligns with the reduced wait times in other tapes to speed up automated demos without altering behavior.

tapes/toggle.tape (1)

10-10: Unify sleep duration to 5 seconds
Matches the standardized 5 s wait used across tape scripts for consistency and faster execution.

.gitignore (1)

9-9: Ignore deprecated published.js file
Ensures the removed/legacy published.js script remains excluded from version control.

tapes/deploy.tape (1)

6-6: Reduce deployment sleep to 5 seconds
Decreases the post-deploy pause for quicker tape runs while preserving functionality.

src/cmds/types.ts (2)

2-9: Define CommonOptions for CLI consistency
The CommonOptions interface neatly centralizes frequently used CLI flags and credentials, enhancing maintainability and reducing boilerplate across commands.


11-19: Expand Credentials interface for full key coverage
The Credentials interface covers all required API and service keys, ensuring consumer code can rely on a single source of truth for sensitive values.

tapes/set.tape (1)

6-6: Standardize tape sleep duration
Reducing the final sleep to 5 seconds aligns this tape with the updated timings in other scripts, speeding up CI demos without impacting reliability.

tapes/published.tape (1)

6-6: Standardize tape sleep duration
The change from 10s to 5s matches the sleep adjustments made across all tape files, improving consistency and test speed.

src/cmds/index.ts (2)

19-19: Include bankCommand into commands index
Importing bankCommand here integrates the new AI-driven banking operation into the CLI’s command registry.


40-40: Export bankCommand for CLI entry
Exposing bankCommand in the exports object makes the new "bank" command available to the user-facing entry point.

scripts/tapes.sh (1)

16-21: Integrate new tape scripts into vhs workflow
Appending the new tapes for accounts, beneficiaries, balances, transactions, pay, and transfer ensures the full suite of CLI commands is covered in automated demos/tests.

tapes/accounts.tape (1)

1-2:

Details

✅ Verification successful

Verify asset and source references.
Ensure assets/accounts.gif exists and tapes/config.tape is correctly referenced relative to this file’s location.


🏁 Script executed:

#!/bin/bash
# Verify that the referenced files exist
ls assets/accounts.gif && ls tapes/config.tape

Length of output: 85


Asset and source references are valid
Both assets/accounts.gif and tapes/config.tape exist at their referenced paths; no changes needed.

tapes/beneficiaries.tape (1)

1-2:

Details

✅ Verification successful

Verify asset and source file paths.
Confirm that assets/beneficiaries.gif and tapes/config.tape exist and are correctly referenced.


🏁 Script executed:

#!/bin/bash
ls assets/beneficiaries.gif && ls tapes/config.tape

Length of output: 95


Asset and Source File Paths Verified
Both assets/beneficiaries.gif and tapes/config.tape exist and are correctly referenced.

• assets/beneficiaries.gif
• tapes/config.tape

tapes/transactions.tape (1)

1-2:

Details

✅ Verification successful

Confirm asset and source paths.
Ensure assets/transactions.gif and tapes/config.tape exist and are referenced correctly.


🏁 Script executed:

#!/bin/bash
ls assets/transactions.gif && ls tapes/config.tape

Length of output: 93


Paths confirmed: assets/transactions.gif & tapes/config.tape exist
Both files are present and correctly referenced.

tapes/balances.tape (1)

1-2:

Details

✅ Verification successful

Validate reference files.
Check that assets/balances.gif and tapes/config.tape are present and accessible relative to this tape.


🏁 Script executed:

#!/bin/bash
ls assets/balances.gif && ls tapes/config.tape

Length of output: 85


References Verified
The following files are present and accessible:

  • assets/balances.gif
  • tapes/config.tape
package.json (2)

34-34: Dependency addition: @inquirer/prompts.
This aligns with interactive CLI enhancements—ensure it's used only where needed and peer dependencies are satisfied.


39-39: Dependency addition: investec-pb-api.
Bringing in the programmable banking API client complements the new commands. Verify compatibility with your CLI modules.

tapes/transfer.tape (1)

1-7: LGTM! Well-structured automation script.

The tape script correctly follows VHS conventions with proper output specification, configuration sourcing, and realistic command simulation with appropriate timing delays.

src/cmds/env.ts (3)

3-4: Good refactoring to centralize error handling and standardize options.

The addition of centralized error handling and shared option types improves code consistency across CLI commands.


5-8: Consistent adoption of CommonOptions interface.

Extending CommonOptions reduces code duplication and ensures consistent option handling across commands.


30-30: Improved error handling with centralized utility.

The replacement of manual error logging with handleCliError provides consistent error formatting and verbose handling across the CLI.

tapes/pay.tape (1)

1-7: LGTM! Consistent automation script structure.

The tape script follows the same well-structured pattern as other automation scripts with proper configuration, realistic command simulation, and appropriate timing.

src/cmds/set.ts (2)

3-3: Good adoption of centralized error handling.

Adding the centralized handleCliError utility improves consistency with other CLI commands.


51-51: Improved error handling with centralized utility.

The replacement of manual error logging with handleCliError provides consistent error formatting and context reporting.

src/cmds/new.ts (2)

5-5: LGTM: Clean import of centralized error handler.

Good addition of the centralized error handling utility import.


52-52: LGTM: Excellent refactoring to centralized error handling.

The replacement of inline error handling with handleCliError improves consistency and maintainability. The centralized function provides proper formatting, context, and verbose mode support as seen in the utils.ts implementation.

.github/workflows/node.js.yml (1)

22-30: LGTM: Well-structured CI workflow.

The workflow follows GitHub Actions best practices with:

  • Proper action versions (v4)
  • npm caching for performance
  • Conditional build/test steps with --if-present
  • Clean dependency installation with npm ci

This provides robust CI coverage for the project.

src/cmds/accounts.ts (4)

5-7: LGTM: Clean interface extension.

Good use of interface extension to add the json option to CommonOptions. The optional boolean type is appropriate for a flag.


15-22: LGTM: Proper API initialization and error handling.

Good use of the centralized initializePbApi function and proper handling of the empty accounts case with early return.


23-36: LGTM: Well-implemented output formatting.

Excellent implementation of dual output modes:

  • JSON output for programmatic use
  • Table output with simplified fields for human readability
  • Summary count for table mode

The field selection for the table view (accountId, accountNumber, referenceName, productName) provides the most relevant information without overwhelming the user.


37-39: LGTM: Consistent error handling.

Proper use of the centralized error handler with appropriate context message.

.github/workflows/publish.yml (1)

4-6: LGTM: Appropriate trigger for version tags.

The semantic version tag pattern v*.*.* properly triggers on version releases.

test/cmds/cards.test.ts (1)

50-53: LGTM! Test expectations correctly updated for new table format.

The test assertions have been properly updated to match the new table output format using the printTable utility, replacing the previous colored output format.

src/cmds/publish.ts (3)

3-5: LGTM! Excellent refactoring to use shared utilities.

The changes properly utilize the handleCliError utility and CommonOptions interface, improving consistency across the codebase.


13-21: Good improvement: Validations moved inside try block.

Moving the file existence and cardKey validations inside the try block ensures they are properly caught and handled by the centralized error handler.


33-33: LGTM! Centralized error handling.

Replacing manual error handling with handleCliError provides consistent error reporting across all commands.

src/cmds/simulate.ts (2)

5-5: LGTM! Centralized error handling improves consistency.

The import of handleCliError aligns with the broader refactoring to centralize error handling across CLI commands.


25-33: Consider the implications of moving validation inside the try block.

Moving the validation checks inside the try block changes the error handling behavior. Previously, validation errors would be thrown immediately, but now they'll be caught and processed by handleCliError. While this provides consistent error formatting, ensure this behavior change is intentional and doesn't affect error codes or user experience.

src/cmds/logs.ts (1)

4-9: LGTM! Consistent interface refactoring.

The interface extension and import changes align with the project's standardization effort to use CommonOptions and centralized error handling.

src/cmds/disable.ts (2)

2-6: LGTM! Consistent with project-wide refactoring.

The interface extension and import changes follow the same pattern applied across other CLI commands for consistency and maintainability.


11-11: Good standardization of error message.

The error message "card-key is required" aligns with the hyphenated flag naming convention and addresses the previous review concern about consistency between the flag name and error message.

src/cmds/toggle.ts (2)

2-4: LGTM: Consistent refactoring pattern applied.

The import changes and interface simplification align perfectly with the broader CLI modernization effort. Extending CommonOptions removes boilerplate while maintaining type safety.


25-28: LGTM: Centralized error handling improves consistency.

The replacement of manual error logging with handleCliError provides consistent error formatting and proper verbose output handling across the CLI.

src/cmds/upload-env.ts (2)

3-5: LGTM: Consistent with refactoring pattern.

The interface simplification and utility import changes follow the established modernization pattern, reducing boilerplate while maintaining functionality.


29-32: LGTM: Error handling correctly centralized.

The error handling follows the same pattern as other commands, providing consistent user experience and proper verbose error reporting.

src/cmds/cards.ts (3)

2-4: LGTM: Adopting standardized utilities and typing.

The addition of both handleCliError and printTable utilities, along with the CommonOptions extension, demonstrates consistent adoption of the CLI modernization pattern.


19-26: LGTM: Standardized table output improves consistency.

The replacement of manual console output with the printTable utility provides consistent formatting across CLI commands. The field selection is appropriate for a card listing.


27-30: LGTM: Error handling follows established pattern.

The centralized error handling with appropriate context ensures consistent error reporting across the CLI.

src/cmds/published.ts (2)

3-5: LGTM: Consistent interface modernization.

The changes follow the established pattern of extending CommonOptions and importing centralized utilities, maintaining consistency across the CLI codebase.


26-29: LGTM: Centralized error handling completed.

The error handling follows the same pattern as other commands, completing the consistent error reporting standardization across the CLI.

README.md (1)

38-46: LGTM! Documentation follows established patterns.

The new command sections are well-structured and consistent with the existing documentation style. The table of contents is properly updated to include all new commands.

src/cmds/merchants.ts (2)

2-4: LGTM! Clean refactoring to shared utilities.

The import changes properly utilize the centralized error handling and table printing utilities, improving consistency across commands.


19-23: LGTM! Improved output formatting and error handling.

The refactoring to use printTable for consistent output formatting and handleCliError for centralized error handling is excellent. This reduces code duplication and improves maintainability.

src/cmds/fetch.ts (2)

3-8: LGTM! Consistent refactoring pattern.

The changes follow the same beneficial pattern seen in other commands, using shared types and utilities for better consistency and maintainability.


30-30: LGTM! Centralized error handling.

Using handleCliError provides consistent error reporting across all commands and reduces code duplication.

src/cmds/upload.ts (2)

3-8: LGTM: Clean refactoring to shared types and centralized error handling.

The changes successfully standardize the command interface by extending CommonOptions and using handleCliError for consistent error reporting across CLI commands.


12-20: Good: Validation moved inside try block for centralized error handling.

Moving the file existence and cardKey validation inside the try block allows the centralized handleCliError function to handle all error cases consistently.

src/cmds/login.ts (2)

29-43: Excellent: Interactive prompting with validation.

The addition of interactive prompting for email and password with appropriate validation (email format and minimum password length) greatly improves the user experience.


73-81: Good: Improved credential file handling.

The enhanced logic to create the credentials directory and initialize an empty credentials file if it doesn't exist is a solid improvement for first-time users.

src/cmds/ai.ts (2)

95-98: Good: Interactive prompting improves usability.

Adding interactive prompting when no prompt is provided enhances the user experience and makes the command more user-friendly.


172-177:

Details

❓ Verification inconclusive

Verify: Conditional OpenAI configuration logic.

The logic to use sandbox API when OpenAI key is missing looks correct, but ensure that the sandbox endpoint properly supports the GPT-4.1 model being requested.


🏁 Script executed:

#!/bin/bash
# Verify if the sandbox endpoint supports GPT-4.1 model
curl -s "https://ipb.sandboxpay.co.za/proxy/v1/models" -H "Authorization: Bearer test" | jq '.data[] | select(.id | contains("gpt-4"))'

Length of output: 193


Verify GPT-4.1 support on sandbox endpoint

We attempted to list models from https://ipb.sandboxpay.co.za/proxy/v1/models using a dummy token but received a JSON parse error, indicating the endpoint’s response may not include GPT-4.x. Please manually confirm that the sandbox proxy supports the GPT-4.1 model (e.g., via API docs or by reaching out to the sandbox API team). If it doesn’t, consider falling back to the production OpenAI endpoint or adjusting the model selection logic.

• File: src/cmds/ai.ts
• Lines: 172–177

src/cmds/currencies.ts (2)

2-4: Excellent refactoring to use shared utilities and types.

The adoption of CommonOptions, printTable, and handleCliError utilities improves code consistency and maintainability across the CLI commands.


18-22: Good data simplification for table display.

Mapping currencies to only include Code and Name properties provides a clean, focused output that's easy to read in table format.

src/cmds/countries.ts (1)

2-4: Consistent refactoring pattern applied successfully.

The changes mirror the refactoring in currencies.ts, maintaining consistency across commands by using shared utilities and the CommonOptions interface.

Also applies to: 18-21

src/cmds/transfer.ts (1)

36-43:

Details

❌ Incorrect review comment

Consider using single transfer method for clarity.

Using transferMultiple with a single transfer item seems unnecessarily complex. Verify if a simpler single transfer method exists in the API.


🏁 Script executed:

#!/bin/bash
# Description: Check if the API has a single transfer method that might be more appropriate

# Search for transfer-related methods in the codebase
rg -A 5 "transfer(?!Multiple)" --type ts

Length of output: 274


🏁 Script executed:

#!/bin/bash
set -e

# Search for any "transfer(" calls other than transferMultiple
rg --type ts 'transfer\(' -n | grep -v 'transferMultiple' || echo "No other transfer methods found."

# Locate where transferMultiple is defined to inspect available API methods
rg 'transferMultiple' -n -C3 --type ts

Length of output: 2865


No single-item transfer method exists—transferMultiple is correct

After inspecting the codebase, there is no standalone transfer API call; all transfer operations go through transferMultiple. Using transferMultiple with one item is the only available approach.

Likely an incorrect or invalid review comment.

src/cmds/register.ts (1)

20-34: Excellent interactive prompts with validation.

The addition of interactive prompts with proper validation for email and password improves user experience significantly.

src/index.ts (3)

2-6: Good documentation addition.

The file header clearly explains the purpose and structure, improving maintainability.


100-115: Excellent refactoring to reduce code duplication.

The addApiCredentialOptions helper function effectively implements the DRY principle by centralizing common option declarations across all commands.


117-122: Good UX improvement for first-time users.

Automatically displaying help when no arguments are provided is a standard CLI best practice.

{
"name": "investec-ipb",
"version": "0.8.0",
"version": "0.8.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Ensure version bump alignment.
The package version is updated to 0.8.1. Confirm this matches your release tags and changelog entries.


🏁 Script executed:

#!/bin/bash
# Verify git tag and CHANGELOG consistency
git tag | grep -E "^v?0\.8\.1$" && grep -R "0.8.1" CHANGELOG.md

Length of output: 33


🏁 Script executed:

#!/bin/bash
# Check remote tags for version 0.8.1
git ls-remote --tags origin | grep -E 'refs/tags/v?0\.8\.1$'
# Verify CHANGELOG contains an entry for 0.8.1
grep -R "0.8.1" CHANGELOG.md || true

Length of output: 144


🏁 Script executed:

#!/bin/bash
# List all remotes
echo "=== Remotes ==="
git remote -v

# Check tags on each remote for v0.8.1
echo "=== Checking tags for v0.8.1 ==="
for remote in $(git remote); do
  echo "Remote: $remote"
  git ls-remote --tags "$remote" | grep -E 'refs/tags/v?0\.8\.1$' || echo "  No tag v0.8.1 found on $remote"
done

# Locate any changelog-like files and search for version entry
echo "=== Searching for changelog files ==="
find . -type f -iname "*changelog*" | while read filepath; do
  echo "File: $filepath"
  grep -n "0\.8\.1" "$filepath" || echo "  No entry for 0.8.1 in $filepath"
done

# Fallback: search entire repo for 0.8.1 mentions
echo "=== Grepping entire repo for '0.8.1' ==="
grep -R "0\.8\.1" . || echo "No references to 0.8.1 found in repository"

Length of output: 899


Align version bump across codebase
The version in package.json (0.8.1) and package-lock.json is updated, but the release tag, changelog, and source metadata are out of sync.

Action items:

  • Add and push the git tag for v0.8.1
  • Create or update CHANGELOG.md with an entry for 0.8.1
  • Update the version constant in src/index.ts

Affected locations:

  • src/index.ts
  • (new) CHANGELOG.md
  • Git tags on origin remote

Example diff for src/index.ts:

--- a/src/index.ts
+++ b/src/index.ts
@@ -1,3 +1,3 @@
-const version = "0.8.1-rc.3";
+const version = "0.8.1";

And then:

git tag v0.8.1
git push origin v0.8.1
🤖 Prompt for AI Agents
In package.json at line 3, the version is updated to 0.8.1 but the release tag,
changelog, and source metadata are not aligned. To fix this, create and push a
git tag named v0.8.1 to the origin remote, add or update the CHANGELOG.md file
with an entry for version 0.8.1, and update the version constant in src/index.ts
to 0.8.1 to keep all version references consistent.

Comment on lines 18 to 22
- run: npm ci
- run: npm run build --if-present
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding pre-publish safety checks.

The publish workflow could benefit from additional safety measures before publishing to npm.

Consider adding these steps before publishing:

      - run: npm ci
      - run: npm run build --if-present
+     - run: npm test --if-present
+     - run: npm audit --audit-level=moderate
+     - name: Verify package contents
+       run: npm pack --dry-run
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

This adds:

  • Test execution before publish
  • Security audit check
  • Package content verification
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- run: npm ci
- run: npm run build --if-present
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- run: npm ci
- run: npm run build --if-present
- run: npm test --if-present
- run: npm audit --audit-level=moderate
- name: Verify package contents
run: npm pack --dry-run
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
🤖 Prompt for AI Agents
In .github/workflows/publish.yml around lines 18 to 22, the publish step lacks
pre-publish safety checks. Add steps before the npm publish command to run tests
(e.g., npm test), perform a security audit (e.g., npm audit), and verify package
contents (e.g., npm pack --dry-run) to ensure code quality and security before
publishing.

Comment on lines +50 to +52
if (error.message && error.message === "Bad Request") {
console.log("");
console.error(`Account with ID ${accountId} not found.`);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error message comparison for robustness.

String comparison with error.message === "Bad Request" is fragile and could break if the API error format changes. Consider checking the HTTP status code or error type instead.

-    if (error.message && error.message === "Bad Request") {
+    if (error.status === 400 || error.statusCode === 400) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (error.message && error.message === "Bad Request") {
console.log("");
console.error(`Account with ID ${accountId} not found.`);
if (error.status === 400 || error.statusCode === 400) {
console.log("");
console.error(`Account with ID ${accountId} not found.`);
🤖 Prompt for AI Agents
In src/cmds/transactions.ts around lines 50 to 52, the code compares
error.message directly to "Bad Request", which is fragile. Instead, modify the
error handling to check the HTTP status code or a specific error type property
from the error object if available. This will make the error detection more
robust against changes in the error message format.

Comment on lines +144 to +161
// thin out responses as they use too many tokens
export async function getAccountTransactions(options: {
accountId: string;
fromDate: string;
toDate: string;
}): Promise<AccountTransaction[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(
`💳 fetching transactions for account ${options.accountId}, fromDate: ${options.fromDate}, toDate: ${options.toDate}`,
);
const result = await api.getAccountTransactions(
options.accountId,
"2025-05-24",
options.toDate,
);
const transactions = result.data.transactions;
return transactions;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Use the fromDate parameter instead of hardcoded date.

The function accepts a fromDate parameter but uses a hardcoded date "2025-05-24" instead.

   const result = await api.getAccountTransactions(
     options.accountId,
-    "2025-05-24",
+    options.fromDate,
     options.toDate,
   );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// thin out responses as they use too many tokens
export async function getAccountTransactions(options: {
accountId: string;
fromDate: string;
toDate: string;
}): Promise<AccountTransaction[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(
`💳 fetching transactions for account ${options.accountId}, fromDate: ${options.fromDate}, toDate: ${options.toDate}`,
);
const result = await api.getAccountTransactions(
options.accountId,
"2025-05-24",
options.toDate,
);
const transactions = result.data.transactions;
return transactions;
}
// thin out responses as they use too many tokens
export async function getAccountTransactions(options: {
accountId: string;
fromDate: string;
toDate: string;
}): Promise<AccountTransaction[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(
`💳 fetching transactions for account ${options.accountId}, fromDate: ${options.fromDate}, toDate: ${options.toDate}`,
);
const result = await api.getAccountTransactions(
options.accountId,
options.fromDate,
options.toDate,
);
const transactions = result.data.transactions;
return transactions;
}
🤖 Prompt for AI Agents
In src/function-calls.ts between lines 144 and 161, the getAccountTransactions
function incorrectly uses a hardcoded date "2025-05-24" instead of the fromDate
parameter passed in options. Replace the hardcoded date with options.fromDate in
the call to api.getAccountTransactions to correctly use the provided fromDate
value.

Comment on lines +171 to +190
export async function transferMultiple(options: {
accountId: string;
beneficiaryAccountId: string;
amount: string;
myReference: string;
theirReference: string;
}): Promise<Transfer[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(`💳 transfering for account ${options.accountId}`);
const transfer: TransferMultiple = {
beneficiaryAccountId: options.beneficiaryAccountId,
amount: "10", // hardcoded for testing
myReference: options.myReference,
theirReference: options.theirReference,
};
// Fix: always pass as array to match type signature
const result = await api.transferMultiple(options.accountId, [transfer]);
const transferResponse = result.data.TransferResponses;
return transferResponse;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove hardcoded amount - serious bug for transfers.

The function ignores the provided amount and always transfers "10". This is a critical issue that could cause incorrect transfers.

   const transfer: TransferMultiple = {
     beneficiaryAccountId: options.beneficiaryAccountId,
-    amount: "10", // hardcoded for testing
+    amount: options.amount,
     myReference: options.myReference,
     theirReference: options.theirReference,
   };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function transferMultiple(options: {
accountId: string;
beneficiaryAccountId: string;
amount: string;
myReference: string;
theirReference: string;
}): Promise<Transfer[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(`💳 transfering for account ${options.accountId}`);
const transfer: TransferMultiple = {
beneficiaryAccountId: options.beneficiaryAccountId,
amount: "10", // hardcoded for testing
myReference: options.myReference,
theirReference: options.theirReference,
};
// Fix: always pass as array to match type signature
const result = await api.transferMultiple(options.accountId, [transfer]);
const transferResponse = result.data.TransferResponses;
return transferResponse;
}
export async function transferMultiple(options: {
accountId: string;
beneficiaryAccountId: string;
amount: string;
myReference: string;
theirReference: string;
}): Promise<Transfer[]> {
const api = await initializePbApi(credentials, {} as Options);
console.log(`💳 transfering for account ${options.accountId}`);
const transfer: TransferMultiple = {
beneficiaryAccountId: options.beneficiaryAccountId,
amount: options.amount,
myReference: options.myReference,
theirReference: options.theirReference,
};
// Fix: always pass as array to match type signature
const result = await api.transferMultiple(options.accountId, [transfer]);
const transferResponse = result.data.TransferResponses;
return transferResponse;
}
🤖 Prompt for AI Agents
In src/function-calls.ts around lines 171 to 190, the transferMultiple function
currently hardcodes the amount as "10" instead of using the amount provided in
the options parameter. To fix this, replace the hardcoded "10" string with
options.amount so the transfer amount correctly reflects the caller's input and
prevents incorrect transfer values.

Comment on lines +28 to +36
export async function getWeather(latitude: number, longitude: number) {
return "24C";
const response = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`,
);
const data = await response.json();
// Type assertion to fix 'unknown' type error
return (data as any).current.temperature_2m;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove or properly handle the unreachable weather API code.

The function returns a hardcoded value immediately, making the actual API call unreachable. This will always return "24C" regardless of the coordinates.

Either remove the unreachable code or properly implement the function:

 export async function getWeather(latitude: number, longitude: number) {
-  return "24C";
+  // For testing/mock mode
+  if (process.env.DEBUG === "true") {
+    return "24C";
+  }
   const response = await fetch(
     `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`,
   );
   const data = await response.json();
-  // Type assertion to fix 'unknown' type error
-  return (data as any).current.temperature_2m;
+  return `${(data as any).current.temperature_2m}C`;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function getWeather(latitude: number, longitude: number) {
return "24C";
const response = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`,
);
const data = await response.json();
// Type assertion to fix 'unknown' type error
return (data as any).current.temperature_2m;
}
export async function getWeather(latitude: number, longitude: number) {
// For testing/mock mode
if (process.env.DEBUG === "true") {
return "24C";
}
const response = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m`,
);
const data = await response.json();
return `${(data as any).current.temperature_2m}C`;
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 30-35: This code is unreachable

... because this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🤖 Prompt for AI Agents
In src/function-calls.ts around lines 28 to 36, the function getWeather
immediately returns a hardcoded value "24C", making the subsequent API call and
data processing unreachable. To fix this, remove the early return statement so
the function performs the fetch call, processes the response, and returns the
actual temperature data from the API based on the given latitude and longitude.

@devinpearson devinpearson merged commit b7cb0e0 into main Jun 9, 2025
4 of 5 checks passed
@devinpearson devinpearson deleted the ai-refactor branch June 9, 2025 12:50
@coderabbitai coderabbitai bot mentioned this pull request Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants