@maxceem/agw 0.11.2 → 0.12.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/agw.mjs +164 -8
- package/package.json +2 -1
package/dist/agw.mjs
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// <define:__AGW_MANIFEST__>
|
|
9
|
-
var define_AGW_MANIFEST_default = { version: "0.
|
|
9
|
+
var define_AGW_MANIFEST_default = { version: "0.12.0", wrangler: "4.96.0", upgradeFrom: ["0.12.0", "0.11.2", "0.11.1", "0.11.0", "0.10.11", "0.10.10", "0.10.9", "0.10.8", "0.10.7", "0.10.6", "0.10.5", "0.10.4", "0.10.3", "0.10.2", "0.10.1", "0.10.0", "0.9.3", "0.9.2", "0.9.1", "0.9.0", "0.8.3", "0.8.2", "0.8.1", "0.8.0", "0.7.2", "0.7.1", "0.7.0", "0.6.4", "0.6.3", "0.6.2", "0.6.1", "0.6.0", "0.5.2", "0.5.1", "0.5.0", "0.4.0"], release: { url: "https://github.com/maxceem/app-ai-gateway/releases/download/v0.12.0/gateway-0.12.0.tar.gz", sha256: "6865dcab2a4a1043812c31f284321b260b2e0ca64a2a0ad01658f8c850a10300", manifest: "47347e6b473211c44aa35c609877d23cad7f59b5ad9967d354e97a0f6d230c68" } };
|
|
10
10
|
|
|
11
11
|
// src/main.ts
|
|
12
12
|
import { Writable as Writable2 } from "node:stream";
|
|
@@ -15886,6 +15886,30 @@ var ConfirmEmailVerificationRequestSchema = external_exports.object({
|
|
|
15886
15886
|
description: "The `token` query parameter of the link in the verification email."
|
|
15887
15887
|
})
|
|
15888
15888
|
}).strict();
|
|
15889
|
+
var SupportMessageKindSchema = external_exports.enum(["bug", "support", "feedback"]);
|
|
15890
|
+
var SUPPORT_TOPICS = {
|
|
15891
|
+
bug: "Bug report",
|
|
15892
|
+
support: "Support request",
|
|
15893
|
+
feedback: "Feedback"
|
|
15894
|
+
};
|
|
15895
|
+
var SUPPORT_CONTEXT_KEY = /^[A-Za-z][A-Za-z0-9_.-]{0,39}$/;
|
|
15896
|
+
var SupportMessageRequestSchema = external_exports.object({
|
|
15897
|
+
kind: SupportMessageKindSchema,
|
|
15898
|
+
message: external_exports.string().trim().min(1, "Write a message").max(1e4).meta({
|
|
15899
|
+
description: "What the person wants support to know, in their words. Never include a key, token or password."
|
|
15900
|
+
}),
|
|
15901
|
+
/** The console page the message was written from, for context. */
|
|
15902
|
+
page: ConsoleReturnPathSchema.optional(),
|
|
15903
|
+
context: external_exports.record(
|
|
15904
|
+
external_exports.string().regex(SUPPORT_CONTEXT_KEY, "Context names are letters, digits, _ . and -, up to 40 characters"),
|
|
15905
|
+
external_exports.string().trim().min(1).max(500)
|
|
15906
|
+
).refine((value) => Object.keys(value).length <= 20, "At most 20 context entries").optional().meta({
|
|
15907
|
+
description: "Facts that help support act without asking back, such as app_id, request_id, error_code or agw_version. Never a credential."
|
|
15908
|
+
}),
|
|
15909
|
+
client: external_exports.string().trim().min(1).max(100).optional().meta({
|
|
15910
|
+
description: "What sent the message, such as `agw 0.10.3`, as the client reports it. A label only."
|
|
15911
|
+
})
|
|
15912
|
+
}).strict();
|
|
15889
15913
|
|
|
15890
15914
|
// src/common.ts
|
|
15891
15915
|
import { randomBytes } from "node:crypto";
|
|
@@ -16120,7 +16144,8 @@ var commands = {
|
|
|
16120
16144
|
"usage show": { args: 0, flags: "app month" },
|
|
16121
16145
|
"usage breakdown": { args: 0, flags: "app by from to limit" },
|
|
16122
16146
|
"operation status": { args: 1, flags: "" },
|
|
16123
|
-
"operation wait": { args: 1, flags: "timeout" }
|
|
16147
|
+
"operation wait": { args: 1, flags: "timeout" },
|
|
16148
|
+
"support send": { args: 0, flags: "type message message-stdin! context* yes!" }
|
|
16124
16149
|
};
|
|
16125
16150
|
function flagList(value) {
|
|
16126
16151
|
if (value === void 0) return [];
|
|
@@ -16201,6 +16226,7 @@ function parse3(argv) {
|
|
|
16201
16226
|
["pricing", "clear-pricing"],
|
|
16202
16227
|
["route", "clear-route"],
|
|
16203
16228
|
["provider", "all-providers"],
|
|
16229
|
+
["message", "message-stdin"],
|
|
16204
16230
|
...command === "app snippet" ? [["provider", "endpoint"]] : []
|
|
16205
16231
|
]) {
|
|
16206
16232
|
if (group.filter((k) => collected[k] !== void 0).length > 1)
|
|
@@ -16241,6 +16267,7 @@ Login: account login and deployment connect open the browser; check that it show
|
|
|
16241
16267
|
Credentials: ${MANAGEMENT_KEY_ENV}, when set, is the management key for every command and overrides the saved login. account logout revokes the saved key.
|
|
16242
16268
|
Secrets: hidden prompt by default; --key-stdin reads one line. Provider --browser submits credentials directly to your gateway.
|
|
16243
16269
|
Browser operations: --json or --no-input returns pending; operation wait resumes.
|
|
16270
|
+
Support: support send emails human support for the signed-in person, who gets the reply by email. Without a terminal it needs --yes: show the person the message first. Never put a key or token in it.
|
|
16244
16271
|
No account is created by help, status, list, validation or dry runs.
|
|
16245
16272
|
`;
|
|
16246
16273
|
}
|
|
@@ -17575,7 +17602,13 @@ var ConsoleCapabilitiesResponseSchema = external_exports.object({
|
|
|
17575
17602
|
* account's apps serve requests only once its owner has verified theirs, and
|
|
17576
17603
|
* the console offers the link to do it.
|
|
17577
17604
|
*/
|
|
17578
|
-
emailVerification: external_exports.boolean()
|
|
17605
|
+
emailVerification: external_exports.boolean(),
|
|
17606
|
+
/**
|
|
17607
|
+
* The inbox the Support menu writes to, present only where the deployment
|
|
17608
|
+
* has billing and can send email. The console still offers the menu only to
|
|
17609
|
+
* an organization on a paid plan, and the gateway refuses anyone else.
|
|
17610
|
+
*/
|
|
17611
|
+
supportEmail: external_exports.email().optional()
|
|
17579
17612
|
});
|
|
17580
17613
|
var GoogleSignInResponseSchema = external_exports.object({
|
|
17581
17614
|
url: external_exports.url().meta({ description: "Provider authorization URL for the browser to navigate to." }),
|
|
@@ -18069,6 +18102,16 @@ var ConfirmEmailVerificationResponseSchema = external_exports.object({
|
|
|
18069
18102
|
description: "The console path the link was asked for from, to continue there; null for none."
|
|
18070
18103
|
})
|
|
18071
18104
|
});
|
|
18105
|
+
var SupportMessageResponseSchema = external_exports.object({
|
|
18106
|
+
status: external_exports.literal("sent"),
|
|
18107
|
+
reference: external_exports.string().meta({
|
|
18108
|
+
description: "The request's reference, such as SUP-7F3K2Q, in the email's subject too. Quote it when following up."
|
|
18109
|
+
}),
|
|
18110
|
+
replyTo: external_exports.string().meta({ description: "The address support will reply to: the sender's own." }),
|
|
18111
|
+
duplicate: external_exports.boolean().meta({
|
|
18112
|
+
description: "True when the same message was sent in the last ten minutes: nothing new was sent, and reference is the earlier one's."
|
|
18113
|
+
})
|
|
18114
|
+
});
|
|
18072
18115
|
var OrganizationListResponseSchema = external_exports.object({
|
|
18073
18116
|
organizations: external_exports.array(OrganizationMembershipSchema)
|
|
18074
18117
|
});
|
|
@@ -18977,6 +19020,38 @@ var CATALOG = {
|
|
|
18977
19020
|
response: BillingAccessSchema,
|
|
18978
19021
|
responseDescription: "Trial access state."
|
|
18979
19022
|
},
|
|
19023
|
+
/*
|
|
19024
|
+
* Support is part of a paid plan, so it sits with billing: it is offered
|
|
19025
|
+
* only to an organization on one, and refused to everyone else. A person in
|
|
19026
|
+
* the console, the CLI and an MCP client all send through this one entry, so
|
|
19027
|
+
* the plan check, the secret check and the limits are the same for each.
|
|
19028
|
+
*
|
|
19029
|
+
* Any role may write, read-only members included: a message changes nothing
|
|
19030
|
+
* in the account. The grant is the default `manage` all the same, because it
|
|
19031
|
+
* emails a person, and a `read` credential changes nothing outside the
|
|
19032
|
+
* gateway either.
|
|
19033
|
+
*/
|
|
19034
|
+
sendSupportMessage: {
|
|
19035
|
+
method: "POST",
|
|
19036
|
+
path: "/v1/admin/support",
|
|
19037
|
+
hidden: true,
|
|
19038
|
+
tags: ["Admin billing"],
|
|
19039
|
+
summary: "Send a message to support",
|
|
19040
|
+
description: "Opens a support ticket for the person the credential belongs to: they get an email with its reference and their message, copied to the deployment's support inbox, and support answers them by replying to it. Send only what the person asked to send, and never a credential: a message or context value that looks like a key, token or password is refused. The same message sent again within ten minutes is not sent twice; the answer says so and repeats the reference.",
|
|
19041
|
+
security: "management",
|
|
19042
|
+
policy: { role: "member", access: "read" },
|
|
19043
|
+
request: SupportMessageRequestSchema,
|
|
19044
|
+
response: SupportMessageResponseSchema,
|
|
19045
|
+
responseDescription: "The ticket was opened; support replies to the sender's email address.",
|
|
19046
|
+
errors: {
|
|
19047
|
+
400: "The body is malformed, or carries something that looks like a credential (`invalid_request`).",
|
|
19048
|
+
403: "The account's plan does not include human support (`support_plan_required`), or the credential has the read grant (`grant_insufficient`).",
|
|
19049
|
+
404: "This deployment does not offer human support (`not_found`).",
|
|
19050
|
+
409: "The credential's owner has no email address to reply to (`conflict`).",
|
|
19051
|
+
429: "Too many messages were sent by this person. Carries Retry-After.",
|
|
19052
|
+
503: "The help desk could not be reached; try again later (`email_unavailable`)."
|
|
19053
|
+
}
|
|
19054
|
+
},
|
|
18980
19055
|
getApp: {
|
|
18981
19056
|
method: "GET",
|
|
18982
19057
|
path: "/v1/admin/apps/{app}",
|
|
@@ -21935,8 +22010,19 @@ function render(command, result, context, style2) {
|
|
|
21935
22010
|
case "deployment update":
|
|
21936
22011
|
case "deployment domain":
|
|
21937
22012
|
return deployment(result, style2);
|
|
22013
|
+
case "support send":
|
|
22014
|
+
return support(result, style2);
|
|
21938
22015
|
}
|
|
21939
22016
|
}
|
|
22017
|
+
function support(result, style2) {
|
|
22018
|
+
if (!("reference" in result)) return [];
|
|
22019
|
+
return [
|
|
22020
|
+
style2.headline(
|
|
22021
|
+
result.duplicate ? `Already sent as ${result.reference} in the last ten minutes; nothing new was sent.` : `Sent to human support as ${result.reference}.`
|
|
22022
|
+
),
|
|
22023
|
+
...kv([["Replies go to", result.replyTo]], style2)
|
|
22024
|
+
];
|
|
22025
|
+
}
|
|
21940
22026
|
function status(command, result, context, style2) {
|
|
21941
22027
|
const did = command === "account login" ? [style2.headline(`Signed in to ${context.url}.`)] : command === "deployment connect" ? [style2.headline(`Connected to ${context.url}.`)] : [];
|
|
21942
22028
|
if ("billing" in result)
|
|
@@ -22364,6 +22450,73 @@ function deployment(result, style2) {
|
|
|
22364
22450
|
return [style2.json(result)];
|
|
22365
22451
|
}
|
|
22366
22452
|
|
|
22453
|
+
// src/support.ts
|
|
22454
|
+
import { stderr as stderr2, stdin as stdin2 } from "node:process";
|
|
22455
|
+
var MAX_MESSAGE = 1e4;
|
|
22456
|
+
async function supportCommand(ctx, flags) {
|
|
22457
|
+
const kind = supportKind(flags.type ?? await prompt("Type (bug, support or feedback)", flags));
|
|
22458
|
+
if (flags.message !== void 0 && flags["message-stdin"])
|
|
22459
|
+
fail("conflicting_flags", "--message and --message-stdin conflict.");
|
|
22460
|
+
const message = (flags["message-stdin"] ? await readMessage() : flags.message ?? await prompt("Message", flags)).trim();
|
|
22461
|
+
if (!message) fail("invalid_input", "Supply a nonempty message.");
|
|
22462
|
+
if (message.length > MAX_MESSAGE)
|
|
22463
|
+
fail("invalid_input", `The message is longer than ${MAX_MESSAGE} characters.`);
|
|
22464
|
+
const context = supportContext(flagList(flags.context));
|
|
22465
|
+
if (!flags.yes) {
|
|
22466
|
+
if (flags["no-input"] || !stdin2.isTTY || !stderr2.isTTY)
|
|
22467
|
+
fail(
|
|
22468
|
+
"confirmation_required",
|
|
22469
|
+
"Sending to human support needs confirmation.",
|
|
22470
|
+
"Show the person the exact message, and once they agree run the same command with --yes."
|
|
22471
|
+
);
|
|
22472
|
+
stderr2.write(preview(kind, message, context));
|
|
22473
|
+
await confirm("Send this to human support?", flags);
|
|
22474
|
+
}
|
|
22475
|
+
return (await ctx.call("sendSupportMessage", {
|
|
22476
|
+
body: {
|
|
22477
|
+
kind,
|
|
22478
|
+
message,
|
|
22479
|
+
...Object.keys(context).length ? { context } : {},
|
|
22480
|
+
client: `agw ${VERSION}`
|
|
22481
|
+
}
|
|
22482
|
+
})).data;
|
|
22483
|
+
}
|
|
22484
|
+
function supportKind(value) {
|
|
22485
|
+
const parsed = SupportMessageKindSchema.safeParse(value.trim().toLowerCase());
|
|
22486
|
+
if (!parsed.success) fail("invalid_input", "--type must be bug, support or feedback.");
|
|
22487
|
+
return parsed.data;
|
|
22488
|
+
}
|
|
22489
|
+
function supportContext(entries) {
|
|
22490
|
+
const context = {};
|
|
22491
|
+
for (const entry of entries) {
|
|
22492
|
+
const at = entry.indexOf("=");
|
|
22493
|
+
if (at < 1 || at === entry.length - 1)
|
|
22494
|
+
fail("invalid_input", "--context takes name=value, such as --context app_id=my-app.");
|
|
22495
|
+
context[entry.slice(0, at).trim()] = entry.slice(at + 1).trim();
|
|
22496
|
+
}
|
|
22497
|
+
return context;
|
|
22498
|
+
}
|
|
22499
|
+
async function readMessage() {
|
|
22500
|
+
const chunks = [];
|
|
22501
|
+
let size = 0;
|
|
22502
|
+
for await (const chunk of stdin2) {
|
|
22503
|
+
size += chunk.length;
|
|
22504
|
+
if (size > MAX_MESSAGE * 4) fail("invalid_input", `The message is longer than ${MAX_MESSAGE} characters.`);
|
|
22505
|
+
chunks.push(chunk);
|
|
22506
|
+
}
|
|
22507
|
+
return Buffer.concat(chunks).toString();
|
|
22508
|
+
}
|
|
22509
|
+
function preview(kind, message, context) {
|
|
22510
|
+
const lines = [
|
|
22511
|
+
`To: human support (${SUPPORT_TOPICS[kind]})`,
|
|
22512
|
+
...Object.entries(context).map(([name, value]) => `${name}: ${value}`),
|
|
22513
|
+
"",
|
|
22514
|
+
message,
|
|
22515
|
+
""
|
|
22516
|
+
];
|
|
22517
|
+
return lines.join("\n") + "\n";
|
|
22518
|
+
}
|
|
22519
|
+
|
|
22367
22520
|
// src/transport.ts
|
|
22368
22521
|
var MESSAGE_LIMIT = 300;
|
|
22369
22522
|
function* strings(value) {
|
|
@@ -22392,6 +22545,8 @@ function nextActionFor(status2, code, details) {
|
|
|
22392
22545
|
if (status2 === 401) return "Run agw account login.";
|
|
22393
22546
|
if (code === "billing_plan_limit_reached")
|
|
22394
22547
|
return "Delete one you no longer need, or move to a plan whose limits are higher.";
|
|
22548
|
+
if (code === "support_plan_required")
|
|
22549
|
+
return "Tell the person human support is included with paid plans; an account owner can choose one on the console's Billing page.";
|
|
22395
22550
|
if (status2 === 429) {
|
|
22396
22551
|
const seconds = details.retryAfterSeconds;
|
|
22397
22552
|
if (seconds === void 0)
|
|
@@ -22541,6 +22696,7 @@ async function execute(parsed, ctx) {
|
|
|
22541
22696
|
return resourceCommand(ctx, command, args, flags);
|
|
22542
22697
|
if (command.startsWith("app ")) return appCommand(ctx, command, args, flags);
|
|
22543
22698
|
if (command.startsWith("usage ")) return usageCommand(ctx, command, flags);
|
|
22699
|
+
if (command === "support send") return supportCommand(ctx, flags);
|
|
22544
22700
|
if (command.startsWith("operation "))
|
|
22545
22701
|
return command === "operation wait" ? ctx.wait(args[0] ?? "", positive(flags.timeout ?? 300)) : ctx.poll(args[0] ?? "");
|
|
22546
22702
|
if (command === "account status") return (await ctx.call("getCliAccount")).data;
|
|
@@ -22571,7 +22727,7 @@ async function main(argv = process.argv.slice(2), {
|
|
|
22571
22727
|
store = new StateStore(),
|
|
22572
22728
|
transport = new Transport(),
|
|
22573
22729
|
stdout = process.stdout,
|
|
22574
|
-
stderr:
|
|
22730
|
+
stderr: stderr3 = process.stderr,
|
|
22575
22731
|
io = {}
|
|
22576
22732
|
} = {}) {
|
|
22577
22733
|
const json2 = argv.includes("--json");
|
|
@@ -22586,8 +22742,8 @@ async function main(argv = process.argv.slice(2), {
|
|
|
22586
22742
|
return 0;
|
|
22587
22743
|
}
|
|
22588
22744
|
const run = async () => {
|
|
22589
|
-
const state = await store.read((line) =>
|
|
22590
|
-
const ctx = new Context(store, state, transport, parsed.flags, { ...io, stderr:
|
|
22745
|
+
const state = await store.read((line) => stderr3.write(line + "\n"));
|
|
22746
|
+
const ctx = new Context(store, state, transport, parsed.flags, { ...io, stderr: stderr3 });
|
|
22591
22747
|
const result = await execute(parsed, ctx);
|
|
22592
22748
|
const context = {
|
|
22593
22749
|
url: ctx.url,
|
|
@@ -22631,7 +22787,7 @@ async function main(argv = process.argv.slice(2), {
|
|
|
22631
22787
|
);
|
|
22632
22788
|
return e.exitCode;
|
|
22633
22789
|
}
|
|
22634
|
-
const style2 = styleFor(
|
|
22790
|
+
const style2 = styleFor(stderr3);
|
|
22635
22791
|
const lines = [
|
|
22636
22792
|
style2.alert(`Error: ${e.message}`),
|
|
22637
22793
|
style2.warn(`Next: ${e.nextAction}`),
|
|
@@ -22639,7 +22795,7 @@ async function main(argv = process.argv.slice(2), {
|
|
|
22639
22795
|
];
|
|
22640
22796
|
for (const [key, value] of Object.entries(reported2.details ?? {}))
|
|
22641
22797
|
lines.push(` ${style2.dim(`${key}:`)} ${String(value)}`);
|
|
22642
|
-
|
|
22798
|
+
stderr3.write(lines.join("\n") + "\n");
|
|
22643
22799
|
return e.exitCode;
|
|
22644
22800
|
}
|
|
22645
22801
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maxceem/agw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Manage App AI Gateway from a terminal or coding agent: providers, iOS and server apps, usage, and self-hosted deployment on Cloudflare",
|
|
6
6
|
"keywords": [
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"bugs": "https://github.com/maxceem/app-ai-gateway/issues",
|
|
28
28
|
"upgradeFrom": [
|
|
29
|
+
"0.11.2",
|
|
29
30
|
"0.11.1",
|
|
30
31
|
"0.11.0",
|
|
31
32
|
"0.10.11",
|