agental 0.3.0 → 0.4.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/dist/cli.js +97 -6
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -46,7 +46,7 @@ import { parseArgs } from "node:util";
|
|
|
46
46
|
|
|
47
47
|
// ../src/cli-build.ts
|
|
48
48
|
var PUBLISHED = true;
|
|
49
|
-
var CLI_VERSION = true ? "0.
|
|
49
|
+
var CLI_VERSION = true ? "0.4.0" : "dev";
|
|
50
50
|
var DEFAULT_API_URL = true ? "https://agental.io" : "http://127.0.0.1:8741";
|
|
51
51
|
var PACKAGE_NAME = "agental";
|
|
52
52
|
var USER_AGENT = `agental-cli/${CLI_VERSION}`;
|
|
@@ -2407,7 +2407,7 @@ function topUpByDollars(dollars) {
|
|
|
2407
2407
|
var TOP_UPS = [20, 50, 100, 250, 500, 1e3, 5e3, 1e4].map((dollars) => topUpByDollars(dollars));
|
|
2408
2408
|
|
|
2409
2409
|
// ../src/sandbox-where.ts
|
|
2410
|
-
var TERMS = /* @__PURE__ */ new Set(["status", "size", "region", "template", "tag", "archived", "memory", "outbound", "stops", "made-by"]);
|
|
2410
|
+
var TERMS = /* @__PURE__ */ new Set(["status", "size", "region", "template", "tag", "archived", "memory", "outbound", "stops", "made-by", "activity"]);
|
|
2411
2411
|
function words(text) {
|
|
2412
2412
|
const found = [];
|
|
2413
2413
|
for (const match of text.matchAll(/(?:[^\s"]+|"[^"]*")+/g)) {
|
|
@@ -2443,8 +2443,8 @@ function whereQuery(text, query = new URLSearchParams()) {
|
|
|
2443
2443
|
query.append(`${not ? "notMetadata" : "metadata"}[${key2}]`, value);
|
|
2444
2444
|
continue;
|
|
2445
2445
|
}
|
|
2446
|
-
if (not && key2 !== "tag") {
|
|
2447
|
-
throw new Error(`${word}: only tags and metadata keys can be left out with -.`);
|
|
2446
|
+
if (not && key2 !== "tag" && key2 !== "activity") {
|
|
2447
|
+
throw new Error(`${word}: only tags, activity and metadata keys can be left out with -.`);
|
|
2448
2448
|
}
|
|
2449
2449
|
switch (key2) {
|
|
2450
2450
|
case "status":
|
|
@@ -2479,6 +2479,11 @@ function whereQuery(text, query = new URLSearchParams()) {
|
|
|
2479
2479
|
case "made-by":
|
|
2480
2480
|
query.append("createdBy", value);
|
|
2481
2481
|
break;
|
|
2482
|
+
case "activity":
|
|
2483
|
+
for (const each of value.split(",")) {
|
|
2484
|
+
query.append(not ? "notActivity" : "activity", each);
|
|
2485
|
+
}
|
|
2486
|
+
break;
|
|
2482
2487
|
case "archived":
|
|
2483
2488
|
query.set("archived", value);
|
|
2484
2489
|
break;
|
|
@@ -2623,6 +2628,8 @@ async function main() {
|
|
|
2623
2628
|
never: { type: "boolean", default: false },
|
|
2624
2629
|
outbound: { type: "string" },
|
|
2625
2630
|
allow: { type: "string", multiple: true },
|
|
2631
|
+
// Where a sandbox's web traffic leaves, as agental create takes it: box, or residential:<country>[:sticky|rotating].
|
|
2632
|
+
egress: { type: "string" },
|
|
2626
2633
|
"ssh-key": { type: "string", multiple: true },
|
|
2627
2634
|
none: { type: "boolean", default: false },
|
|
2628
2635
|
host: { type: "string", multiple: true },
|
|
@@ -2770,6 +2777,9 @@ async function main() {
|
|
|
2770
2777
|
case "network":
|
|
2771
2778
|
await network(positionals.slice(1), values);
|
|
2772
2779
|
return;
|
|
2780
|
+
case "egress":
|
|
2781
|
+
await egress(positionals.slice(1), values);
|
|
2782
|
+
return;
|
|
2773
2783
|
case "templates":
|
|
2774
2784
|
await listTemplates(values.json);
|
|
2775
2785
|
return;
|
|
@@ -2875,6 +2885,7 @@ async function create(values) {
|
|
|
2875
2885
|
);
|
|
2876
2886
|
}
|
|
2877
2887
|
const allow = values.allow === void 0 ? void 0 : listedIn(values.allow);
|
|
2888
|
+
const egressAsked = values.egress === void 0 ? void 0 : egressFrom(values.egress.split(":"), "--egress takes box, or residential:<country>, as residential:de or residential:us:rotating.");
|
|
2878
2889
|
const sshKeys2 = values["ssh-key"] === void 0 ? void 0 : publicKeysFrom(values["ssh-key"]);
|
|
2879
2890
|
const box = boxNamed(values.box);
|
|
2880
2891
|
const templateId = values.template === void 0 ? void 0 : (await templateNamed(values.template)).id;
|
|
@@ -2888,6 +2899,7 @@ async function create(values) {
|
|
|
2888
2899
|
...templateId ? { templateId } : {},
|
|
2889
2900
|
...regionsOption(values.region),
|
|
2890
2901
|
...allow ? { network: { allow } } : {},
|
|
2902
|
+
...egressAsked ? { egress: egressAsked } : {},
|
|
2891
2903
|
...ttlSeconds === void 0 ? {} : { ttlSeconds },
|
|
2892
2904
|
...sshKeys2 === void 0 ? {} : { sshKeys: sshKeys2 },
|
|
2893
2905
|
...given
|
|
@@ -3751,6 +3763,72 @@ async function network(positionals, values) {
|
|
|
3751
3763
|
].join("\n")
|
|
3752
3764
|
);
|
|
3753
3765
|
}
|
|
3766
|
+
function egressFrom(words2, how) {
|
|
3767
|
+
const [via, country, session, ...more] = words2.map((word) => word.trim());
|
|
3768
|
+
if (via === "box" && country === void 0) {
|
|
3769
|
+
return { via: "box" };
|
|
3770
|
+
}
|
|
3771
|
+
if (via !== "residential" || country === void 0 || !/^[a-zA-Z]{2}$/.test(country) || more.length > 0 || session !== void 0 && session !== "sticky" && session !== "rotating") {
|
|
3772
|
+
throw new Error(how);
|
|
3773
|
+
}
|
|
3774
|
+
return { via: "residential", country: country.toLowerCase(), ...session === void 0 ? {} : { session } };
|
|
3775
|
+
}
|
|
3776
|
+
function egressInWords(body) {
|
|
3777
|
+
if (body?.via !== "residential") {
|
|
3778
|
+
return "from its server (box)";
|
|
3779
|
+
}
|
|
3780
|
+
return `residential, from ${String(body.country ?? "").toUpperCase()}, ${body.session === "rotating" ? "a new address each connection" : "one address kept (sticky)"}`;
|
|
3781
|
+
}
|
|
3782
|
+
async function egress(positionals, values) {
|
|
3783
|
+
const [first, ...rest] = positionals;
|
|
3784
|
+
const print4 = (body2, words2) => {
|
|
3785
|
+
process.stdout.write(values.json ? `${JSON.stringify(body2, null, 2)}
|
|
3786
|
+
` : words2);
|
|
3787
|
+
};
|
|
3788
|
+
if (first === void 0 || first === "use-case" || first === "budget") {
|
|
3789
|
+
let body2;
|
|
3790
|
+
if (first === "use-case") {
|
|
3791
|
+
const useCase = rest.join(" ").trim();
|
|
3792
|
+
if (useCase === "") {
|
|
3793
|
+
throw new Error('egress use-case takes what your sandboxes will use residential addresses for, in a few sentences, as agental egress use-case "Our agents test sign-up flows from the countries we sell in."');
|
|
3794
|
+
}
|
|
3795
|
+
body2 = await call2("/v1/egress/use-case", { method: "PUT", body: JSON.stringify({ useCase }) });
|
|
3796
|
+
} else if (first === "budget") {
|
|
3797
|
+
const given = rest[0];
|
|
3798
|
+
const dollars = given === void 0 || given.trim() === "" ? Number.NaN : Number(given.replace(/^\$/, ""));
|
|
3799
|
+
if (rest.length !== 1 || given !== "default" && (!Number.isFinite(dollars) || dollars < 0)) {
|
|
3800
|
+
throw new Error("egress budget takes the most residential traffic may cost in a month, in US dollars, as agental egress budget 20, or default.");
|
|
3801
|
+
}
|
|
3802
|
+
body2 = await call2("/v1/egress/budget", { method: "PUT", body: JSON.stringify({ budgetMicros: given === "default" ? null : Math.round(dollars * 1e6) }) });
|
|
3803
|
+
} else {
|
|
3804
|
+
body2 = await call2("/v1/egress", { method: "GET" });
|
|
3805
|
+
}
|
|
3806
|
+
const account3 = body2 && typeof body2 === "object" ? body2 : {};
|
|
3807
|
+
const number = (name) => typeof account3[name] === "number" ? account3[name] : 0;
|
|
3808
|
+
const missing = Array.isArray(account3["missing"]) ? account3["missing"].map(String) : [];
|
|
3809
|
+
const needs = {
|
|
3810
|
+
plan: "a plan of Fleet ($100 a month) or larger: agental billing",
|
|
3811
|
+
card: "a card saved: agental billing card",
|
|
3812
|
+
use_case: 'what your sandboxes will use it for: agental egress use-case "<what for>"'
|
|
3813
|
+
};
|
|
3814
|
+
const refused = account3["refused"];
|
|
3815
|
+
const lines = !account3["offered"] ? ["Residential egress is not offered here."] : [
|
|
3816
|
+
`residential: ${account3["enabled"] ? "on for this account" : refused ? `refused: ${String(refused.reason ?? "")}` : "not yet"}`,
|
|
3817
|
+
...missing.map((need) => ` needs ${needs[need] ?? need}`),
|
|
3818
|
+
`price: ${money(number("microsPerGb"))} a GB, both directions counted`,
|
|
3819
|
+
`this month: ${money(number("spentMicros"))} of a ${money(number("budgetMicros"))} budget${account3["budgetSet"] ? "" : " (the default)"}`,
|
|
3820
|
+
...account3["blocked"] && account3["blocked"] !== "refused" ? [`blocked now: ${String(account3["blocked"]).replaceAll("_", " ")}`] : []
|
|
3821
|
+
];
|
|
3822
|
+
print4(body2, `${lines.join("\n")}
|
|
3823
|
+
`);
|
|
3824
|
+
return;
|
|
3825
|
+
}
|
|
3826
|
+
const path4 = `/v1/sandboxes/${encodeURIComponent(first)}/egress`;
|
|
3827
|
+
const how = `egress takes <sandbox-id>, and then nothing, box, or residential <country> [sticky|rotating], as agental egress ${first} residential de.`;
|
|
3828
|
+
const body = await call2(path4, rest.length === 0 ? { method: "GET" } : { method: "PUT", body: JSON.stringify(egressFrom(rest, how)) });
|
|
3829
|
+
print4(body, `${first}: ${egressInWords(body)}
|
|
3830
|
+
`);
|
|
3831
|
+
}
|
|
3754
3832
|
function templateSshInWords(ssh2) {
|
|
3755
3833
|
const keys = ssh2.keys.length === 1 ? "1 key" : `${ssh2.keys.length} keys`;
|
|
3756
3834
|
return `${ssh2.enabled ? "on" : "off"} as a sandbox is made, ${keys} let in`;
|
|
@@ -3832,7 +3910,7 @@ function showTemplate(each) {
|
|
|
3832
3910
|
}
|
|
3833
3911
|
async function template(positionals, values) {
|
|
3834
3912
|
const [action, first, ...rest] = positionals;
|
|
3835
|
-
const usage = "template takes create, show, rename, delete, start, network, ssh, ssh-keys, tags, meta, sandboxes, apply, of or put. agental help says how.";
|
|
3913
|
+
const usage = "template takes create, show, rename, delete, start, network, egress, ssh, ssh-keys, tags, meta, sandboxes, apply, of or put. agental help says how.";
|
|
3836
3914
|
const print4 = (body, words2) => {
|
|
3837
3915
|
process.stdout.write(values.json ? `${JSON.stringify(body, null, 2)}
|
|
3838
3916
|
` : words2);
|
|
@@ -3922,6 +4000,15 @@ ${mode === void 0 ? "" : "A sandbox on it takes this when it next starts, or now
|
|
|
3922
4000
|
);
|
|
3923
4001
|
return;
|
|
3924
4002
|
}
|
|
4003
|
+
case "egress": {
|
|
4004
|
+
const found = await templateNamed(need(first, "<template>"));
|
|
4005
|
+
const path4 = `/v1/templates/${encodeURIComponent(found.id)}/egress`;
|
|
4006
|
+
const how = `template egress takes <template>, and then nothing, box, or residential <country> [sticky|rotating], as agental template egress ${first ?? ""} residential de.`;
|
|
4007
|
+
const set = await call2(path4, rest.length === 0 ? { method: "GET" } : { method: "PUT", body: JSON.stringify(egressFrom(rest, how)) });
|
|
4008
|
+
print4(set, `${found.name}: ${egressInWords(set)}${rest.length === 0 ? "" : ", for sandboxes made from it from now on"}
|
|
4009
|
+
`);
|
|
4010
|
+
return;
|
|
4011
|
+
}
|
|
3925
4012
|
case "ssh": {
|
|
3926
4013
|
const found = await templateNamed(need(first, "<template>"));
|
|
3927
4014
|
const path4 = `/v1/templates/${encodeURIComponent(found.id)}/ssh`;
|
|
@@ -4847,7 +4934,7 @@ Setting up
|
|
|
4847
4934
|
|
|
4848
4935
|
Usage
|
|
4849
4936
|
agental create --name <name> [--template <template>] [--size tiny|small|medium|large] [--region <region>[,<region>...]] [--ttl <time> | --ttl default] [--idempotency-key <key>]
|
|
4850
|
-
${operator ? "[--box <name-or-id>] " : ""}[--allow <address>[,<address>...]] [--max-burst-fee <dollars>]
|
|
4937
|
+
${operator ? "[--box <name-or-id>] " : ""}[--allow <address>[,<address>...]] [--egress box | residential:<country>[:sticky|rotating]] [--max-burst-fee <dollars>]
|
|
4851
4938
|
[--ssh-key <public-key-or-file>]... [--tag <tag>[,<tag>...]]... [--meta <key>=<value>]...
|
|
4852
4939
|
agental summary [--where '<words>'] [--tag <tag>[,<tag>...]]... [--meta <key>=<value>]... [--facets <field>[,<field>...]] [--json]
|
|
4853
4940
|
agental list [--where '<words>'] [--tag <tag>[,<tag>...]]... [--meta <key>=<value>]... [--sort=<sort>] [--limit <n>] [--json]
|
|
@@ -4865,6 +4952,7 @@ Usage
|
|
|
4865
4952
|
agental recover <sandbox-id> [--max-burst-fee <dollars>]
|
|
4866
4953
|
agental auto-stop <sandbox-id> [--in <time> | --at <date-time> | --never] [--json]
|
|
4867
4954
|
agental network <sandbox-id> [--allow <address>[,<address>...] | --none] [--json]
|
|
4955
|
+
agental egress <sandbox-id> [box | residential <country> [sticky | rotating]] [--json]
|
|
4868
4956
|
agental templates [--json]
|
|
4869
4957
|
agental template create <name> [--tag <tag>[,<tag>...]]... [--meta <key>=<value>]...
|
|
4870
4958
|
agental template show <template> [--json]
|
|
@@ -4872,6 +4960,7 @@ Usage
|
|
|
4872
4960
|
agental template delete <template>
|
|
4873
4961
|
agental template start <template> [--size tiny|small|medium|large] [--snapshot <snapshot-id> | --new-machine] [--ttl <time> | --ttl default]
|
|
4874
4962
|
agental template network <template> [open | blocked | allowlist <address>...] [--json]
|
|
4963
|
+
agental template egress <template> [box | residential <country> [sticky | rotating]] [--json]
|
|
4875
4964
|
agental template ssh <template> [on | off] [--json]
|
|
4876
4965
|
agental template ssh-keys <template> [<public-key-or-file>... | --remove <key-id>] [--json]
|
|
4877
4966
|
agental template tags <template> [add|rm <tag>...] [--json]
|
|
@@ -4920,6 +5009,8 @@ Usage
|
|
|
4920
5009
|
agental key delete <key>
|
|
4921
5010
|
agental billing [prices | card | top-up <dollars> | auto-reload <dollars | off>] [--json]
|
|
4922
5011
|
agental burst [budget <dollars> | budget default] [--json]
|
|
5012
|
+
agental egress [budget <dollars> | budget default] [--json]
|
|
5013
|
+
agental egress use-case "<what your sandboxes will use it for>" [--json]
|
|
4923
5014
|
agental account export [--out <file>]
|
|
4924
5015
|
agental ssh <sandbox-id> [--tmux] [ssh options] [command...]
|
|
4925
5016
|
agental scp [scp options] <source>... <target>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agental",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "The agental command: Linux sandboxes for your agents, from the terminal. npx agental@latest signs you in and installs the agent skills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "VERTIXER LTD",
|