@actionway/cli 0.18.3 → 0.18.5
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 +2 -0
- package/assets/skill/actionway/SKILL.md +3 -2
- package/dist/index.js +65 -12
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ actionway init
|
|
|
33
33
|
- **命令面 = 明码写出的注册表**(无 profile flag、无运行期分叉):
|
|
34
34
|
- `tools search / inspect / call` 是长尾 capability 的规范发现与执行面;
|
|
35
35
|
- 高频 typed command 继续提供参数与文件 UX,但投影到同一个 Tool Call;
|
|
36
|
+
- `account invitation` 获取或首次创建当前账户的永久邀请码、链接和服务端本地化分享文案;
|
|
36
37
|
- `account usage / wallet / transactions` 只读 Actionway Business 数据;
|
|
37
38
|
- 本壳另有 `init` / `doctor` / `update` / `login` / `logout` / `whoami`,cli-core
|
|
38
39
|
继续提供 wait/poll 与已冻结的共享 typed commands。
|
|
@@ -63,6 +64,7 @@ pnpm cli logout # 删除本机凭据;重复执行也是成功的幂
|
|
|
63
64
|
pnpm cli update --check # 查新版(24h 缓存)
|
|
64
65
|
pnpm cli -- tools search "generate a product image"
|
|
65
66
|
pnpm cli -- tools inspect media.image.generate
|
|
67
|
+
pnpm cli -- account invitation --locale zh-cn
|
|
66
68
|
pnpm cli -- account usage
|
|
67
69
|
pnpm cli -- account usage --from 2026-08-01 --to 2026-09-01 --service generate-image
|
|
68
70
|
pnpm cli -- account transactions --from 2026-08-01 --kind top_up
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: actionway
|
|
3
|
-
description: Use the local Actionway CLI to discover, inspect, price, and call Actionway capabilities; continue asynchronous jobs or confirmed calls;
|
|
3
|
+
description: Use the local Actionway CLI to discover, inspect, price, and call Actionway capabilities; continue asynchronous jobs or confirmed calls; get the signed-in user's Actionway invitation, account usage, wallet, and transactions; authenticate; or update the CLI. Trigger when a local Agent can complete a task through `actionway`, when a `job_ref` or `call_ref` must be continued, or when the user asks about Actionway tools or account data.
|
|
4
4
|
metadata:
|
|
5
5
|
version: "0.0.0-dev"
|
|
6
6
|
---
|
|
@@ -23,7 +23,8 @@ Use the installed `actionway` CLI and its server-backed Capability Registry as t
|
|
|
23
23
|
- If Search returns `clarification_required`, ask its bounded question. If it returns candidates, choose only a supported `tool_ref` and run `actionway tools inspect <tool_ref>` before the generic call. Inspect is the authority for the current input Schema, variants, effects, guidance, and Actionway USD price.
|
|
24
24
|
- `actionway search` is the Web Search business capability. Capability discovery is always `actionway tools search`.
|
|
25
25
|
- Use a high-frequency typed command only when `actionway --help` exposes an exact fit. Read `actionway <command> --help` and, when available, `--print-schema`; typed commands are parameter/file conveniences over the same Tool Call, confirmation, billing, and Job path.
|
|
26
|
-
-
|
|
26
|
+
- When the signed-in user asks to generate, show, copy, or share their invitation, run `actionway account invitation --locale <zh-cn|zh-tw|en|ja>` using the conversation language. Return the server-provided `code`, `url`, and `message`; do not invent reward amounts or rewrite promotion terms. The first request creates one permanent code and later requests return that same code.
|
|
27
|
+
- For other account questions, use only the requested read command: `actionway account usage`, `actionway account wallet`, or `actionway account transactions`.
|
|
27
28
|
|
|
28
29
|
## Inspect and call
|
|
29
30
|
|
package/dist/index.js
CHANGED
|
@@ -12434,7 +12434,7 @@ var REFRESH_SKEW_S = 30;
|
|
|
12434
12434
|
var TOKEN_TIMEOUT_MS = 2e4;
|
|
12435
12435
|
var DISCOVERY_TIMEOUT_MS = 1e4;
|
|
12436
12436
|
var SESSION_TIMEOUT_MS = 2e4;
|
|
12437
|
-
var DEFAULT_LOGIN_TIMEOUT_MS =
|
|
12437
|
+
var DEFAULT_LOGIN_TIMEOUT_MS = 12e5;
|
|
12438
12438
|
function stripSlash(url) {
|
|
12439
12439
|
return url.replace(/\/+$/, "");
|
|
12440
12440
|
}
|
|
@@ -12521,7 +12521,15 @@ async function fetchCliOAuthConfig(gateway, fetchImpl = fetch) {
|
|
|
12521
12521
|
signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
|
|
12522
12522
|
});
|
|
12523
12523
|
if (!response.ok) {
|
|
12524
|
-
|
|
12524
|
+
let detail = "";
|
|
12525
|
+
try {
|
|
12526
|
+
const body2 = await response.json();
|
|
12527
|
+
const code = typeof body2?.error?.code === "string" ? body2.error.code : "";
|
|
12528
|
+
const message = typeof body2?.error?.message === "string" ? body2.error.message : "";
|
|
12529
|
+
detail = [code, message].filter(Boolean).join(": ");
|
|
12530
|
+
} catch {
|
|
12531
|
+
}
|
|
12532
|
+
throw new Error(`Actionway login configuration is unavailable (${response.status}${detail ? `; ${detail}` : ""})`);
|
|
12525
12533
|
}
|
|
12526
12534
|
const body = await response.json();
|
|
12527
12535
|
if (typeof body !== "object" || body === null || !("issuer" in body) || typeof body.issuer !== "string" || !("client_id" in body) || typeof body.client_id !== "string" || !body.issuer.trim() || !body.client_id.trim()) {
|
|
@@ -12694,14 +12702,21 @@ async function waitForCode(state, timeoutMs) {
|
|
|
12694
12702
|
const port = server.address().port;
|
|
12695
12703
|
const timer = setTimeout(() => {
|
|
12696
12704
|
rejectCode(
|
|
12697
|
-
new CliError(
|
|
12705
|
+
new CliError(
|
|
12706
|
+
"E_BACKEND",
|
|
12707
|
+
`login timed out after ${Math.round(timeoutMs / 1e3)} seconds`,
|
|
12708
|
+
"run `actionway login` again and ask the user to finish the browser sign-in promptly; pass --timeout-seconds <n> to allow more time"
|
|
12709
|
+
)
|
|
12698
12710
|
);
|
|
12699
12711
|
server.close();
|
|
12700
12712
|
}, timeoutMs);
|
|
12701
12713
|
return {
|
|
12702
12714
|
redirectUri: `http://127.0.0.1:${port}/callback`,
|
|
12703
12715
|
code: code.finally(() => clearTimeout(timer)),
|
|
12704
|
-
close: () =>
|
|
12716
|
+
close: () => {
|
|
12717
|
+
clearTimeout(timer);
|
|
12718
|
+
return new Promise((resolve3) => server.listening ? server.close(() => resolve3()) : resolve3());
|
|
12719
|
+
}
|
|
12705
12720
|
};
|
|
12706
12721
|
}
|
|
12707
12722
|
async function readJsonObject(response) {
|
|
@@ -12720,8 +12735,14 @@ async function tokenRequest(issuer, body, fetchImpl) {
|
|
|
12720
12735
|
});
|
|
12721
12736
|
const value = await readJsonObject(response);
|
|
12722
12737
|
if (!response.ok || typeof value.access_token !== "string") {
|
|
12723
|
-
const
|
|
12724
|
-
|
|
12738
|
+
const code = typeof value.error === "string" ? value.error : "";
|
|
12739
|
+
const description = typeof value.error_description === "string" ? value.error_description : "";
|
|
12740
|
+
const message = [code, description].filter(Boolean).join(": ") || "token request failed";
|
|
12741
|
+
throw new CliError(
|
|
12742
|
+
"E_BACKEND",
|
|
12743
|
+
message,
|
|
12744
|
+
code === "invalid_client" ? "the client_id/issuer pair does not belong to one Actionway environment: clear ACTIONWAY_OAUTH_CLIENT_ID and ACTIONWAY_OAUTH_ISSUER (or drop --client-id/--issuer) and run `actionway login` again to rediscover both; if no overrides are set, the stored credentials are stale \u2014 run `actionway logout` then `actionway login`" : void 0
|
|
12745
|
+
);
|
|
12725
12746
|
}
|
|
12726
12747
|
return {
|
|
12727
12748
|
accessToken: value.access_token,
|
|
@@ -12796,19 +12817,44 @@ async function login(options = {}) {
|
|
|
12796
12817
|
const onNotice = options.onNotice ?? ((message) => process.stderr.write(`${message}
|
|
12797
12818
|
`));
|
|
12798
12819
|
const gateway = resolveGatewayUrl(options.gateway, env);
|
|
12820
|
+
const gatewaySource = options.gateway?.trim() ? "flag" : (env.ACTIONWAY_GATEWAY_URL ?? "").trim() ? "env" : "default";
|
|
12799
12821
|
let clientId = options.clientId?.trim() || (env.ACTIONWAY_OAUTH_CLIENT_ID ?? "").trim();
|
|
12800
12822
|
let issuer = options.issuer?.trim() || (env.ACTIONWAY_OAUTH_ISSUER ?? "").trim();
|
|
12823
|
+
const clientIdSource = options.clientId?.trim() ? "flag" : (env.ACTIONWAY_OAUTH_CLIENT_ID ?? "").trim() ? "env" : "discovery";
|
|
12824
|
+
const issuerSource = options.issuer?.trim() ? "flag" : (env.ACTIONWAY_OAUTH_ISSUER ?? "").trim() ? "env" : "discovery";
|
|
12825
|
+
const authContext = () => ({
|
|
12826
|
+
gateway_url: gateway,
|
|
12827
|
+
gateway_source: gatewaySource,
|
|
12828
|
+
...issuer ? { issuer } : {},
|
|
12829
|
+
issuer_source: issuerSource,
|
|
12830
|
+
...clientId ? { client_id: clientId } : {},
|
|
12831
|
+
client_id_source: clientIdSource
|
|
12832
|
+
});
|
|
12833
|
+
const withAuthContext = (error) => {
|
|
12834
|
+
if (error instanceof CliError) {
|
|
12835
|
+
throw new CliError(error.code, error.message, error.hint, { ...error.extra ?? {}, auth_context: authContext() });
|
|
12836
|
+
}
|
|
12837
|
+
throw error;
|
|
12838
|
+
};
|
|
12839
|
+
if (!!clientId !== !!issuer) {
|
|
12840
|
+
throw new CliError(
|
|
12841
|
+
"E_SCHEMA",
|
|
12842
|
+
"client_id and issuer overrides must be provided together",
|
|
12843
|
+
"pass both --client-id and --issuer (or set both ACTIONWAY_OAUTH_CLIENT_ID and ACTIONWAY_OAUTH_ISSUER), or neither to use discovery",
|
|
12844
|
+
{ auth_context: authContext() }
|
|
12845
|
+
);
|
|
12846
|
+
}
|
|
12801
12847
|
if (!clientId || !issuer) {
|
|
12802
12848
|
let discovered;
|
|
12803
12849
|
try {
|
|
12804
12850
|
discovered = await fetchCliOAuthConfig(gateway, fetchImpl);
|
|
12805
12851
|
} catch (error) {
|
|
12806
12852
|
const message = error instanceof Error ? error.message : String(error);
|
|
12807
|
-
|
|
12853
|
+
return withAuthContext(new CliError(
|
|
12808
12854
|
"E_BACKEND",
|
|
12809
12855
|
`login failed: ${message}`,
|
|
12810
|
-
"
|
|
12811
|
-
);
|
|
12856
|
+
"check auth_context.gateway_url is the intended Actionway environment (unset ACTIONWAY_GATEWAY_URL or fix --gateway if not) and run `actionway login` again; if the gateway is correct, the environment is misconfigured \u2014 report this error to the user instead of retrying (passing both --client-id and --issuer explicitly remains available as a temporary override)"
|
|
12857
|
+
));
|
|
12812
12858
|
}
|
|
12813
12859
|
clientId ||= discovered.clientId;
|
|
12814
12860
|
issuer ||= discovered.issuer;
|
|
@@ -12865,6 +12911,8 @@ ${authorizeUrl}`);
|
|
|
12865
12911
|
};
|
|
12866
12912
|
saveCredentials(credentials, env);
|
|
12867
12913
|
return { credentials, account };
|
|
12914
|
+
} catch (error) {
|
|
12915
|
+
return withAuthContext(error);
|
|
12868
12916
|
} finally {
|
|
12869
12917
|
await callback.close();
|
|
12870
12918
|
}
|
|
@@ -12917,7 +12965,7 @@ function failFromError2(err, fallbackHint) {
|
|
|
12917
12965
|
});
|
|
12918
12966
|
}
|
|
12919
12967
|
function registerAuthCommands(program2) {
|
|
12920
|
-
program2.command("login").description("Authenticate with Actionway in the browser (Clerk OAuth with PKCE).").option("--gateway <url>", "Actionway public origin").option("--client-id <id>", "Actionway OAuth client id (default: discovered from the public origin)").option("--issuer <url>", "Actionway OAuth issuer (default: discovered from the public origin)").option("--timeout-seconds <n>", "how long to wait for browser authentication").option("--no-browser", "print the authorize URL instead of opening a browser").action(async (opts) => {
|
|
12968
|
+
program2.command("login").description("Authenticate with Actionway in the browser (Clerk OAuth with PKCE).").option("--gateway <url>", "Actionway public origin").option("--client-id <id>", "Actionway OAuth client id (must be paired with --issuer; default: both discovered from the public origin)").option("--issuer <url>", "Actionway OAuth issuer (must be paired with --client-id; default: both discovered from the public origin)").option("--timeout-seconds <n>", "how long to wait for browser authentication").option("--no-browser", "print the authorize URL instead of opening a browser").action(async (opts) => {
|
|
12921
12969
|
try {
|
|
12922
12970
|
const { credentials, account } = await login({
|
|
12923
12971
|
...opts.gateway ? { gateway: opts.gateway } : {},
|
|
@@ -12967,6 +13015,10 @@ function failAccount(error) {
|
|
|
12967
13015
|
}
|
|
12968
13016
|
fail({ code: "E_BACKEND", message: error instanceof Error ? error.message : String(error) });
|
|
12969
13017
|
}
|
|
13018
|
+
function invitationEndpoint(locale = "en") {
|
|
13019
|
+
const parameters = new URLSearchParams({ locale });
|
|
13020
|
+
return `v1/account/invitation?${parameters.toString()}`;
|
|
13021
|
+
}
|
|
12970
13022
|
function accountEndpoint(path, options) {
|
|
12971
13023
|
const parameters = new URLSearchParams();
|
|
12972
13024
|
for (const [name, value] of [
|
|
@@ -12992,7 +13044,8 @@ async function read(endpoint, getTransport3) {
|
|
|
12992
13044
|
}
|
|
12993
13045
|
}
|
|
12994
13046
|
function registerAccountCommands(program2, getTransport3) {
|
|
12995
|
-
const account = program2.command("account").description("
|
|
13047
|
+
const account = program2.command("account").description("Access your Actionway invitation, USD wallet, service usage, and wallet transactions.");
|
|
13048
|
+
account.command("invitation").description("Get or create your permanent invitation code, link, and localized share message.").option("--locale <locale>", "Share-message locale: zh-cn, zh-tw, en, or ja.", "en").action((options) => read(invitationEndpoint(options.locale), getTransport3));
|
|
12996
13049
|
account.command("usage").description("Query held, charged, released, and free capability calls.").option("--limit <count>", "Maximum records in this page (1-100).").option("--cursor <cursor>", "Opaque nextCursor returned by the previous page.").option("--from <date>", "Inclusive ISO date or timestamp (UTC for date-only values).").option("--to <date>", "Exclusive ISO date or timestamp (UTC for date-only values).").option("--status <status>", "held, settled, or expired.").option("--service <service-id>", "Exact public serviceId.").option("--pricing-kind <kind>", "priced or free.").action((options) => read(accountEndpoint("usage", options), getTransport3));
|
|
12997
13050
|
account.command("wallet").description("Show the current available and held Actionway USD wallet balance.").action(() => read("v1/account/wallet", getTransport3));
|
|
12998
13051
|
account.command("transactions").description("Query wallet top-ups, charges, promotions, refunds, and other fund movements.").option("--limit <count>", "Maximum records in this page (1-50).").option("--cursor <cursor>", "Opaque nextCursor returned by the previous page.").option("--from <date>", "Inclusive ISO date or timestamp (UTC for date-only values).").option("--to <date>", "Exclusive ISO date or timestamp (UTC for date-only values).").option("--status <status>", "pending, succeeded, or failed.").option("--kind <kind>", "top_up, charge, refund, dispute, or promotion kind.").action((options) => read(accountEndpoint("transactions", options), getTransport3));
|
|
@@ -13415,7 +13468,7 @@ function failFromError3(err) {
|
|
|
13415
13468
|
function registerInitCommand(program2) {
|
|
13416
13469
|
program2.command("init").description(
|
|
13417
13470
|
"Complete browser authentication and stage the Actionway Skill for your agent to install. The CLI never writes into an agent's own configuration directory."
|
|
13418
|
-
).option("--gateway <url>", "Actionway public origin").option("--client-id <id>", "Actionway OAuth client id").option("--issuer <url>", "Actionway OAuth issuer").option("--timeout-seconds <n>", "how long to wait for browser authentication").option("--install-session-id <uuid>", "onboarding install session id").option("--no-browser", "print the authorize URL instead of opening a browser").addOption(new Option("--skill-only").hideHelp()).action(async (opts) => {
|
|
13471
|
+
).option("--gateway <url>", "Actionway public origin").option("--client-id <id>", "Actionway OAuth client id (must be paired with --issuer)").option("--issuer <url>", "Actionway OAuth issuer (must be paired with --client-id)").option("--timeout-seconds <n>", "how long to wait for browser authentication").option("--install-session-id <uuid>", "onboarding install session id").option("--no-browser", "print the authorize URL instead of opening a browser").addOption(new Option("--skill-only").hideHelp()).action(async (opts) => {
|
|
13419
13472
|
try {
|
|
13420
13473
|
const skill = materializeSkill();
|
|
13421
13474
|
if (opts.skillOnly) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actionway/cli",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5",
|
|
4
4
|
"description": "actionway CLI 的本地端壳:Clerk OAuth 鉴权 + cli-core 共享命令面 + init / update / skill 物化 / 版本三链路(终端用户本地 Codex / Claude Code 使用)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"tsx": "^4.20.0",
|
|
20
20
|
"typescript": "7.0.2",
|
|
21
21
|
"vitest": "^3.2.7",
|
|
22
|
-
"@actionway/
|
|
23
|
-
"@actionway/
|
|
22
|
+
"@actionway/cli-core": "0.1.0",
|
|
23
|
+
"@actionway/contracts": "0.1.0"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=20"
|