lua-cli 2.5.7 → 3.0.0-alpha.1

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 (124) hide show
  1. package/dist/api/agent.api.service.d.ts +45 -0
  2. package/dist/api/agent.api.service.js +54 -0
  3. package/dist/api/job.api.service.d.ts +210 -0
  4. package/dist/api/job.api.service.js +200 -0
  5. package/dist/api/lazy-instances.d.ts +24 -0
  6. package/dist/api/lazy-instances.js +48 -0
  7. package/dist/api/postprocessor.api.service.d.ts +98 -0
  8. package/dist/api/postprocessor.api.service.js +76 -0
  9. package/dist/api/preprocessor.api.service.d.ts +98 -0
  10. package/dist/api/preprocessor.api.service.js +76 -0
  11. package/dist/api/user.data.api.service.d.ts +28 -0
  12. package/dist/api/user.data.api.service.js +51 -0
  13. package/dist/api/webhook.api.service.d.ts +151 -0
  14. package/dist/api/webhook.api.service.js +134 -0
  15. package/dist/api-exports.d.ts +156 -41
  16. package/dist/api-exports.js +182 -21
  17. package/dist/cli/command-definitions.js +149 -7
  18. package/dist/commands/compile.js +124 -5
  19. package/dist/commands/completion.d.ts +11 -0
  20. package/dist/commands/completion.js +209 -0
  21. package/dist/commands/env.d.ts +3 -2
  22. package/dist/commands/env.js +42 -17
  23. package/dist/commands/features.d.ts +16 -0
  24. package/dist/commands/features.js +352 -0
  25. package/dist/commands/index.d.ts +7 -0
  26. package/dist/commands/index.js +7 -0
  27. package/dist/commands/init.js +53 -7
  28. package/dist/commands/jobs.d.ts +20 -0
  29. package/dist/commands/jobs.js +533 -0
  30. package/dist/commands/logs.js +2 -5
  31. package/dist/commands/persona.d.ts +3 -2
  32. package/dist/commands/persona.js +43 -18
  33. package/dist/commands/postprocessors.d.ts +8 -0
  34. package/dist/commands/postprocessors.js +431 -0
  35. package/dist/commands/preprocessors.d.ts +8 -0
  36. package/dist/commands/preprocessors.js +431 -0
  37. package/dist/commands/push.d.ts +9 -13
  38. package/dist/commands/push.js +937 -69
  39. package/dist/commands/skills.d.ts +16 -0
  40. package/dist/commands/skills.js +438 -0
  41. package/dist/commands/test.d.ts +9 -18
  42. package/dist/commands/test.js +558 -82
  43. package/dist/commands/webhooks.d.ts +18 -0
  44. package/dist/commands/webhooks.js +424 -0
  45. package/dist/common/data.entry.instance.d.ts +7 -0
  46. package/dist/common/data.entry.instance.js +15 -0
  47. package/dist/common/job.instance.d.ts +77 -0
  48. package/dist/common/job.instance.js +108 -0
  49. package/dist/common/order.instance.d.ts +6 -0
  50. package/dist/common/order.instance.js +14 -0
  51. package/dist/common/product.instance.d.ts +6 -0
  52. package/dist/common/product.instance.js +14 -0
  53. package/dist/common/user.instance.d.ts +15 -0
  54. package/dist/common/user.instance.js +38 -0
  55. package/dist/config/constants.d.ts +2 -2
  56. package/dist/config/constants.js +4 -4
  57. package/dist/index.js +14 -3
  58. package/dist/interfaces/agent.d.ts +33 -1
  59. package/dist/interfaces/chat.d.ts +22 -0
  60. package/dist/interfaces/index.d.ts +10 -0
  61. package/dist/interfaces/index.js +7 -0
  62. package/dist/interfaces/jobs.d.ts +172 -0
  63. package/dist/interfaces/jobs.js +5 -0
  64. package/dist/interfaces/message.d.ts +18 -0
  65. package/dist/interfaces/message.js +1 -0
  66. package/dist/interfaces/postprocessors.d.ts +35 -0
  67. package/dist/interfaces/postprocessors.js +4 -0
  68. package/dist/interfaces/preprocessors.d.ts +35 -0
  69. package/dist/interfaces/preprocessors.js +4 -0
  70. package/dist/interfaces/webhooks.d.ts +104 -0
  71. package/dist/interfaces/webhooks.js +5 -0
  72. package/dist/types/api-contracts.d.ts +14 -0
  73. package/dist/types/api-contracts.js +0 -7
  74. package/dist/types/compile.types.d.ts +49 -0
  75. package/dist/types/index.d.ts +1 -1
  76. package/dist/types/index.js +1 -1
  77. package/dist/types/skill.d.ts +502 -0
  78. package/dist/types/skill.js +477 -0
  79. package/dist/utils/agent-management.d.ts +25 -0
  80. package/dist/utils/agent-management.js +67 -0
  81. package/dist/utils/bundling.d.ts +31 -1
  82. package/dist/utils/bundling.js +653 -10
  83. package/dist/utils/compile.d.ts +63 -0
  84. package/dist/utils/compile.js +691 -36
  85. package/dist/utils/deployment.d.ts +2 -1
  86. package/dist/utils/deployment.js +16 -2
  87. package/dist/utils/init-agent.d.ts +3 -1
  88. package/dist/utils/init-agent.js +6 -4
  89. package/dist/utils/init-prompts.d.ts +2 -1
  90. package/dist/utils/init-prompts.js +14 -9
  91. package/dist/utils/job-management.d.ts +24 -0
  92. package/dist/utils/job-management.js +264 -0
  93. package/dist/utils/postprocessor-management.d.ts +9 -0
  94. package/dist/utils/postprocessor-management.js +118 -0
  95. package/dist/utils/preprocessor-management.d.ts +9 -0
  96. package/dist/utils/preprocessor-management.js +118 -0
  97. package/dist/utils/sandbox.d.ts +61 -1
  98. package/dist/utils/sandbox.js +283 -72
  99. package/dist/utils/tool-detection.d.ts +3 -2
  100. package/dist/utils/tool-detection.js +18 -4
  101. package/dist/utils/webhook-management.d.ts +24 -0
  102. package/dist/utils/webhook-management.js +256 -0
  103. package/dist/web/app.css +152 -736
  104. package/dist/web/app.js +45 -45
  105. package/package.json +2 -2
  106. package/template/AGENT_CONFIGURATION.md +251 -0
  107. package/template/COMPLEX_JOB_EXAMPLES.md +795 -0
  108. package/template/DYNAMIC_JOB_CREATION.md +371 -0
  109. package/template/README.md +30 -2
  110. package/template/WEBHOOKS_JOBS_QUICKSTART.md +318 -0
  111. package/template/WEBHOOK_JOB_EXAMPLES.md +817 -0
  112. package/template/package.json +1 -1
  113. package/template/src/index-agent-example.ts +201 -0
  114. package/template/src/index.ts +39 -0
  115. package/template/src/jobs/AbandonedBasketProcessorJob.ts +139 -0
  116. package/template/src/jobs/DailyCleanupJob.ts +100 -0
  117. package/template/src/jobs/DataMigrationJob.ts +133 -0
  118. package/template/src/jobs/HealthCheckJob.ts +87 -0
  119. package/template/src/postprocessors/ResponseFormatter.ts +151 -0
  120. package/template/src/preprocessors/MessageFilter.ts +91 -0
  121. package/template/src/tools/GameScoreTrackerTool.ts +356 -0
  122. package/template/src/tools/SmartBasketTool.ts +188 -0
  123. package/template/src/webhooks/PaymentWebhook.ts +113 -0
  124. package/template/src/webhooks/UserEventWebhook.ts +77 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Completion Command
3
+ * Generates shell completion scripts for the Lua CLI
4
+ */
5
+ import { withErrorHandling } from '../utils/cli.js';
6
+ /**
7
+ * Bash completion script
8
+ */
9
+ const BASH_COMPLETION = `# Bash completion for lua CLI
10
+ _lua_completion() {
11
+ local cur prev commands
12
+ COMPREPLY=()
13
+ cur="\${COMP_WORDS[COMP_CWORD]}"
14
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
15
+
16
+ # Main commands
17
+ commands="auth init compile test push deploy chat env persona production resources admin docs channels logs skills features completion"
18
+
19
+ # Subcommands
20
+ case "\${prev}" in
21
+ lua)
22
+ COMPREPLY=( $(compgen -W "\${commands}" -- \${cur}) )
23
+ return 0
24
+ ;;
25
+ auth)
26
+ COMPREPLY=( $(compgen -W "configure logout key" -- \${cur}) )
27
+ return 0
28
+ ;;
29
+ push)
30
+ COMPREPLY=( $(compgen -W "skill persona" -- \${cur}) )
31
+ return 0
32
+ ;;
33
+ env)
34
+ COMPREPLY=( $(compgen -W "sandbox staging production" -- \${cur}) )
35
+ return 0
36
+ ;;
37
+ persona)
38
+ COMPREPLY=( $(compgen -W "sandbox staging production" -- \${cur}) )
39
+ return 0
40
+ ;;
41
+ skills)
42
+ COMPREPLY=( $(compgen -W "sandbox staging production" -- \${cur}) )
43
+ return 0
44
+ ;;
45
+ chat)
46
+ COMPREPLY=( $(compgen -W "clear" -- \${cur}) )
47
+ return 0
48
+ ;;
49
+ completion)
50
+ COMPREPLY=( $(compgen -W "bash zsh fish" -- \${cur}) )
51
+ return 0
52
+ ;;
53
+ esac
54
+ }
55
+
56
+ complete -F _lua_completion lua
57
+ `;
58
+ /**
59
+ * Zsh completion script
60
+ */
61
+ const ZSH_COMPLETION = `#compdef lua
62
+
63
+ # Zsh completion for lua CLI
64
+ _lua() {
65
+ local line state
66
+
67
+ _arguments -C \\
68
+ "1: :(auth init compile test push deploy chat env persona production resources admin docs channels logs skills features completion)" \\
69
+ "*::arg:->args"
70
+
71
+ case $line[1] in
72
+ auth)
73
+ _arguments "1: :(configure logout key)"
74
+ ;;
75
+ push)
76
+ _arguments "1: :(skill persona)"
77
+ ;;
78
+ env)
79
+ _arguments "1: :(sandbox staging production)"
80
+ ;;
81
+ persona)
82
+ _arguments "1: :(sandbox staging production)"
83
+ ;;
84
+ skills)
85
+ _arguments "1: :(sandbox staging production)"
86
+ ;;
87
+ chat)
88
+ _arguments "1: :(clear)"
89
+ ;;
90
+ completion)
91
+ _arguments "1: :(bash zsh fish)"
92
+ ;;
93
+ esac
94
+ }
95
+
96
+ _lua
97
+ `;
98
+ /**
99
+ * Fish completion script
100
+ */
101
+ const FISH_COMPLETION = `# Fish completion for lua CLI
102
+
103
+ # Main commands
104
+ complete -c lua -f -n "__fish_use_subcommand" -a "auth" -d "Authentication management"
105
+ complete -c lua -f -n "__fish_use_subcommand" -a "init" -d "Initialize a new project"
106
+ complete -c lua -f -n "__fish_use_subcommand" -a "compile" -d "Compile skill"
107
+ complete -c lua -f -n "__fish_use_subcommand" -a "test" -d "Test skill tools"
108
+ complete -c lua -f -n "__fish_use_subcommand" -a "push" -d "Push skill or persona"
109
+ complete -c lua -f -n "__fish_use_subcommand" -a "deploy" -d "Deploy to production"
110
+ complete -c lua -f -n "__fish_use_subcommand" -a "chat" -d "Interactive chat"
111
+ complete -c lua -f -n "__fish_use_subcommand" -a "env" -d "Manage environment"
112
+ complete -c lua -f -n "__fish_use_subcommand" -a "persona" -d "Manage persona"
113
+ complete -c lua -f -n "__fish_use_subcommand" -a "production" -d "View production"
114
+ complete -c lua -f -n "__fish_use_subcommand" -a "resources" -d "Manage resources"
115
+ complete -c lua -f -n "__fish_use_subcommand" -a "admin" -d "Open admin dashboard"
116
+ complete -c lua -f -n "__fish_use_subcommand" -a "docs" -d "Open documentation"
117
+ complete -c lua -f -n "__fish_use_subcommand" -a "channels" -d "Manage channels"
118
+ complete -c lua -f -n "__fish_use_subcommand" -a "logs" -d "View logs"
119
+ complete -c lua -f -n "__fish_use_subcommand" -a "skills" -d "Manage skills"
120
+ complete -c lua -f -n "__fish_use_subcommand" -a "features" -d "Manage agent features"
121
+ complete -c lua -f -n "__fish_use_subcommand" -a "completion" -d "Generate completion script"
122
+
123
+ # Auth subcommands
124
+ complete -c lua -f -n "__fish_seen_subcommand_from auth" -a "configure" -d "Set up API key"
125
+ complete -c lua -f -n "__fish_seen_subcommand_from auth" -a "logout" -d "Delete API key"
126
+ complete -c lua -f -n "__fish_seen_subcommand_from auth" -a "key" -d "Display API key"
127
+
128
+ # Push subcommands
129
+ complete -c lua -f -n "__fish_seen_subcommand_from push" -a "skill" -d "Push a skill"
130
+ complete -c lua -f -n "__fish_seen_subcommand_from push" -a "persona" -d "Push a persona"
131
+
132
+ # Env subcommands
133
+ complete -c lua -f -n "__fish_seen_subcommand_from env" -a "sandbox" -d "Manage sandbox env vars"
134
+ complete -c lua -f -n "__fish_seen_subcommand_from env" -a "staging" -d "Manage staging env vars"
135
+ complete -c lua -f -n "__fish_seen_subcommand_from env" -a "production" -d "Manage production env vars"
136
+
137
+ # Persona subcommands
138
+ complete -c lua -f -n "__fish_seen_subcommand_from persona" -a "sandbox" -d "Manage sandbox persona"
139
+ complete -c lua -f -n "__fish_seen_subcommand_from persona" -a "staging" -d "Manage staging persona"
140
+ complete -c lua -f -n "__fish_seen_subcommand_from persona" -a "production" -d "Manage production persona"
141
+
142
+ # Skills subcommands
143
+ complete -c lua -f -n "__fish_seen_subcommand_from skills" -a "sandbox" -d "View sandbox skills"
144
+ complete -c lua -f -n "__fish_seen_subcommand_from skills" -a "staging" -d "View staging skills"
145
+ complete -c lua -f -n "__fish_seen_subcommand_from skills" -a "production" -d "Manage production skills"
146
+
147
+ # Chat subcommands
148
+ complete -c lua -f -n "__fish_seen_subcommand_from chat" -a "clear" -d "Clear history"
149
+
150
+ # Completion subcommands
151
+ complete -c lua -f -n "__fish_seen_subcommand_from completion" -a "bash" -d "Generate bash completion"
152
+ complete -c lua -f -n "__fish_seen_subcommand_from completion" -a "zsh" -d "Generate zsh completion"
153
+ complete -c lua -f -n "__fish_seen_subcommand_from completion" -a "fish" -d "Generate fish completion"
154
+ `;
155
+ /**
156
+ * Main completion command - generates shell completion scripts
157
+ *
158
+ * @param shell - Shell type (bash, zsh, fish)
159
+ * @returns Promise that resolves when command completes
160
+ */
161
+ export async function completionCommand(shell) {
162
+ return withErrorHandling(async () => {
163
+ // If no shell specified, show instructions
164
+ if (!shell) {
165
+ console.log(`
166
+ 🎯 Lua CLI Shell Completion
167
+
168
+ To enable autocomplete, run one of the following commands based on your shell:
169
+
170
+ Bash:
171
+ $ lua completion bash >> ~/.bashrc
172
+ $ source ~/.bashrc
173
+
174
+ Zsh:
175
+ $ lua completion zsh >> ~/.zshrc
176
+ $ source ~/.zshrc
177
+
178
+ Fish:
179
+ $ lua completion fish > ~/.config/fish/completions/lua.fish
180
+
181
+ Or manually:
182
+ $ lua completion bash # Output bash completion script
183
+ $ lua completion zsh # Output zsh completion script
184
+ $ lua completion fish # Output fish completion script
185
+
186
+ Then follow the instructions above to add it to your shell configuration.
187
+ `);
188
+ return;
189
+ }
190
+ // Validate shell type
191
+ const validShells = ['bash', 'zsh', 'fish'];
192
+ if (!validShells.includes(shell.toLowerCase())) {
193
+ console.error(`❌ Invalid shell: "${shell}". Must be one of: ${validShells.join(', ')}`);
194
+ process.exit(1);
195
+ }
196
+ // Output the appropriate completion script
197
+ switch (shell.toLowerCase()) {
198
+ case 'bash':
199
+ console.log(BASH_COMPLETION);
200
+ break;
201
+ case 'zsh':
202
+ console.log(ZSH_COMPLETION);
203
+ break;
204
+ case 'fish':
205
+ console.log(FISH_COMPLETION);
206
+ break;
207
+ }
208
+ }, "completion");
209
+ }
@@ -6,7 +6,7 @@
6
6
  * Main env command - manages environment variables
7
7
  *
8
8
  * Features:
9
- * - Environment selection (sandbox or production)
9
+ * - Environment selection (sandbox/staging or production)
10
10
  * - List all environment variables
11
11
  * - Add new variables
12
12
  * - Update existing variables
@@ -14,6 +14,7 @@
14
14
  * - Sandbox: manages .env file
15
15
  * - Production: uses API endpoints
16
16
  *
17
+ * @param env - Optional environment argument ('sandbox', 'staging', or 'production')
17
18
  * @returns Promise that resolves when command completes
18
19
  */
19
- export declare function envCommand(): Promise<void>;
20
+ export declare function envCommand(env?: string): Promise<void>;
@@ -15,7 +15,7 @@ import DeveloperApi from '../api/developer.api.service.js';
15
15
  * Main env command - manages environment variables
16
16
  *
17
17
  * Features:
18
- * - Environment selection (sandbox or production)
18
+ * - Environment selection (sandbox/staging or production)
19
19
  * - List all environment variables
20
20
  * - Add new variables
21
21
  * - Update existing variables
@@ -23,34 +23,59 @@ import DeveloperApi from '../api/developer.api.service.js';
23
23
  * - Sandbox: manages .env file
24
24
  * - Production: uses API endpoints
25
25
  *
26
+ * @param env - Optional environment argument ('sandbox', 'staging', or 'production')
26
27
  * @returns Promise that resolves when command completes
27
28
  */
28
- export async function envCommand() {
29
+ export async function envCommand(env) {
29
30
  return withErrorHandling(async () => {
30
31
  // Step 1: Load configuration
31
32
  const config = readSkillConfig();
32
33
  validateConfig(config);
33
34
  validateAgentConfig(config);
34
35
  const agentId = config.agent.agentId;
35
- // Step 2: Select environment
36
- const { environment } = await inquirer.prompt([
37
- {
38
- type: 'list',
39
- name: 'environment',
40
- message: 'Select environment:',
41
- choices: [
42
- { name: '🔧 Sandbox (.env file)', value: 'sandbox' },
43
- { name: '🚀 Production (API)', value: 'production' }
44
- ]
36
+ let selectedEnvironment;
37
+ // Step 2: Check if environment was provided as argument
38
+ if (env) {
39
+ // Normalize the environment (staging is an alias for sandbox)
40
+ const normalizedEnv = env.toLowerCase();
41
+ if (normalizedEnv === 'sandbox' || normalizedEnv === 'staging') {
42
+ selectedEnvironment = 'sandbox';
45
43
  }
46
- ]);
44
+ else if (normalizedEnv === 'production') {
45
+ selectedEnvironment = 'production';
46
+ }
47
+ else {
48
+ console.error(`❌ Invalid environment: "${env}". Must be "sandbox", "staging", or "production".`);
49
+ console.log('\nUsage:');
50
+ console.log(' lua env - Interactive selection');
51
+ console.log(' lua env sandbox - Manage sandbox env vars directly');
52
+ console.log(' lua env staging - Manage staging env vars (alias for sandbox)');
53
+ console.log(' lua env production - Manage production env vars directly');
54
+ process.exit(1);
55
+ }
56
+ }
57
+ else {
58
+ // Step 3: Prompt for environment selection
59
+ const { environment } = await inquirer.prompt([
60
+ {
61
+ type: 'list',
62
+ name: 'environment',
63
+ message: 'Select environment:',
64
+ choices: [
65
+ { name: '🔧 Sandbox (.env file)', value: 'sandbox' },
66
+ { name: '🚀 Production (API)', value: 'production' }
67
+ ]
68
+ }
69
+ ]);
70
+ selectedEnvironment = environment;
71
+ }
47
72
  let context = {
48
- environment,
73
+ environment: selectedEnvironment,
49
74
  agentId,
50
75
  apiKey: '',
51
76
  };
52
- // Step 3: Authenticate (needed for production)
53
- if (environment === 'production') {
77
+ // Step 4: Authenticate (needed for production)
78
+ if (selectedEnvironment === 'production') {
54
79
  const apiKey = await loadApiKey();
55
80
  if (!apiKey) {
56
81
  console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
@@ -61,7 +86,7 @@ export async function envCommand() {
61
86
  context.developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
62
87
  writeProgress("✅ Authenticated");
63
88
  }
64
- // Step 4: Start management loop
89
+ // Step 5: Start management loop
65
90
  await manageEnvironmentVariables(context);
66
91
  }, "env");
67
92
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Features Command
3
+ * Manages agent features (tickets, RAG, webSearch, etc.)
4
+ */
5
+ /**
6
+ * Main features command - manages agent features
7
+ *
8
+ * Features:
9
+ * - List all available features
10
+ * - View feature details (active status and context)
11
+ * - Enable/disable features
12
+ * - Update feature context
13
+ *
14
+ * @returns Promise that resolves when command completes
15
+ */
16
+ export declare function featuresCommand(): Promise<void>;
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Features Command
3
+ * Manages agent features (tickets, RAG, webSearch, etc.)
4
+ */
5
+ import { loadApiKey, checkApiKey } from '../services/auth.js';
6
+ import { readSkillConfig } from '../utils/files.js';
7
+ import { withErrorHandling, writeProgress, writeSuccess } from '../utils/cli.js';
8
+ import { BASE_URLS } from '../config/constants.js';
9
+ import { safePrompt } from '../utils/prompt-handler.js';
10
+ import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
11
+ import AgentApi from '../api/agent.api.service.js';
12
+ /**
13
+ * Main features command - manages agent features
14
+ *
15
+ * Features:
16
+ * - List all available features
17
+ * - View feature details (active status and context)
18
+ * - Enable/disable features
19
+ * - Update feature context
20
+ *
21
+ * @returns Promise that resolves when command completes
22
+ */
23
+ export async function featuresCommand() {
24
+ return withErrorHandling(async () => {
25
+ // Step 1: Load configuration
26
+ const config = readSkillConfig();
27
+ validateConfig(config);
28
+ validateAgentConfig(config);
29
+ const agentId = config.agent.agentId;
30
+ // Step 2: Authenticate
31
+ const apiKey = await loadApiKey();
32
+ if (!apiKey) {
33
+ console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
34
+ process.exit(1);
35
+ }
36
+ await checkApiKey(apiKey);
37
+ writeProgress("✅ Authenticated");
38
+ // Step 3: Create API instance
39
+ const agentApi = new AgentApi(BASE_URLS.API, apiKey);
40
+ const context = {
41
+ agentId,
42
+ apiKey,
43
+ agentApi,
44
+ };
45
+ // Step 4: Start feature management
46
+ await manageFeatures(context);
47
+ }, "features");
48
+ }
49
+ /**
50
+ * Main management loop for features
51
+ */
52
+ async function manageFeatures(context) {
53
+ let continueManaging = true;
54
+ while (continueManaging) {
55
+ // Load current features
56
+ writeProgress("🔄 Loading features...");
57
+ let features;
58
+ try {
59
+ const response = await context.agentApi.getAgentFeatures(context.agentId);
60
+ if (!response.data) {
61
+ throw new Error("No data returned from API");
62
+ }
63
+ features = response.data.features;
64
+ }
65
+ catch (error) {
66
+ console.error("❌ Error loading features:", error);
67
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to try again...' }]);
68
+ continue;
69
+ }
70
+ // Show current state
71
+ console.log("\n" + "=".repeat(60));
72
+ console.log("🎯 Agent Features");
73
+ console.log("=".repeat(60) + "\n");
74
+ if (features.length === 0) {
75
+ console.log("ℹ️ No features available for this agent.\n");
76
+ }
77
+ else {
78
+ console.log("Available features:\n");
79
+ features.forEach((feature, index) => {
80
+ const status = feature.active ? "✅" : "❌";
81
+ console.log(`${index + 1}. ${status} ${feature.title}`);
82
+ console.log(` Name: ${feature.name}`);
83
+ console.log(` Status: ${feature.active ? "Active" : "Inactive"}`);
84
+ console.log();
85
+ });
86
+ }
87
+ // Show menu
88
+ const actionAnswer = await safePrompt([
89
+ {
90
+ type: 'list',
91
+ name: 'action',
92
+ message: 'What would you like to do?',
93
+ choices: [
94
+ { name: '👁️ View feature details', value: 'view' },
95
+ { name: '✏️ Manage a feature', value: 'manage' },
96
+ { name: '🔄 Refresh list', value: 'refresh' },
97
+ { name: '❌ Exit', value: 'exit' }
98
+ ]
99
+ }
100
+ ]);
101
+ if (!actionAnswer)
102
+ return;
103
+ const { action } = actionAnswer;
104
+ switch (action) {
105
+ case 'view':
106
+ await viewFeatureDetails(context, features);
107
+ break;
108
+ case 'manage':
109
+ await manageFeature(context, features);
110
+ break;
111
+ case 'refresh':
112
+ // Just loop again to refresh
113
+ break;
114
+ case 'exit':
115
+ continueManaging = false;
116
+ console.log("\n👋 Goodbye!\n");
117
+ break;
118
+ }
119
+ }
120
+ }
121
+ /**
122
+ * View detailed information about a feature
123
+ */
124
+ async function viewFeatureDetails(context, features) {
125
+ if (features.length === 0) {
126
+ console.log("\nℹ️ No features available.\n");
127
+ return;
128
+ }
129
+ // Prompt to select a feature
130
+ const featureAnswer = await safePrompt([
131
+ {
132
+ type: 'list',
133
+ name: 'selectedFeature',
134
+ message: 'Select a feature to view:',
135
+ choices: features.map(feature => ({
136
+ name: `${feature.active ? '✅' : '❌'} ${feature.title}`,
137
+ value: feature
138
+ }))
139
+ }
140
+ ]);
141
+ if (!featureAnswer)
142
+ return;
143
+ const feature = featureAnswer.selectedFeature;
144
+ // Display feature details
145
+ console.log("\n" + "=".repeat(60));
146
+ console.log(`🎯 ${feature.title}`);
147
+ console.log("=".repeat(60));
148
+ console.log(`Name: ${feature.name}`);
149
+ console.log(`Status: ${feature.active ? '✅ Active' : '❌ Inactive'}`);
150
+ console.log("\nContext/Instructions:");
151
+ console.log("─".repeat(60));
152
+ console.log(feature.context);
153
+ console.log("=".repeat(60) + "\n");
154
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
155
+ }
156
+ /**
157
+ * Manage a specific feature (activate/deactivate or update context)
158
+ */
159
+ async function manageFeature(context, features) {
160
+ if (features.length === 0) {
161
+ console.log("\nℹ️ No features available.\n");
162
+ return;
163
+ }
164
+ // Step 1: Select feature
165
+ const featureAnswer = await safePrompt([
166
+ {
167
+ type: 'list',
168
+ name: 'selectedFeature',
169
+ message: 'Select a feature to manage:',
170
+ choices: features.map(feature => ({
171
+ name: `${feature.active ? '✅' : '❌'} ${feature.title}`,
172
+ value: feature
173
+ }))
174
+ }
175
+ ]);
176
+ if (!featureAnswer)
177
+ return;
178
+ const feature = featureAnswer.selectedFeature;
179
+ // Step 2: Show current status
180
+ console.log("\n" + "─".repeat(60));
181
+ console.log(`Feature: ${feature.title}`);
182
+ console.log(`Current Status: ${feature.active ? '✅ Active' : '❌ Inactive'}`);
183
+ console.log("─".repeat(60) + "\n");
184
+ // Step 3: Select action
185
+ const actionAnswer = await safePrompt([
186
+ {
187
+ type: 'list',
188
+ name: 'action',
189
+ message: 'What would you like to do?',
190
+ choices: [
191
+ {
192
+ name: feature.active ? '❌ Deactivate feature' : '✅ Activate feature',
193
+ value: 'toggle'
194
+ },
195
+ { name: '✏️ Update context/instructions', value: 'context' },
196
+ { name: '🔄 Update both status and context', value: 'both' },
197
+ { name: '⬅️ Back', value: 'back' }
198
+ ]
199
+ }
200
+ ]);
201
+ if (!actionAnswer || actionAnswer.action === 'back')
202
+ return;
203
+ try {
204
+ switch (actionAnswer.action) {
205
+ case 'toggle':
206
+ await toggleFeature(context, feature);
207
+ break;
208
+ case 'context':
209
+ await updateFeatureContext(context, feature);
210
+ break;
211
+ case 'both':
212
+ await updateBoth(context, feature);
213
+ break;
214
+ }
215
+ }
216
+ catch (error) {
217
+ console.error("\n❌ Error updating feature:", error);
218
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
219
+ }
220
+ }
221
+ /**
222
+ * Toggle feature active status
223
+ */
224
+ async function toggleFeature(context, feature) {
225
+ const newStatus = !feature.active;
226
+ const action = newStatus ? 'activate' : 'deactivate';
227
+ const confirmAnswer = await safePrompt([
228
+ {
229
+ type: 'confirm',
230
+ name: 'confirm',
231
+ message: `Are you sure you want to ${action} "${feature.title}"?`,
232
+ default: true
233
+ }
234
+ ]);
235
+ if (!confirmAnswer || !confirmAnswer.confirm) {
236
+ console.log("\n❌ Operation cancelled.\n");
237
+ return;
238
+ }
239
+ writeProgress(`🔄 ${newStatus ? 'Activating' : 'Deactivating'} feature...`);
240
+ const response = await context.agentApi.updateAgentFeature(context.agentId, {
241
+ featureName: feature.name,
242
+ active: newStatus
243
+ });
244
+ writeSuccess(`✅ Feature "${feature.title}" ${newStatus ? 'activated' : 'deactivated'} successfully`);
245
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
246
+ }
247
+ /**
248
+ * Update feature context
249
+ */
250
+ async function updateFeatureContext(context, feature) {
251
+ console.log("\n📝 Current context:");
252
+ console.log("─".repeat(60));
253
+ console.log(feature.context);
254
+ console.log("─".repeat(60) + "\n");
255
+ const contextAnswer = await safePrompt([
256
+ {
257
+ type: 'editor',
258
+ name: 'newContext',
259
+ message: 'Edit feature context (will open in your default editor):',
260
+ default: feature.context,
261
+ validate: (input) => {
262
+ if (!input || !input.trim()) {
263
+ return 'Context cannot be empty';
264
+ }
265
+ return true;
266
+ }
267
+ }
268
+ ]);
269
+ if (!contextAnswer)
270
+ return;
271
+ const confirmAnswer = await safePrompt([
272
+ {
273
+ type: 'confirm',
274
+ name: 'confirm',
275
+ message: 'Save updated context?',
276
+ default: true
277
+ }
278
+ ]);
279
+ if (!confirmAnswer || !confirmAnswer.confirm) {
280
+ console.log("\n❌ Update cancelled.\n");
281
+ return;
282
+ }
283
+ writeProgress("🔄 Updating feature context...");
284
+ const response = await context.agentApi.updateAgentFeature(context.agentId, {
285
+ featureName: feature.name,
286
+ featureContext: contextAnswer.newContext.trim()
287
+ });
288
+ writeSuccess(`✅ Context for "${feature.title}" updated successfully`);
289
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
290
+ }
291
+ /**
292
+ * Update both status and context
293
+ */
294
+ async function updateBoth(context, feature) {
295
+ // Step 1: Select new status
296
+ const statusAnswer = await safePrompt([
297
+ {
298
+ type: 'confirm',
299
+ name: 'active',
300
+ message: 'Should this feature be active?',
301
+ default: feature.active
302
+ }
303
+ ]);
304
+ if (!statusAnswer)
305
+ return;
306
+ // Step 2: Edit context
307
+ console.log("\n📝 Current context:");
308
+ console.log("─".repeat(60));
309
+ console.log(feature.context);
310
+ console.log("─".repeat(60) + "\n");
311
+ const contextAnswer = await safePrompt([
312
+ {
313
+ type: 'editor',
314
+ name: 'newContext',
315
+ message: 'Edit feature context (will open in your default editor):',
316
+ default: feature.context,
317
+ validate: (input) => {
318
+ if (!input || !input.trim()) {
319
+ return 'Context cannot be empty';
320
+ }
321
+ return true;
322
+ }
323
+ }
324
+ ]);
325
+ if (!contextAnswer)
326
+ return;
327
+ // Step 3: Confirm
328
+ console.log("\n📋 Summary of changes:");
329
+ console.log(`Status: ${feature.active ? '✅ Active' : '❌ Inactive'} → ${statusAnswer.active ? '✅ Active' : '❌ Inactive'}`);
330
+ console.log(`Context: ${contextAnswer.newContext === feature.context ? 'No change' : 'Updated'}`);
331
+ console.log();
332
+ const confirmAnswer = await safePrompt([
333
+ {
334
+ type: 'confirm',
335
+ name: 'confirm',
336
+ message: 'Save all changes?',
337
+ default: true
338
+ }
339
+ ]);
340
+ if (!confirmAnswer || !confirmAnswer.confirm) {
341
+ console.log("\n❌ Update cancelled.\n");
342
+ return;
343
+ }
344
+ writeProgress("🔄 Updating feature...");
345
+ const response = await context.agentApi.updateAgentFeature(context.agentId, {
346
+ featureName: feature.name,
347
+ active: statusAnswer.active,
348
+ featureContext: contextAnswer.newContext.trim()
349
+ });
350
+ writeSuccess(`✅ Feature "${feature.title}" updated successfully`);
351
+ await safePrompt([{ type: 'input', name: 'continue', message: 'Press Enter to continue...' }]);
352
+ }