Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/cli/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { APP_NAME, CLI_VERSION } from '@meta';
import { flushTelemetry, telemetryMiddleware } from '@utils/index.js';
import {
loginCommand,
logoutCommand,
Expand All @@ -18,7 +20,6 @@ import {
pluginCommand,
migrateCommand,
} from '../src/commands/index.js';
import { APP_NAME, CLI_VERSION } from '@meta';

const cli = yargs(hideBin(process.argv))
.scriptName(APP_NAME)
Expand Down Expand Up @@ -65,6 +66,12 @@ const cli = yargs(hideBin(process.argv))
describe: 'Verbose/diagnostic output',
hidden: true,
})
.option('telemetry', {
type: 'boolean',
default: true,
describe: 'Collect anonymous usage telemetry (disable with --no-telemetry)',
})
.middleware(telemetryMiddleware)
.command(loginCommand)
.command(logoutCommand)
.command(whoamiCommand)
Expand All @@ -91,4 +98,8 @@ const cli = yargs(hideBin(process.argv))
.help()
.version(CLI_VERSION);

cli.parse();
try {
await cli.parseAsync();
} finally {
await flushTelemetry();
}
2 changes: 1 addition & 1 deletion packages/cli/src/commands/docs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Argv } from 'yargs';
import { searchDocs, grepDocs, readDocs } from '@features/docs/index.js';
import { safely } from '../utils/safely.js';
import { safely } from '@utils/index.js';

export const docsCommand = {
command: 'docs <action>',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
deleteEvent,
eventUsage,
} from '@features/events/index.js';
import { safely } from '../utils/safely.js';
import { safely } from '@utils/index.js';

export const eventsCommand = {
command: 'events <action>',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
targetFlagCmd,
archiveFlagCmd,
} from '@features/flags/index.js';
import { safely } from '../utils/safely.js';
import { safely } from '@utils/index.js';

export const flagsCommand = {
command: 'flags <action>',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Argv } from 'yargs';
import { getProviders } from '@spotify-confidence/core';
import { detectAndPrint, launchMigration } from '@features/migrate/index.js';
import { safely } from '../utils/safely.js';
import { safely } from '@utils/index.js';

export const migrateCommand = {
command: 'migrate <action>',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
uninstallPluginForIde,
updatePluginForIde,
} from '@features/plugin/index.js';
import { safely } from '@utils/safely.js';
import { safely } from '@utils/index.js';

export const pluginCommand = {
command: 'plugin <action>',
Expand Down
3 changes: 1 addition & 2 deletions packages/cli/src/commands/recordings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import {
showTargetingKeys,
addTargetingKey,
} from '@features/recordings/index.js';
import { safely } from '../utils/safely.js';
import { validateRange } from '../utils/validation.js';
import { safely, validateRange } from '@utils/index.js';

export const recordingsCommand = {
command: 'recordings <action>',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/docs/grep.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ora from 'ora';
import { grepDocumentation } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const grepDocs = withAuth(async function grepDocs(argv, token) {
const pattern = argv.pattern as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/docs/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import ora from 'ora';
import { CONFIDENCE_DOCS_URL } from '@spotify-confidence/core';
import { getFullSource } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

function normalizeSource(input: string): string {
if (input.includes('://')) return input;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/docs/search.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ora from 'ora';
import { searchDocumentation } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const searchDocs = withAuth(async function searchDocs(argv, token) {
const query = argv.query as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/create.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { JsonObject } from '@spotify-confidence/shared-kernel';
import { createEventDefinition } from '@network/index.js';
import { message, printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';
import { parseFieldArg } from './field-spec.js';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import confirm from '@inquirer/confirm';
import { extractText } from '@spotify-confidence/core';
import { deleteEventDefinition } from '@network/index.js';
import { message, fail } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const deleteEvent = withAuth(async function deleteEvent(argv, token) {
const name = argv.name as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getEventDefinition } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const getEvent = withAuth(async function getEvent(argv, token) {
const name = argv.name as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/list.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { listEventDefinitions } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const listEvents = withAuth(async function listEvents(argv, token) {
const result = await listEventDefinitions(token, {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/update.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { updateEventDefinition } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { parseFieldArg } from './field-spec.js';

export const updateEvent = withAuth(async function updateEvent(argv, token) {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/events/usage.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isDefined } from '@spotify-confidence/shared-kernel';
import { queryEventsUsage } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const eventUsage = withAuth(async function eventUsage(argv, token) {
const name = argv.name as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/archive.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import confirm from '@inquirer/confirm';
import { archiveFlag } from '@network/index.js';
import { message, fail } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const archiveFlagCmd = withAuth(async function archiveFlagCmd(argv, token) {
const flagKey = argv['flag-key'] as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/create.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createFlag } from '@network/index.js';
import { message, printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';

export const createFlagCmd = withAuth(async function createFlagCmd(argv, token) {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getFlag } from '@network/index.js';
import { resolveFormat, formatJson, extractFlags, fail, message, print } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { flagStatus } from './status.js';

export const getFlagCmd = withAuth(async function getFlagCmd(argv, token) {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/list.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { listFlags } from '@network/index.js';
import { resolveFormat, formatJson, extractFlags, fail, message, print } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { flagStatus } from './status.js';

export const listFlagsCmd = withAuth(async function listFlagsCmd(argv, token) {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { resolveFlag } from '@network/index.js';
import { printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

function parseContextPair(spec: string): [string, string] {
const eqIndex = spec.indexOf('=');
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
print,
printMcpResult,
} from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';

function parseAllocations(spec: string): Record<string, number> {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/toggle.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toggleFlag } from '@network/index.js';
import { fail, message } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';

export const toggleFlagCmd = withAuth(async function toggleFlagCmd(argv, token) {
const flagKey = argv['flag-key'] as string;
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/flags/update.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { JsonObject } from '@spotify-confidence/shared-kernel';
import { getFlag, updateFlag } from '@network/index.js';
import { resolveFormat, formatJson, extractFlags, fail, message, print } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { flagStatus } from './status.js';
import { resolveInput } from '@input/index.js';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/add-rule.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addRecordingRule } from '@network/index.js';
import { printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';
import { requireKeys, validateRange } from '@utils/validation.js';
import { tryHandleMcpError } from './format-mcp-error.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/add-targeting-key.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addContextField } from '@network/index.js';
import { printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';
import { requireKeys } from '@utils/validation.js';
import { tryHandleMcpError } from './format-mcp-error.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/create-policy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createRecordingPolicy } from '@network/index.js';
import { printMcpResult } from '@output/index.js';
import { withAuth } from '@utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { resolveInput } from '@input/index.js';
import { requireKeys } from '@utils/validation.js';
import { tryHandleMcpError } from './format-mcp-error.js';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/get-policy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { extractText, parseToolJson } from '@spotify-confidence/core';
import { getRecordingPolicy } from '@network/index.js';
import { resolveFormat, formatJson, message, print, extractFlags } from '@output/index.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { tryHandleMcpError } from './format-mcp-error.js';

type PolicyDetail = {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/list-policies.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { extractText, parseToolJson } from '@spotify-confidence/core';
import { listRecordingPolicies } from '@network/index.js';
import { resolveFormat, formatJson, message, print, extractFlags } from '@output/index.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { tryHandleMcpError } from './format-mcp-error.js';

type PolicyRow = {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/features/recordings/set-rule-enabled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setRecordingRuleEnabled } from '@network/index.js';
import { printMcpResult } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { tryHandleMcpError } from './format-mcp-error.js';

function makeToggle(enabled: boolean) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { extractText, parseToolJson } from '@spotify-confidence/core';
import { getContextSchema } from '@network/index.js';
import { message, print, extractFlags } from '@output/print.js';
import { withAuth } from '../../utils/require-auth.js';
import { withAuth } from '@utils/index.js';
import { tryHandleMcpError } from './format-mcp-error.js';

type ContextField = {
Expand Down
File renamed without changes.
4 changes: 4 additions & 0 deletions packages/cli/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './auth.js';
export * from './safely.js';
export * from './telemetry.js';
export * from './validation.js';
11 changes: 11 additions & 0 deletions packages/cli/src/utils/telemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { initTelemetry, isTelemetryEnabled, getTelemetry, flush } from '@spotify-confidence/core';

export { flush as flushTelemetry };

export function telemetryMiddleware(argv: { telemetry: boolean; _: (string | number)[] }) {
if (!isTelemetryEnabled() || argv.telemetry === false) return;
initTelemetry({ source: 'cli' });

const command = argv._.join('.') || 'unknown';
getTelemetry().track({ step: command, action: 'invoked' });
}
14 changes: 7 additions & 7 deletions packages/core/__tests__/telemetry/telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('when telemetry is initialized', () => {
}),
);

initTelemetry({ sessionId: 'test-session-id' });
initTelemetry({ source: 'test', sessionId: 'test-session-id' });
const sut = getTelemetry();

sut.track({ step: 'welcome.menu', action: 'start' });
Expand All @@ -55,7 +55,7 @@ describe('when telemetry is initialized', () => {
event_definition: 'eventDefinitions/agent-telemetry',
payload: {
session_id: 'test-session-id',
skill: 'wizard',
skill: 'test',
step: 'welcome.menu',
action: 'start',
sentiment: 'neutral',
Expand All @@ -81,7 +81,7 @@ describe('when telemetry is initialized', () => {
}),
);

initTelemetry({ sessionId: 'region-test' });
initTelemetry({ source: 'test', sessionId: 'region-test' });
const sut = getTelemetry();

sut.track({ step: 'warmup', action: 'init' });
Expand Down Expand Up @@ -109,7 +109,7 @@ describe('when telemetry is initialized', () => {
}),
);

initTelemetry({ sessionId: 'defaults-test' });
initTelemetry({ source: 'test', sessionId: 'defaults-test' });
getTelemetry().track({ step: 'test.step', action: 'test' });

await vi.waitFor(() => {
Expand All @@ -133,7 +133,7 @@ describe('when telemetry is initialized', () => {
}),
);

initTelemetry({ sessionId: 'explicit-test' });
initTelemetry({ source: 'test', sessionId: 'explicit-test' });
getTelemetry().track({
step: 'done.action',
action: 'exit',
Expand Down Expand Up @@ -166,7 +166,7 @@ describe('when key acquisition fails', () => {
}),
);

initTelemetry({ sessionId: 'fail-test' });
initTelemetry({ source: 'test', sessionId: 'fail-test' });
const sut = getTelemetry();

sut.track({ step: 'welcome.menu', action: 'start' });
Expand All @@ -185,7 +185,7 @@ describe('when event publishing fails', () => {
}),
);

initTelemetry({ sessionId: 'publish-fail-test' });
initTelemetry({ source: 'test', sessionId: 'publish-fail-test' });
const sut = getTelemetry();

expect(() => sut.track({ step: 'test', action: 'test' })).not.toThrow();
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ export {
initTelemetry,
getTelemetry,
track,
flush,
resetTelemetry,
isTelemetryEnabled,
type TelemetryClient,
type TelemetryOptions,
type TelemetryEvent,
type TelemetrySentiment,
type TelemetryCompletion,
Expand Down
Loading
Loading