🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@voyagier/cli

Package Overview
Dependencies
Maintainers
2
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@voyagier/cli - npm Package Compare versions

Comparing version
2.19.0
to
2.19.1
+3
-1
AGENT.md

@@ -277,2 +277,4 @@ # Voyagier CLI — Agent Reference

Argument-parse failures (unknown option, missing required option/argument, invalid argument value) also honor this envelope **when you pass `--json`**: they emit `{ "error": true, "code": "VALIDATION", "message": ... }` on stdout and exit 1. Without `--json` those failures print a bare `error: ...` line to stderr instead — so always drive the CLI with `--json` if you parse stdout.
### Error codes (what the CLI actually emits today)

@@ -444,3 +446,3 @@

voyagier travellers list --plan <id> --json
voyagier travellers update <travellerId> [...] --json # incl. --frequent-flyer / --hotel-loyalty (replace) and --clear-frequent-flyer / --clear-hotel-loyalty
voyagier travellers update <travellerId> [--plan <id>] [...] --json # --plan is optional context (the traveller id already identifies the record); incl. --frequent-flyer / --hotel-loyalty (replace) and --clear-frequent-flyer / --clear-hotel-loyalty
voyagier travellers remove <travellerId> --json

@@ -447,0 +449,0 @@ ```

import { Command } from "commander";
import { CliErrorCode } from "./errors.js";
import { registerAuthCommands } from "./commands/auth.js";

@@ -27,2 +28,21 @@ import { registerChatCommands } from "./commands/chat.js";

import { registerMcpCommand } from "./commands/mcp.js";
export function routeParseErrorsToJson(cmd) {
cmd.configureOutput({
outputError: (str, write) => {
if (argvRequestsJson(process.argv)) {
const message = str.replace(/\n+$/, "");
process.stdout.write(JSON.stringify({ error: true, code: CliErrorCode.VALIDATION, message }, null, 2) + "\n");
}
else {
write(str);
}
},
});
cmd.commands.forEach(routeParseErrorsToJson);
}
export function argvRequestsJson(argv) {
const terminator = argv.indexOf("--");
const options = terminator === -1 ? argv : argv.slice(0, terminator);
return options.includes("--json");
}
export function buildProgram(version) {

@@ -69,3 +89,4 @@ const program = new Command();

registerMcpCommand(program);
routeParseErrorsToJson(program);
return program;
}

@@ -11,3 +11,3 @@ import chalk from "chalk";

import { CliError } from "../errors.js";
import { DOCTOR_PING } from "../queries.js";
import { DOCTOR_PING, DOCTOR_IDENTITY } from "../queries.js";
import * as queries from "../queries.js";

@@ -54,2 +54,12 @@ export const PERIPHERAL_OP_PATTERN = /(^|_)(PLACES?|COMMENTS?|BOOKING_RECORDS?)(_|$)/;

}
async function resolveAuthIdentity() {
const ctx = getUserContext();
try {
const { me } = await graphql(DOCTOR_IDENTITY);
return me?.email ?? me?.name ?? ctx?.email ?? ctx?.name ?? "unknown";
}
catch {
return ctx?.email ?? ctx?.name ?? "unknown";
}
}
async function checkAuth() {

@@ -65,9 +75,2 @@ if (!credentialsExist()) {

await graphql(DOCTOR_PING);
const ctx = getUserContext();
const who = ctx?.email ?? ctx?.name ?? "unknown";
return {
name: "auth",
status: "PASS",
message: `Authenticated as ${who}`,
};
}

@@ -88,2 +91,8 @@ catch (err) {

}
const who = await resolveAuthIdentity();
return {
name: "auth",
status: "PASS",
message: `Authenticated as ${sanitizeExternalText(who)}`,
};
}

@@ -90,0 +99,0 @@ const DOCTOR_PROBE_TIMEOUT_MS = 5000;

@@ -7,3 +7,3 @@ import { printPlanFooter } from "../plan-footer.js";

import { loadSearchState, clearSearchState, isSearchStateStale } from "../state.js";
import { deriveBaseUrl, shellArg } from "../utils.js";
import { deriveBaseUrl, shellArg, validateId } from "../utils.js";
import { clientPlanUrl, planUrls } from "../plan-urls.js";

@@ -212,13 +212,15 @@ import { GET_PLAN_STATUS } from "../queries.js";

}
if (opts.selectionId || opts.optionId) {
if (!opts.selectionId || !opts.optionId) {
if (opts.selectionId !== undefined || opts.optionId !== undefined) {
if (opts.selectionId === undefined || opts.optionId === undefined) {
throw new CliError(CliErrorCode.VALIDATION, "Direct mode requires BOTH --selection-id and --option-id.");
}
const selectionId = validateId(opts.selectionId, "--selection-id");
const optionId = validateId(opts.optionId, "--option-id");
try {
if (!opts.json)
progress("Selecting option...");
const result = await setSelectedOption(opts.selectionId, opts.optionId, opts);
const name = result.parentOption?.name ?? opts.optionId;
const result = await setSelectedOption(selectionId, optionId, opts);
const name = result.parentOption?.name ?? optionId;
const forScope = scopeLabel(opts);
const waitOutcome = opts.wait ? await runPickWait(opts.selectionId, opts.optionId, opts) : undefined;
const waitOutcome = opts.wait ? await runPickWait(selectionId, optionId, opts) : undefined;
if (opts.json) {

@@ -225,0 +227,0 @@ jsonOutput({

@@ -342,2 +342,3 @@ import { printPlanFooter } from "../plan-footer.js";

.description("Update a traveller's details")
.option("--plan <id>", "Trip plan ID (optional context; the traveller id already identifies the record)")
.option("--first <name>", "First name")

@@ -344,0 +345,0 @@ .option("--last <name>", "Last name")

#!/usr/bin/env node
import { readFileSync } from "fs";
import { buildProgram } from "./build-program.js";
import { buildProgram, argvRequestsJson } from "./build-program.js";
import { trackCommand, getTraceId, isTelemetryEnabled, telemetryErrorCode } from "./telemetry.js";

@@ -58,3 +58,3 @@ import { gracefulExit } from "./exit.js";

if (err instanceof CliError) {
const isJson = process.argv.includes("--json");
const isJson = argvRequestsJson(process.argv);
if (isJson) {

@@ -61,0 +61,0 @@ const payload = { error: true, code: err.code, message: err.message };

@@ -652,2 +652,7 @@ export const GET_CART = `

`;
export const DOCTOR_IDENTITY = `
query DoctorIdentity {
me { email name }
}
`;
export const GET_TRIP_PLAN_EVENTS = `

@@ -654,0 +659,0 @@ query TripPlanEvents($id: String!) {

@@ -98,2 +98,10 @@ import chalk from "chalk";

}
export function validateId(value, flagName) {
const trimmed = value.trim();
const lowered = trimmed.toLowerCase();
if (trimmed === "" || lowered === "null" || lowered === "undefined") {
throw new CliError(CliErrorCode.VALIDATION, `Invalid ${flagName}: "${value}". Pass a real id (an empty or "null"/"undefined" value usually means a broken script or jq extraction).`);
}
return trimmed;
}
export function subSelectionLabel(type) {

@@ -100,0 +108,0 @@ switch (type) {

{
"name": "@voyagier/cli",
"version": "2.19.0",
"version": "2.19.1",
"mcpName": "com.voyagier/cli",

@@ -5,0 +5,0 @@ "description": "Agent-ready travel CLI — search, plan, quote, and book real trips (flights, hotels, activities) against the Voyagier platform. Built for AI agents: --json everywhere, uniform error codes, price-gated checkout, printable agent reference (voyagier agent-docs).",