superuser.app 0.0.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 (45) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +296 -0
  3. package/commands/domains/add.js +102 -0
  4. package/commands/domains/list.js +71 -0
  5. package/commands/domains/remove.js +97 -0
  6. package/commands/domains/verify.js +130 -0
  7. package/commands/g/endpoint.js +32 -0
  8. package/commands/g/test.js +42 -0
  9. package/commands/init.js +220 -0
  10. package/commands/login.js +123 -0
  11. package/commands/me.js +54 -0
  12. package/commands/organizations/create.js +68 -0
  13. package/commands/profile.js +58 -0
  14. package/commands/register.js +127 -0
  15. package/commands/run.js +194 -0
  16. package/commands/serve.js +35 -0
  17. package/commands/test.js +68 -0
  18. package/commands/up.js +257 -0
  19. package/commands/update.js +84 -0
  20. package/commands/version.js +31 -0
  21. package/helpers/constants.js +3 -0
  22. package/helpers/draw_box.js +38 -0
  23. package/helpers/draw_table.js +144 -0
  24. package/helpers/file_writer.js +101 -0
  25. package/helpers/generate/endpoint/_index.js +44 -0
  26. package/helpers/generate/test/_index.js +112 -0
  27. package/helpers/load_package.js +62 -0
  28. package/helpers/local_server.js +72 -0
  29. package/helpers/settings_manager.js +108 -0
  30. package/helpers/verify_packages.js +85 -0
  31. package/index.js +7 -0
  32. package/package.json +31 -0
  33. package/src/endpoint/functions/index.js +35 -0
  34. package/src/init/__.env +1 -0
  35. package/src/init/__.env.production +1 -0
  36. package/src/init/__.env.staging +1 -0
  37. package/src/init/__.gitignore +6 -0
  38. package/src/init/functions/index.js +15 -0
  39. package/src/init/instant.package.json +3 -0
  40. package/src/init/package.json +16 -0
  41. package/src/init/serve.instant.js +52 -0
  42. package/src/init/test/run.js +45 -0
  43. package/src/init/test/tests/_index.js +53 -0
  44. package/src/test/blank.mjs +16 -0
  45. package/src/test/endpoint.mjs +20 -0
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Keith William Horwood
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,296 @@
1
+ # Superuser Package Manager
2
+ ## Extend AI agents with tools, instantly
3
+
4
+ `ibot` is the official CLI for publishing [Superuser](https://instant.chat) packages.
5
+ You can use this utility to publish new packages to the Superuser package registry,
6
+ available at [instant.chat/packages](https://instant.chat/packages).
7
+
8
+ [Superuser](https://instant.chat) enables you to rapidly build custom
9
+ chatbots and AI agents that can be extended with custom tools. It provides four
10
+ major features;
11
+
12
+ 1. Chat with and develop your agent in real time from the web
13
+ 2. Extend your agent with [hosted tool packages](https://instant.chat/packages)
14
+ 3. Write your own private tool packages for your agents
15
+ 4. Deploy your agent to third-party services like Discord and Slack
16
+
17
+ ## What is the Superuser Package Registry?
18
+
19
+ The Superuser Package Registry is a **serverless hosting platform and registry** for
20
+ building tools that extend AI chatbots and agents.
21
+
22
+ **Superuser packages are just REST API servers.**
23
+ Every package is an [Instant API](https://github.com/instant-dev/api) project,
24
+ which is a simple way to export and auto-document JavaScript functions as REST endpoints
25
+ that can be called via any HTTP client.
26
+
27
+ Authentication to your published packages are handled via **API keychains** which
28
+ are delegated via [Superuser](https://instant.chat).
29
+
30
+ **NOTE:** While in beta, only Superuser agents can use your published tools.
31
+ We'll be opening up the gateway to programmatic access in the coming months.
32
+
33
+ ## Superuser Package vs. MCP
34
+
35
+ Reminder, **Superuser packages are just REST API servers.**
36
+
37
+ MCP, or Model Context Protocol, is a standard for passing tool and prompt context
38
+ between AI models and service providers. Superuser packages are **not**
39
+ MCP compatible out of the box, as they are simply REST APIs. However, it is our goal to add
40
+ MCP bindings to the [Instant API](https://github.com/instant-dev/api) framework which
41
+ powers all Superuser packages. When formalized, this will allow you to use
42
+ Superuser packages with any MCP-compatible client or service provider.
43
+ Contributors welcome!
44
+
45
+ ## Quickstart
46
+
47
+ Visit [instant.chat/signup](https://instant.chat/signup) to register.
48
+ Creating a new bot is easy, you can then use this CLI to develop
49
+ and publish custom packages to extend your bots.
50
+
51
+ ```shell
52
+ $ npm i ibot -g
53
+ $ mkdir new-project
54
+ $ cd new-project
55
+ $ ibot init # initialize project in this directory
56
+ $ ibot login # log in to Superuser Package Registry with your Superuser account
57
+ $ ibot serve # run your tool package on a local server to test
58
+ $ ibot run / # test a single endpoint (like curl)
59
+ $ ibot up # publish to development environment
60
+ $ ibot up --env staging # publish to staging environment
61
+ $ ibot up --env production # publish to production environment
62
+ ```
63
+
64
+ You can run `ibot help` at any time to see available commands.
65
+
66
+ # Table of contents
67
+
68
+ 1. [How does Superuser work?](#how-does-instant-bot-work)
69
+ 1. [How is hosting billed?](#how-is-hosting-billed)
70
+ 1. [Building custom packages for your bots](#building-custom-packages-for-your-bots)
71
+ 1. [Initialize a project](#initialize-a-project)
72
+ 1. [Defining tools aka endpoints](#defining-tools-aka-endpoints)
73
+ 1. [Endpoint name, description, types](#endpoint-name-description-types)
74
+ 1. [Deploy an Superuser Package](#deploy-an-instant-tool-package)
75
+ 1. [Public packages](#public-packages)
76
+ 1. [Private packages](#private-packages)
77
+ 1. [Additional utilities](#additional-utilities)
78
+ 1. [Generate endpoints](#generate-endpoints)
79
+ 1. [Generate tests](#generate-tests)
80
+ 1. [Run tests](#run-tests)
81
+ 1. [Environment variables](#environment-variables)
82
+ 1. [Roadmap](#roadmap)
83
+ 1. [Contact](#contact)
84
+
85
+ # How does Superuser work?
86
+
87
+ Superuser provides hosting for both (1) your agent and (2) your tool packages.
88
+ Your agent is a chatbot that you can chat with directly via the Superuser web interface.
89
+ Tool packages are REST APIs that can be used by your agent. You can publish tool packages
90
+ for use by your agent and others or keep them private.
91
+
92
+ When you ask your agent a question that requires a tool call, Superuser will
93
+ automatically route the request to the appropriate tool from the Superuser Package Registry
94
+ and call the tool on your behalf.
95
+
96
+ ## How is hosting billed?
97
+
98
+ Model usage (generating responses) is a subscription-based service. However,
99
+ for development purposes, you can use our lowest-tier model indefinitely in rate-limited mode
100
+ on the free tier **but only while on the web interface**.
101
+
102
+ Tools cost money to run, and are billed as serverless functions
103
+ at a rate of [$0.50 of credits per 1,000 GB-s](https://instant.chat/pricing) of usage.
104
+ Credits are prepaid, and during our beta period all users get a one-time bonus of $1.00
105
+ in free usage credits.
106
+
107
+ GB-s represents a "gigabyte-second" and is calculated by the function RAM × execution time.
108
+ For example, a function with 512 MB (0.5 GB) of RAM running for 200ms would use:
109
+
110
+ - Used GB-s = 0.5GB × 0.2s = 0.1 GB-s
111
+ - Used credits = $0.50 / 1,000 GB-s × 0.1 GB-s = $0.00005
112
+
113
+ # Building custom packages for your bots
114
+
115
+ Building bots on [Superuser](https://instant.chat) is straightforward. Extending
116
+ with custom tool packages can be done online via the web interface, or if you prefer
117
+ working with your own editor, you can use this CLI.
118
+
119
+ ## Initialize a project
120
+
121
+ To initialize a new Superuser package:
122
+
123
+ ```shell
124
+ $ npm i ibot -g
125
+ $ mkdir new-project
126
+ $ cd new-project
127
+ $ ibot init
128
+ ```
129
+
130
+ You'll be walked through the process. The `ibot` CLI will automatically check for
131
+ updates to core packages, so make sure you update when available. To play around with your
132
+ Superuser package locally;
133
+
134
+ ```shell
135
+ $ ibot serve
136
+ ```
137
+
138
+ Will start an HTTP server. To execute a standalone endpoint / tool:
139
+
140
+ ```shell
141
+ $ ibot run /
142
+ ```
143
+
144
+ ### Defining tools aka endpoints
145
+
146
+ Defining custom tools is easy. You'll find the terms **tool** and
147
+ **endpoint** used interchangeably as they all refer
148
+ to the same thing: your bot executing custom code in the cloud.
149
+
150
+ A **tool** is just an **endpoint** hosted by the Superuser Package Registry.
151
+
152
+ All endpoints for Superuser packages live in the `functions/` directory.
153
+ Each file name maps to the endpoint route e.g. `functions/hello.js`
154
+ routes to `localhost:8000/hello`. You can export custom `GET`, `POST`, `PUT`
155
+ and `DELETE` functions from every file. Here's an example "hello world" endpoint:
156
+
157
+ ```javascript
158
+ // functions/hello.js
159
+
160
+ /**
161
+ * A basic hello world function
162
+ * @param {string} name Your name
163
+ * @returns {string} message The return message
164
+ */
165
+ export async function GET (name = 'world') {
166
+ return `hello ${name}`!
167
+ };
168
+ ```
169
+
170
+ You can write any code you want and install any NPM packages you'd like to
171
+ your tool package.
172
+
173
+ ### Endpoint name, description, types
174
+
175
+ Using the comment block above every exported method (e.g. GET) you can
176
+ define your endpoint. Superuser packages use an open source specification called
177
+ [Instant API](https://github.com/instant-dev/api) to export JavaScript
178
+ functions as type safe web APIs. You can learn more about how to properly
179
+ define and document the shape (parameters) of your API there.
180
+
181
+ ## Deploy an Superuser Package
182
+
183
+ ### Public packages
184
+
185
+ **NOTE:** You **will not** be charged for other people using your public actions.
186
+ They are billed directly from their account.
187
+
188
+ By default all packages are created as public projects. Public
189
+ projects are namespaced to your username, e.g. `@my-username/project`.
190
+ This can be found in the `"name"` field of `superuser.json`.
191
+
192
+ Note that the code for public projects will be shared publicly for anybody
193
+ to see, and the expectation is that others can use this code in their bots
194
+ as well.
195
+ they will be billed from their balance.
196
+
197
+ To deploy a public project to a `development` environment, you can use:
198
+
199
+ ```shell
200
+ $ ibot up
201
+ ```
202
+
203
+ You can also publish to `staging` and `production` using:
204
+
205
+ ```shell
206
+ $ ibot up --env staging
207
+ $ ibot up --env production
208
+ ```
209
+
210
+ ### Private packages
211
+
212
+ **NOTE:** You **_WILL_** be charged by anybody accessing your private
213
+ packages. However, all code and endpoints will not be publicly available;
214
+ you must share the URL with somebody in order for them to use it.
215
+
216
+ You can publish private project by prepending `private/` on the
217
+ `"name"` field in `superuser.json`, e.g.
218
+
219
+ ```json
220
+ {
221
+ "name": "private/@my-username/private-package"
222
+ }
223
+ ```
224
+
225
+ You then deploy as normal. These packages will be visible by you in the
226
+ registry but nobody else.
227
+
228
+ # Additional utilities
229
+
230
+ There are a few additional utilities you may find useful with this package;
231
+
232
+ ## Generate endpoints
233
+
234
+ ```shell
235
+ # generates functions/my-endpoint/example.js
236
+ $ ibot g:endpoint my-endpoint/example
237
+ ```
238
+
239
+ ## Generate tests
240
+
241
+ ```shell
242
+ # Generate blank tests or ones for an endpoint
243
+ $ ibot g:test my_test # OR ...
244
+ $ ibot g:test --endpoint my-endpoint/example
245
+ ```
246
+
247
+ ## Run tests
248
+
249
+ You can write tests for your tools to verify they work. Simply run;
250
+
251
+ ```shell
252
+ $ ibot test
253
+ ```
254
+
255
+ And voila!
256
+
257
+ ## Environment variables
258
+
259
+ You can store environment variables with your packages in;
260
+
261
+ ```
262
+ .env
263
+ .env.production
264
+ .env.staging
265
+ ```
266
+
267
+ These files **will not** be published for everybody to see, so
268
+ you can use them to hide secrets within your code. However, be
269
+ careful when using environment variables with public packages:
270
+ if you ever return them in an endpoint response, or connect to
271
+ sensitive data, there's a chance you may expose that information
272
+ to another user of the platform.
273
+
274
+ # Roadmap
275
+
276
+ There's a lot to build! [Superuser](https://instant.chat) is still in early beta. Coming soon;
277
+
278
+ - Deploy to Slack
279
+ - Uploading image support
280
+ - Knowledge bases
281
+ - Much more!
282
+
283
+ Submit requests via Discord at [discord.gg/instant](https://discord.gg/instant)!
284
+
285
+ # Contact
286
+
287
+ The best place for help and support is Discord at [discord.gg/instant](https://discord.gg/instant),
288
+ but feel free to bookmark all of these links.
289
+
290
+ | Destination | Link |
291
+ | ----------- | ---- |
292
+ | Superuser | [instant.chat](https://instant.chat) |
293
+ | GitHub | [github.com/instantbots](https://github.com/instantbots) |
294
+ | Discord | [discord.gg/instant](https://discord.gg/instant) |
295
+ | X / instantbots | [x.com/instantbots](https://x.com/instantbots) |
296
+ | X / Keith Horwood | [x.com/keithwhor](https://x.com/keithwhor) |
@@ -0,0 +1,102 @@
1
+ const { Command } = require('cmnd');
2
+ const io = require('io');
3
+ const colors = require('colors/safe');
4
+ const inquirer = require('inquirer');
5
+
6
+ const constants = require('../../helpers/constants.js');
7
+ const SettingsManager = require('../../helpers/settings_manager.js');
8
+
9
+ class DomainsAddCommand extends Command {
10
+
11
+ constructor() {
12
+ super('domains', 'add');
13
+ }
14
+
15
+ help () {
16
+ return {
17
+ description: 'Add a custom domain to a package',
18
+ args: [],
19
+ flags: {},
20
+ vflags: {}
21
+ };
22
+ }
23
+
24
+ async run (params) {
25
+
26
+ const settings = SettingsManager.read(true);
27
+ const host = settings.activeProfile.host || constants.BASE_URL;
28
+
29
+ let addResult = await inquirer.prompt([
30
+ {
31
+ name: 'hostname',
32
+ type: 'input',
33
+ message: `Hostname`,
34
+ validate: e => {
35
+ if (!e.match(/^([a-z0-9\-]+.)+[a-z0-9\-]+$/gi)) {
36
+ return 'Must be a valid hostname'
37
+ } else {
38
+ return true;
39
+ }
40
+ }
41
+ },
42
+ {
43
+ name: 'name',
44
+ type: 'input',
45
+ message: `Package name`,
46
+ validate: v => {
47
+ if (
48
+ v.match(/@[a-z][a-z0-9\-]*[a-z0-9]\/[a-z][a-z0-9\-]*[a-z0-9]/i) &&
49
+ v.indexOf('--') === -1
50
+ ) {
51
+ return true;
52
+ } else {
53
+ return 'must be a valid package name in format "@org/package"';
54
+ }
55
+ }
56
+ },
57
+ {
58
+ name: 'environment',
59
+ type: 'list',
60
+ message: 'Environment',
61
+ choices: [
62
+ 'development',
63
+ 'staging',
64
+ 'production'
65
+ ]
66
+ }
67
+ ]);
68
+
69
+ const postParams = {...addResult};
70
+
71
+ const result = await io.post(
72
+ `${host}/v1/custom_domains`,
73
+ settings.activeProfile.key,
74
+ null,
75
+ postParams
76
+ );
77
+
78
+ if (result.statusCode !== 200) {
79
+ const message = result.data?.error?.message || `Invalid statusCode: ${result.statusCode}`;
80
+ throw new Error(message);
81
+ }
82
+
83
+ const customDomain = result.data;
84
+ const packageName = `@${customDomain.package.organization.name}/${customDomain.package.name}`;
85
+ const environment = customDomain.environment;
86
+
87
+ console.log();
88
+ console.log(`${colors.bold.green('Success!')} Custom domain created.`);
89
+ console.log(`${colors.bold(`hostname`)}: ${customDomain.hostname}`);
90
+ console.log(`${colors.bold(`package`)}: ${packageName}`);
91
+ console.log(`${colors.bold(`environment`)}: ${environment}`);
92
+ console.log(`${colors.bold(`verified at`)}: ${customDomain.verified_at || '(unverified)'}`);
93
+ console.log(`${colors.bold(`created`)}: ${customDomain.created_at}`);
94
+ console.log();
95
+
96
+ return void 0;
97
+
98
+ }
99
+
100
+ }
101
+
102
+ module.exports = DomainsAddCommand;
@@ -0,0 +1,71 @@
1
+ const { Command } = require('cmnd');
2
+ const io = require('io');
3
+ const colors = require('colors/safe');
4
+
5
+ const constants = require('../../helpers/constants.js');
6
+ const SettingsManager = require('../../helpers/settings_manager.js');
7
+ const DrawTable = require('../../helpers/draw_table.js');
8
+
9
+ class DomainsListCommand extends Command {
10
+
11
+ constructor() {
12
+ super('domains', 'list');
13
+ }
14
+
15
+ help () {
16
+ return {
17
+ description: 'List all custom domains',
18
+ args: [],
19
+ flags: {},
20
+ vflags: {}
21
+ };
22
+ }
23
+
24
+ async run (params) {
25
+
26
+ const settings = SettingsManager.read(true);
27
+ const host = settings.activeProfile.host || constants.BASE_URL;
28
+
29
+ const result = await io.get(
30
+ `${host}/v1/custom_domains`,
31
+ settings.activeProfile.key,
32
+ null,
33
+ {invalidated: false},
34
+ );
35
+
36
+ if (result.statusCode !== 200) {
37
+ const message = result.data?.error?.message || `Invalid statusCode: ${result.statusCode}`;
38
+ throw new Error(message);
39
+ }
40
+
41
+ const customDomains = result.data.data;
42
+
43
+ const columns = [
44
+ 'hostname',
45
+ 'package',
46
+ 'environment',
47
+ 'verified_at'
48
+ ];
49
+
50
+ const rows = customDomains.map(customDomain => {
51
+ const packageName = `${customDomain.package.is_private ? `private/` : ``}@${customDomain.package.organization.name}/${customDomain.package.name}`;
52
+ const environment = customDomain.environment;
53
+ return {
54
+ hostname: customDomain.hostname,
55
+ package: packageName,
56
+ environment: environment,
57
+ verified_at: customDomain.verified_at
58
+ }
59
+ });
60
+
61
+ console.log();
62
+ DrawTable.render(columns, rows);
63
+ console.log();
64
+
65
+ return void 0;
66
+
67
+ }
68
+
69
+ }
70
+
71
+ module.exports = DomainsListCommand;
@@ -0,0 +1,97 @@
1
+ const { Command } = require('cmnd');
2
+ const io = require('io');
3
+ const colors = require('colors/safe');
4
+ const inquirer = require('inquirer');
5
+
6
+ const constants = require('../../helpers/constants.js');
7
+ const SettingsManager = require('../../helpers/settings_manager.js');
8
+ const DrawTable = require('../../helpers/draw_table.js');
9
+
10
+ class DomainsRemoveCommand extends Command {
11
+
12
+ constructor() {
13
+ super('domains', 'remove');
14
+ }
15
+
16
+ help () {
17
+ return {
18
+ description: 'Remove domains from your packages',
19
+ args: [],
20
+ flags: {},
21
+ vflags: {}
22
+ };
23
+ }
24
+
25
+ async run (params) {
26
+
27
+ const settings = SettingsManager.read(true);
28
+ const host = settings.activeProfile.host || constants.BASE_URL;
29
+
30
+ const result = await io.get(
31
+ `${host}/v1/custom_domains`,
32
+ settings.activeProfile.key,
33
+ null,
34
+ {invalidated: false}
35
+ );
36
+
37
+ if (result.statusCode !== 200) {
38
+ const message = result.data?.error?.message || `Invalid statusCode: ${result.statusCode}`;
39
+ throw new Error(message);
40
+ }
41
+
42
+ const customDomains = result.data.data;
43
+
44
+ const columns = [
45
+ 'hostname',
46
+ 'package',
47
+ 'environment',
48
+ 'verified_at'
49
+ ];
50
+
51
+ const rows = customDomains.map(customDomain => {
52
+ const packageName = `@${customDomain.package.organization.name}/${customDomain.package.name}`;
53
+ const environment = customDomain.environment;
54
+ return {
55
+ hostname: customDomain.hostname,
56
+ package: packageName,
57
+ environment: environment,
58
+ verified_at: customDomain.verified_at
59
+ }
60
+ });
61
+
62
+ console.log();
63
+ const index = await DrawTable.selectIndexFromTable('Choose a domain to remove', columns, rows);
64
+
65
+ if (index === -1) {
66
+ console.log();
67
+ return;
68
+ }
69
+
70
+ const removeParams = {};
71
+ removeParams.hostname = rows[index].hostname;
72
+ removeParams.name = rows[index].package;
73
+ removeParams.environment = rows[index].environment;
74
+
75
+ const removeResult = await io.del(
76
+ `${host}/v1/custom_domains`,
77
+ settings.activeProfile.key,
78
+ null,
79
+ removeParams
80
+ );
81
+
82
+ if (removeResult.statusCode !== 200) {
83
+ const message = removeResult.data?.error?.message || `Invalid statusCode: ${removeResult.statusCode}`;
84
+ throw new Error(message);
85
+ }
86
+
87
+ console.log();
88
+ console.log(`${colors.bold.green('Success!')} Domain ${colors.bold(removeParams.hostname)} removed.`);
89
+ console.log();
90
+
91
+ return void 0;
92
+
93
+ }
94
+
95
+ }
96
+
97
+ module.exports = DomainsRemoveCommand;