@actionway/cli 0.18.5 → 0.18.7
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 +25 -2
- package/assets/dev/actionway-dev-entry.mjs +19 -0
- package/assets/dev/actionway-dev-launcher.mjs +370 -0
- package/assets/dev/install-actionway-dev.mjs +185 -0
- package/assets/skill/actionway/SKILL.md +11 -0
- package/assets/skill/actionway-dev/SKILL.md +29 -0
- package/assets/skill/actionway-dev/agents/openai.yaml +4 -0
- package/dist/index.js +245 -82
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9353,9 +9353,11 @@ var Transport = class {
|
|
|
9353
9353
|
authHeader;
|
|
9354
9354
|
fetchImpl;
|
|
9355
9355
|
onResponse;
|
|
9356
|
+
requestHeaders;
|
|
9356
9357
|
constructor(init) {
|
|
9357
9358
|
this.baseUrl = init.baseUrl.replace(/\/+$/, "");
|
|
9358
9359
|
this.authHeader = init.authHeader;
|
|
9360
|
+
this.requestHeaders = init.requestHeaders;
|
|
9359
9361
|
this.fetchImpl = init.fetchImpl ?? fetch;
|
|
9360
9362
|
this.onResponse = init.onResponse;
|
|
9361
9363
|
}
|
|
@@ -9392,7 +9394,9 @@ var Transport = class {
|
|
|
9392
9394
|
}
|
|
9393
9395
|
async headers(hasBody, opts) {
|
|
9394
9396
|
const auth = typeof this.authHeader === "function" ? await this.authHeader() : this.authHeader;
|
|
9397
|
+
const requestHeaders = typeof this.requestHeaders === "function" ? await this.requestHeaders() : this.requestHeaders;
|
|
9395
9398
|
return {
|
|
9399
|
+
...requestHeaders,
|
|
9396
9400
|
authorization: auth,
|
|
9397
9401
|
accept: "application/json",
|
|
9398
9402
|
"x-actionway-cli-version": getCliVersion(),
|
|
@@ -10324,7 +10328,7 @@ function emitUseWaitHint() {
|
|
|
10324
10328
|
message: "The job is still pending. Run actionway wait with this job_ref now; never resubmit the job or create a shell polling loop."
|
|
10325
10329
|
});
|
|
10326
10330
|
}
|
|
10327
|
-
function registerPollCommand(program2,
|
|
10331
|
+
function registerPollCommand(program2, getTransport2) {
|
|
10328
10332
|
program2.command("poll").description(
|
|
10329
10333
|
"Run one authenticated status snapshot for recovery or diagnostics. Use actionway wait for normal async completion."
|
|
10330
10334
|
).addHelpText(
|
|
@@ -10337,7 +10341,7 @@ function registerPollCommand(program2, getTransport3) {
|
|
|
10337
10341
|
).requiredOption("--job-ref <ref>", "the job_ref returned by a previous async submit").action(async (opts) => {
|
|
10338
10342
|
try {
|
|
10339
10343
|
const jobRef = validateJobRef(opts.jobRef);
|
|
10340
|
-
const body = await pollJob(jobRef,
|
|
10344
|
+
const body = await pollJob(jobRef, getTransport2());
|
|
10341
10345
|
if (body.status === "pending") emitUseWaitHint();
|
|
10342
10346
|
ok({ job_ref: jobRef, ...body });
|
|
10343
10347
|
} catch (err) {
|
|
@@ -10409,7 +10413,7 @@ async function waitForJob(options) {
|
|
|
10409
10413
|
await sleep(Math.min(intervalMs, timeoutMs - elapsedMs));
|
|
10410
10414
|
}
|
|
10411
10415
|
}
|
|
10412
|
-
function registerWaitCommand(program2,
|
|
10416
|
+
function registerWaitCommand(program2, getTransport2) {
|
|
10413
10417
|
program2.command("wait").description("Wait for an async job and print only its terminal result.").requiredOption("--job-ref <ref>", "the full job_ref returned by the submit command").option("--timeout-seconds <n>", "maximum wait time in seconds (default: 1800)", Number, 1800).addHelpText(
|
|
10414
10418
|
"after",
|
|
10415
10419
|
[
|
|
@@ -10427,7 +10431,7 @@ function registerWaitCommand(program2, getTransport3) {
|
|
|
10427
10431
|
job_ref: jobRef
|
|
10428
10432
|
});
|
|
10429
10433
|
}
|
|
10430
|
-
const transport =
|
|
10434
|
+
const transport = getTransport2();
|
|
10431
10435
|
const terminal = await waitForJob({
|
|
10432
10436
|
jobRef,
|
|
10433
10437
|
timeoutMs: opts.timeoutSeconds * 1e3,
|
|
@@ -11068,7 +11072,7 @@ function emitCall(response) {
|
|
|
11068
11072
|
}
|
|
11069
11073
|
ok(response);
|
|
11070
11074
|
}
|
|
11071
|
-
function registerToolsCommands(program2,
|
|
11075
|
+
function registerToolsCommands(program2, getTransport2) {
|
|
11072
11076
|
const tools = program2.command("tools").description("Discover, inspect, and call Actionway capabilities through the canonical Tool protocol.");
|
|
11073
11077
|
tools.command("search <query>").description("Search the current capability catalog by natural-language intent.").option("--limit <n>", "maximum candidates (1-5)", (value) => Number(value)).option("--domain <id>", "required capability domain; repeatable", values, []).option("--input-modality <name>", "required input modality; repeatable", values, []).option("--output-modality <name>", "required output modality; repeatable", values, []).option("--effect <name>", "required capability effect; repeatable", values, []).option("--max-price-usd <amount>", "maximum fixed Actionway USD price").action(async (query, options) => {
|
|
11074
11078
|
const filters = {};
|
|
@@ -11078,14 +11082,14 @@ function registerToolsCommands(program2, getTransport3) {
|
|
|
11078
11082
|
if (Array.isArray(options.effect) && options.effect.length) filters.effects = options.effect;
|
|
11079
11083
|
if (typeof options.maxPriceUsd === "string") filters.maxPriceUsd = options.maxPriceUsd;
|
|
11080
11084
|
try {
|
|
11081
|
-
ok(await
|
|
11085
|
+
ok(await getTransport2().searchTools({ query, ...options.limit !== void 0 ? { limit: Number(options.limit) } : {}, ...filters }, { retries: 1 }));
|
|
11082
11086
|
} catch (error) {
|
|
11083
11087
|
failTool(error);
|
|
11084
11088
|
}
|
|
11085
11089
|
});
|
|
11086
11090
|
tools.command("inspect <tool_ref>").description("Read the current canonical Schema, variants, effects, guidance, and Actionway USD price.").action(async (toolRef) => {
|
|
11087
11091
|
try {
|
|
11088
|
-
ok(await
|
|
11092
|
+
ok(await getTransport2().inspectTool(toolRef, { retries: 1 }));
|
|
11089
11093
|
} catch (error) {
|
|
11090
11094
|
failTool(error);
|
|
11091
11095
|
}
|
|
@@ -11096,7 +11100,7 @@ function registerToolsCommands(program2, getTransport3) {
|
|
|
11096
11100
|
if (toolRef || options.variant || options.inputJson || options.inputFile) {
|
|
11097
11101
|
throw new CliError("E_SCHEMA", "--resume cannot be combined with tool_ref, --variant, or input arguments.");
|
|
11098
11102
|
}
|
|
11099
|
-
emitCall(await
|
|
11103
|
+
emitCall(await getTransport2().resumeToolCall(options.resume, { retries: 1 }));
|
|
11100
11104
|
}
|
|
11101
11105
|
if (!toolRef) throw new CliError("E_SCHEMA", "tool_ref is required unless --resume is used.");
|
|
11102
11106
|
const args = await resolveJsonObjectInlineOrFile(options.inputJson, options.inputFile, {
|
|
@@ -11104,7 +11108,7 @@ function registerToolsCommands(program2, getTransport3) {
|
|
|
11104
11108
|
file: "--input-file"
|
|
11105
11109
|
});
|
|
11106
11110
|
if (!options.inputJson && !options.inputFile) throw new CliError("E_SCHEMA", "Use --input-json or --input-file for canonical arguments.");
|
|
11107
|
-
const response = await
|
|
11111
|
+
const response = await getTransport2().callTool({
|
|
11108
11112
|
toolRef,
|
|
11109
11113
|
...typeof options.variant === "string" ? { variantId: options.variant } : {},
|
|
11110
11114
|
arguments: args,
|
|
@@ -11216,7 +11220,7 @@ function failFromError(err) {
|
|
|
11216
11220
|
}
|
|
11217
11221
|
fail({ code: "E_BACKEND", message: err instanceof Error ? err.message : String(err) });
|
|
11218
11222
|
}
|
|
11219
|
-
function registerAssetCommands(program2,
|
|
11223
|
+
function registerAssetCommands(program2, getTransport2) {
|
|
11220
11224
|
const asset = program2.command("asset").description("Register / fetch media assets (groups + assets) for downstream generate-* verbs.");
|
|
11221
11225
|
asset.command("register").description(
|
|
11222
11226
|
"Create an asset group and register one Image / Video / Audio asset under it; the server assigns the real group_id."
|
|
@@ -11258,7 +11262,7 @@ Examples:
|
|
|
11258
11262
|
assetType,
|
|
11259
11263
|
projectName: String(opts.projectName ?? "default")
|
|
11260
11264
|
},
|
|
11261
|
-
|
|
11265
|
+
getTransport2()
|
|
11262
11266
|
);
|
|
11263
11267
|
ok(res);
|
|
11264
11268
|
} catch (err) {
|
|
@@ -11267,7 +11271,7 @@ Examples:
|
|
|
11267
11271
|
});
|
|
11268
11272
|
asset.command("get").description("Fetch a single asset by id.").requiredOption("--id <id>").action(async (opts) => {
|
|
11269
11273
|
try {
|
|
11270
|
-
const res = await
|
|
11274
|
+
const res = await getTransport2().post(
|
|
11271
11275
|
ASSET_GET_ENDPOINT,
|
|
11272
11276
|
{ id: String(opts.id) },
|
|
11273
11277
|
{ timeoutMs: ASSET_TIMEOUT_MS, retries: 1 }
|
|
@@ -11333,7 +11337,7 @@ async function resolveKnowledgeFilters(params) {
|
|
|
11333
11337
|
file: "--filters-file"
|
|
11334
11338
|
});
|
|
11335
11339
|
}
|
|
11336
|
-
async function executeKnowledgeSearch(input, opts,
|
|
11340
|
+
async function executeKnowledgeSearch(input, opts, getTransport2) {
|
|
11337
11341
|
if (input.provider && input.domain !== "voice") {
|
|
11338
11342
|
return {
|
|
11339
11343
|
kind: "fail",
|
|
@@ -11351,7 +11355,7 @@ async function executeKnowledgeSearch(input, opts, getTransport3) {
|
|
|
11351
11355
|
};
|
|
11352
11356
|
}
|
|
11353
11357
|
try {
|
|
11354
|
-
const res = await
|
|
11358
|
+
const res = await getTransport2().post(KNOWLEDGE_SEARCH_ENDPOINT, body, {
|
|
11355
11359
|
timeoutMs: KNOWLEDGE_TIMEOUT_MS,
|
|
11356
11360
|
retries: 1
|
|
11357
11361
|
});
|
|
@@ -11376,7 +11380,7 @@ async function executeKnowledgeSearch(input, opts, getTransport3) {
|
|
|
11376
11380
|
return { kind: "fail", code: "E_BACKEND", exitCode: 1, message: err instanceof Error ? err.message : String(err) };
|
|
11377
11381
|
}
|
|
11378
11382
|
}
|
|
11379
|
-
function registerKnowledgeCommands(program2,
|
|
11383
|
+
function registerKnowledgeCommands(program2, getTransport2) {
|
|
11380
11384
|
const kb = program2.command("knowledge").description("Knowledge-base search across domain libraries (sfx, bgm, visual_style, voice, writing, meme).");
|
|
11381
11385
|
const filtersFileFlag = {
|
|
11382
11386
|
flag: "filters-file",
|
|
@@ -11449,7 +11453,7 @@ function registerKnowledgeCommands(program2, getTransport3) {
|
|
|
11449
11453
|
...typeof params.k === "number" ? { k: params.k } : {},
|
|
11450
11454
|
...Object.keys(filters).length > 0 ? { filters } : {}
|
|
11451
11455
|
};
|
|
11452
|
-
const outcome = await executeKnowledgeSearch(input, { dryRun: rawOpts.dryRun === true },
|
|
11456
|
+
const outcome = await executeKnowledgeSearch(input, { dryRun: rawOpts.dryRun === true }, getTransport2);
|
|
11453
11457
|
emitOutcome(outcome);
|
|
11454
11458
|
});
|
|
11455
11459
|
}
|
|
@@ -12007,7 +12011,7 @@ async function searchFanout(enabled, opts, limit, searchFn) {
|
|
|
12007
12011
|
}
|
|
12008
12012
|
return { results: mergeResults(perProviderResults, limit), queried: [...enabled], failed };
|
|
12009
12013
|
}
|
|
12010
|
-
function registerStockSearch(parent,
|
|
12014
|
+
function registerStockSearch(parent, getTransport2) {
|
|
12011
12015
|
parent.command("search").description(
|
|
12012
12016
|
"Sequential-fallback search across providers (Pexels -> Pixabay -> Openverse). Use --mode=fanout for parallel."
|
|
12013
12017
|
).addHelpText(
|
|
@@ -12079,7 +12083,7 @@ function registerStockSearch(parent, getTransport3) {
|
|
|
12079
12083
|
};
|
|
12080
12084
|
const jobRef = randomUUID4();
|
|
12081
12085
|
try {
|
|
12082
|
-
const transport =
|
|
12086
|
+
const transport = getTransport2();
|
|
12083
12087
|
const searchFn = (name, o) => {
|
|
12084
12088
|
const provider = ALL_PROVIDERS[name];
|
|
12085
12089
|
if (!provider) throw new Error(`unknown stock provider: ${name}`);
|
|
@@ -12117,9 +12121,9 @@ function registerStockSearch(parent, getTransport3) {
|
|
|
12117
12121
|
}
|
|
12118
12122
|
|
|
12119
12123
|
// ../cli-core/src/commands/stock.ts
|
|
12120
|
-
function registerStockCommands(program2,
|
|
12124
|
+
function registerStockCommands(program2, getTransport2) {
|
|
12121
12125
|
const stock = program2.command("stock").description("Search and download public stock media (Pexels / Pixabay / Openverse) for b-roll.");
|
|
12122
|
-
registerStockSearch(stock,
|
|
12126
|
+
registerStockSearch(stock, getTransport2);
|
|
12123
12127
|
registerStockDownload(stock);
|
|
12124
12128
|
}
|
|
12125
12129
|
|
|
@@ -12152,13 +12156,36 @@ import { chmodSync, existsSync, mkdirSync, readFileSync as readFileSync2, writeF
|
|
|
12152
12156
|
import { homedir } from "node:os";
|
|
12153
12157
|
import { join } from "node:path";
|
|
12154
12158
|
|
|
12159
|
+
// src/distribution.ts
|
|
12160
|
+
var PRODUCTION_DISTRIBUTION = {
|
|
12161
|
+
channel: "production",
|
|
12162
|
+
packageName: "@actionway/cli",
|
|
12163
|
+
distTag: "latest",
|
|
12164
|
+
commandName: "actionway",
|
|
12165
|
+
configDirectoryName: ".actionway",
|
|
12166
|
+
skillName: "actionway",
|
|
12167
|
+
gatewayUrl: "https://actionway.ai"
|
|
12168
|
+
};
|
|
12169
|
+
var DEVELOPMENT_DISTRIBUTION = {
|
|
12170
|
+
channel: "development",
|
|
12171
|
+
packageName: "@actionway/cli-dev",
|
|
12172
|
+
distTag: "latest",
|
|
12173
|
+
commandName: "actionway-dev",
|
|
12174
|
+
configDirectoryName: ".actionway-dev",
|
|
12175
|
+
skillName: "actionway-dev",
|
|
12176
|
+
gatewayUrl: "https://dev.actionway.ai"
|
|
12177
|
+
};
|
|
12178
|
+
function cliDistribution(env = process.env) {
|
|
12179
|
+
return env.ACTIONWAY_CLI_CHANNEL === "development" ? DEVELOPMENT_DISTRIBUTION : PRODUCTION_DISTRIBUTION;
|
|
12180
|
+
}
|
|
12181
|
+
|
|
12155
12182
|
// src/version.ts
|
|
12156
12183
|
import { readFileSync } from "node:fs";
|
|
12157
12184
|
import { dirname as dirname2, resolve } from "node:path";
|
|
12158
12185
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
12159
|
-
|
|
12160
|
-
function readOwnVersion(moduleUrl = import.meta.url) {
|
|
12186
|
+
function readOwnPackage(moduleUrl = import.meta.url, env = process.env) {
|
|
12161
12187
|
const here = dirname2(fileURLToPath2(moduleUrl));
|
|
12188
|
+
const expectedPackage = cliDistribution(env).packageName;
|
|
12162
12189
|
for (const path of [
|
|
12163
12190
|
resolve(here, "package.json"),
|
|
12164
12191
|
resolve(here, "../package.json"),
|
|
@@ -12168,13 +12195,27 @@ function readOwnVersion(moduleUrl = import.meta.url) {
|
|
|
12168
12195
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
12169
12196
|
if (typeof parsed !== "object" || parsed === null) continue;
|
|
12170
12197
|
const manifest = parsed;
|
|
12171
|
-
if (manifest.name ===
|
|
12172
|
-
|
|
12198
|
+
if (manifest.name === expectedPackage && typeof manifest.version === "string" && manifest.version.trim()) {
|
|
12199
|
+
const result = {
|
|
12200
|
+
name: expectedPackage,
|
|
12201
|
+
version: manifest.version.trim(),
|
|
12202
|
+
...typeof manifest.actionway === "object" && manifest.actionway !== null ? { actionway: manifest.actionway } : {}
|
|
12203
|
+
};
|
|
12204
|
+
if (expectedPackage === "@actionway/cli-dev") {
|
|
12205
|
+
const metadata = result.actionway;
|
|
12206
|
+
if (metadata?.channel !== "development" || !/^[0-9a-f]{40}$/.test(metadata.source_sha ?? "") || !Number.isSafeInteger(metadata.run_id) || (metadata.run_id ?? 0) <= 0 || metadata.run_url !== `https://github.com/PawLogic/actionway/actions/runs/${metadata.run_id}` || metadata.gateway_url !== "https://dev.actionway.ai") {
|
|
12207
|
+
throw new Error("the installed @actionway/cli-dev package metadata is invalid");
|
|
12208
|
+
}
|
|
12209
|
+
}
|
|
12210
|
+
return result;
|
|
12173
12211
|
}
|
|
12174
12212
|
} catch {
|
|
12175
12213
|
}
|
|
12176
12214
|
}
|
|
12177
|
-
throw new Error(`cannot determine the installed ${
|
|
12215
|
+
throw new Error(`cannot determine the installed ${expectedPackage} version`);
|
|
12216
|
+
}
|
|
12217
|
+
function readOwnVersion(moduleUrl = import.meta.url, env = process.env) {
|
|
12218
|
+
return readOwnPackage(moduleUrl, env).version;
|
|
12178
12219
|
}
|
|
12179
12220
|
|
|
12180
12221
|
// src/lib/npm-runner.ts
|
|
@@ -12275,14 +12316,14 @@ function runNpmText(args, operation, options = {}) {
|
|
|
12275
12316
|
}
|
|
12276
12317
|
|
|
12277
12318
|
// src/lib/update-state.ts
|
|
12278
|
-
var PACKAGE_NAME2 = "@actionway/cli";
|
|
12279
12319
|
var UPDATE_STATE_BASENAME = "update.json";
|
|
12280
12320
|
var UPDATE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
12321
|
+
var DEVELOPMENT_VERSION_PATTERN = /^0\.0\.0-dev\.[1-9]\d*\.[0-9a-f]{12}$/;
|
|
12281
12322
|
function actionwayConfigDir(env = process.env) {
|
|
12282
12323
|
const override = (env.ACTIONWAY_CONFIG_DIR ?? "").trim();
|
|
12283
12324
|
if (override) return override;
|
|
12284
12325
|
const home = (env.HOME ?? "").trim() || homedir();
|
|
12285
|
-
return join(home,
|
|
12326
|
+
return join(home, cliDistribution(env).configDirectoryName);
|
|
12286
12327
|
}
|
|
12287
12328
|
function updateStatePath(env = process.env) {
|
|
12288
12329
|
return join(actionwayConfigDir(env), UPDATE_STATE_BASENAME);
|
|
@@ -12331,7 +12372,15 @@ function loadState(env) {
|
|
|
12331
12372
|
if (existsSync(path)) {
|
|
12332
12373
|
try {
|
|
12333
12374
|
const parsed = parseState(readFileSync2(path, "utf8"));
|
|
12334
|
-
if (parsed)
|
|
12375
|
+
if (parsed) {
|
|
12376
|
+
if (cliDistribution(env).channel === "development") {
|
|
12377
|
+
if (parsed.latest_version && !DEVELOPMENT_VERSION_PATTERN.test(parsed.latest_version)) {
|
|
12378
|
+
return emptyState();
|
|
12379
|
+
}
|
|
12380
|
+
return { ...parsed, min_version: null };
|
|
12381
|
+
}
|
|
12382
|
+
return parsed;
|
|
12383
|
+
}
|
|
12335
12384
|
} catch {
|
|
12336
12385
|
}
|
|
12337
12386
|
}
|
|
@@ -12353,6 +12402,7 @@ function readVersionState(env = process.env) {
|
|
|
12353
12402
|
return { latest_version: state.latest_version, min_version: state.min_version, checked_at: state.checked_at };
|
|
12354
12403
|
}
|
|
12355
12404
|
function recordVersionSignal(signal, env = process.env, now = /* @__PURE__ */ new Date()) {
|
|
12405
|
+
if (cliDistribution(env).channel === "development") return;
|
|
12356
12406
|
const latest = (signal.latest ?? "").trim();
|
|
12357
12407
|
const min = (signal.min ?? "").trim();
|
|
12358
12408
|
const validLatest = latest && isValidVersion(latest) ? latest : null;
|
|
@@ -12375,19 +12425,28 @@ function recordVersionSignal(signal, env = process.env, now = /* @__PURE__ */ ne
|
|
|
12375
12425
|
);
|
|
12376
12426
|
}
|
|
12377
12427
|
function fetchLatestVersionFromNpm(env) {
|
|
12428
|
+
const distribution = cliDistribution(env);
|
|
12378
12429
|
const output = runNpmText(
|
|
12379
|
-
["view", `${
|
|
12380
|
-
`npm registry check for ${
|
|
12430
|
+
["view", `${distribution.packageName}@${distribution.distTag}`, "version"],
|
|
12431
|
+
`npm registry check for ${distribution.packageName}@${distribution.distTag}`,
|
|
12381
12432
|
{ env, timeoutMs: 15e3 }
|
|
12382
12433
|
);
|
|
12383
12434
|
const version = output.split(/\r?\n/).at(-1)?.trim() ?? "";
|
|
12384
|
-
if (!version) throw new Error(`npm returned no version for ${
|
|
12435
|
+
if (!version) throw new Error(`npm returned no version for ${distribution.packageName}@${distribution.distTag}`);
|
|
12385
12436
|
return version;
|
|
12386
12437
|
}
|
|
12387
12438
|
function installFromNpm(env) {
|
|
12439
|
+
const distribution = cliDistribution(env);
|
|
12388
12440
|
runNpmText(
|
|
12389
|
-
[
|
|
12390
|
-
|
|
12441
|
+
[
|
|
12442
|
+
"install",
|
|
12443
|
+
"--global",
|
|
12444
|
+
"--no-audit",
|
|
12445
|
+
"--no-fund",
|
|
12446
|
+
"--no-update-notifier",
|
|
12447
|
+
`${distribution.packageName}@${distribution.distTag}`
|
|
12448
|
+
],
|
|
12449
|
+
`npm global update for ${distribution.packageName}`,
|
|
12391
12450
|
{ env, timeoutMs: 12e4 }
|
|
12392
12451
|
);
|
|
12393
12452
|
}
|
|
@@ -12396,12 +12455,13 @@ function isFresh(state, now) {
|
|
|
12396
12455
|
const checkedAt = Date.parse(state.checked_at);
|
|
12397
12456
|
return Number.isFinite(checkedAt) && now.getTime() - checkedAt >= 0 && now.getTime() - checkedAt < UPDATE_CACHE_TTL_MS;
|
|
12398
12457
|
}
|
|
12399
|
-
function statusFrom(currentVersion, latestVersion, checkedAt, fromCache) {
|
|
12458
|
+
function statusFrom(currentVersion, latestVersion, checkedAt, fromCache, env) {
|
|
12459
|
+
const distribution = cliDistribution(env);
|
|
12400
12460
|
return {
|
|
12401
|
-
package:
|
|
12461
|
+
package: distribution.packageName,
|
|
12402
12462
|
current_version: currentVersion,
|
|
12403
12463
|
latest_version: latestVersion,
|
|
12404
|
-
update_available: isValidVersion(latestVersion) && compareVersions(latestVersion, currentVersion) > 0,
|
|
12464
|
+
update_available: isValidVersion(latestVersion) && (distribution.channel === "development" ? latestVersion !== currentVersion : compareVersions(latestVersion, currentVersion) > 0),
|
|
12405
12465
|
checked_at: checkedAt,
|
|
12406
12466
|
from_cache: fromCache
|
|
12407
12467
|
};
|
|
@@ -12412,12 +12472,12 @@ function getUpdateStatus(options = {}) {
|
|
|
12412
12472
|
const currentVersion = options.currentVersion ?? readOwnVersion();
|
|
12413
12473
|
const state = loadState(env);
|
|
12414
12474
|
if (!options.refresh && isFresh(state, now) && state.latest_version) {
|
|
12415
|
-
return statusFrom(currentVersion, state.latest_version, state.checked_at ?? now.toISOString(), true);
|
|
12475
|
+
return statusFrom(currentVersion, state.latest_version, state.checked_at ?? now.toISOString(), true, env);
|
|
12416
12476
|
}
|
|
12417
12477
|
const latestVersion = (options.fetchLatestVersion ?? fetchLatestVersionFromNpm)(env);
|
|
12418
12478
|
const checkedAt = now.toISOString();
|
|
12419
12479
|
saveState({ version: 2, checked_at: checkedAt, latest_version: latestVersion, min_version: state.min_version }, env);
|
|
12420
|
-
return statusFrom(currentVersion, latestVersion, checkedAt, false);
|
|
12480
|
+
return statusFrom(currentVersion, latestVersion, checkedAt, false, env);
|
|
12421
12481
|
}
|
|
12422
12482
|
function runUpdate(options = {}) {
|
|
12423
12483
|
const env = options.env ?? process.env;
|
|
@@ -13036,19 +13096,19 @@ function accountEndpoint(path, options) {
|
|
|
13036
13096
|
const query = parameters.toString();
|
|
13037
13097
|
return `v1/account/${path}${query ? `?${query}` : ""}`;
|
|
13038
13098
|
}
|
|
13039
|
-
async function read(endpoint,
|
|
13099
|
+
async function read(endpoint, getTransport2) {
|
|
13040
13100
|
try {
|
|
13041
|
-
ok(await
|
|
13101
|
+
ok(await getTransport2().getBusiness(endpoint, { retries: 1 }));
|
|
13042
13102
|
} catch (error) {
|
|
13043
13103
|
failAccount(error);
|
|
13044
13104
|
}
|
|
13045
13105
|
}
|
|
13046
|
-
function registerAccountCommands(program2,
|
|
13106
|
+
function registerAccountCommands(program2, getTransport2) {
|
|
13047
13107
|
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),
|
|
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),
|
|
13050
|
-
account.command("wallet").description("Show the current available and held Actionway USD wallet balance.").action(() => read("v1/account/wallet",
|
|
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),
|
|
13108
|
+
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), getTransport2));
|
|
13109
|
+
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), getTransport2));
|
|
13110
|
+
account.command("wallet").description("Show the current available and held Actionway USD wallet balance.").action(() => read("v1/account/wallet", getTransport2));
|
|
13111
|
+
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), getTransport2));
|
|
13052
13112
|
}
|
|
13053
13113
|
|
|
13054
13114
|
// src/commands/doctor.ts
|
|
@@ -13057,7 +13117,6 @@ import { existsSync as existsSync2, rmSync as rmSync2, statSync, writeFileSync a
|
|
|
13057
13117
|
import { createServer as createServer2 } from "node:http";
|
|
13058
13118
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
13059
13119
|
import { dirname as dirname3, join as join3, posix, win32 } from "node:path";
|
|
13060
|
-
var PACKAGE_NAME3 = "@actionway/cli";
|
|
13061
13120
|
function pass(id, message) {
|
|
13062
13121
|
return { id, status: "pass", message };
|
|
13063
13122
|
}
|
|
@@ -13146,6 +13205,7 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13146
13205
|
const readPolicy = dependencies.readPowerShellPolicy ?? powerShellPolicy;
|
|
13147
13206
|
const resolveCommand = dependencies.resolveCommand ?? defaultResolveCommand;
|
|
13148
13207
|
const checks = [];
|
|
13208
|
+
const distribution = cliDistribution(env);
|
|
13149
13209
|
const configDir = actionwayConfigDir(env);
|
|
13150
13210
|
const nodeMajor = Number.parseInt(nodeVersion.split(".")[0] ?? "", 10);
|
|
13151
13211
|
checks.push(
|
|
@@ -13177,7 +13237,7 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13177
13237
|
safe.startsWith("https://registry.npmjs.org/") ? pass("scope_registry", `@actionway packages use ${safe}.`) : warn(
|
|
13178
13238
|
"scope_registry",
|
|
13179
13239
|
`@actionway packages are mapped to ${safe}.`,
|
|
13180
|
-
|
|
13240
|
+
`make sure that registry mirrors public ${distribution.packageName}, or install from the public npm registry when policy permits`
|
|
13181
13241
|
)
|
|
13182
13242
|
);
|
|
13183
13243
|
} else if (scopeResult.error || scopeResult.status !== 0) {
|
|
@@ -13193,14 +13253,21 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13193
13253
|
} else {
|
|
13194
13254
|
const api = pathApi(platform);
|
|
13195
13255
|
const binDir = platform === "win32" ? prefix : api.join(prefix, "bin");
|
|
13196
|
-
const binName = platform === "win32" ?
|
|
13256
|
+
const binName = platform === "win32" ? `${distribution.commandName}.cmd` : distribution.commandName;
|
|
13197
13257
|
let resolvedCache;
|
|
13198
|
-
const resolved = () => resolvedCache !== void 0 ? resolvedCache : resolvedCache = resolveCommand(
|
|
13258
|
+
const resolved = () => resolvedCache !== void 0 ? resolvedCache : resolvedCache = resolveCommand(distribution.commandName);
|
|
13199
13259
|
checks.push(
|
|
13200
|
-
pathContains(binDir, env, platform) ? pass("global_path", `npm global executable directory is in PATH: ${binDir}`) : resolved() ? pass(
|
|
13260
|
+
pathContains(binDir, env, platform) ? pass("global_path", `npm global executable directory is in PATH: ${binDir}`) : resolved() ? pass(
|
|
13261
|
+
"global_path",
|
|
13262
|
+
`${distribution.commandName} resolves from PATH at ${resolved()} (outside the npm global prefix ${binDir}).`
|
|
13263
|
+
) : fail2("global_path", `npm global executable directory is not in PATH: ${binDir}`, "add it to the user PATH and open a new terminal")
|
|
13201
13264
|
);
|
|
13202
13265
|
checks.push(
|
|
13203
|
-
pathExists(api.join(binDir, binName)) ? pass("command", `${binName} is installed in the npm global prefix.`) : resolved() ? pass("command",
|
|
13266
|
+
pathExists(api.join(binDir, binName)) ? pass("command", `${binName} is installed in the npm global prefix.`) : resolved() ? pass("command", `${distribution.commandName} command resolves at ${resolved()}.`) : fail2(
|
|
13267
|
+
"command",
|
|
13268
|
+
`${binName} was not found in the npm global prefix.`,
|
|
13269
|
+
`reinstall ${distribution.packageName}@${distribution.distTag} in the same Node/npm environment`
|
|
13270
|
+
)
|
|
13204
13271
|
);
|
|
13205
13272
|
}
|
|
13206
13273
|
if (platform === "win32") {
|
|
@@ -13208,9 +13275,12 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13208
13275
|
checks.push(
|
|
13209
13276
|
policy && ["Restricted", "AllSigned"].includes(policy) ? warn(
|
|
13210
13277
|
"powershell_policy",
|
|
13211
|
-
`PowerShell execution policy is ${policy}; npm's
|
|
13212
|
-
|
|
13213
|
-
) : pass(
|
|
13278
|
+
`PowerShell execution policy is ${policy}; npm's ${distribution.commandName}.ps1 shim may be blocked.`,
|
|
13279
|
+
`use ${distribution.commandName}.cmd; do not weaken organization policy without approval`
|
|
13280
|
+
) : pass(
|
|
13281
|
+
"powershell_policy",
|
|
13282
|
+
`PowerShell execution policy is ${policy || "not available"}; ${distribution.commandName}.cmd remains the entrypoint.`
|
|
13283
|
+
)
|
|
13214
13284
|
);
|
|
13215
13285
|
}
|
|
13216
13286
|
try {
|
|
@@ -13229,13 +13299,19 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13229
13299
|
checks.push({ id: "npm_registry", status: "skip", message: "npm registry check was skipped." });
|
|
13230
13300
|
checks.push({ id: "actionway_oauth", status: "skip", message: "Actionway OAuth discovery check was skipped." });
|
|
13231
13301
|
} else {
|
|
13232
|
-
const packageResult = npm(
|
|
13302
|
+
const packageResult = npm(
|
|
13303
|
+
["view", `${distribution.packageName}@${distribution.distTag}`, "version"],
|
|
13304
|
+
{ env, platform, timeoutMs: 15e3 }
|
|
13305
|
+
);
|
|
13233
13306
|
checks.push(
|
|
13234
13307
|
npmCheck(
|
|
13235
13308
|
"npm_registry",
|
|
13236
13309
|
packageResult,
|
|
13237
13310
|
"Actionway package lookup",
|
|
13238
|
-
(version) => pass(
|
|
13311
|
+
(version) => pass(
|
|
13312
|
+
"npm_registry",
|
|
13313
|
+
`${distribution.packageName}@${distribution.distTag} is reachable (${version.split(/\r?\n/).at(-1)}).`
|
|
13314
|
+
)
|
|
13239
13315
|
)
|
|
13240
13316
|
);
|
|
13241
13317
|
try {
|
|
@@ -13261,9 +13337,10 @@ async function diagnoseActionway(options = {}, dependencies = {}) {
|
|
|
13261
13337
|
};
|
|
13262
13338
|
}
|
|
13263
13339
|
function registerDoctorCommand(program2) {
|
|
13340
|
+
const distribution = cliDistribution();
|
|
13264
13341
|
program2.command("doctor").description("Diagnose Node, npm, PATH, registry, configuration, and local OAuth callback readiness.").option("--no-network", "skip npm registry and Actionway OAuth discovery checks").action(async (options) => {
|
|
13265
13342
|
const report = await diagnoseActionway({ network: options.network !== false });
|
|
13266
|
-
const command = process.platform === "win32" ?
|
|
13343
|
+
const command = process.platform === "win32" ? `${distribution.commandName}.cmd` : distribution.commandName;
|
|
13267
13344
|
ok({
|
|
13268
13345
|
...report,
|
|
13269
13346
|
hint: report.ready ? `Actionway CLI prerequisites are ready. Run \`${command} init\`.` : `Resolve the failed checks, then run \`${command} doctor\` again.`
|
|
@@ -13287,15 +13364,21 @@ var InitError = class extends Error {
|
|
|
13287
13364
|
}
|
|
13288
13365
|
};
|
|
13289
13366
|
var ACTIONWAY_SKILL_INSTRUCTION = "Install this skill from `source` into your agent's skill directory and make sure it loads in future sessions. If a skill named `actionway` already exists there, replace it only when it is an earlier Actionway skill (check its frontmatter metadata.version); otherwise ask the user first.";
|
|
13290
|
-
|
|
13367
|
+
var ACTIONWAY_DEV_SKILL_INSTRUCTION = "Install this skill from `source` into your agent's skill directory and make sure it loads in future sessions. If a skill named `actionway-dev` already exists there, replace it only when it is an earlier Actionway development skill (check its frontmatter metadata.version); otherwise ask the user first. Never replace the stable `actionway` Skill.";
|
|
13368
|
+
function resolveBundledSkill(moduleUrl = import.meta.url, env = process.env) {
|
|
13291
13369
|
const here = dirname4(fileURLToPath3(moduleUrl));
|
|
13292
|
-
|
|
13370
|
+
const skillName = cliDistribution(env).skillName;
|
|
13371
|
+
for (const candidate of [resolve2(here, `../assets/skill/${skillName}`), resolve2(here, `../../assets/skill/${skillName}`)]) {
|
|
13293
13372
|
if (existsSync3(join4(candidate, "SKILL.md"))) return realpathSync2(candidate);
|
|
13294
13373
|
}
|
|
13295
|
-
|
|
13374
|
+
const distribution = cliDistribution(env);
|
|
13375
|
+
throw new InitError(
|
|
13376
|
+
"the bundled Actionway Skill is missing",
|
|
13377
|
+
`reinstall ${distribution.packageName}@${distribution.distTag}, then run \`${distribution.commandName} init\` again`
|
|
13378
|
+
);
|
|
13296
13379
|
}
|
|
13297
13380
|
function skillSourcePath(env = process.env) {
|
|
13298
|
-
return join4(actionwayConfigDir(env), "skill",
|
|
13381
|
+
return join4(actionwayConfigDir(env), "skill", cliDistribution(env).skillName);
|
|
13299
13382
|
}
|
|
13300
13383
|
function stampSkillVersion(skillMarkdown, version) {
|
|
13301
13384
|
const newline = skillMarkdown.includes("\r\n") ? "\r\n" : "\n";
|
|
@@ -13334,18 +13417,55 @@ function stampSkillVersion(skillMarkdown, version) {
|
|
|
13334
13417
|
}
|
|
13335
13418
|
function materializeSkill(options = {}) {
|
|
13336
13419
|
const env = options.env ?? process.env;
|
|
13337
|
-
const
|
|
13420
|
+
const distribution = cliDistribution(env);
|
|
13421
|
+
const source = options.source ? realpathSync2(options.source) : resolveBundledSkill(import.meta.url, env);
|
|
13338
13422
|
if (!existsSync3(join4(source, "SKILL.md"))) {
|
|
13339
|
-
throw new InitError(
|
|
13423
|
+
throw new InitError(
|
|
13424
|
+
"the Actionway Skill source is invalid",
|
|
13425
|
+
`reinstall ${distribution.packageName}@${distribution.distTag} and retry init`
|
|
13426
|
+
);
|
|
13340
13427
|
}
|
|
13341
|
-
const version = options.version ?? readOwnVersion();
|
|
13428
|
+
const version = options.version ?? readOwnVersion(import.meta.url, env);
|
|
13342
13429
|
const target = skillSourcePath(env);
|
|
13343
13430
|
mkdirSync3(dirname4(target), { recursive: true, mode: 448 });
|
|
13344
13431
|
rmSync3(target, { recursive: true, force: true });
|
|
13345
13432
|
cpSync(source, target, { recursive: true });
|
|
13346
13433
|
const skillPath = join4(target, "SKILL.md");
|
|
13347
13434
|
writeFileSync4(skillPath, stampSkillVersion(readFileSync4(skillPath, "utf8"), version));
|
|
13348
|
-
return {
|
|
13435
|
+
return {
|
|
13436
|
+
source: target,
|
|
13437
|
+
version,
|
|
13438
|
+
instruction: distribution.channel === "development" ? ACTIONWAY_DEV_SKILL_INSTRUCTION : ACTIONWAY_SKILL_INSTRUCTION
|
|
13439
|
+
};
|
|
13440
|
+
}
|
|
13441
|
+
|
|
13442
|
+
// src/lib/client-context.ts
|
|
13443
|
+
var ACTIONWAY_AGENT_HOST_HEADER = "x-actionway-agent-host";
|
|
13444
|
+
var ACTIONWAY_RUNTIME_OS_HEADER = "x-actionway-runtime-os";
|
|
13445
|
+
var ACTIONWAY_AGENT_HOSTS = ["codex", "claude_code", "workbuddy"];
|
|
13446
|
+
function isActionwayAgentHost(value) {
|
|
13447
|
+
return typeof value === "string" && ACTIONWAY_AGENT_HOSTS.includes(value);
|
|
13448
|
+
}
|
|
13449
|
+
function detectRuntimeOs(platform = process.platform, env = process.env) {
|
|
13450
|
+
if (platform === "win32") return "windows";
|
|
13451
|
+
if (platform === "darwin") return "macos";
|
|
13452
|
+
if (platform === "linux") {
|
|
13453
|
+
if ((env.WSL_DISTRO_NAME ?? "").trim() || (env.WSL_INTEROP ?? "").trim()) return "wsl";
|
|
13454
|
+
return "linux";
|
|
13455
|
+
}
|
|
13456
|
+
return "other";
|
|
13457
|
+
}
|
|
13458
|
+
function localClientContext(agentHost, platform = process.platform, env = process.env) {
|
|
13459
|
+
return {
|
|
13460
|
+
...isActionwayAgentHost(agentHost) ? { agentHost } : {},
|
|
13461
|
+
runtimeOs: detectRuntimeOs(platform, env)
|
|
13462
|
+
};
|
|
13463
|
+
}
|
|
13464
|
+
function localClientContextHeaders(context) {
|
|
13465
|
+
return {
|
|
13466
|
+
...context.agentHost ? { [ACTIONWAY_AGENT_HOST_HEADER]: context.agentHost } : {},
|
|
13467
|
+
[ACTIONWAY_RUNTIME_OS_HEADER]: context.runtimeOs
|
|
13468
|
+
};
|
|
13349
13469
|
}
|
|
13350
13470
|
|
|
13351
13471
|
// src/lib/install-session.ts
|
|
@@ -13387,7 +13507,12 @@ async function captureInstallStarted(input) {
|
|
|
13387
13507
|
`${stripSlash2(input.gateway)}/api/analytics/install-started`,
|
|
13388
13508
|
{
|
|
13389
13509
|
method: "POST",
|
|
13390
|
-
headers: {
|
|
13510
|
+
headers: {
|
|
13511
|
+
Accept: "application/json",
|
|
13512
|
+
"Content-Type": "application/json",
|
|
13513
|
+
"x-actionway-cli-version": getCliVersion(),
|
|
13514
|
+
...input.clientContext ? localClientContextHeaders(input.clientContext) : {}
|
|
13515
|
+
},
|
|
13391
13516
|
body: JSON.stringify({
|
|
13392
13517
|
installSessionId: input.installSessionId,
|
|
13393
13518
|
installSource: input.installSource
|
|
@@ -13411,7 +13536,12 @@ async function requestCliInstallSession(input) {
|
|
|
13411
13536
|
url.toString(),
|
|
13412
13537
|
{
|
|
13413
13538
|
method: "GET",
|
|
13414
|
-
headers: {
|
|
13539
|
+
headers: {
|
|
13540
|
+
Accept: "application/json",
|
|
13541
|
+
Authorization: `Bearer ${input.accessToken}`,
|
|
13542
|
+
"x-actionway-cli-version": getCliVersion(),
|
|
13543
|
+
...input.clientContext ? localClientContextHeaders(input.clientContext) : {}
|
|
13544
|
+
}
|
|
13415
13545
|
},
|
|
13416
13546
|
SESSION_TIMEOUT_MS2,
|
|
13417
13547
|
input.fetchImpl ?? fetch
|
|
@@ -13451,6 +13581,7 @@ async function connectInstallSession(input) {
|
|
|
13451
13581
|
accessToken: credentials.access_token,
|
|
13452
13582
|
installSessionId: input.installSessionId,
|
|
13453
13583
|
installSource: input.installSource,
|
|
13584
|
+
...input.clientContext ? { clientContext: input.clientContext } : {},
|
|
13454
13585
|
fetchImpl
|
|
13455
13586
|
});
|
|
13456
13587
|
}
|
|
@@ -13465,11 +13596,14 @@ function failFromError3(err) {
|
|
|
13465
13596
|
}
|
|
13466
13597
|
fail({ code: "E_BACKEND", message: err instanceof Error ? err.message : String(err) });
|
|
13467
13598
|
}
|
|
13468
|
-
function registerInitCommand(program2) {
|
|
13599
|
+
function registerInitCommand(program2, getClientContext = () => ({ runtimeOs: "other" })) {
|
|
13600
|
+
const distribution = cliDistribution();
|
|
13469
13601
|
program2.command("init").description(
|
|
13470
13602
|
"Complete browser authentication and stage the Actionway Skill for your agent to install. The CLI never writes into an agent's own configuration directory."
|
|
13471
13603
|
).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) => {
|
|
13472
13604
|
try {
|
|
13605
|
+
const clientContext = getClientContext();
|
|
13606
|
+
const invocation = clientContext.agentHost ? `${distribution.commandName} --agent-host=${clientContext.agentHost}` : distribution.commandName;
|
|
13473
13607
|
const skill = materializeSkill();
|
|
13474
13608
|
if (opts.skillOnly) {
|
|
13475
13609
|
ok({ skill });
|
|
@@ -13480,7 +13614,8 @@ function registerInitCommand(program2) {
|
|
|
13480
13614
|
await captureInstallStarted({
|
|
13481
13615
|
gateway: initGateway,
|
|
13482
13616
|
installSessionId,
|
|
13483
|
-
installSource
|
|
13617
|
+
installSource,
|
|
13618
|
+
clientContext
|
|
13484
13619
|
});
|
|
13485
13620
|
let loginStarted = false;
|
|
13486
13621
|
if (!whoamiSnapshot()) {
|
|
@@ -13497,7 +13632,8 @@ function registerInitCommand(program2) {
|
|
|
13497
13632
|
const account = await connectInstallSession({
|
|
13498
13633
|
...opts.gateway ? { explicitGateway: opts.gateway } : {},
|
|
13499
13634
|
installSessionId,
|
|
13500
|
-
installSource
|
|
13635
|
+
installSource,
|
|
13636
|
+
clientContext
|
|
13501
13637
|
});
|
|
13502
13638
|
const snapshot = whoamiSnapshot();
|
|
13503
13639
|
ok({
|
|
@@ -13507,7 +13643,7 @@ function registerInitCommand(program2) {
|
|
|
13507
13643
|
skill,
|
|
13508
13644
|
workspace_id: account.workspaceId,
|
|
13509
13645
|
...snapshot?.user ? { user: snapshot.user } : {},
|
|
13510
|
-
hint:
|
|
13646
|
+
hint: `Actionway is ready. Install the skill from \`skill.source\` into your agent's skill directory, then run \`${invocation} --help\` to discover supported capabilities.`
|
|
13511
13647
|
});
|
|
13512
13648
|
} catch (error) {
|
|
13513
13649
|
failFromError3(error);
|
|
@@ -13515,6 +13651,26 @@ function registerInitCommand(program2) {
|
|
|
13515
13651
|
});
|
|
13516
13652
|
}
|
|
13517
13653
|
|
|
13654
|
+
// src/commands/status.ts
|
|
13655
|
+
function registerDevelopmentStatusCommand(program2) {
|
|
13656
|
+
const distribution = cliDistribution();
|
|
13657
|
+
if (distribution.channel !== "development") return;
|
|
13658
|
+
program2.command("status").description("Show the installed Actionway development channel and immutable source revision.").action(() => {
|
|
13659
|
+
const manifest = readOwnPackage();
|
|
13660
|
+
const metadata = manifest.actionway;
|
|
13661
|
+
ok({
|
|
13662
|
+
channel: "development",
|
|
13663
|
+
package: manifest.name,
|
|
13664
|
+
version: manifest.version,
|
|
13665
|
+
source_sha: metadata?.source_sha ?? null,
|
|
13666
|
+
run_id: metadata?.run_id ?? null,
|
|
13667
|
+
run_url: metadata?.run_url ?? null,
|
|
13668
|
+
gateway_url: metadata?.gateway_url ?? distribution.gatewayUrl,
|
|
13669
|
+
config_dir: process.env.ACTIONWAY_CONFIG_DIR ?? null
|
|
13670
|
+
});
|
|
13671
|
+
});
|
|
13672
|
+
}
|
|
13673
|
+
|
|
13518
13674
|
// src/commands/update.ts
|
|
13519
13675
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
13520
13676
|
function refreshSkillWithNewBinary() {
|
|
@@ -13535,7 +13691,8 @@ function refreshSkillWithNewBinary() {
|
|
|
13535
13691
|
}
|
|
13536
13692
|
}
|
|
13537
13693
|
function registerUpdateCommand(program2) {
|
|
13538
|
-
|
|
13694
|
+
const distribution = cliDistribution();
|
|
13695
|
+
program2.command("update").description(`Check for or install the latest ${distribution.packageName} version from npm.`).option("--check", "check for a newer version without installing").option("--refresh", "ignore the 24-hour update-check cache").action((opts) => {
|
|
13539
13696
|
try {
|
|
13540
13697
|
if (opts.check) {
|
|
13541
13698
|
ok({ ...getUpdateStatus({ ...opts.refresh ? { refresh: true } : {} }) });
|
|
@@ -13558,7 +13715,7 @@ function registerUpdateCommand(program2) {
|
|
|
13558
13715
|
fail({
|
|
13559
13716
|
code: "E_UPDATE_FAILED",
|
|
13560
13717
|
message: error instanceof Error ? error.message : String(error),
|
|
13561
|
-
hint:
|
|
13718
|
+
hint: `retry later or reinstall ${distribution.packageName}@${distribution.distTag}`
|
|
13562
13719
|
});
|
|
13563
13720
|
}
|
|
13564
13721
|
});
|
|
@@ -13568,6 +13725,7 @@ function registerUpdateCommand(program2) {
|
|
|
13568
13725
|
function withVersionMetadata(payload, deps = {}) {
|
|
13569
13726
|
const env = deps.env ?? process.env;
|
|
13570
13727
|
const cliVersion2 = deps.currentVersion ?? getCliVersion();
|
|
13728
|
+
const distribution = cliDistribution(env);
|
|
13571
13729
|
const skillSource = skillSourcePath(env);
|
|
13572
13730
|
const isUpdateCommandOutput = "update_available" in payload;
|
|
13573
13731
|
const notes = [];
|
|
@@ -13575,12 +13733,12 @@ function withVersionMetadata(payload, deps = {}) {
|
|
|
13575
13733
|
const state = readVersionState(env);
|
|
13576
13734
|
if (!isUpdateCommandOutput && state.latest_version && isValidVersion(state.latest_version) && compareVersions(state.latest_version, cliVersion2) > 0) {
|
|
13577
13735
|
notes.push(
|
|
13578
|
-
`Update available: ${cliVersion2} -> ${state.latest_version}. Run
|
|
13736
|
+
`Update available: ${cliVersion2} -> ${state.latest_version}. Run \`${distribution.commandName} update\` at the next session boundary, then refresh the installed skill from ${skillSource}.`
|
|
13579
13737
|
);
|
|
13580
13738
|
}
|
|
13581
13739
|
if (state.min_version && isValidVersion(state.min_version) && compareVersions(cliVersion2, state.min_version) < 0) {
|
|
13582
13740
|
notes.push(
|
|
13583
|
-
`This CLI version (${cliVersion2}) is below the minimum supported version (${state.min_version}). Run
|
|
13741
|
+
`This CLI version (${cliVersion2}) is below the minimum supported version (${state.min_version}). Run \`${distribution.commandName} update\` now, then refresh the installed skill from ${skillSource}.`
|
|
13584
13742
|
);
|
|
13585
13743
|
}
|
|
13586
13744
|
} catch {
|
|
@@ -13634,7 +13792,7 @@ function authFailure(err) {
|
|
|
13634
13792
|
extra: { ...err.extra ?? {}, ...err.hint ? { hint: err.hint } : {} }
|
|
13635
13793
|
});
|
|
13636
13794
|
}
|
|
13637
|
-
function getTransport(env = process.env, fetchImpl) {
|
|
13795
|
+
function getTransport(env = process.env, fetchImpl, clientContext) {
|
|
13638
13796
|
return new Transport({
|
|
13639
13797
|
baseUrl: resolveTransportBaseUrl(env),
|
|
13640
13798
|
authHeader: async () => {
|
|
@@ -13656,6 +13814,7 @@ function getTransport(env = process.env, fetchImpl) {
|
|
|
13656
13814
|
}
|
|
13657
13815
|
return `Bearer ${creds.access_token}`;
|
|
13658
13816
|
},
|
|
13817
|
+
...clientContext ? { requestHeaders: localClientContextHeaders(clientContext) } : {},
|
|
13659
13818
|
...fetchImpl ? { fetchImpl } : {},
|
|
13660
13819
|
onResponse: (res) => {
|
|
13661
13820
|
const latest = res.headers.get("x-actionway-cli-latest");
|
|
@@ -13794,19 +13953,23 @@ function projectTypedToolCall(spec, commandParams, prepared) {
|
|
|
13794
13953
|
}
|
|
13795
13954
|
|
|
13796
13955
|
// src/index.ts
|
|
13797
|
-
function getTransport2() {
|
|
13798
|
-
return getTransport();
|
|
13799
|
-
}
|
|
13800
|
-
var actionDeps = { getTransport: getTransport2, projectToolCall: projectTypedToolCall };
|
|
13801
13956
|
function buildProgram() {
|
|
13957
|
+
const distribution = cliDistribution();
|
|
13802
13958
|
const version = readOwnVersion();
|
|
13803
13959
|
setCliVersion(version);
|
|
13804
|
-
const program2 = new Command(
|
|
13960
|
+
const program2 = new Command(distribution.commandName);
|
|
13805
13961
|
program2.version(version);
|
|
13806
13962
|
program2.description("Actionway CLI: run Actionway media and research capabilities from your local agent.");
|
|
13807
|
-
|
|
13963
|
+
program2.addOption(
|
|
13964
|
+
new Option("--agent-host <host>", "declare the local Agent invoking this command").choices([...ACTIONWAY_AGENT_HOSTS])
|
|
13965
|
+
);
|
|
13966
|
+
const getClientContext = () => localClientContext(program2.opts().agentHost);
|
|
13967
|
+
const getTransport2 = () => getTransport(process.env, void 0, getClientContext());
|
|
13968
|
+
const actionDeps = { getTransport: getTransport2, projectToolCall: projectTypedToolCall };
|
|
13969
|
+
registerInitCommand(program2, getClientContext);
|
|
13808
13970
|
registerDoctorCommand(program2);
|
|
13809
13971
|
registerUpdateCommand(program2);
|
|
13972
|
+
registerDevelopmentStatusCommand(program2);
|
|
13810
13973
|
registerAuthCommands(program2);
|
|
13811
13974
|
registerAccountCommands(program2, getTransport2);
|
|
13812
13975
|
registerToolsCommands(program2, getTransport2);
|