myask 0.0.1 → 1.1.0

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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/bin/myask +1 -1
  4. data/html/App.html +116 -0
  5. data/html/MyAsk/Api/Helper.html +207 -0
  6. data/html/MyAsk/Api/Invitation.html +212 -0
  7. data/html/MyAsk/Api/Project.html +355 -0
  8. data/html/MyAsk/Api/ProjectHelper.html +299 -0
  9. data/html/MyAsk/Api/Question.html +261 -0
  10. data/html/MyAsk/Api.html +120 -0
  11. data/html/MyAsk/Config.html +195 -0
  12. data/html/MyAsk/ConfigHelper.html +251 -0
  13. data/html/MyAsk/Prompt.html +221 -0
  14. data/html/MyAsk/PromptHelper.html +330 -0
  15. data/html/MyAsk.html +114 -0
  16. data/html/README_rdoc.html +394 -0
  17. data/html/created.rid +14 -0
  18. data/html/css/fonts.css +167 -0
  19. data/html/css/rdoc.css +681 -0
  20. data/html/fonts/Lato-Light.ttf +0 -0
  21. data/html/fonts/Lato-LightItalic.ttf +0 -0
  22. data/html/fonts/Lato-Regular.ttf +0 -0
  23. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  24. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  25. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  26. data/html/images/add.png +0 -0
  27. data/html/images/arrow_up.png +0 -0
  28. data/html/images/brick.png +0 -0
  29. data/html/images/brick_link.png +0 -0
  30. data/html/images/bug.png +0 -0
  31. data/html/images/bullet_black.png +0 -0
  32. data/html/images/bullet_toggle_minus.png +0 -0
  33. data/html/images/bullet_toggle_plus.png +0 -0
  34. data/html/images/date.png +0 -0
  35. data/html/images/delete.png +0 -0
  36. data/html/images/find.png +0 -0
  37. data/html/images/loadingAnimation.gif +0 -0
  38. data/html/images/macFFBgHack.png +0 -0
  39. data/html/images/package.png +0 -0
  40. data/html/images/page_green.png +0 -0
  41. data/html/images/page_white_text.png +0 -0
  42. data/html/images/page_white_width.png +0 -0
  43. data/html/images/plugin.png +0 -0
  44. data/html/images/ruby.png +0 -0
  45. data/html/images/tag_blue.png +0 -0
  46. data/html/images/tag_green.png +0 -0
  47. data/html/images/transparent.png +0 -0
  48. data/html/images/wrench.png +0 -0
  49. data/html/images/wrench_orange.png +0 -0
  50. data/html/images/zoom.png +0 -0
  51. data/html/index.html +403 -0
  52. data/html/js/darkfish.js +120 -0
  53. data/html/js/navigation.js +105 -0
  54. data/html/js/navigation.js.gz +0 -0
  55. data/html/js/search.js +110 -0
  56. data/html/js/search_index.js +1 -0
  57. data/html/js/search_index.js.gz +0 -0
  58. data/html/js/searcher.js +229 -0
  59. data/html/js/searcher.js.gz +0 -0
  60. data/html/table_of_contents.html +257 -0
  61. data/lib/myask/prompt_helper.rb +4 -1
  62. data/lib/myask/version.rb +1 -1
  63. data/pkg/myask-0.0.1/Gemfile +10 -0
  64. data/pkg/myask-0.0.1/Gemfile.lock +70 -0
  65. data/pkg/myask-0.0.1/README.rdoc +6 -0
  66. data/pkg/myask-0.0.1/Rakefile +21 -0
  67. data/pkg/myask-0.0.1/bin/myask +101 -0
  68. data/pkg/myask-0.0.1/lib/myask/api/api_helper.rb +45 -0
  69. data/pkg/myask-0.0.1/lib/myask/api/invitation.rb +49 -0
  70. data/pkg/myask-0.0.1/lib/myask/api/project.rb +193 -0
  71. data/pkg/myask-0.0.1/lib/myask/api/project_helper.rb +46 -0
  72. data/pkg/myask-0.0.1/lib/myask/api/question.rb +99 -0
  73. data/pkg/myask-0.0.1/lib/myask/config.rb +37 -0
  74. data/pkg/myask-0.0.1/lib/myask/config_helper.rb +28 -0
  75. data/pkg/myask-0.0.1/lib/myask/prompt.rb +63 -0
  76. data/pkg/myask-0.0.1/lib/myask/prompt_helper.rb +83 -0
  77. data/pkg/myask-0.0.1/lib/myask/version.rb +3 -0
  78. data/pkg/myask-0.0.1/lib/myask.rb +28 -0
  79. data/pkg/myask-0.0.1/myask.gemspec +22 -0
  80. data/pkg/myask-0.0.1/myask.rdoc +138 -0
  81. data/pkg/myask-0.0.1/test/default_test.rb +14 -0
  82. data/pkg/myask-0.0.1/test/test_helper.rb +4 -0
  83. data/pkg/myask-0.0.1.gem +0 -0
  84. data/pkg/myask-1.0.0/Gemfile +10 -0
  85. data/pkg/myask-1.0.0/Gemfile.lock +70 -0
  86. data/pkg/myask-1.0.0/README.rdoc +6 -0
  87. data/pkg/myask-1.0.0/Rakefile +21 -0
  88. data/pkg/myask-1.0.0/bin/myask +101 -0
  89. data/pkg/myask-1.0.0/html/App.html +116 -0
  90. data/pkg/myask-1.0.0/html/MyAsk/Api/Helper.html +207 -0
  91. data/pkg/myask-1.0.0/html/MyAsk/Api/Invitation.html +212 -0
  92. data/pkg/myask-1.0.0/html/MyAsk/Api/Project.html +355 -0
  93. data/pkg/myask-1.0.0/html/MyAsk/Api/ProjectHelper.html +299 -0
  94. data/pkg/myask-1.0.0/html/MyAsk/Api/Question.html +261 -0
  95. data/pkg/myask-1.0.0/html/MyAsk/Api.html +120 -0
  96. data/pkg/myask-1.0.0/html/MyAsk/Config.html +195 -0
  97. data/pkg/myask-1.0.0/html/MyAsk/ConfigHelper.html +251 -0
  98. data/pkg/myask-1.0.0/html/MyAsk/Prompt.html +221 -0
  99. data/pkg/myask-1.0.0/html/MyAsk/PromptHelper.html +330 -0
  100. data/pkg/myask-1.0.0/html/MyAsk.html +114 -0
  101. data/pkg/myask-1.0.0/html/README_rdoc.html +394 -0
  102. data/pkg/myask-1.0.0/html/created.rid +14 -0
  103. data/pkg/myask-1.0.0/html/css/fonts.css +167 -0
  104. data/pkg/myask-1.0.0/html/css/rdoc.css +681 -0
  105. data/pkg/myask-1.0.0/html/fonts/Lato-Light.ttf +0 -0
  106. data/pkg/myask-1.0.0/html/fonts/Lato-LightItalic.ttf +0 -0
  107. data/pkg/myask-1.0.0/html/fonts/Lato-Regular.ttf +0 -0
  108. data/pkg/myask-1.0.0/html/fonts/Lato-RegularItalic.ttf +0 -0
  109. data/pkg/myask-1.0.0/html/fonts/SourceCodePro-Bold.ttf +0 -0
  110. data/pkg/myask-1.0.0/html/fonts/SourceCodePro-Regular.ttf +0 -0
  111. data/pkg/myask-1.0.0/html/images/add.png +0 -0
  112. data/pkg/myask-1.0.0/html/images/arrow_up.png +0 -0
  113. data/pkg/myask-1.0.0/html/images/brick.png +0 -0
  114. data/pkg/myask-1.0.0/html/images/brick_link.png +0 -0
  115. data/pkg/myask-1.0.0/html/images/bug.png +0 -0
  116. data/pkg/myask-1.0.0/html/images/bullet_black.png +0 -0
  117. data/pkg/myask-1.0.0/html/images/bullet_toggle_minus.png +0 -0
  118. data/pkg/myask-1.0.0/html/images/bullet_toggle_plus.png +0 -0
  119. data/pkg/myask-1.0.0/html/images/date.png +0 -0
  120. data/pkg/myask-1.0.0/html/images/delete.png +0 -0
  121. data/pkg/myask-1.0.0/html/images/find.png +0 -0
  122. data/pkg/myask-1.0.0/html/images/loadingAnimation.gif +0 -0
  123. data/pkg/myask-1.0.0/html/images/macFFBgHack.png +0 -0
  124. data/pkg/myask-1.0.0/html/images/package.png +0 -0
  125. data/pkg/myask-1.0.0/html/images/page_green.png +0 -0
  126. data/pkg/myask-1.0.0/html/images/page_white_text.png +0 -0
  127. data/pkg/myask-1.0.0/html/images/page_white_width.png +0 -0
  128. data/pkg/myask-1.0.0/html/images/plugin.png +0 -0
  129. data/pkg/myask-1.0.0/html/images/ruby.png +0 -0
  130. data/pkg/myask-1.0.0/html/images/tag_blue.png +0 -0
  131. data/pkg/myask-1.0.0/html/images/tag_green.png +0 -0
  132. data/pkg/myask-1.0.0/html/images/transparent.png +0 -0
  133. data/pkg/myask-1.0.0/html/images/wrench.png +0 -0
  134. data/pkg/myask-1.0.0/html/images/wrench_orange.png +0 -0
  135. data/pkg/myask-1.0.0/html/images/zoom.png +0 -0
  136. data/pkg/myask-1.0.0/html/index.html +403 -0
  137. data/pkg/myask-1.0.0/html/js/darkfish.js +120 -0
  138. data/pkg/myask-1.0.0/html/js/navigation.js +105 -0
  139. data/pkg/myask-1.0.0/html/js/navigation.js.gz +0 -0
  140. data/pkg/myask-1.0.0/html/js/search.js +110 -0
  141. data/pkg/myask-1.0.0/html/js/search_index.js +1 -0
  142. data/pkg/myask-1.0.0/html/js/search_index.js.gz +0 -0
  143. data/pkg/myask-1.0.0/html/js/searcher.js +229 -0
  144. data/pkg/myask-1.0.0/html/js/searcher.js.gz +0 -0
  145. data/pkg/myask-1.0.0/html/table_of_contents.html +257 -0
  146. data/pkg/myask-1.0.0/lib/myask/api/api_helper.rb +45 -0
  147. data/pkg/myask-1.0.0/lib/myask/api/invitation.rb +49 -0
  148. data/pkg/myask-1.0.0/lib/myask/api/project.rb +193 -0
  149. data/pkg/myask-1.0.0/lib/myask/api/project_helper.rb +46 -0
  150. data/pkg/myask-1.0.0/lib/myask/api/question.rb +99 -0
  151. data/pkg/myask-1.0.0/lib/myask/config.rb +37 -0
  152. data/pkg/myask-1.0.0/lib/myask/config_helper.rb +28 -0
  153. data/pkg/myask-1.0.0/lib/myask/prompt.rb +63 -0
  154. data/pkg/myask-1.0.0/lib/myask/prompt_helper.rb +83 -0
  155. data/pkg/myask-1.0.0/lib/myask/version.rb +3 -0
  156. data/pkg/myask-1.0.0/lib/myask.rb +28 -0
  157. data/pkg/myask-1.0.0/myask.gemspec +22 -0
  158. data/pkg/myask-1.0.0/myask.rdoc +138 -0
  159. data/pkg/myask-1.0.0/pkg/myask-0.0.1/Gemfile +10 -0
  160. data/pkg/myask-1.0.0/pkg/myask-0.0.1/Gemfile.lock +70 -0
  161. data/pkg/myask-1.0.0/pkg/myask-0.0.1/README.rdoc +6 -0
  162. data/pkg/myask-1.0.0/pkg/myask-0.0.1/Rakefile +21 -0
  163. data/pkg/myask-1.0.0/pkg/myask-0.0.1/bin/myask +101 -0
  164. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/api/api_helper.rb +45 -0
  165. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/api/invitation.rb +49 -0
  166. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/api/project.rb +193 -0
  167. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/api/project_helper.rb +46 -0
  168. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/api/question.rb +99 -0
  169. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/config.rb +37 -0
  170. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/config_helper.rb +28 -0
  171. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/prompt.rb +63 -0
  172. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/prompt_helper.rb +83 -0
  173. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask/version.rb +3 -0
  174. data/pkg/myask-1.0.0/pkg/myask-0.0.1/lib/myask.rb +28 -0
  175. data/pkg/myask-1.0.0/pkg/myask-0.0.1/myask.gemspec +22 -0
  176. data/pkg/myask-1.0.0/pkg/myask-0.0.1/myask.rdoc +138 -0
  177. data/pkg/myask-1.0.0/pkg/myask-0.0.1/test/default_test.rb +14 -0
  178. data/pkg/myask-1.0.0/pkg/myask-0.0.1/test/test_helper.rb +4 -0
  179. data/pkg/myask-1.0.0/pkg/myask-0.0.1.gem +0 -0
  180. data/pkg/myask-1.0.0/test/default_test.rb +14 -0
  181. data/pkg/myask-1.0.0/test/test_helper.rb +4 -0
  182. data/pkg/myask-1.0.0.gem +0 -0
  183. metadata +179 -2
@@ -0,0 +1,49 @@
1
+ module MyAsk
2
+ module Api
3
+ class Invitation
4
+
5
+ def initialize(c)
6
+ c.desc 'List MyAsk invitations.'
7
+ c.command :list do |c|
8
+ c.action do |global_options, _options, _args|
9
+ uri = URI("#{global_options[:api_host]}/api/invitations")
10
+ response = MyAsk::Api::Helper.make_request("Get", uri, global_options[:api_key])
11
+
12
+ puts "Invitation sent successfully:" unless global_options[:json]
13
+ puts JSON.pretty_generate(JSON.parse(response.body))
14
+ end
15
+ end
16
+
17
+ c.desc "Send MyAsk invitation to a new user"
18
+ c.command :send do |c|
19
+ c.desc "Send MyAsk invitation to a new user"
20
+ c.flag [:email], desc: "Email of the user to invite to MyAsk"
21
+
22
+ c.action do |global_options, options, args|
23
+ email = options[:email]
24
+
25
+ if !email
26
+ prompt = TTY::Prompt.new
27
+ email = prompt.ask('Enter invitee email:')
28
+ end
29
+
30
+ payload = {
31
+ invitation: {
32
+ email: email
33
+ }
34
+ }
35
+
36
+ uri = URI("#{global_options[:api_host]}/api/invitations")
37
+ response = MyAsk::Api::Helper.make_request("Post", uri, global_options[:api_key], payload)
38
+
39
+ puts "Invitation sent successfully:" unless global_options[:json]
40
+ puts JSON.pretty_generate(JSON.parse(response.body))
41
+ end
42
+ end
43
+
44
+ c.default_command :list
45
+ c
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,193 @@
1
+ module MyAsk
2
+ module Api
3
+ class Project
4
+
5
+ def initialize(c)
6
+ c.desc "Show MyAsk Project Details"
7
+ c.arg_name "project"
8
+ c.command :show do |c|
9
+ c.desc "List projects and select to view"
10
+ c.switch [:l, :list]
11
+
12
+ c.flag [:project], desc: "ID of project to display"
13
+
14
+ c.action do |global_options, options, args|
15
+ config = global_options
16
+ project = options[:project] || config[:project]
17
+
18
+ helper = MyAsk::Api::ProjectHelper.new(global_options, options, args)
19
+
20
+ project = if options[:list]
21
+ helper.project_id_from_selection
22
+ else
23
+ args[0] || project
24
+ end
25
+
26
+ helper.show_project_info(project)
27
+ end
28
+ end
29
+
30
+ c.desc "Set MyAsk Project"
31
+ c.arg_name "project"
32
+ c.command :set do |c|
33
+ c.desc "Set current MyAsk project"
34
+ c.switch [:l, :list]
35
+
36
+ c.flag [:project], desc: "ID of MyAsk Project to display"
37
+
38
+ c.action do |global_options, options, args|
39
+ config = global_options
40
+ project = options[:project] || config[:project]
41
+
42
+ helper = MyAsk::Api::ProjectHelper.new(global_options, options, args)
43
+
44
+ project = if options[:list]
45
+ helper.project_id_from_selection
46
+ else
47
+ args[0] || project
48
+ end
49
+
50
+ helper = MyAsk::ConfigHelper.new(global_options, options.merge(project: project), args)
51
+ response = helper.save_config
52
+ end
53
+ end
54
+
55
+ c.desc "Edit MyAsk Project"
56
+ c.arg_name "project"
57
+ c.command :edit do |c|
58
+ c.desc "Edit MyAsk project"
59
+ c.switch [:l, :list]
60
+
61
+ c.flag [:project], desc: "ID of MyAsk Project to Edit"
62
+
63
+ c.action do |global_options, options, args|
64
+ config = global_options
65
+ project = options[:project] || config[:project]
66
+
67
+ helper = MyAsk::Api::ProjectHelper.new(global_options, options, args)
68
+
69
+ project = if options[:list]
70
+ helper.project_id_from_selection
71
+ else
72
+ args[0] || project
73
+ end
74
+
75
+ payload = helper.show_project_info(project)
76
+
77
+ ai_models = ["gpt-4o-mini", "o3-mini", "o1-mini", "gpt-3.5-turbo", "gpt-4o", "chatgpt-4o-latest"]
78
+
79
+ prompt = TTY::Prompt.new
80
+
81
+ payload["project"]["name"] = prompt.read_line("Enter project name:", value: payload["project"]["name"]).strip
82
+ payload["project"]["description"] = prompt.read_line("Enter project description:", value: payload["project"]["description"]).strip
83
+
84
+ payload["project"]["ai_model"] = prompt.enum_select(
85
+ "Select an AI model for this project:",
86
+ ai_models,
87
+ default: payload["project"]["ai_model"]
88
+ )
89
+
90
+ payload["project"]["system_message"] = prompt.read_line(
91
+ "Enter project system_message (optional):",
92
+ value: payload["project"]["metadata"]["system_message"]["content"]
93
+ ).strip
94
+
95
+ puts payload
96
+
97
+ uri = URI("#{global_options[:api_host]}/api/projects/#{payload["project"]["id"]}")
98
+ response = MyAsk::Api::Helper.make_request("Patch", uri, global_options[:api_key], payload)
99
+
100
+ if response.is_a?(Net::HTTPSuccess)
101
+ puts "Project successfully edited:" unless global_options[:json]
102
+ puts JSON.pretty_generate(JSON.parse(response.body))
103
+ else
104
+ raise "Failed to edit project. Response code: #{response.code}, Body: #{response.body}"
105
+ end
106
+ end
107
+ end
108
+
109
+ c.desc "Create MyAsk Project"
110
+ c.command :create do |c|
111
+ c.flag [:name], desc: "Project Name"
112
+ c.flag [:description], desc: "Project Description"
113
+ c.flag [:ai_model], desc: "Project AI Model"
114
+ c.flag [:system_message], desc: "Project System Message"
115
+
116
+ c.action do |global_options, options, _args|
117
+ ai_models = ["gpt-4o-mini", "o3-mini", "o1-mini", "gpt-3.5-turbo", "gpt-4o", "chatgpt-4o-latest"]
118
+
119
+ prompt = TTY::Prompt.new
120
+
121
+ project_name = options[:name] || prompt.read_line("Enter project name:")
122
+ project_description = options[:description] || prompt.read_line("Enter project description:")
123
+
124
+ project_ai_model = options[:ai_model] || prompt.enum_select(
125
+ "Select an AI model for this project:",
126
+ ai_models
127
+ )
128
+
129
+ project_system_message = options[:system_message] || prompt.read_line(
130
+ "Enter project system_message (optional):"
131
+ )
132
+
133
+ payload = {
134
+ project: {
135
+ name: project_name.strip,
136
+ description: project_description.strip,
137
+ ai_model: project_ai_model,
138
+ system_message: { role: "developer", content: project_system_message.strip }
139
+ }
140
+ }
141
+
142
+ uri = URI("#{global_options[:api_host]}/api/projects")
143
+ response = MyAsk::Api::Helper.make_request("Post", uri, global_options[:api_key], payload)
144
+
145
+ if response.is_a?(Net::HTTPSuccess)
146
+ puts "Project created successfully:" unless global_options[:json]
147
+ puts JSON.pretty_generate(JSON.parse(response.body))
148
+ else
149
+ raise "Failed to create project. Response code: #{response.code}, Body: #{response.body}"
150
+ end
151
+ end
152
+ end
153
+
154
+ c.desc "Delete MyAsk Project"
155
+ c.command :delete do |c|
156
+ c.desc "List projects and select to view"
157
+ c.switch [:l, :list]
158
+
159
+ c.flag [:project], desc: "Project ID"
160
+
161
+ c.action do |global_options, options, args|
162
+ helper = MyAsk::Api::ProjectHelper.new(global_options, options, args)
163
+
164
+ project = if options[:list]
165
+ helper.project_id_from_selection
166
+ else
167
+ args[0] || project
168
+ end
169
+
170
+ payload = {
171
+ project: {
172
+ id: project
173
+ }
174
+ }
175
+
176
+ uri = URI("#{global_options[:api_host]}/api/projects/#{project}")
177
+ response = MyAsk::Api::Helper.make_request("Delete", uri, global_options[:api_key], payload)
178
+
179
+ if response.is_a?(Net::HTTPSuccess)
180
+ puts "Project deleted successfully:" unless global_options[:json]
181
+ puts JSON.pretty_generate(JSON.parse(response.body))
182
+ else
183
+ raise "Failed to delete project. Response code: #{response.code}, Body: #{response.body}"
184
+ end
185
+ end
186
+ end
187
+
188
+ c
189
+ end
190
+
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,46 @@
1
+ module MyAsk
2
+ module Api
3
+ class ProjectHelper
4
+
5
+ def initialize(global_options, options, args)
6
+ @global_options = global_options
7
+ @options = options
8
+ @args = args
9
+
10
+ @api_host = global_options[:api_host]
11
+ @api_key = global_options[:api_key]
12
+ end
13
+
14
+ def project_id_from_selection
15
+ uri = URI("#{@api_host}/api/projects")
16
+ response = MyAsk::Api::Helper.make_request('Get', uri, @api_key)
17
+
18
+ projects = JSON.parse(response.body)
19
+ if projects.empty?
20
+ puts 'No projects found.'
21
+ exit
22
+ end
23
+
24
+ select_project(projects)
25
+ end
26
+
27
+ def select_project(projects)
28
+ prompt = TTY::Prompt.new
29
+ selected_project = prompt.select(
30
+ "Select MyAsk Project:",
31
+ projects.map { |project| {"#{project["name"]}": project["id"]} }
32
+ )
33
+ end
34
+
35
+ def show_project_info(project_id)
36
+ uri = URI("#{@api_host}/api/projects/#{project_id}")
37
+ response = MyAsk::Api::Helper.make_request('Get', uri, @api_key)
38
+
39
+ project_info = JSON.parse(response.body)
40
+ puts JSON.pretty_generate(project_info.except("question_ids"))
41
+ project_info.except("question_ids")
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,99 @@
1
+ module MyAsk
2
+ module Api
3
+ class Question
4
+
5
+ def initialize(c)
6
+ c.desc "Show details for MyAsk question"
7
+ c.arg_name "question_id"
8
+
9
+ c.command :show do |c|
10
+ c.desc "List questions and select to view"
11
+ c.switch [:l, :list]
12
+
13
+ c.flag [:q, :question_id], desc: "ID of question to display"
14
+ c.switch [:skip_response], desc: "Do not include question response in output"
15
+
16
+ c.action do |global_options, options, args|
17
+ api_host = global_options[:api_host]
18
+ api_key = global_options[:api_key]
19
+
20
+ if options[:list]
21
+ response = MyAsk::Api::Helper.make_request("Get", URI("#{api_host}/api/questions"), api_key)
22
+ questions = JSON.parse(response.body).reverse
23
+
24
+ if questions.empty?
25
+ puts "No questions found."
26
+ exit
27
+ end
28
+
29
+ selected_question_id = TTY::Prompt.new.select("Select a question:", per_page: 10) do |menu|
30
+ questions.each do |q|
31
+ menu.choice "[#{q["id"]}] #{q["content"][0, 80]}", q["id"]
32
+ end
33
+ end
34
+
35
+ selected_question = selected_question_id
36
+ end
37
+
38
+ response = MyAsk::Api::Helper.make_request("Get", URI("#{api_host}/api/questions/#{selected_question || options[:question_id]}"), api_key)
39
+ response = JSON.parse(response.body)
40
+ response = response.except("response") if options[:skip_response]
41
+
42
+ puts "\n#{"\\" * 30} BEGIN Question (#{response["question"]["id"]}) #{"/" * 30}\n\n" unless global_options[:json]
43
+ puts global_options[:json] ? response.to_json : response["question"]["content"]
44
+ puts "\n#{"\\" * 35} END Question #{"/" * 35}\n" unless global_options[:json]
45
+
46
+ unless options[:skip_response] || global_options[:json] || response["response"].nil?
47
+ puts "\n\n#{"\\" * 30} BEGIN Response (#{response["response"]["id"]}) #{"/" * 30}\n\n" unless global_options[:json]
48
+ puts response["response"]["content"]
49
+ puts "\n#{"\\" * 35} END Response #{"/" * 35}\n" unless global_options[:json]
50
+ end
51
+ end
52
+ end
53
+
54
+ c.desc "Delete MyAsk question"
55
+ c.arg_name "question_id"
56
+
57
+ c.command :delete do |c|
58
+ c.desc "List questions and select to delete"
59
+ c.switch [:l, :list]
60
+
61
+ c.flag [:question_id], desc: "ID of question to delete"
62
+
63
+ c.action do |global_options, options, args|
64
+ api_host = global_options[:api_host]
65
+ api_key = global_options[:api_key]
66
+
67
+ if options[:list]
68
+ response = MyAsk::Api::Helper.make_request("Get", URI("#{api_host}/api/questions"), api_key)
69
+ questions = JSON.parse(response.body).reverse
70
+
71
+ if questions.empty?
72
+ puts "No questions found."
73
+ exit
74
+ end
75
+
76
+ selected_question_id = TTY::Prompt.new.select("Select a question:", per_page: 10) do |menu|
77
+ questions.each do |q|
78
+ menu.choice "[#{q["id"]}] #{q["content"][0, 80]}", q["id"]
79
+ end
80
+ end
81
+
82
+ selected_question = selected_question_id
83
+ end
84
+
85
+ response = MyAsk::Api::Helper.make_request("Delete", URI("#{api_host}/api/questions/#{selected_question || options[:question_id]}"), api_key)
86
+ response = JSON.parse(response.body)
87
+
88
+ puts JSON.pretty_generate(response["question"])
89
+
90
+ end
91
+ end
92
+
93
+ c.default_command :show
94
+ c
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,37 @@
1
+ module MyAsk
2
+ class Config
3
+
4
+ def initialize(c)
5
+ c.command :save do |c|
6
+ c.desc "Set MyAsk API URL"
7
+ c.flag [:api_host], type: String
8
+
9
+ c.desc "Set MyAsk API Key"
10
+ c.flag [:api_key], type: String
11
+
12
+ c.desc "Set MyAsk Project"
13
+ c.flag [:project], type: String
14
+
15
+ c.action do |global_options, options, args|
16
+ helper = MyAsk::ConfigHelper.new(global_options, options, args)
17
+ response = helper.save_config
18
+ puts response
19
+ response
20
+ end
21
+ end
22
+
23
+ c.command :show do |c|
24
+ c.action do |global_options, options, args|
25
+ helper = MyAsk::ConfigHelper.new(global_options, options, args)
26
+ response = helper.get_config
27
+ puts response
28
+ response
29
+ end
30
+ end
31
+
32
+ c.default_command :show
33
+ c
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ module MyAsk
2
+ class ConfigHelper
3
+
4
+ def initialize(global_options, options, args)
5
+ @global_options = global_options
6
+ @options = options
7
+ @args = args
8
+ @rc_file_path = File.expand_path("~/.myask.rc")
9
+ @config_data = YAML.load_file(@rc_file_path)
10
+ end
11
+
12
+ def get_config
13
+ @config_data.reject { |key, _| ["commands", "version", "s", "help"].include?(key.to_s) }.to_json
14
+ end
15
+
16
+ def save_config
17
+ @config_data[:api_key] = @options[:api_key] if @options[:api_key]
18
+ @config_data[:api_host] = @options[:api_host] if @options[:api_host]
19
+ @config_data[:project] = @options[:project] if @options[:project]
20
+
21
+ File.open(@rc_file_path, "w") do |file|
22
+ file.write(@config_data.to_yaml)
23
+ end
24
+ @config_data.reject { |key, _| ["commands", "version", "s", "help"].include?(key.to_s) }.to_json
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,63 @@
1
+ module MyAsk
2
+ class Prompt
3
+
4
+ def initialize(c)
5
+ c.desc "Skip Follow-Up Question"
6
+ c.switch [:no_followup]
7
+
8
+ c.desc "Project ID"
9
+ c.flag [:project]
10
+
11
+ c.desc "Prompt to send"
12
+ c.flag [:p, :prompt]
13
+
14
+ c.desc "Question IDs to include in prompt context"
15
+ c.flag [:c, :context_ids], multiple: true
16
+
17
+ c.desc "Path to source file(s)"
18
+ c.flag [:F, :input_file], multiple: true
19
+
20
+ c.action do |global_options, options, args|
21
+ helper = MyAsk::PromptHelper.new(global_options, options, args)
22
+
23
+ config = global_options
24
+ auth_token = config[:api_key]
25
+ project = options[:project] || config[:project]
26
+
27
+ content = helper.get_initial_question
28
+ context_ids = options[:"context_ids"]
29
+
30
+ loop do
31
+ begin
32
+ question_id = helper.submit_question(config[:api_host], auth_token, project, content, context_ids)
33
+ abort if question_id.nil?
34
+
35
+ context_ids << question_id
36
+
37
+ response = helper.poll_for_response(config[:api_host], auth_token, question_id)
38
+
39
+ if global_options[:json]
40
+ puts "\n\n#{JSON.dump({response: response})}\n\n"
41
+ else
42
+ puts "\n\n#{response}\n\n"
43
+ end
44
+
45
+ break if options[:no_followup]
46
+
47
+ prompt = TTY::Prompt.new
48
+ is_follow_up = prompt.yes?("Would you like to ask a follow-up question?", default: false)
49
+
50
+ break unless is_follow_up
51
+
52
+ follow_up_question = prompt.ask("Enter your follow-up question:").strip
53
+ content = follow_up_question
54
+ rescue => e
55
+ abort "Error: #{e}"
56
+ end
57
+ end
58
+ end
59
+ c
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,83 @@
1
+ module MyAsk
2
+ class PromptHelper
3
+ def initialize(global_options, options, args)
4
+ @global_options = global_options
5
+ @options = options
6
+ @args = args
7
+ end
8
+
9
+ def submit_question(api_host, auth_token, project_id, content, context_ids)
10
+ uri = URI("#{api_host}/api/questions")
11
+ http = Net::HTTP.new(uri.host, uri.port)
12
+ http.use_ssl = (uri.scheme == "https")
13
+
14
+ request = Net::HTTP::Post.new(uri.path)
15
+ request["Authorization"] = "Bearer #{auth_token}"
16
+ request["Content-Type"] = "application/json"
17
+
18
+ request.body = {
19
+ question: {
20
+ project_id: project_id,
21
+ content: content,
22
+ context_ids: context_ids
23
+ }
24
+ }.to_json
25
+
26
+ response = http.request(request)
27
+ parsed_response = JSON.parse(response.body)
28
+
29
+ parsed_response['id'] || nil
30
+ end
31
+
32
+ def poll_for_response(api_host, auth_token, question_id)
33
+ unless @global_options[:silent]
34
+ spinner = TTY::Spinner.new('🔄 Waiting for response from MyAsk API... [:spinner]', format: :dots)
35
+ spinner.auto_spin
36
+ end
37
+
38
+ max_retries = 50
39
+ attempt = 0
40
+
41
+ while attempt < max_retries
42
+ sleep 3
43
+ uri = URI("#{api_host}/api/responses/#{question_id}")
44
+ response = Net::HTTP.get(uri, { 'Authorization' => "Bearer #{auth_token}" })
45
+ parsed_response = JSON.parse(response)
46
+
47
+ if parsed_response.key?('content')
48
+ spinner.success('✅ Response received!') unless @global_options[:silent]
49
+ return parsed_response['content']
50
+ end
51
+
52
+ attempt += 1
53
+ end
54
+
55
+ spinner.error('❌ Timed out waiting for MyAsk API response.') unless @global_options[:silent]
56
+ raise 'No response received from MyAsk API after multiple attempts.'
57
+ end
58
+
59
+ def get_initial_question
60
+ file_contents = []
61
+
62
+ current_directory = Dir.pwd
63
+
64
+ if @options[:input_file]&.any?
65
+ @options[:input_file].each do |file_path|
66
+ begin
67
+ file_path = file_path[0] == "/" ? file_path : "#{current_directory}/#{file_path}"
68
+ content = File.read("#{current_directory}/#{file_path}").strip
69
+ file_contents << "**File**: #{file_path}**\n#{content}"
70
+ rescue => e
71
+ raise "❌ Failed to read input file: #{file_path}"
72
+ end
73
+ end
74
+ end
75
+
76
+ combined_question = "#{@options[:prompt]}\n\n---\n#{file_contents.join("\n\n---\n")}" unless file_contents.empty?
77
+ combined_question ||= @options[:prompt] || TTY::Prompt.new.ask('Please enter a prompt:').strip
78
+
79
+ combined_question.empty? ? nil : combined_question
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,3 @@
1
+ module Myask
2
+ VERSION = '1.1.0'
3
+ end
@@ -0,0 +1,28 @@
1
+ require 'myask/version.rb'
2
+
3
+ require 'myask/config.rb'
4
+ require 'myask/config_helper.rb'
5
+
6
+ require 'myask/api/api_helper.rb'
7
+
8
+ require 'myask/api/question.rb'
9
+ require 'myask/api/invitation.rb'
10
+
11
+ require 'myask/api/project.rb'
12
+ require 'myask/api/project_helper.rb'
13
+
14
+ require 'myask/prompt.rb'
15
+ require 'myask/prompt_helper.rb'
16
+
17
+ # Add requires for other files you add to your project here, so
18
+ # you just need to require this one file in your bin file
19
+
20
+ require 'net/http'
21
+ require 'json'
22
+
23
+ require 'io/console'
24
+ require 'tty-spinner'
25
+ require 'tty-prompt'
26
+ require 'yaml'
27
+
28
+ require 'pry-byebug'
@@ -0,0 +1,22 @@
1
+ # Ensure we require the local version and not one we might have installed already
2
+ require File.join([File.dirname(__FILE__),'lib','myask','version.rb'])
3
+ spec = Gem::Specification.new do |s|
4
+ s.name = 'myask'
5
+ s.version = Myask::VERSION
6
+ s.author = 'Andrew Chaney (netuoso)'
7
+ s.email = 'netuoso@myask.io'
8
+ s.homepage = 'https://myask.io'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.summary = 'MyAsk Command Line Tool Integrates with MyAsk AI API (https://myask.io).'
11
+ s.files = `git ls-files`.split("
12
+ ")
13
+ s.require_paths << 'lib'
14
+ s.extra_rdoc_files = ['README.rdoc','myask.rdoc']
15
+ s.rdoc_options << '--title' << 'myask' << '--main' << 'README.rdoc' << '-ri'
16
+ s.bindir = 'bin'
17
+ s.executables << 'myask'
18
+ s.add_development_dependency('rake')
19
+ s.add_development_dependency('rdoc')
20
+ s.add_development_dependency('minitest')
21
+ s.add_runtime_dependency('gli','~> 2.22.2')
22
+ end