@asterai/cli 0.4.0 → 0.5.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.
- package/README.md +40 -59
- package/asterai-init-plugin/package.json +14 -11
- package/asterai-init-plugin/plugin.ts +9 -33
- package/asterai-init-plugin/plugin.wit +12 -0
- package/asterai-init-plugin/tsconfig.json +9 -2
- package/dist/commands/deploy.d.ts +4 -6
- package/dist/commands/deploy.js +41 -64
- package/dist/commands/pkg.d.ts +27 -0
- package/dist/commands/pkg.js +98 -0
- package/dist/const.d.ts +2 -0
- package/dist/const.js +2 -0
- package/oclif.manifest.json +72 -121
- package/package.json +1 -1
- package/asterai-init-plugin/plugin.asterai.proto +0 -22
- package/dist/commands/build.d.ts +0 -23
- package/dist/commands/build.js +0 -139
- package/dist/commands/codegen.d.ts +0 -22
- package/dist/commands/codegen.js +0 -149
- package/dist/compile.d.ts +0 -7
- package/dist/compile.js +0 -25
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @asterai/cli
|
|
|
20
20
|
$ asterai COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ asterai (--version)
|
|
23
|
-
@asterai/cli/0.
|
|
23
|
+
@asterai/cli/0.5.0 linux-x64 node-v20.12.2
|
|
24
24
|
$ asterai --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ asterai COMMAND
|
|
@@ -32,11 +32,10 @@ USAGE
|
|
|
32
32
|
|
|
33
33
|
<!-- commands -->
|
|
34
34
|
* [`asterai auth KEY`](#asterai-auth-key)
|
|
35
|
-
* [`asterai
|
|
36
|
-
* [`asterai codegen`](#asterai-codegen)
|
|
37
|
-
* [`asterai deploy [INPUT]`](#asterai-deploy-input)
|
|
35
|
+
* [`asterai deploy`](#asterai-deploy)
|
|
38
36
|
* [`asterai help [COMMAND]`](#asterai-help-command)
|
|
39
37
|
* [`asterai init [OUTDIR]`](#asterai-init-outdir)
|
|
38
|
+
* [`asterai pkg [INPUT]`](#asterai-pkg-input)
|
|
40
39
|
* [`asterai query`](#asterai-query)
|
|
41
40
|
|
|
42
41
|
## `asterai auth KEY`
|
|
@@ -54,74 +53,31 @@ EXAMPLES
|
|
|
54
53
|
$ asterai auth
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
_See code: [src/commands/auth.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
56
|
+
_See code: [src/commands/auth.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.5.0/src/commands/auth.ts)_
|
|
58
57
|
|
|
59
|
-
## `asterai
|
|
58
|
+
## `asterai deploy`
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
uploads a plugin to asterai
|
|
62
61
|
|
|
63
62
|
```
|
|
64
63
|
USAGE
|
|
65
|
-
$ asterai
|
|
64
|
+
$ asterai deploy [-a <value>] [-e <value>] [-s] [--plugin <value>] [--pkg <value>]
|
|
66
65
|
|
|
67
66
|
FLAGS
|
|
68
|
-
-
|
|
69
|
-
|
|
70
|
-
DESCRIPTION
|
|
71
|
-
compiles the plugin
|
|
72
|
-
|
|
73
|
-
EXAMPLES
|
|
74
|
-
$ asterai build
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
_See code: [src/commands/build.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.4.0/src/commands/build.ts)_
|
|
78
|
-
|
|
79
|
-
## `asterai codegen`
|
|
80
|
-
|
|
81
|
-
Generate code from the plugin manifest
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
USAGE
|
|
85
|
-
$ asterai codegen [-m <value>] [-o <value>] [-a <value>] [-l <value>] [-s]
|
|
86
|
-
|
|
87
|
-
FLAGS
|
|
88
|
-
-a, --appId=<value> app id
|
|
89
|
-
-l, --language=<value> [default: js] language of generated typings
|
|
90
|
-
-m, --manifest=<value> [default: plugin.asterai.proto] manifest path
|
|
91
|
-
-o, --outputDir=<value> [default: generated] output directory
|
|
92
|
-
-s, --staging use staging endpoint
|
|
93
|
-
|
|
94
|
-
DESCRIPTION
|
|
95
|
-
Generate code from the plugin manifest
|
|
96
|
-
|
|
97
|
-
EXAMPLES
|
|
98
|
-
$ asterai codegen
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
_See code: [src/commands/codegen.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.4.0/src/commands/codegen.ts)_
|
|
102
|
-
|
|
103
|
-
## `asterai deploy [INPUT]`
|
|
104
|
-
|
|
105
|
-
compiles and uploads the plugin to asterai
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
USAGE
|
|
109
|
-
$ asterai deploy [INPUT] -a <value> [-m <value>] [-e <value>] [-s]
|
|
110
|
-
|
|
111
|
-
FLAGS
|
|
112
|
-
-a, --app=<value> (required) app ID to immediately configure this plugin with
|
|
113
|
-
-e, --endpoint=<value> [default: https://api.asterai.io/app/plugin]
|
|
114
|
-
-m, --manifest=<value> [default: plugin.asterai.proto] manifest path
|
|
67
|
+
-a, --agent=<value> agent ID to immediately activate this plugin for
|
|
68
|
+
-e, --endpoint=<value> [default: https://api.asterai.io]
|
|
115
69
|
-s, --staging
|
|
70
|
+
--pkg=<value> [default: package.wasm] package WASM path
|
|
71
|
+
--plugin=<value> [default: plugin.wasm] plugin WASM path
|
|
116
72
|
|
|
117
73
|
DESCRIPTION
|
|
118
|
-
|
|
74
|
+
uploads a plugin to asterai
|
|
119
75
|
|
|
120
76
|
EXAMPLES
|
|
121
77
|
$ asterai deploy --app 66a46b12-b1a7-4b72-a64a-0e4fe21902b6
|
|
122
78
|
```
|
|
123
79
|
|
|
124
|
-
_See code: [src/commands/deploy.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
80
|
+
_See code: [src/commands/deploy.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.5.0/src/commands/deploy.ts)_
|
|
125
81
|
|
|
126
82
|
## `asterai help [COMMAND]`
|
|
127
83
|
|
|
@@ -158,7 +114,32 @@ EXAMPLES
|
|
|
158
114
|
$ asterai init project-name
|
|
159
115
|
```
|
|
160
116
|
|
|
161
|
-
_See code: [src/commands/init.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
117
|
+
_See code: [src/commands/init.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.5.0/src/commands/init.ts)_
|
|
118
|
+
|
|
119
|
+
## `asterai pkg [INPUT]`
|
|
120
|
+
|
|
121
|
+
bundles the WIT into a binary WASM package
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
USAGE
|
|
125
|
+
$ asterai pkg [INPUT] [-o <value>] [-w <value>] [-e <value>]
|
|
126
|
+
|
|
127
|
+
ARGUMENTS
|
|
128
|
+
INPUT [default: plugin.wit] path to the plugin's WIT file
|
|
129
|
+
|
|
130
|
+
FLAGS
|
|
131
|
+
-e, --endpoint=<value> [default: https://api.asterai.io]
|
|
132
|
+
-o, --output=<value> [default: package.wasm] output file name for the binary WASM package
|
|
133
|
+
-w, --wit=<value> [default: package.wit] output package converted to the WIT format
|
|
134
|
+
|
|
135
|
+
DESCRIPTION
|
|
136
|
+
bundles the WIT into a binary WASM package
|
|
137
|
+
|
|
138
|
+
EXAMPLES
|
|
139
|
+
$ asterai pkg
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
_See code: [src/commands/pkg.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.5.0/src/commands/pkg.ts)_
|
|
162
143
|
|
|
163
144
|
## `asterai query`
|
|
164
145
|
|
|
@@ -181,5 +162,5 @@ EXAMPLES
|
|
|
181
162
|
$ asterai query
|
|
182
163
|
```
|
|
183
164
|
|
|
184
|
-
_See code: [src/commands/query.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
165
|
+
_See code: [src/commands/query.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.5.0/src/commands/query.ts)_
|
|
185
166
|
<!-- commandsstop -->
|
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plugin",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "",
|
|
5
|
-
"author": "
|
|
6
|
-
"license": "
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"auth": "asterai auth",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
10
|
+
"gen:pkg": "mkdirp build && asterai pkg -o build/package.wasm -w build/package.wit",
|
|
11
|
+
"gen:types": "jco guest-types build/package.wit -n plugin -o generated/",
|
|
12
|
+
"compile": "tsc",
|
|
13
|
+
"componentize": "jco componentize build/plugin.js -w build/package.wit -n plugin -o build/plugin.wasm",
|
|
14
|
+
"build": "run-s gen:pkg gen:types compile componentize",
|
|
11
15
|
"deploy": "asterai deploy"
|
|
12
16
|
},
|
|
13
|
-
"type": "module",
|
|
14
17
|
"devDependencies": {
|
|
15
18
|
"@asterai/cli": "latest",
|
|
16
19
|
"@asterai/sdk": "latest",
|
|
17
|
-
"@
|
|
18
|
-
"@
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
20
|
+
"@bytecodealliance/jco": "^1.9.1",
|
|
21
|
+
"@types/node": "^22.13.4",
|
|
22
|
+
"mkdirp": "^3.0.1",
|
|
23
|
+
"npm-run-all": "^4.1.5",
|
|
24
|
+
"typescript": "^5.7.3"
|
|
22
25
|
}
|
|
23
26
|
}
|
|
@@ -1,35 +1,11 @@
|
|
|
1
|
-
import { BinaryOperationInput } from "./generated/
|
|
2
|
-
import
|
|
3
|
-
import { PluginContext } from "./generated/PluginContext";
|
|
4
|
-
import { ProcessQueryOutput } from "./generated/ProcessQueryOutput";
|
|
5
|
-
import { Log } from "@asterai/sdk";
|
|
1
|
+
import { BinaryOperationInput } from "./generated/plugin";
|
|
2
|
+
import * as asterai from "asterai:host/api@0.1.0";
|
|
6
3
|
|
|
7
|
-
export
|
|
8
|
-
Log.info(`math plugin received a query: ${input.query.content}`);
|
|
9
|
-
// This doesn't return any data, but protobuf requires functions
|
|
10
|
-
// to always have one input and one output exactly to ensure
|
|
11
|
-
// backward compatibility.
|
|
12
|
-
return new ProcessQueryOutput();
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function add(input: BinaryOperationInput): CalculationOutput {
|
|
4
|
+
export const add = (input: BinaryOperationInput): number => {
|
|
16
5
|
const result = input.a + input.b;
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const result = input.a * input.b;
|
|
24
|
-
return new CalculationOutput(`the result is ${result}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function div(input: BinaryOperationInput): CalculationOutput {
|
|
28
|
-
const result = input.a / input.b;
|
|
29
|
-
return new CalculationOutput(`the result is ${result}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function pow(input: BinaryOperationInput): CalculationOutput {
|
|
33
|
-
const result = input.a ** input.b;
|
|
34
|
-
return new CalculationOutput(`the result is ${result}`);
|
|
35
|
-
}
|
|
6
|
+
// Send the calculation result to the agent.
|
|
7
|
+
asterai.sendResponseToAgent(`the result is ${result}`);
|
|
8
|
+
// This result is not seen by the agent, but it can be consumed by
|
|
9
|
+
// other plugins calling this function.
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
2
|
+
"include": ["./**/*.ts"],
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "build",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"paths": {
|
|
8
|
+
"asterai:host/api@0.1.0": ["./generated/interfaces/asterai-host-api.d.ts"]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
4
11
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
export default class Deploy extends Command {
|
|
3
|
-
static args: {
|
|
4
|
-
input: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
5
|
-
};
|
|
3
|
+
static args: {};
|
|
6
4
|
static description: string;
|
|
7
5
|
static examples: string[];
|
|
8
6
|
static flags: {
|
|
9
|
-
|
|
10
|
-
manifest: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
|
+
agent: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
8
|
endpoint: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
12
9
|
staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
plugin: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
pkg: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
13
12
|
};
|
|
14
13
|
run(): Promise<void>;
|
|
15
14
|
}
|
|
16
|
-
export declare const mergeProtoImports: (proto: string, protoPath: string, excludeSdk?: boolean, excludeSyntaxDefinition?: boolean, n?: number) => string;
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,59 +1,57 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Command, Flags } from "@oclif/core";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
3
|
import FormData from "form-data";
|
|
5
4
|
import axios from "axios";
|
|
6
5
|
import { getConfigValue } from "../config.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { BASE_API_URL, BASE_API_URL_STAGING } from "../const.js";
|
|
7
|
+
import path from "path";
|
|
8
|
+
// If the input file doesn't exist, try looking into this dir.
|
|
9
|
+
const RETRY_FIND_FILE_DIR = "build/";
|
|
10
10
|
export default class Deploy extends Command {
|
|
11
|
-
static args = {
|
|
12
|
-
|
|
13
|
-
default: "plugin.ts",
|
|
14
|
-
}),
|
|
15
|
-
};
|
|
16
|
-
static description = "compiles and uploads the plugin to asterai";
|
|
11
|
+
static args = {};
|
|
12
|
+
static description = "uploads a plugin to asterai";
|
|
17
13
|
static examples = [
|
|
18
14
|
`<%= config.bin %> <%= command.id %> --app 66a46b12-b1a7-4b72-a64a-0e4fe21902b6`,
|
|
19
15
|
];
|
|
20
16
|
static flags = {
|
|
21
|
-
|
|
17
|
+
agent: Flags.string({
|
|
22
18
|
char: "a",
|
|
23
|
-
description: "
|
|
24
|
-
required:
|
|
25
|
-
}),
|
|
26
|
-
manifest: Flags.string({
|
|
27
|
-
char: "m",
|
|
28
|
-
description: "manifest path",
|
|
29
|
-
default: "plugin.asterai.proto",
|
|
19
|
+
description: "agent ID to immediately activate this plugin for",
|
|
20
|
+
required: false,
|
|
30
21
|
}),
|
|
31
22
|
endpoint: Flags.string({
|
|
32
23
|
char: "e",
|
|
33
|
-
default:
|
|
24
|
+
default: BASE_API_URL,
|
|
34
25
|
}),
|
|
35
26
|
staging: Flags.boolean({
|
|
36
27
|
char: "s",
|
|
37
28
|
}),
|
|
29
|
+
plugin: Flags.string({
|
|
30
|
+
description: "plugin WASM path",
|
|
31
|
+
default: "plugin.wasm",
|
|
32
|
+
}),
|
|
33
|
+
pkg: Flags.string({
|
|
34
|
+
description: "package WASM path",
|
|
35
|
+
default: "package.wasm",
|
|
36
|
+
}),
|
|
38
37
|
};
|
|
39
38
|
async run() {
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
await deploy(output, flags);
|
|
39
|
+
const { flags } = await this.parse(Deploy);
|
|
40
|
+
await deploy(flags);
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
|
-
const deploy = async (
|
|
43
|
+
const deploy = async (flags) => {
|
|
46
44
|
const form = new FormData();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
form.append("
|
|
54
|
-
const
|
|
45
|
+
if (flags.agent) {
|
|
46
|
+
form.append("agent_id", flags.agent);
|
|
47
|
+
}
|
|
48
|
+
const plugin = readFile(flags.plugin);
|
|
49
|
+
const pkg = readFile(flags.pkg);
|
|
50
|
+
form.append("plugin.wasm", plugin);
|
|
51
|
+
form.append("package.wasm", pkg);
|
|
52
|
+
const baseApiUrl = flags.staging ? BASE_API_URL_STAGING : flags.endpoint;
|
|
55
53
|
await axios({
|
|
56
|
-
url
|
|
54
|
+
url: `${baseApiUrl}/v1/plugin`,
|
|
57
55
|
method: "put",
|
|
58
56
|
data: form,
|
|
59
57
|
headers: {
|
|
@@ -64,38 +62,17 @@ const deploy = async (args, flags) => {
|
|
|
64
62
|
.then(() => console.log("done"))
|
|
65
63
|
.catch(logRequestError);
|
|
66
64
|
};
|
|
67
|
-
export const mergeProtoImports = (proto, protoPath, excludeSdk = true, excludeSyntaxDefinition = true, n = 0) => {
|
|
68
|
-
let mergedManifestString = "";
|
|
69
|
-
const lines = proto.split("\n");
|
|
70
|
-
for (let line of lines) {
|
|
71
|
-
line = line.trim();
|
|
72
|
-
const isSyntaxLine = line.startsWith("syntax");
|
|
73
|
-
if (isSyntaxLine && (excludeSyntaxDefinition || n > 1)) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const isImportLine = line.startsWith("import");
|
|
77
|
-
if (!isImportLine) {
|
|
78
|
-
mergedManifestString = `${mergedManifestString}\n${line}`;
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const importLine = line.replaceAll("'", '"');
|
|
82
|
-
const pathStart = importLine.indexOf('"') + 1;
|
|
83
|
-
const pathEnd = importLine.lastIndexOf('"');
|
|
84
|
-
const pathRelative = importLine.substring(pathStart, pathEnd);
|
|
85
|
-
const isSdkImport = pathRelative.startsWith("node_modules/@asterai/sdk");
|
|
86
|
-
if (isSdkImport && excludeSdk) {
|
|
87
|
-
// Asterai protobuf definitions should not be uploaded
|
|
88
|
-
// as part of the plugin manifest.
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const pathAbsolute = path.join(path.dirname(protoPath), pathRelative);
|
|
92
|
-
const importProto = fs.readFileSync(pathAbsolute, { encoding: "utf8" });
|
|
93
|
-
const importProtoMerged = mergeProtoImports(importProto, pathAbsolute, excludeSdk, excludeSyntaxDefinition, n + 1);
|
|
94
|
-
mergedManifestString = `${mergedManifestString}\n${importProtoMerged}`;
|
|
95
|
-
}
|
|
96
|
-
return mergedManifestString.trim();
|
|
97
|
-
};
|
|
98
65
|
const logRequestError = (e) => {
|
|
99
66
|
const info = e.response?.data ?? e;
|
|
100
67
|
console.log("request error:", info);
|
|
101
68
|
};
|
|
69
|
+
const readFile = (relativePath) => {
|
|
70
|
+
if (fs.existsSync(relativePath)) {
|
|
71
|
+
return fs.readFileSync(relativePath);
|
|
72
|
+
}
|
|
73
|
+
const retryPath = path.join(RETRY_FIND_FILE_DIR, relativePath);
|
|
74
|
+
if (fs.existsSync(retryPath)) {
|
|
75
|
+
return fs.readFileSync(retryPath);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`file not found: ${relativePath}`);
|
|
78
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
export type PkgArgs = {
|
|
3
|
+
input: string;
|
|
4
|
+
};
|
|
5
|
+
export type PkgFlags = {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
output: string;
|
|
8
|
+
wit?: string;
|
|
9
|
+
};
|
|
10
|
+
export type PkgOutput = {
|
|
11
|
+
outputFile: string;
|
|
12
|
+
witPath: string;
|
|
13
|
+
};
|
|
14
|
+
export default class Pkg extends Command {
|
|
15
|
+
static args: {
|
|
16
|
+
input: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
17
|
+
};
|
|
18
|
+
static flags: {
|
|
19
|
+
output: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
20
|
+
wit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
21
|
+
endpoint: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
22
|
+
};
|
|
23
|
+
static description: string;
|
|
24
|
+
static examples: string[];
|
|
25
|
+
run(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare const pkg: (args: PkgArgs, flags: PkgFlags) => Promise<PkgOutput>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs/promises";
|
|
4
|
+
import fsSync from "fs";
|
|
5
|
+
import { BASE_API_URL } from "../const.js";
|
|
6
|
+
import axios from "axios";
|
|
7
|
+
import FormData from "form-data";
|
|
8
|
+
import { getConfigValue } from "../config.js";
|
|
9
|
+
export default class Pkg extends Command {
|
|
10
|
+
static args = {
|
|
11
|
+
input: Args.string({
|
|
12
|
+
default: "plugin.wit",
|
|
13
|
+
description: "path to the plugin's WIT file",
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
output: Flags.string({
|
|
18
|
+
char: "o",
|
|
19
|
+
default: "package.wasm",
|
|
20
|
+
description: "output file name for the binary WASM package",
|
|
21
|
+
}),
|
|
22
|
+
wit: Flags.string({
|
|
23
|
+
char: "w",
|
|
24
|
+
default: "package.wit",
|
|
25
|
+
description: "output package converted to the WIT format",
|
|
26
|
+
}),
|
|
27
|
+
endpoint: Flags.string({
|
|
28
|
+
char: "e",
|
|
29
|
+
default: BASE_API_URL,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
static description = "bundles the WIT into a binary WASM package";
|
|
33
|
+
static examples = [`<%= config.bin %> <%= command.id %>`];
|
|
34
|
+
async run() {
|
|
35
|
+
const { args, flags } = await this.parse(Pkg);
|
|
36
|
+
await pkg(args, flags);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export const pkg = async (args, flags) => {
|
|
40
|
+
const witPath = path.resolve(args.input);
|
|
41
|
+
if (!fsSync.existsSync(witPath)) {
|
|
42
|
+
throw new Error(`WIT file not found at ${witPath}`);
|
|
43
|
+
}
|
|
44
|
+
const baseDir = path.dirname(witPath);
|
|
45
|
+
const outputFile = path.join(baseDir, flags.output);
|
|
46
|
+
const form = new FormData();
|
|
47
|
+
form.append("package.wit", await fs.readFile(witPath));
|
|
48
|
+
const response = await axios({
|
|
49
|
+
url: `${flags.endpoint}/v1/pkg`,
|
|
50
|
+
method: "post",
|
|
51
|
+
data: form,
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: getConfigValue("key"),
|
|
54
|
+
...form.getHeaders(),
|
|
55
|
+
},
|
|
56
|
+
responseType: "arraybuffer",
|
|
57
|
+
}).catch(catchAxiosError);
|
|
58
|
+
validateResponseStatus(response.status);
|
|
59
|
+
await fs.writeFile(outputFile, Buffer.from(response.data), {
|
|
60
|
+
encoding: "binary",
|
|
61
|
+
});
|
|
62
|
+
if (flags.wit) {
|
|
63
|
+
await wasm2wit(flags.endpoint, outputFile, path.join(baseDir, flags.wit));
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
outputFile,
|
|
67
|
+
witPath,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const wasm2wit = async (endpoint, inputFilePath, outputFilePath) => {
|
|
71
|
+
const form = new FormData();
|
|
72
|
+
form.append("package.wasm", await fs.readFile(inputFilePath));
|
|
73
|
+
const response = await axios({
|
|
74
|
+
url: `${endpoint}/v1/wasm2wit`,
|
|
75
|
+
method: "post",
|
|
76
|
+
data: form,
|
|
77
|
+
headers: {
|
|
78
|
+
Authorization: getConfigValue("key"),
|
|
79
|
+
...form.getHeaders(),
|
|
80
|
+
},
|
|
81
|
+
responseType: "text",
|
|
82
|
+
});
|
|
83
|
+
validateResponseStatus(response.status);
|
|
84
|
+
await fs.writeFile(outputFilePath, response.data, { encoding: "utf8" });
|
|
85
|
+
};
|
|
86
|
+
const validateResponseStatus = (status) => {
|
|
87
|
+
if (status < 200 || status >= 300) {
|
|
88
|
+
throw new Error("request failed");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const catchAxiosError = (error) => {
|
|
92
|
+
const data = error.response?.data?.toString() ?? "";
|
|
93
|
+
if (axios.isAxiosError(error) && data.length > 0) {
|
|
94
|
+
const errorMessage = data.replace(/\\n/g, "\n");
|
|
95
|
+
throw new Error(`Request failed: ${errorMessage}`);
|
|
96
|
+
}
|
|
97
|
+
throw new Error("Request failed");
|
|
98
|
+
};
|
package/dist/const.d.ts
ADDED
package/dist/const.js
ADDED
package/oclif.manifest.json
CHANGED
|
@@ -28,24 +28,49 @@
|
|
|
28
28
|
"auth.js"
|
|
29
29
|
]
|
|
30
30
|
},
|
|
31
|
-
"
|
|
31
|
+
"deploy": {
|
|
32
32
|
"aliases": [],
|
|
33
|
-
"args": {
|
|
34
|
-
|
|
35
|
-
"default": "plugin.ts",
|
|
36
|
-
"name": "input"
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
"description": "compiles the plugin",
|
|
33
|
+
"args": {},
|
|
34
|
+
"description": "uploads a plugin to asterai",
|
|
40
35
|
"examples": [
|
|
41
|
-
"<%= config.bin %> <%= command.id %>"
|
|
36
|
+
"<%= config.bin %> <%= command.id %> --app 66a46b12-b1a7-4b72-a64a-0e4fe21902b6"
|
|
42
37
|
],
|
|
43
38
|
"flags": {
|
|
44
|
-
"
|
|
45
|
-
"char": "
|
|
46
|
-
"description": "
|
|
47
|
-
"name": "
|
|
48
|
-
"
|
|
39
|
+
"agent": {
|
|
40
|
+
"char": "a",
|
|
41
|
+
"description": "agent ID to immediately activate this plugin for",
|
|
42
|
+
"name": "agent",
|
|
43
|
+
"required": false,
|
|
44
|
+
"hasDynamicHelp": false,
|
|
45
|
+
"multiple": false,
|
|
46
|
+
"type": "option"
|
|
47
|
+
},
|
|
48
|
+
"endpoint": {
|
|
49
|
+
"char": "e",
|
|
50
|
+
"name": "endpoint",
|
|
51
|
+
"default": "https://api.asterai.io",
|
|
52
|
+
"hasDynamicHelp": false,
|
|
53
|
+
"multiple": false,
|
|
54
|
+
"type": "option"
|
|
55
|
+
},
|
|
56
|
+
"staging": {
|
|
57
|
+
"char": "s",
|
|
58
|
+
"name": "staging",
|
|
59
|
+
"allowNo": false,
|
|
60
|
+
"type": "boolean"
|
|
61
|
+
},
|
|
62
|
+
"plugin": {
|
|
63
|
+
"description": "plugin WASM path",
|
|
64
|
+
"name": "plugin",
|
|
65
|
+
"default": "plugin.wasm",
|
|
66
|
+
"hasDynamicHelp": false,
|
|
67
|
+
"multiple": false,
|
|
68
|
+
"type": "option"
|
|
69
|
+
},
|
|
70
|
+
"pkg": {
|
|
71
|
+
"description": "package WASM path",
|
|
72
|
+
"name": "pkg",
|
|
73
|
+
"default": "package.wasm",
|
|
49
74
|
"hasDynamicHelp": false,
|
|
50
75
|
"multiple": false,
|
|
51
76
|
"type": "option"
|
|
@@ -53,7 +78,7 @@
|
|
|
53
78
|
},
|
|
54
79
|
"hasDynamicHelp": false,
|
|
55
80
|
"hiddenAliases": [],
|
|
56
|
-
"id": "
|
|
81
|
+
"id": "deploy",
|
|
57
82
|
"pluginAlias": "@asterai/cli",
|
|
58
83
|
"pluginName": "@asterai/cli",
|
|
59
84
|
"pluginType": "core",
|
|
@@ -63,66 +88,25 @@
|
|
|
63
88
|
"relativePath": [
|
|
64
89
|
"dist",
|
|
65
90
|
"commands",
|
|
66
|
-
"
|
|
91
|
+
"deploy.js"
|
|
67
92
|
]
|
|
68
93
|
},
|
|
69
|
-
"
|
|
94
|
+
"init": {
|
|
70
95
|
"aliases": [],
|
|
71
|
-
"args": {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
],
|
|
76
|
-
"flags": {
|
|
77
|
-
"manifest": {
|
|
78
|
-
"char": "m",
|
|
79
|
-
"description": "manifest path",
|
|
80
|
-
"name": "manifest",
|
|
81
|
-
"default": "plugin.asterai.proto",
|
|
82
|
-
"hasDynamicHelp": false,
|
|
83
|
-
"multiple": false,
|
|
84
|
-
"type": "option"
|
|
85
|
-
},
|
|
86
|
-
"outputDir": {
|
|
87
|
-
"char": "o",
|
|
88
|
-
"description": "output directory",
|
|
89
|
-
"name": "outputDir",
|
|
90
|
-
"default": "generated",
|
|
91
|
-
"hasDynamicHelp": false,
|
|
92
|
-
"multiple": false,
|
|
93
|
-
"type": "option"
|
|
94
|
-
},
|
|
95
|
-
"appId": {
|
|
96
|
-
"char": "a",
|
|
97
|
-
"description": "app id",
|
|
98
|
-
"name": "appId",
|
|
99
|
-
"required": false,
|
|
100
|
-
"hasDynamicHelp": false,
|
|
101
|
-
"multiple": false,
|
|
102
|
-
"type": "option"
|
|
103
|
-
},
|
|
104
|
-
"language": {
|
|
105
|
-
"char": "l",
|
|
106
|
-
"description": "language of generated typings",
|
|
107
|
-
"name": "language",
|
|
108
|
-
"required": false,
|
|
109
|
-
"default": "js",
|
|
110
|
-
"hasDynamicHelp": false,
|
|
111
|
-
"multiple": false,
|
|
112
|
-
"type": "option"
|
|
113
|
-
},
|
|
114
|
-
"staging": {
|
|
115
|
-
"char": "s",
|
|
116
|
-
"description": "use staging endpoint",
|
|
117
|
-
"name": "staging",
|
|
118
|
-
"required": false,
|
|
119
|
-
"allowNo": false,
|
|
120
|
-
"type": "boolean"
|
|
96
|
+
"args": {
|
|
97
|
+
"outDir": {
|
|
98
|
+
"default": "plugin",
|
|
99
|
+
"name": "outDir"
|
|
121
100
|
}
|
|
122
101
|
},
|
|
102
|
+
"description": "Initialise a new plugin project",
|
|
103
|
+
"examples": [
|
|
104
|
+
"<%= config.bin %> <%= command.id %> project-name"
|
|
105
|
+
],
|
|
106
|
+
"flags": {},
|
|
123
107
|
"hasDynamicHelp": false,
|
|
124
108
|
"hiddenAliases": [],
|
|
125
|
-
"id": "
|
|
109
|
+
"id": "init",
|
|
126
110
|
"pluginAlias": "@asterai/cli",
|
|
127
111
|
"pluginName": "@asterai/cli",
|
|
128
112
|
"pluginType": "core",
|
|
@@ -132,36 +116,37 @@
|
|
|
132
116
|
"relativePath": [
|
|
133
117
|
"dist",
|
|
134
118
|
"commands",
|
|
135
|
-
"
|
|
119
|
+
"init.js"
|
|
136
120
|
]
|
|
137
121
|
},
|
|
138
|
-
"
|
|
122
|
+
"pkg": {
|
|
139
123
|
"aliases": [],
|
|
140
124
|
"args": {
|
|
141
125
|
"input": {
|
|
142
|
-
"default": "plugin.
|
|
126
|
+
"default": "plugin.wit",
|
|
127
|
+
"description": "path to the plugin's WIT file",
|
|
143
128
|
"name": "input"
|
|
144
129
|
}
|
|
145
130
|
},
|
|
146
|
-
"description": "
|
|
131
|
+
"description": "bundles the WIT into a binary WASM package",
|
|
147
132
|
"examples": [
|
|
148
|
-
"<%= config.bin %> <%= command.id %>
|
|
133
|
+
"<%= config.bin %> <%= command.id %>"
|
|
149
134
|
],
|
|
150
135
|
"flags": {
|
|
151
|
-
"
|
|
152
|
-
"char": "
|
|
153
|
-
"description": "
|
|
154
|
-
"name": "
|
|
155
|
-
"
|
|
136
|
+
"output": {
|
|
137
|
+
"char": "o",
|
|
138
|
+
"description": "output file name for the binary WASM package",
|
|
139
|
+
"name": "output",
|
|
140
|
+
"default": "package.wasm",
|
|
156
141
|
"hasDynamicHelp": false,
|
|
157
142
|
"multiple": false,
|
|
158
143
|
"type": "option"
|
|
159
144
|
},
|
|
160
|
-
"
|
|
161
|
-
"char": "
|
|
162
|
-
"description": "
|
|
163
|
-
"name": "
|
|
164
|
-
"default": "
|
|
145
|
+
"wit": {
|
|
146
|
+
"char": "w",
|
|
147
|
+
"description": "output package converted to the WIT format",
|
|
148
|
+
"name": "wit",
|
|
149
|
+
"default": "package.wit",
|
|
165
150
|
"hasDynamicHelp": false,
|
|
166
151
|
"multiple": false,
|
|
167
152
|
"type": "option"
|
|
@@ -169,49 +154,15 @@
|
|
|
169
154
|
"endpoint": {
|
|
170
155
|
"char": "e",
|
|
171
156
|
"name": "endpoint",
|
|
172
|
-
"default": "https://api.asterai.io
|
|
157
|
+
"default": "https://api.asterai.io",
|
|
173
158
|
"hasDynamicHelp": false,
|
|
174
159
|
"multiple": false,
|
|
175
160
|
"type": "option"
|
|
176
|
-
},
|
|
177
|
-
"staging": {
|
|
178
|
-
"char": "s",
|
|
179
|
-
"name": "staging",
|
|
180
|
-
"allowNo": false,
|
|
181
|
-
"type": "boolean"
|
|
182
161
|
}
|
|
183
162
|
},
|
|
184
163
|
"hasDynamicHelp": false,
|
|
185
164
|
"hiddenAliases": [],
|
|
186
|
-
"id": "
|
|
187
|
-
"pluginAlias": "@asterai/cli",
|
|
188
|
-
"pluginName": "@asterai/cli",
|
|
189
|
-
"pluginType": "core",
|
|
190
|
-
"strict": true,
|
|
191
|
-
"enableJsonFlag": false,
|
|
192
|
-
"isESM": true,
|
|
193
|
-
"relativePath": [
|
|
194
|
-
"dist",
|
|
195
|
-
"commands",
|
|
196
|
-
"deploy.js"
|
|
197
|
-
]
|
|
198
|
-
},
|
|
199
|
-
"init": {
|
|
200
|
-
"aliases": [],
|
|
201
|
-
"args": {
|
|
202
|
-
"outDir": {
|
|
203
|
-
"default": "plugin",
|
|
204
|
-
"name": "outDir"
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
"description": "Initialise a new plugin project",
|
|
208
|
-
"examples": [
|
|
209
|
-
"<%= config.bin %> <%= command.id %> project-name"
|
|
210
|
-
],
|
|
211
|
-
"flags": {},
|
|
212
|
-
"hasDynamicHelp": false,
|
|
213
|
-
"hiddenAliases": [],
|
|
214
|
-
"id": "init",
|
|
165
|
+
"id": "pkg",
|
|
215
166
|
"pluginAlias": "@asterai/cli",
|
|
216
167
|
"pluginName": "@asterai/cli",
|
|
217
168
|
"pluginType": "core",
|
|
@@ -221,7 +172,7 @@
|
|
|
221
172
|
"relativePath": [
|
|
222
173
|
"dist",
|
|
223
174
|
"commands",
|
|
224
|
-
"
|
|
175
|
+
"pkg.js"
|
|
225
176
|
]
|
|
226
177
|
},
|
|
227
178
|
"query": {
|
|
@@ -280,5 +231,5 @@
|
|
|
280
231
|
]
|
|
281
232
|
}
|
|
282
233
|
},
|
|
283
|
-
"version": "0.
|
|
234
|
+
"version": "0.5.0"
|
|
284
235
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asterai/cli",
|
|
3
3
|
"description": "CLI for building and deploying asterai plugins",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"author": "asterai <support@asterai.io>",
|
|
6
6
|
"repository": "asterai-io/asterai-sdk",
|
|
7
7
|
"homepage": "https://github.com/asterai-io/asterai-sdk",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
syntax = "proto3";
|
|
2
|
-
import "node_modules/@asterai/sdk/protobuf/asterai.proto";
|
|
3
|
-
|
|
4
|
-
service Math {
|
|
5
|
-
rpc processQuery(PluginContext) returns (ProcessQueryOutput);
|
|
6
|
-
rpc add(BinaryOperationInput) returns (CalculationOutput);
|
|
7
|
-
rpc mul(BinaryOperationInput) returns (CalculationOutput);
|
|
8
|
-
rpc div(BinaryOperationInput) returns (CalculationOutput);
|
|
9
|
-
rpc pow(BinaryOperationInput) returns (CalculationOutput);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
message ProcessQueryOutput {}
|
|
13
|
-
|
|
14
|
-
message BinaryOperationInput {
|
|
15
|
-
PluginContext context = 1;
|
|
16
|
-
double a = 2;
|
|
17
|
-
double b = 3;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
message CalculationOutput {
|
|
21
|
-
string system_message = 1;
|
|
22
|
-
}
|
package/dist/commands/build.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Command } from "@oclif/core";
|
|
2
|
-
export type BuildArgs = {
|
|
3
|
-
input: string;
|
|
4
|
-
};
|
|
5
|
-
export type BuildFlags = {
|
|
6
|
-
manifest: string;
|
|
7
|
-
};
|
|
8
|
-
export type BuildOutput = {
|
|
9
|
-
outputFile: string;
|
|
10
|
-
manifestPath: string;
|
|
11
|
-
};
|
|
12
|
-
export default class Build extends Command {
|
|
13
|
-
static args: {
|
|
14
|
-
input: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
15
|
-
};
|
|
16
|
-
static description: string;
|
|
17
|
-
static examples: string[];
|
|
18
|
-
static flags: {
|
|
19
|
-
manifest: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
20
|
-
};
|
|
21
|
-
run(): Promise<void>;
|
|
22
|
-
}
|
|
23
|
-
export declare const build: (args: BuildArgs, flags: BuildFlags) => Promise<BuildOutput>;
|
package/dist/commands/build.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { Args, Command, Flags } from "@oclif/core";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import { compile } from "../compile.js";
|
|
5
|
-
import Mustache from "mustache";
|
|
6
|
-
import protobuf from "protobufjs";
|
|
7
|
-
import { mergeProtoImports } from "./deploy.js";
|
|
8
|
-
export default class Build extends Command {
|
|
9
|
-
static args = {
|
|
10
|
-
input: Args.string({
|
|
11
|
-
default: "plugin.ts",
|
|
12
|
-
}),
|
|
13
|
-
};
|
|
14
|
-
static description = "compiles the plugin";
|
|
15
|
-
static examples = [`<%= config.bin %> <%= command.id %>`];
|
|
16
|
-
static flags = {
|
|
17
|
-
manifest: Flags.string({
|
|
18
|
-
char: "m",
|
|
19
|
-
description: "manifest path",
|
|
20
|
-
default: "plugin.asterai.proto",
|
|
21
|
-
}),
|
|
22
|
-
};
|
|
23
|
-
async run() {
|
|
24
|
-
const { args, flags } = await this.parse(Build);
|
|
25
|
-
await build(args, flags);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
export const build = async (args, flags) => {
|
|
29
|
-
const manifestPath = path.resolve(flags.manifest);
|
|
30
|
-
const inputFile = path.resolve(args.input);
|
|
31
|
-
if (!fs.existsSync(inputFile)) {
|
|
32
|
-
throw new Error(`input file not found (${args.input})`);
|
|
33
|
-
}
|
|
34
|
-
const inputFileName = path.parse(inputFile).name;
|
|
35
|
-
const baseDir = path.dirname(manifestPath);
|
|
36
|
-
const outDir = path.join(baseDir, "build");
|
|
37
|
-
const outputFile = path.join(outDir, `${inputFileName}.wasm`);
|
|
38
|
-
const libsDir = path.join(baseDir, "node_modules");
|
|
39
|
-
if (!fs.existsSync(libsDir)) {
|
|
40
|
-
throw new Error("no node_modules found in the plugin directory");
|
|
41
|
-
}
|
|
42
|
-
const proto = fs.readFileSync(manifestPath, { encoding: "utf8" });
|
|
43
|
-
const functionDescriptors = getPluginFunctionDescriptors(proto, manifestPath);
|
|
44
|
-
const inputFileContent = fs.readFileSync(inputFile, { encoding: "utf8" });
|
|
45
|
-
assertPluginCodeHasAllFunctionsFromManifest(inputFileContent, functionDescriptors);
|
|
46
|
-
const entryPointCode = generateEntryPointCode(functionDescriptors);
|
|
47
|
-
const mergedPluginCode = mergeInputPluginCodeWithEntrypoint(inputFileContent, entryPointCode);
|
|
48
|
-
const mergedTempFilePath = writeMergedPluginCodeTempFile(mergedPluginCode, path.parse(inputFile).dir, inputFileName);
|
|
49
|
-
const globalFile = path.join(libsDir, "@asterai/sdk/global.ts");
|
|
50
|
-
const options = {
|
|
51
|
-
inputFiles: [mergedTempFilePath, globalFile],
|
|
52
|
-
baseDir,
|
|
53
|
-
outputFile,
|
|
54
|
-
libs: libsDir,
|
|
55
|
-
};
|
|
56
|
-
try {
|
|
57
|
-
await compile(options);
|
|
58
|
-
}
|
|
59
|
-
finally {
|
|
60
|
-
fs.unlinkSync(mergedTempFilePath);
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
manifestPath,
|
|
64
|
-
outputFile,
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
const getPluginFunctionDescriptors = (proto, protoPath) => {
|
|
68
|
-
const protoMerged = mergeProtoImports(proto, protoPath, false, false);
|
|
69
|
-
const result = protobuf.parse(protoMerged);
|
|
70
|
-
const namespace = result.root.resolveAll();
|
|
71
|
-
const objects = namespace.nestedArray;
|
|
72
|
-
const serviceObject = objects.find(o => o.methods !== undefined);
|
|
73
|
-
if (!serviceObject) {
|
|
74
|
-
throw new Error("no service found in plugin manifest");
|
|
75
|
-
}
|
|
76
|
-
const service = serviceObject;
|
|
77
|
-
return service.methodsArray.map(m => ({
|
|
78
|
-
functionName: m.name,
|
|
79
|
-
inputType: m.requestType,
|
|
80
|
-
outputType: m.responseType,
|
|
81
|
-
}));
|
|
82
|
-
};
|
|
83
|
-
const generateEntryPointCode = (functionDescriptors) => {
|
|
84
|
-
const importsCode = `
|
|
85
|
-
import { Protobuf } from "@asterai/as-proto/assembly";
|
|
86
|
-
import { readBufferFromPtr, writeBufferToPr } from "@asterai/sdk/buffer";
|
|
87
|
-
`;
|
|
88
|
-
let code = "\n// generated plugin entry points\n\n";
|
|
89
|
-
for (const functionDescriptor of functionDescriptors) {
|
|
90
|
-
const template = `
|
|
91
|
-
export function {{func}}_entry_point(ptr: u32): u32 {
|
|
92
|
-
const inputBuffer = readBufferFromPtr(ptr);
|
|
93
|
-
const input = Protobuf.decode<{{inpt}}>(
|
|
94
|
-
inputBuffer,
|
|
95
|
-
{{inpt}}.decode,
|
|
96
|
-
);
|
|
97
|
-
const output = {{func}}(input);
|
|
98
|
-
const outputBuffer = Protobuf.encode<{{outp}}>(
|
|
99
|
-
output,
|
|
100
|
-
{{outp}}.encode,
|
|
101
|
-
);
|
|
102
|
-
return writeBufferToPr(outputBuffer);
|
|
103
|
-
}
|
|
104
|
-
`;
|
|
105
|
-
const view = {
|
|
106
|
-
func: functionDescriptor.functionName,
|
|
107
|
-
inpt: functionDescriptor.inputType,
|
|
108
|
-
outp: functionDescriptor.outputType,
|
|
109
|
-
};
|
|
110
|
-
const functionEntryPoint = Mustache.render(template, view);
|
|
111
|
-
code = `${code}\n${functionEntryPoint}`;
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
importsCode,
|
|
115
|
-
entryPointsCode: code,
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
const mergeInputPluginCodeWithEntrypoint = (pluginCode, entryPoint) => `${entryPoint.importsCode}\n${pluginCode}\n${entryPoint.entryPointsCode}`;
|
|
119
|
-
const writeMergedPluginCodeTempFile = (source, inputFileDir, inputFileName) => {
|
|
120
|
-
const tempFileName = `.entrypoint.${inputFileName}.ts`;
|
|
121
|
-
const tempFilePath = path.join(inputFileDir, tempFileName);
|
|
122
|
-
fs.writeFileSync(tempFilePath, source, { encoding: "utf8" });
|
|
123
|
-
return tempFilePath;
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Throw an error if the plugin WASM source is missing a function from
|
|
127
|
-
* the manifest.
|
|
128
|
-
* The only purpose of this function is to let the user know about
|
|
129
|
-
* the issue in a direct way.
|
|
130
|
-
*/
|
|
131
|
-
const assertPluginCodeHasAllFunctionsFromManifest = (source, functionDescriptors) => {
|
|
132
|
-
for (const functionDescriptor of functionDescriptors) {
|
|
133
|
-
const includesFunction = source.includes(`function ${functionDescriptor.functionName}`);
|
|
134
|
-
if (!includesFunction) {
|
|
135
|
-
throw new Error(`function "${functionDescriptor.functionName}" was defined in plugin ` +
|
|
136
|
-
"manifest (.proto file) but is missing from plugin code");
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Command } from "@oclif/core";
|
|
2
|
-
export type CodegenFlags = {
|
|
3
|
-
manifest: string;
|
|
4
|
-
outputDir: string;
|
|
5
|
-
appId?: string;
|
|
6
|
-
language?: string;
|
|
7
|
-
staging?: boolean;
|
|
8
|
-
};
|
|
9
|
-
export default class Codegen extends Command {
|
|
10
|
-
static args: {};
|
|
11
|
-
static description: string;
|
|
12
|
-
static examples: string[];
|
|
13
|
-
static flags: {
|
|
14
|
-
manifest: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
15
|
-
outputDir: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
16
|
-
appId: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
17
|
-
language: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
18
|
-
staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
19
|
-
};
|
|
20
|
-
run(): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
export declare const codegen: (flags: CodegenFlags) => Promise<void>;
|
package/dist/commands/codegen.js
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { Command, Flags } from "@oclif/core";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs";
|
|
4
|
-
import { execSync } from "node:child_process";
|
|
5
|
-
import axios from "axios";
|
|
6
|
-
import { getConfigValue } from "../config.js";
|
|
7
|
-
import os from "os";
|
|
8
|
-
// Relative path from the plugin root directory.
|
|
9
|
-
const AS_PROTO_GEN_PATH = "./node_modules/.bin/as-proto-gen";
|
|
10
|
-
const PRODUCTION_ENDPOINT_BASE_URL = "https://api.asterai.io";
|
|
11
|
-
const STAGING_ENDPOINT_BASE_URL = "https://staging.api.asterai.io";
|
|
12
|
-
export default class Codegen extends Command {
|
|
13
|
-
static args = {};
|
|
14
|
-
static description = "Generate code from the plugin manifest";
|
|
15
|
-
static examples = [`<%= config.bin %> <%= command.id %>`];
|
|
16
|
-
static flags = {
|
|
17
|
-
manifest: Flags.string({
|
|
18
|
-
char: "m",
|
|
19
|
-
description: "manifest path",
|
|
20
|
-
default: "plugin.asterai.proto",
|
|
21
|
-
}),
|
|
22
|
-
outputDir: Flags.string({
|
|
23
|
-
char: "o",
|
|
24
|
-
description: "output directory",
|
|
25
|
-
default: "generated",
|
|
26
|
-
}),
|
|
27
|
-
appId: Flags.string({
|
|
28
|
-
char: "a",
|
|
29
|
-
description: "app id",
|
|
30
|
-
required: false,
|
|
31
|
-
}),
|
|
32
|
-
language: Flags.string({
|
|
33
|
-
char: "l",
|
|
34
|
-
description: "language of generated typings",
|
|
35
|
-
required: false,
|
|
36
|
-
default: "js",
|
|
37
|
-
}),
|
|
38
|
-
staging: Flags.boolean({
|
|
39
|
-
char: "s",
|
|
40
|
-
description: "use staging endpoint",
|
|
41
|
-
required: false,
|
|
42
|
-
default: false,
|
|
43
|
-
}),
|
|
44
|
-
};
|
|
45
|
-
async run() {
|
|
46
|
-
const { flags } = await this.parse(Codegen);
|
|
47
|
-
codegen(flags);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export const codegen = (flags) => {
|
|
51
|
-
const manifestPath = path.resolve(flags.manifest);
|
|
52
|
-
const baseDir = path.dirname(manifestPath);
|
|
53
|
-
const outDir = path.join(baseDir, flags.outputDir);
|
|
54
|
-
if (!fs.existsSync(outDir)) {
|
|
55
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
deleteOldGeneratedFiles(outDir);
|
|
59
|
-
}
|
|
60
|
-
if (flags.appId && flags.language) {
|
|
61
|
-
return generateClientTypings(outDir, flags.language, flags.appId, flags.staging ?? false);
|
|
62
|
-
}
|
|
63
|
-
return generateAssemblyScriptPluginTypings(flags, baseDir);
|
|
64
|
-
};
|
|
65
|
-
const generateAssemblyScriptPluginTypings = async (flags, baseDir) => {
|
|
66
|
-
const absoluteAsProtoGenPath = path.join(baseDir, AS_PROTO_GEN_PATH);
|
|
67
|
-
try {
|
|
68
|
-
execSync("protoc --version");
|
|
69
|
-
}
|
|
70
|
-
catch (e) {
|
|
71
|
-
console.error("No protoc binary found. " +
|
|
72
|
-
"Is protocol buffers installed on the system? " +
|
|
73
|
-
"Download protocol buffers here: https://protobuf.dev/downloads");
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
execSync("protoc " +
|
|
78
|
-
`--plugin='protoc-gen-as=${absoluteAsProtoGenPath}' ` +
|
|
79
|
-
`--experimental_allow_proto3_optional ` +
|
|
80
|
-
`--as_out='./${flags.outputDir}' ./${flags.manifest}`);
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
console.error("Failed to generate protobuf types:", e);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
const deleteOldGeneratedFiles = (outDir) => {
|
|
87
|
-
const oldFiles = fs.readdirSync(outDir);
|
|
88
|
-
for (const oldFile of oldFiles) {
|
|
89
|
-
const file = path.parse(oldFile);
|
|
90
|
-
if (file.ext !== ".ts") {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const deletePath = path.join(outDir, oldFile);
|
|
94
|
-
fs.unlinkSync(deletePath);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
const generateClientTypings = async (outDir, language, appId, shouldUseStaging) => {
|
|
98
|
-
const manifestsResponse = await downloadEnabledPluginsManifests(appId, shouldUseStaging);
|
|
99
|
-
const asteraiProto = await fetchAsteraiProto();
|
|
100
|
-
const aggregatedManifest = aggregateManifests(manifestsResponse.manifests, asteraiProto);
|
|
101
|
-
const appPrefix = `app.${appId}`;
|
|
102
|
-
fs.writeFileSync(path.join(outDir, `${appPrefix}.proto`), aggregatedManifest.content);
|
|
103
|
-
if (language === "ts") {
|
|
104
|
-
console.log("generating TypeScript typings for plugin manifest...");
|
|
105
|
-
const jsOutput = `${appPrefix}.js`;
|
|
106
|
-
const dTsOutput = `${appPrefix}.d.ts`;
|
|
107
|
-
execSync(`
|
|
108
|
-
npx -p protobufjs-cli pbjs -t static --no-service ${aggregatedManifest.filePath} -o ${path.join(outDir, jsOutput)}
|
|
109
|
-
`);
|
|
110
|
-
execSync(`
|
|
111
|
-
npx -p protobufjs-cli pbts -o ${path.join(outDir, dTsOutput)} ${path.join(outDir, jsOutput)}
|
|
112
|
-
`);
|
|
113
|
-
fs.unlinkSync(aggregatedManifest.filePath);
|
|
114
|
-
console.log("Typings generated successfully.");
|
|
115
|
-
}
|
|
116
|
-
console.log("done.");
|
|
117
|
-
};
|
|
118
|
-
const fetchAsteraiProto = () => {
|
|
119
|
-
// TODO: fetch this from the local file system instead.
|
|
120
|
-
return axios
|
|
121
|
-
.get("https://unpkg.com/@asterai/sdk@latest/protobuf/asterai.proto")
|
|
122
|
-
.then(r => r.data);
|
|
123
|
-
};
|
|
124
|
-
const aggregateManifests = (manifests, asteraiProto) => {
|
|
125
|
-
let aggregatedManifest = `${asteraiProto}\n`;
|
|
126
|
-
const osTmpDir = os.tmpdir();
|
|
127
|
-
const aggregatedManifestPath = path.join(osTmpDir, "plugins.asterai.proto");
|
|
128
|
-
for (const manifest of manifests) {
|
|
129
|
-
aggregatedManifest += `${manifest.proto}\n`;
|
|
130
|
-
}
|
|
131
|
-
fs.writeFileSync(aggregatedManifestPath, aggregatedManifest);
|
|
132
|
-
return {
|
|
133
|
-
content: aggregatedManifest,
|
|
134
|
-
filePath: aggregatedManifestPath,
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
const downloadEnabledPluginsManifests = async (appId, shouldUseStaging) => {
|
|
138
|
-
const baseUrl = shouldUseStaging
|
|
139
|
-
? STAGING_ENDPOINT_BASE_URL
|
|
140
|
-
: PRODUCTION_ENDPOINT_BASE_URL;
|
|
141
|
-
const response = await axios({
|
|
142
|
-
url: `${baseUrl}/app/${appId}/plugin/manifests`,
|
|
143
|
-
method: "GET",
|
|
144
|
-
headers: {
|
|
145
|
-
Authorization: getConfigValue("key"),
|
|
146
|
-
},
|
|
147
|
-
});
|
|
148
|
-
return response.data;
|
|
149
|
-
};
|
package/dist/compile.d.ts
DELETED
package/dist/compile.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as asc from "assemblyscript/asc";
|
|
2
|
-
const COMPILER_OPTIONS = {
|
|
3
|
-
stdout: process.stdout,
|
|
4
|
-
stderr: process.stderr,
|
|
5
|
-
};
|
|
6
|
-
export const compile = async (options) => {
|
|
7
|
-
const args = [
|
|
8
|
-
"--exportRuntime",
|
|
9
|
-
"--runtime",
|
|
10
|
-
"stub",
|
|
11
|
-
...options.inputFiles,
|
|
12
|
-
"--baseDir",
|
|
13
|
-
options.baseDir,
|
|
14
|
-
"--lib",
|
|
15
|
-
options.libs,
|
|
16
|
-
"--outFile",
|
|
17
|
-
options.outputFile,
|
|
18
|
-
"--optimize",
|
|
19
|
-
"--debug",
|
|
20
|
-
];
|
|
21
|
-
const result = await asc.main(args, COMPILER_OPTIONS);
|
|
22
|
-
if (result.error) {
|
|
23
|
-
throw result.error;
|
|
24
|
-
}
|
|
25
|
-
};
|