@tolinax/ayoune-cli 2026.2.1 → 2026.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/data/defaultActions.js +9 -0
  2. package/data/modelsAndRights.js +3189 -0
  3. package/data/modules.js +111 -0
  4. package/data/operations.js +5 -0
  5. package/data/services.js +139 -0
  6. package/lib/api/apiCallHandler.js +68 -0
  7. package/lib/api/apiClient.js +100 -0
  8. package/lib/api/auditCallHandler.js +21 -0
  9. package/lib/api/decodeToken.js +4 -0
  10. package/lib/api/handleAPIError.js +59 -0
  11. package/lib/api/login.js +45 -0
  12. package/lib/commands/createActionsCommand.js +109 -0
  13. package/lib/commands/createAiCommand.js +188 -0
  14. package/lib/commands/createAliasCommand.js +106 -0
  15. package/lib/commands/createAuditCommand.js +49 -0
  16. package/lib/commands/createCompletionsCommand.js +136 -0
  17. package/lib/commands/createConfigCommand.js +208 -0
  18. package/lib/commands/createCopyCommand.js +39 -0
  19. package/lib/commands/createCreateCommand.js +50 -0
  20. package/lib/commands/createDeployCommand.js +666 -0
  21. package/lib/commands/createDescribeCommand.js +42 -0
  22. package/lib/commands/createEditCommand.js +43 -0
  23. package/lib/commands/createEventsCommand.js +60 -0
  24. package/lib/commands/createExecCommand.js +182 -0
  25. package/lib/commands/createGetCommand.js +47 -0
  26. package/lib/commands/createListCommand.js +49 -0
  27. package/lib/commands/createLoginCommand.js +18 -0
  28. package/lib/commands/createLogoutCommand.js +21 -0
  29. package/lib/commands/createModulesCommand.js +89 -0
  30. package/lib/commands/createMonitorCommand.js +283 -0
  31. package/lib/commands/createProgram.js +163 -0
  32. package/lib/commands/createServicesCommand.js +228 -0
  33. package/lib/commands/createStorageCommand.js +54 -0
  34. package/lib/commands/createStreamCommand.js +50 -0
  35. package/lib/commands/createWhoAmICommand.js +88 -0
  36. package/lib/exitCodes.js +6 -0
  37. package/lib/helpers/addSpacesToCamelCase.js +5 -0
  38. package/lib/helpers/config.js +6 -0
  39. package/lib/helpers/configLoader.js +60 -0
  40. package/lib/helpers/formatDocument.js +176 -0
  41. package/lib/helpers/handleResponseFormatOptions.js +85 -0
  42. package/lib/helpers/initializeSettings.js +14 -0
  43. package/lib/helpers/localStorage.js +4 -0
  44. package/lib/helpers/makeRandomToken.js +27 -0
  45. package/lib/helpers/parseInt.js +7 -0
  46. package/lib/helpers/requireArg.js +9 -0
  47. package/lib/helpers/saveFile.js +39 -0
  48. package/lib/models/getCollections.js +15 -0
  49. package/lib/models/getModelsInModules.js +13 -0
  50. package/lib/models/getModuleFromCollection.js +7 -0
  51. package/lib/operations/handleAuditOperation.js +22 -0
  52. package/lib/operations/handleCollectionOperation.js +91 -0
  53. package/lib/operations/handleCopySingleOperation.js +22 -0
  54. package/lib/operations/handleCreateSingleOperation.js +35 -0
  55. package/lib/operations/handleDeleteSingleOperation.js +14 -0
  56. package/lib/operations/handleDescribeSingleOperation.js +22 -0
  57. package/lib/operations/handleEditOperation.js +51 -0
  58. package/lib/operations/handleEditRawOperation.js +35 -0
  59. package/lib/operations/handleGetOperation.js +29 -0
  60. package/lib/operations/handleGetSingleOperation.js +20 -0
  61. package/lib/operations/handleListOperation.js +63 -0
  62. package/lib/operations/handleSingleAuditOperation.js +27 -0
  63. package/lib/prompts/promptAudits.js +15 -0
  64. package/lib/prompts/promptCollection.js +13 -0
  65. package/lib/prompts/promptCollectionInModule.js +13 -0
  66. package/lib/prompts/promptCollectionWithModule.js +15 -0
  67. package/lib/prompts/promptConfirm.js +12 -0
  68. package/lib/prompts/promptDefaultAction.js +13 -0
  69. package/lib/prompts/promptEntry.js +19 -0
  70. package/lib/prompts/promptFileName.js +12 -0
  71. package/lib/prompts/promptFilePath.js +18 -0
  72. package/lib/prompts/promptModule.js +19 -0
  73. package/lib/prompts/promptName.js +11 -0
  74. package/lib/prompts/promptOperation.js +13 -0
  75. package/lib/socket/customerSocketClient.js +13 -0
  76. package/lib/socket/socketClient.js +12 -0
  77. package/lib/types.js +1 -0
  78. package/package.json +2 -2
@@ -0,0 +1,188 @@
1
+ import { apiCallHandler } from "../api/apiCallHandler.js";
2
+ import { api } from "../api/apiClient.js";
3
+ import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
4
+ import { saveFile } from "../helpers/saveFile.js";
5
+ import { localStorage } from "../helpers/localStorage.js";
6
+ import { spinner } from "../../index.js";
7
+ import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
8
+ const AI_HOST = "ai.ayoune.app";
9
+ export function createAiCommand(program) {
10
+ const ai = program
11
+ .command("ai")
12
+ .description("Interact with aYOUne AI services");
13
+ // ay ai actions — list all AI endpoints
14
+ ai.command("actions")
15
+ .description("List all registered AI API actions")
16
+ .action(async () => {
17
+ try {
18
+ const opts = { ...program.opts() };
19
+ spinner.start({ text: "Fetching AI actions...", color: "magenta" });
20
+ const res = await apiCallHandler("config", "ayouneapiactions", "get", null, {
21
+ q: "ai",
22
+ limit: 200,
23
+ responseFormat: "json",
24
+ });
25
+ if (!(res === null || res === void 0 ? void 0 : res.payload)) {
26
+ spinner.error({ text: "No AI actions found" });
27
+ return;
28
+ }
29
+ const actions = (Array.isArray(res.payload) ? res.payload : [])
30
+ .filter((a) => a.nameSpace === "ai" && !a.deprecated)
31
+ .map((a) => ({
32
+ operationId: a.operationId || "",
33
+ method: (a.method || "GET").toUpperCase(),
34
+ endpoint: a.endpoint || "",
35
+ description: a.shortDescription || a.description || "",
36
+ }));
37
+ const formattedRes = {
38
+ payload: actions,
39
+ meta: { responseTime: 0, pageInfo: { totalEntries: actions.length, page: 1, totalPages: 1 } },
40
+ };
41
+ handleResponseFormatOptions(opts, formattedRes);
42
+ spinner.success({ text: `Found ${actions.length} AI actions` });
43
+ spinner.stop();
44
+ }
45
+ catch (e) {
46
+ spinner.error({ text: e.message || "Failed to fetch AI actions" });
47
+ process.exit(EXIT_GENERAL_ERROR);
48
+ }
49
+ });
50
+ // ay ai conversations — list AI conversations
51
+ ai.command("conversations")
52
+ .description("List AI conversations")
53
+ .option("-l, --limit <number>", "Limit", parseInt, 20)
54
+ .option("-p, --page <number>", "Page", parseInt, 1)
55
+ .action(async (options) => {
56
+ var _a, _b, _c;
57
+ try {
58
+ const opts = { ...program.opts(), ...options };
59
+ spinner.start({ text: "Fetching AI conversations...", color: "magenta" });
60
+ const res = await apiCallHandler("ai", "conversations", "get", null, {
61
+ page: opts.page,
62
+ limit: opts.limit,
63
+ responseFormat: opts.responseFormat,
64
+ verbosity: opts.verbosity,
65
+ hideMeta: opts.hideMeta,
66
+ });
67
+ const { plainResult, result, content } = handleResponseFormatOptions(opts, res);
68
+ const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
69
+ spinner.success({ text: `Got ${total} AI conversations` });
70
+ spinner.stop();
71
+ if (opts.save)
72
+ await saveFile("ai-conversations", opts, res);
73
+ }
74
+ catch (e) {
75
+ spinner.error({ text: e.message || "Failed to list conversations" });
76
+ process.exit(EXIT_GENERAL_ERROR);
77
+ }
78
+ });
79
+ // ay ai prompts — list AI prompt templates
80
+ ai.command("prompts")
81
+ .description("List AI prompt templates")
82
+ .option("-l, --limit <number>", "Limit", parseInt, 20)
83
+ .option("-p, --page <number>", "Page", parseInt, 1)
84
+ .action(async (options) => {
85
+ var _a, _b, _c;
86
+ try {
87
+ const opts = { ...program.opts(), ...options };
88
+ spinner.start({ text: "Fetching AI prompts...", color: "magenta" });
89
+ const res = await apiCallHandler("ai", "prompts", "get", null, {
90
+ page: opts.page,
91
+ limit: opts.limit,
92
+ responseFormat: opts.responseFormat,
93
+ verbosity: opts.verbosity,
94
+ hideMeta: opts.hideMeta,
95
+ });
96
+ const { plainResult, result, content } = handleResponseFormatOptions(opts, res);
97
+ const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
98
+ spinner.success({ text: `Got ${total} AI prompts` });
99
+ spinner.stop();
100
+ if (opts.save)
101
+ await saveFile("ai-prompts", opts, res);
102
+ }
103
+ catch (e) {
104
+ spinner.error({ text: e.message || "Failed to list prompts" });
105
+ process.exit(EXIT_GENERAL_ERROR);
106
+ }
107
+ });
108
+ // ay ai ask <prompt> — send a prompt to AI
109
+ ai.command("ask <prompt...>")
110
+ .description("Send a prompt to aYOUne AI")
111
+ .option("--conversation <id>", "Continue an existing conversation")
112
+ .option("--model <model>", "AI model to use")
113
+ .action(async (promptWords, options) => {
114
+ try {
115
+ const opts = { ...program.opts(), ...options };
116
+ const prompt = promptWords.join(" ");
117
+ spinner.start({ text: "Sending prompt to AI...", color: "magenta" });
118
+ const body = { prompt };
119
+ if (opts.conversation)
120
+ body.conversationId = opts.conversation;
121
+ if (opts.model)
122
+ body.model = opts.model;
123
+ const res = await apiCallHandler("ai", "ask", "post", body, {
124
+ responseFormat: opts.responseFormat,
125
+ verbosity: opts.verbosity,
126
+ hideMeta: opts.hideMeta,
127
+ });
128
+ const { plainResult, result, content } = handleResponseFormatOptions(opts, res);
129
+ spinner.success({ text: "AI response received" });
130
+ spinner.stop();
131
+ if (opts.save)
132
+ await saveFile("ai-ask", opts, res);
133
+ }
134
+ catch (e) {
135
+ spinner.error({ text: e.message || "AI request failed" });
136
+ process.exit(EXIT_GENERAL_ERROR);
137
+ }
138
+ });
139
+ // ay ai generate <type> <prompt> — generate content
140
+ ai.command("generate <type> <prompt...>")
141
+ .description("Generate content (text, image, video)")
142
+ .addHelpText("after", `
143
+ Types: text, image, video
144
+
145
+ Examples:
146
+ ay ai generate text "Write a product description for..."
147
+ ay ai generate image "A modern office building"`)
148
+ .action(async (type, promptWords, options) => {
149
+ try {
150
+ const opts = { ...program.opts(), ...options };
151
+ const prompt = promptWords.join(" ");
152
+ const typeHostMap = {
153
+ text: "text-generation",
154
+ image: "image-generation",
155
+ video: "video-generation",
156
+ };
157
+ const host = typeHostMap[type];
158
+ if (!host) {
159
+ spinner.error({ text: `Unknown type: ${type}. Use: text, image, video` });
160
+ process.exit(EXIT_GENERAL_ERROR);
161
+ }
162
+ spinner.start({ text: `Generating ${type}...`, color: "magenta" });
163
+ const response = await api({
164
+ baseURL: `https://${host}.ayoune.app`,
165
+ method: "post",
166
+ url: "/generate",
167
+ data: { prompt },
168
+ params: {
169
+ responseFormat: opts.responseFormat,
170
+ verbosity: opts.verbosity,
171
+ },
172
+ headers: {
173
+ Authorization: `Bearer ${localStorage.getItem("token")}`,
174
+ },
175
+ });
176
+ const res = response.data;
177
+ handleResponseFormatOptions(opts, res);
178
+ spinner.success({ text: `${type} generation complete` });
179
+ spinner.stop();
180
+ if (opts.save)
181
+ await saveFile(`ai-generate-${type}`, opts, res);
182
+ }
183
+ catch (e) {
184
+ spinner.error({ text: e.message || `${type} generation failed` });
185
+ process.exit(EXIT_GENERAL_ERROR);
186
+ }
187
+ });
188
+ }
@@ -0,0 +1,106 @@
1
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
2
+ import path from "path";
3
+ import os from "os";
4
+ import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
5
+ import { spinner } from "../../index.js";
6
+ const ALIASES_PATH = path.join(os.homedir(), ".config", "ayoune", "aliases.json");
7
+ export function loadAliases() {
8
+ if (!existsSync(ALIASES_PATH)) {
9
+ return {};
10
+ }
11
+ try {
12
+ return JSON.parse(readFileSync(ALIASES_PATH, "utf-8"));
13
+ }
14
+ catch (_a) {
15
+ return {};
16
+ }
17
+ }
18
+ function saveAliases(aliases) {
19
+ const dir = path.dirname(ALIASES_PATH);
20
+ if (!existsSync(dir)) {
21
+ mkdirSync(dir, { recursive: true });
22
+ }
23
+ writeFileSync(ALIASES_PATH, JSON.stringify(aliases, null, 2), "utf-8");
24
+ }
25
+ export function createAliasCommand(program) {
26
+ const alias = program
27
+ .command("alias")
28
+ .description("Manage custom command aliases")
29
+ .addHelpText("after", `
30
+ Examples:
31
+ ay alias set ll "list leads" Create alias 'll' for 'list leads'
32
+ ay alias list Show all custom aliases
33
+ ay alias remove ll Remove the 'll' alias`);
34
+ alias
35
+ .command("set <name> <command>")
36
+ .description("Create or update a custom alias")
37
+ .action((name, command) => {
38
+ try {
39
+ const aliases = loadAliases();
40
+ aliases[name] = command;
41
+ saveAliases(aliases);
42
+ spinner.success({ text: `Alias '${name}' set to '${command}'` });
43
+ }
44
+ catch (e) {
45
+ spinner.error({ text: e.message || "Failed to save alias" });
46
+ process.exit(EXIT_GENERAL_ERROR);
47
+ }
48
+ });
49
+ alias
50
+ .command("list")
51
+ .description("List all custom aliases")
52
+ .action(() => {
53
+ const aliases = loadAliases();
54
+ const entries = Object.entries(aliases);
55
+ if (entries.length === 0) {
56
+ console.log("No custom aliases defined.");
57
+ return;
58
+ }
59
+ for (const [name, command] of entries) {
60
+ console.log(` ${name} -> ${command}`);
61
+ }
62
+ });
63
+ alias
64
+ .command("remove <name>")
65
+ .description("Remove a custom alias")
66
+ .action((name) => {
67
+ try {
68
+ const aliases = loadAliases();
69
+ if (!(name in aliases)) {
70
+ spinner.error({ text: `Alias '${name}' not found` });
71
+ process.exit(EXIT_MISUSE);
72
+ }
73
+ delete aliases[name];
74
+ saveAliases(aliases);
75
+ spinner.success({ text: `Alias '${name}' removed` });
76
+ }
77
+ catch (e) {
78
+ spinner.error({ text: e.message || "Failed to remove alias" });
79
+ process.exit(EXIT_GENERAL_ERROR);
80
+ }
81
+ });
82
+ }
83
+ export function registerUserAliases(program) {
84
+ const aliases = loadAliases();
85
+ for (const [name, command] of Object.entries(aliases)) {
86
+ // Check if we'd conflict with a built-in command
87
+ const existing = program.commands.find((cmd) => cmd.name() === name || cmd.aliases().includes(name));
88
+ if (existing)
89
+ continue;
90
+ program
91
+ .command(name)
92
+ .description(`Alias for '${command}'`)
93
+ .allowUnknownOption()
94
+ .allowExcessArguments()
95
+ .action(async (...args) => {
96
+ // Re-parse with the aliased command substituted in
97
+ const argv = process.argv.slice(0, 2).concat(command.split(/\s+/));
98
+ // Append any extra args passed after the alias
99
+ const extraArgs = args.slice(0, -1); // last arg is the Command object
100
+ if (Array.isArray(extraArgs[0])) {
101
+ argv.push(...extraArgs[0]);
102
+ }
103
+ program.parse(argv);
104
+ });
105
+ }
106
+ }
@@ -0,0 +1,49 @@
1
+ import { Argument } from "commander";
2
+ import { localStorage } from "../helpers/localStorage.js";
3
+ import { handleAuditOperation } from "../operations/handleAuditOperation.js";
4
+ import { promptAudits } from "../prompts/promptAudits.js";
5
+ import { handleSingleAuditOperation } from "../operations/handleSingleAuditOperation.js";
6
+ import yaml from "js-yaml";
7
+ import { spinner } from "../../index.js";
8
+ import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
9
+ export function createAuditCommand(program) {
10
+ program
11
+ .command("audit")
12
+ .addArgument(new Argument("[collection]", "The collection to use").default(localStorage.getItem("lastCollection"), `The last used collection (${localStorage.getItem("lastCollection")})`))
13
+ .addArgument(new Argument("[id]", "The id to get the audit from").default(localStorage.getItem("lastId"), `The last used id (${localStorage.getItem("lastId")})`))
14
+ .alias("history")
15
+ .description("View the change history of an entry")
16
+ .addHelpText("after", `
17
+ Examples:
18
+ ay audit contacts 64a1b2c3d4e5 View audit trail for a contact
19
+ ay history View audit for last used entry`)
20
+ .action(async (collection, id, options) => {
21
+ try {
22
+ if (!collection) {
23
+ spinner.error({ text: "Missing required argument: collection. Run a list or get command first, or provide it explicitly." });
24
+ process.exit(EXIT_MISUSE);
25
+ }
26
+ if (!id) {
27
+ spinner.error({ text: "Missing required argument: id. Provide an entry ID explicitly." });
28
+ process.exit(EXIT_MISUSE);
29
+ }
30
+ const opts = { ...program.opts(), ...options };
31
+ const { data, content, result, meta } = await handleAuditOperation(collection, id, {
32
+ ...opts,
33
+ });
34
+ if (!process.stdin.isTTY) {
35
+ spinner.error({ text: "The audit command requires an interactive terminal for audit selection" });
36
+ process.exit(EXIT_MISUSE);
37
+ }
38
+ const selectedAudit = await promptAudits(result);
39
+ const { singleData, singleContent, singleResult, singleMeta } = await handleSingleAuditOperation(collection, id, selectedAudit, {
40
+ ...opts,
41
+ });
42
+ console.log(yaml.dump(singleContent));
43
+ }
44
+ catch (e) {
45
+ spinner.error({ text: e.message || "An unexpected error occurred" });
46
+ process.exit(EXIT_GENERAL_ERROR);
47
+ }
48
+ });
49
+ }
@@ -0,0 +1,136 @@
1
+ const BASH_COMPLETION = `###-begin-ay-completions-###
2
+ _ay_completions() {
3
+ local cur commands
4
+ COMPREPLY=()
5
+ cur="\${COMP_WORDS[COMP_CWORD]}"
6
+ commands="modules list get edit copy create describe audit stream events storage whoami login logout completions alias config actions exec ai services deploy monitor"
7
+
8
+ if [[ \${COMP_CWORD} -eq 1 ]]; then
9
+ COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
10
+ fi
11
+ }
12
+ complete -F _ay_completions ay
13
+ ###-end-ay-completions-###`;
14
+ const ZSH_COMPLETION = `###-begin-ay-completions-###
15
+ _ay() {
16
+ local -a commands
17
+ commands=(
18
+ 'modules:Browse modules interactively'
19
+ 'list:List entries in a collection'
20
+ 'get:Get entries from a collection'
21
+ 'edit:Edit an entry in a collection'
22
+ 'copy:Copy an entry in a collection'
23
+ 'create:Create a new entry in a collection'
24
+ 'describe:Describe an entry in a collection'
25
+ 'audit:View audit history of an entry'
26
+ 'stream:Attach to the live data stream'
27
+ 'events:Attach to the live event bus'
28
+ 'storage:Show current local storage'
29
+ 'whoami:Show your user information'
30
+ 'login:Login to your aYOUne account'
31
+ 'logout:Logout from your aYOUne account'
32
+ 'completions:Generate shell completion script'
33
+ 'alias:Manage command aliases'
34
+ 'config:Manage CLI configuration'
35
+ 'actions:Discover registered API actions'
36
+ 'exec:Execute any API action by operationId'
37
+ 'ai:AI assistant commands'
38
+ 'services:Discover and manage platform services'
39
+ 'deploy:Manage deployments and pipelines'
40
+ 'monitor:Monitor platform activity, logs, and alerts'
41
+ )
42
+ _describe 'command' commands
43
+ }
44
+ compdef _ay ay
45
+ ###-end-ay-completions-###`;
46
+ const FISH_COMPLETION = `###-begin-ay-completions-###
47
+ complete -c ay -n '__fish_use_subcommand' -a modules -d 'Browse modules interactively'
48
+ complete -c ay -n '__fish_use_subcommand' -a list -d 'List entries in a collection'
49
+ complete -c ay -n '__fish_use_subcommand' -a get -d 'Get entries from a collection'
50
+ complete -c ay -n '__fish_use_subcommand' -a edit -d 'Edit an entry in a collection'
51
+ complete -c ay -n '__fish_use_subcommand' -a copy -d 'Copy an entry in a collection'
52
+ complete -c ay -n '__fish_use_subcommand' -a create -d 'Create a new entry in a collection'
53
+ complete -c ay -n '__fish_use_subcommand' -a describe -d 'Describe an entry in a collection'
54
+ complete -c ay -n '__fish_use_subcommand' -a audit -d 'View audit history of an entry'
55
+ complete -c ay -n '__fish_use_subcommand' -a stream -d 'Attach to the live data stream'
56
+ complete -c ay -n '__fish_use_subcommand' -a events -d 'Attach to the live event bus'
57
+ complete -c ay -n '__fish_use_subcommand' -a storage -d 'Show current local storage'
58
+ complete -c ay -n '__fish_use_subcommand' -a whoami -d 'Show your user information'
59
+ complete -c ay -n '__fish_use_subcommand' -a login -d 'Login to your aYOUne account'
60
+ complete -c ay -n '__fish_use_subcommand' -a logout -d 'Logout from your aYOUne account'
61
+ complete -c ay -n '__fish_use_subcommand' -a completions -d 'Generate shell completion script'
62
+ complete -c ay -n '__fish_use_subcommand' -a alias -d 'Manage command aliases'
63
+ complete -c ay -n '__fish_use_subcommand' -a config -d 'Manage CLI configuration'
64
+ complete -c ay -n '__fish_use_subcommand' -a actions -d 'Discover registered API actions'
65
+ complete -c ay -n '__fish_use_subcommand' -a exec -d 'Execute any API action by operationId'
66
+ complete -c ay -n '__fish_use_subcommand' -a ai -d 'AI assistant commands'
67
+ complete -c ay -n '__fish_use_subcommand' -a services -d 'Discover and manage platform services'
68
+ complete -c ay -n '__fish_use_subcommand' -a deploy -d 'Manage deployments and pipelines'
69
+ complete -c ay -n '__fish_use_subcommand' -a monitor -d 'Monitor platform activity, logs, and alerts'
70
+ ###-end-ay-completions-###`;
71
+ const POWERSHELL_COMPLETION = `###-begin-ay-completions-###
72
+ Register-ArgumentCompleter -CommandName ay -ScriptBlock {
73
+ param($wordToComplete, $commandAst, $cursorPosition)
74
+ $commands = @(
75
+ @{ Name = 'modules'; Description = 'Browse modules interactively' }
76
+ @{ Name = 'list'; Description = 'List entries in a collection' }
77
+ @{ Name = 'get'; Description = 'Get entries from a collection' }
78
+ @{ Name = 'edit'; Description = 'Edit an entry in a collection' }
79
+ @{ Name = 'copy'; Description = 'Copy an entry in a collection' }
80
+ @{ Name = 'create'; Description = 'Create a new entry in a collection' }
81
+ @{ Name = 'describe'; Description = 'Describe an entry in a collection' }
82
+ @{ Name = 'audit'; Description = 'View audit history of an entry' }
83
+ @{ Name = 'stream'; Description = 'Attach to the live data stream' }
84
+ @{ Name = 'events'; Description = 'Attach to the live event bus' }
85
+ @{ Name = 'storage'; Description = 'Show current local storage' }
86
+ @{ Name = 'whoami'; Description = 'Show your user information' }
87
+ @{ Name = 'login'; Description = 'Login to your aYOUne account' }
88
+ @{ Name = 'logout'; Description = 'Logout from your aYOUne account' }
89
+ @{ Name = 'completions'; Description = 'Generate shell completion script' }
90
+ @{ Name = 'alias'; Description = 'Manage command aliases' }
91
+ @{ Name = 'config'; Description = 'Manage CLI configuration' }
92
+ @{ Name = 'actions'; Description = 'Discover registered API actions' }
93
+ @{ Name = 'exec'; Description = 'Execute any API action by operationId' }
94
+ @{ Name = 'ai'; Description = 'AI assistant commands' }
95
+ @{ Name = 'services'; Description = 'Discover and manage platform services' }
96
+ @{ Name = 'deploy'; Description = 'Manage deployments and pipelines' }
97
+ @{ Name = 'monitor'; Description = 'Monitor platform activity, logs, and alerts' }
98
+ )
99
+ $commands | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {
100
+ [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Description)
101
+ }
102
+ }
103
+ ###-end-ay-completions-###`;
104
+ export function createCompletionsCommand(program) {
105
+ program
106
+ .command("completions")
107
+ .alias("completion")
108
+ .description("Generate shell completion script")
109
+ .addHelpText("after", `
110
+ Examples:
111
+ ay completions bash >> ~/.bashrc Add bash completions
112
+ ay completions zsh >> ~/.zshrc Add zsh completions
113
+ ay completions fish > ~/.config/fish/completions/ay.fish
114
+ ay completions powershell >> $PROFILE Add PowerShell completions`)
115
+ .argument("<shell>", "Shell type (bash, zsh, fish, powershell)")
116
+ .action((shell) => {
117
+ switch (shell) {
118
+ case "bash":
119
+ console.log(BASH_COMPLETION);
120
+ break;
121
+ case "zsh":
122
+ console.log(ZSH_COMPLETION);
123
+ break;
124
+ case "fish":
125
+ console.log(FISH_COMPLETION);
126
+ break;
127
+ case "powershell":
128
+ case "pwsh":
129
+ console.log(POWERSHELL_COMPLETION);
130
+ break;
131
+ default:
132
+ console.error(`Unknown shell: ${shell}. Supported: bash, zsh, fish, powershell`);
133
+ process.exit(2);
134
+ }
135
+ });
136
+ }