WIP: A simple cli for daily tangled use cases and AI integration. This is for my personal use right now, but happy if others get mileage from it! :)
1import { confirm, input, password, select } from '@inquirer/prompts';
2import { safeValidateIdentifier } from './validation.js';
3
4/**
5 * Prompt for user's AT Protocol identifier (handle or DID)
6 */
7export async function promptForIdentifier(): Promise<string> {
8 return await input({
9 message: 'Enter your AT Protocol identifier (handle or DID):',
10 validate: (value: string) => {
11 if (!value.trim()) {
12 return 'Identifier cannot be empty';
13 }
14
15 const result = safeValidateIdentifier(value.trim());
16 if (!result.success) {
17 return result.error;
18 }
19
20 return true;
21 },
22 });
23}
24
25/**
26 * Prompt for app password
27 */
28export async function promptForPassword(): Promise<string> {
29 return await password({
30 message: 'Enter your app password:',
31 mask: '*',
32 validate: (value: string) => {
33 if (!value) {
34 return 'Password cannot be empty';
35 }
36 return true;
37 },
38 });
39}
40
41/**
42 * Prompt for login credentials
43 * Returns identifier and password
44 */
45export async function promptForLogin(): Promise<{
46 identifier: string;
47 password: string;
48}> {
49 const identifier = await promptForIdentifier();
50 const passwordValue = await promptForPassword();
51
52 return {
53 identifier,
54 password: passwordValue,
55 };
56}
57
58/**
59 * Prompt user to select a Git remote when multiple tangled remotes exist
60 *
61 * @param remotes - Array of available remotes with name and URL
62 * @returns Selected remote name
63 */
64export async function promptForRemoteSelection(
65 remotes: Array<{ name: string; url: string }>
66): Promise<string> {
67 const choices = remotes.map((remote) => ({
68 name: `${remote.name} (${remote.url})`,
69 value: remote.name,
70 }));
71
72 // Default to "origin" if present
73 const defaultValue = remotes.find((r) => r.name === 'origin')?.name;
74
75 return await select({
76 message: 'Multiple tangled.org remotes found. Which one would you like to use?',
77 choices,
78 default: defaultValue,
79 });
80}
81
82/**
83 * Prompt user whether to save remote selection to config
84 *
85 * @returns true if user wants to save
86 */
87export async function promptToSaveRemote(): Promise<boolean> {
88 return await confirm({
89 message: 'Save this remote selection for this repository? (saves to .tangledrc)',
90 default: false,
91 });
92}