@actionway/cli-dev 0.0.0-dev.32821683196.320940b928ff → 0.0.0-dev.32930928283.846129ead8ae

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.
@@ -71,7 +71,7 @@ Right after a successful `actionway init`, run `actionway account wallet` once a
71
71
  - [Image Search](references/capabilities/image-search.md) (`web.image.search`) — Find visually similar or relevant existing images on the public web.
72
72
  - [Fetch URL](references/capabilities/fetch.md) (`web.fetch`) — Fetch a supported URL as text, Markdown, or bounded raw content.
73
73
  - [Search Stock Media](references/capabilities/stock-search.md) (`stock-media.search`) — Search one or more supported stock-media providers.
74
- - [Download Stock Media](references/capabilities/stock-download.md) (`stock-media.download`) — Download a selected stock-media result.
74
+ - [Download Stock Media](references/capabilities/stock-download.md) (`stock-media.download`) — Authorize a selected stock-media result for local download.
75
75
  - [Knowledge Search](references/capabilities/knowledge-search.md) (`knowledge.search`) — Search curated domain libraries for audio, visual, voice, writing, or meme references.
76
76
 
77
77
  **Live data**
@@ -7,6 +7,6 @@ Get standardized annual or quarterly company income statements.
7
7
 
8
8
  ## Indicative price
9
9
 
10
- free
10
+ $0.01
11
11
 
12
12
  Prices are indicative catalog values refreshed with each skill release. Before calling, Inspect the chosen variant: Inspect's input Schema and USD quote are authoritative.
@@ -7,6 +7,6 @@ Get the latest available market quote for one or more comma-separated symbols.
7
7
 
8
8
  ## Indicative price
9
9
 
10
- free
10
+ $0.01
11
11
 
12
12
  Prices are indicative catalog values refreshed with each skill release. Before calling, Inspect the chosen variant: Inspect's input Schema and USD quote are authoritative.
@@ -7,6 +7,6 @@ Search stocks and other market securities by name or symbol.
7
7
 
8
8
  ## Indicative price
9
9
 
10
- free
10
+ $0.01
11
11
 
12
12
  Prices are indicative catalog values refreshed with each skill release. Before calling, Inspect the chosen variant: Inspect's input Schema and USD quote are authoritative.
@@ -1,6 +1,6 @@
1
1
  # Download Stock Media (`stock-media.download`)
2
2
 
3
- Download a selected stock-media result.
3
+ Authorize a selected stock-media result for local download.
4
4
 
5
5
  - Users ask for it as: download a selected stock-media item; download stock image; download stock video.
6
6
  - Takes url, structured-data → returns image, video. Runs synchronously.
package/dist/index.js CHANGED
@@ -9387,7 +9387,12 @@ var Transport = class {
9387
9387
  return this.request("POST", `v1/tools/${encodeURIComponent(toolRef)}/call`, body, opts);
9388
9388
  }
9389
9389
  async resumeToolCall(callRef, opts = {}) {
9390
- return this.request("POST", `v1/tool-calls/${encodeURIComponent(callRef)}/resume`, {}, opts);
9390
+ return this.request(
9391
+ "POST",
9392
+ `v1/tool-calls/${encodeURIComponent(callRef)}/resume`,
9393
+ {},
9394
+ { ...opts, retries: 0 }
9395
+ );
9391
9396
  }
9392
9397
  async getBusiness(endpoint, opts = {}) {
9393
9398
  return this.request("GET", endpoint.replace(/^\/+/, ""), void 0, opts);
@@ -11460,15 +11465,12 @@ function registerKnowledgeCommands(program2, getTransport2) {
11460
11465
 
11461
11466
  // ../cli-core/src/commands/stock-download.ts
11462
11467
  import { randomUUID as randomUUID3 } from "node:crypto";
11463
- import { mkdir, writeFile } from "node:fs/promises";
11468
+ import { mkdir, rename, rm, writeFile } from "node:fs/promises";
11464
11469
  import { dirname, extname, isAbsolute as isAbsolute2 } from "node:path";
11465
11470
  var DEFAULT_DOWNLOAD_DIR = "/workspace/.stock-media";
11466
11471
  var FETCH_TIMEOUT_MS = 6e4;
11467
11472
  var MAX_DOWNLOAD_BYTES = 200 * 1024 * 1024;
11468
11473
  var ASSET_ID_RE = /^([a-z0-9_-]+):([a-zA-Z0-9_.-]+)$/;
11469
- function stockDownloadAvailable() {
11470
- return false;
11471
- }
11472
11474
  var MIME_TO_EXT = /* @__PURE__ */ new Map([
11473
11475
  ["image/jpeg", "jpg"],
11474
11476
  ["image/jpg", "jpg"],
@@ -11579,7 +11581,7 @@ async function fetchBytes(url) {
11579
11581
  clearTimeout(timer);
11580
11582
  }
11581
11583
  }
11582
- function registerStockDownload(parent) {
11584
+ function registerStockDownload(parent, deps) {
11583
11585
  parent.command("download").description("Fetch a stock-media asset (CDN URL from search result) into /workspace and echo full metadata.").addHelpText(
11584
11586
  "after",
11585
11587
  [
@@ -11589,19 +11591,12 @@ function registerStockDownload(parent) {
11589
11591
  "so the local result retains its source and license metadata."
11590
11592
  ].join("\n")
11591
11593
  ).requiredOption("--asset-id <id>", "<provider>:<native_id> from a search result").requiredOption("--url <url>", "direct CDN URL from search result's download_url").option("--to <path>", `absolute path under /workspace (default: ${DEFAULT_DOWNLOAD_DIR}/<provider>-<id>.<ext>)`).option("--metadata-json <json>", "JSON-encoded metadata object from the search result; echoed back in output").action(async (opts) => {
11592
- if (!stockDownloadAvailable()) {
11593
- fail({
11594
- code: "E_CAPABILITY_NOT_AVAILABLE",
11595
- message: "stock download is deferred until Gateway command-level billing is available",
11596
- hint: "do not fetch the asset directly as a workaround; wait for the stage-two stock billing integration"
11597
- });
11598
- }
11599
11594
  const { provider, nativeId } = parseAssetId(String(opts.assetId));
11600
11595
  const url = String(opts.url);
11601
11596
  try {
11602
11597
  const parsedUrl = new URL(url);
11603
- if (parsedUrl.protocol !== "https:" && parsedUrl.protocol !== "http:") {
11604
- fail({ code: "E_SCHEMA", message: `--url must be http(s); got protocol ${parsedUrl.protocol}` });
11598
+ if (parsedUrl.protocol !== "https:") {
11599
+ fail({ code: "E_SCHEMA", message: `--url must use https; got protocol ${parsedUrl.protocol}` });
11605
11600
  }
11606
11601
  } catch (err) {
11607
11602
  if (err.name === "TypeError") {
@@ -11618,7 +11613,22 @@ function registerStockDownload(parent) {
11618
11613
  const defaultPath = `${DEFAULT_DOWNLOAD_DIR}/${provider}-${nativeId}.${ext}`;
11619
11614
  const destination = explicitDestination ?? validateDestination(void 0, defaultPath);
11620
11615
  await mkdir(dirname(destination), { recursive: true });
11621
- await writeFile(destination, buf);
11616
+ const temporary = `${destination}.actionway-${jobRef}.tmp`;
11617
+ await writeFile(temporary, buf, { flag: "wx" });
11618
+ try {
11619
+ const transport = deps.getTransport();
11620
+ const body = { provider, native_id: nativeId, url, destination, kind: contentType?.startsWith("video/") ? "video" : "image" };
11621
+ if (deps.projectToolCall) {
11622
+ const response = await transport.callTool({ toolRef: "stock-media.download", arguments: body, idempotencyKey: jobRef, confirmation: { kind: "typed-command" } }, { jobRef, retries: 1 });
11623
+ if (response.status !== "completed") throw new StockDownloadError("stock download authorization did not complete");
11624
+ } else {
11625
+ await transport.post("internal/stock/download", body, { jobRef, retries: 1 });
11626
+ }
11627
+ await rename(temporary, destination);
11628
+ } catch (error) {
11629
+ await rm(temporary, { force: true });
11630
+ throw error;
11631
+ }
11622
11632
  ok({
11623
11633
  job_ref: jobRef,
11624
11634
  asset_id: `${provider}:${nativeId}`,
@@ -11900,9 +11910,6 @@ var STOCK_DEFAULT_PROVIDER_ORDER = ["pexels", "pixabay", "openverse"];
11900
11910
  var STOCK_ORIENTATIONS = ["landscape", "portrait", "square"];
11901
11911
  var STOCK_TYPES = ["image", "video"];
11902
11912
  var STOCK_MODES = ["fallback", "fanout"];
11903
- function isStockSearchAvailable() {
11904
- return false;
11905
- }
11906
11913
  function parsePositiveInt(raw, flag, max) {
11907
11914
  const n = Number(raw);
11908
11915
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1 || n > max) {
@@ -11938,88 +11945,15 @@ function parseProviders(csv, type) {
11938
11945
  }
11939
11946
  return enabled;
11940
11947
  }
11941
- function describeProviderFailure(provider, err) {
11942
- if (err instanceof TransportError) {
11943
- return {
11944
- provider,
11945
- ...err.status !== void 0 ? { status: err.status } : {},
11946
- reason: `${err.status ?? "transport"}: ${err.message}`
11947
- };
11948
- }
11949
- if (err instanceof Error) return { provider, reason: err.message };
11950
- return { provider, reason: String(err) };
11951
- }
11952
- function mergeResults(perProvider, limit) {
11953
- const merged = [];
11954
- const seen = /* @__PURE__ */ new Set();
11955
- const cursors = perProvider.map(() => 0);
11956
- let active = perProvider.filter((arr) => arr.length > 0).length;
11957
- while (merged.length < limit && active > 0) {
11958
- active = 0;
11959
- for (let i = 0; i < perProvider.length; i++) {
11960
- const arr = perProvider[i];
11961
- const cursor = cursors[i];
11962
- if (arr === void 0 || cursor === void 0 || cursor >= arr.length) continue;
11963
- const r = arr[cursor];
11964
- cursors[i] = cursor + 1;
11965
- if (r !== void 0 && !seen.has(r.asset_id)) {
11966
- seen.add(r.asset_id);
11967
- merged.push(r);
11968
- if (merged.length >= limit) break;
11969
- }
11970
- if (cursor + 1 < arr.length) active += 1;
11971
- }
11972
- }
11973
- return merged;
11974
- }
11975
- async function searchSequential(enabled, opts, limit, searchFn) {
11976
- const collected = [];
11977
- const seen = /* @__PURE__ */ new Set();
11978
- const queried = [];
11979
- const failed = [];
11980
- for (const name of enabled) {
11981
- queried.push(name);
11982
- try {
11983
- const results = await searchFn(name, opts);
11984
- for (const r of results) {
11985
- if (!seen.has(r.asset_id)) {
11986
- seen.add(r.asset_id);
11987
- collected.push(r);
11988
- if (collected.length >= limit) break;
11989
- }
11990
- }
11991
- } catch (err) {
11992
- failed.push(describeProviderFailure(name, err));
11993
- }
11994
- if (collected.length >= limit) break;
11995
- }
11996
- return { results: collected.slice(0, limit), queried, failed };
11997
- }
11998
- async function searchFanout(enabled, opts, limit, searchFn) {
11999
- const settled = await Promise.allSettled(enabled.map((n) => searchFn(n, opts)));
12000
- const perProviderResults = [];
12001
- const failed = [];
12002
- for (let i = 0; i < enabled.length; i++) {
12003
- const r = settled[i];
12004
- const name = enabled[i];
12005
- if (r !== void 0 && r.status === "fulfilled") {
12006
- perProviderResults.push(r.value);
12007
- } else {
12008
- perProviderResults.push([]);
12009
- if (r !== void 0 && name !== void 0) failed.push(describeProviderFailure(name, r.reason));
12010
- }
12011
- }
12012
- return { results: mergeResults(perProviderResults, limit), queried: [...enabled], failed };
12013
- }
12014
- function registerStockSearch(parent, getTransport2) {
11948
+ function registerStockSearch(parent, deps) {
12015
11949
  parent.command("search").description(
12016
11950
  "Sequential-fallback search across providers (Pexels -> Pixabay -> Openverse). Use --mode=fanout for parallel."
12017
11951
  ).addHelpText(
12018
11952
  "after",
12019
11953
  [
12020
11954
  "",
12021
- "Availability:",
12022
- " Stage one is fail-closed until Gateway command-level billing orchestration is available.",
11955
+ "Execution:",
11956
+ " Gateway orchestrates all selected providers and bills the search once.",
12023
11957
  "",
12024
11958
  "Modes:",
12025
11959
  " fallback (default) - calls Pexels -> Pixabay -> Openverse in order and stops once limit results are collected.",
@@ -12048,13 +11982,6 @@ function registerStockSearch(parent, getTransport2) {
12048
11982
  `search strategy: ${STOCK_MODES.join(" | ")} (default fallback saves API budget)`,
12049
11983
  "fallback"
12050
11984
  ).action(async (opts) => {
12051
- if (!isStockSearchAvailable()) {
12052
- fail({
12053
- code: "E_CAPABILITY_NOT_AVAILABLE",
12054
- message: "stock search is not available in migration stage one",
12055
- hint: "Gateway command-level stock billing/orchestration is required before this command can be enabled."
12056
- });
12057
- }
12058
11985
  const type = String(opts.type);
12059
11986
  if (!STOCK_TYPES.includes(type)) {
12060
11987
  fail({ code: "E_SCHEMA", message: `--type must be image|video; got ${String(opts.type)}` });
@@ -12071,42 +11998,35 @@ function registerStockSearch(parent, getTransport2) {
12071
11998
  }
12072
11999
  const limit = typeof opts.limit === "number" ? opts.limit : 10;
12073
12000
  const enabled = parseProviders(opts.providers !== void 0 ? String(opts.providers) : void 0, type);
12074
- const perProviderLimit = mode === "fanout" ? Math.max(1, Math.ceil(limit * 1.5 / enabled.length)) : limit;
12075
12001
  const searchOpts = {
12076
12002
  query: String(opts.query),
12077
12003
  type,
12078
12004
  ...opts.orientation !== void 0 ? { orientation: String(opts.orientation) } : {},
12079
12005
  ...typeof opts.minWidth === "number" ? { minWidth: opts.minWidth } : {},
12080
12006
  ...typeof opts.durationMin === "number" ? { durationMin: opts.durationMin } : {},
12081
- ...typeof opts.durationMax === "number" ? { durationMax: opts.durationMax } : {},
12082
- perProviderLimit
12007
+ ...typeof opts.durationMax === "number" ? { durationMax: opts.durationMax } : {}
12083
12008
  };
12084
12009
  const jobRef = randomUUID4();
12085
12010
  try {
12086
- const transport = getTransport2();
12087
- const searchFn = (name, o) => {
12088
- const provider = ALL_PROVIDERS[name];
12089
- if (!provider) throw new Error(`unknown stock provider: ${name}`);
12090
- return provider.search(o, transport);
12091
- };
12092
- const { results, queried, failed } = mode === "fanout" ? await searchFanout(enabled, searchOpts, limit, searchFn) : await searchSequential(enabled, searchOpts, limit, searchFn);
12093
- if (results.length === 0 && failed.length > 0 && failed.length === queried.length) {
12094
- fail({
12095
- code: "E_BACKEND",
12096
- message: `all stock-media providers failed for "${String(opts.query)}"`,
12097
- hint: "check gateway provider routes / quota; see providers_failed for per-provider reason.",
12098
- extra: { job_ref: jobRef, mode, providers_queried: queried, providers_failed: failed }
12099
- });
12100
- }
12101
- ok({
12102
- job_ref: jobRef,
12011
+ const transport = deps.getTransport();
12012
+ const body = {
12103
12013
  query: searchOpts.query,
12104
12014
  type,
12105
12015
  mode,
12106
- results,
12107
- providers_queried: queried,
12108
- providers_failed: failed
12109
- });
12016
+ limit,
12017
+ providers: enabled,
12018
+ ...searchOpts.orientation ? { orientation: searchOpts.orientation } : {},
12019
+ ...searchOpts.minWidth !== void 0 ? { min_width: searchOpts.minWidth } : {},
12020
+ ...searchOpts.durationMin !== void 0 ? { duration_min: searchOpts.durationMin } : {},
12021
+ ...searchOpts.durationMax !== void 0 ? { duration_max: searchOpts.durationMax } : {}
12022
+ };
12023
+ if (deps.projectToolCall) {
12024
+ const response2 = await transport.callTool({ toolRef: "stock-media.search", arguments: body, idempotencyKey: jobRef, confirmation: { kind: "typed-command" } }, { jobRef, retries: 1 });
12025
+ if (response2.status !== "completed") return ok({ ...response2, job_ref: jobRef });
12026
+ return ok({ job_ref: jobRef, ...response2.result });
12027
+ }
12028
+ const response = await transport.post("internal/stock/search", body, { jobRef, retries: 1 });
12029
+ ok({ job_ref: jobRef, ...response });
12110
12030
  } catch (err) {
12111
12031
  if (err instanceof TransportError) {
12112
12032
  fail({ code: err.code, message: err.message, extra: { ...err.extra ?? {}, job_ref: jobRef } });
@@ -12121,10 +12041,11 @@ function registerStockSearch(parent, getTransport2) {
12121
12041
  }
12122
12042
 
12123
12043
  // ../cli-core/src/commands/stock.ts
12124
- function registerStockCommands(program2, getTransport2) {
12044
+ function registerStockCommands(program2, depsOrTransport) {
12045
+ const deps = typeof depsOrTransport === "function" ? { getTransport: depsOrTransport } : depsOrTransport;
12125
12046
  const stock = program2.command("stock").description("Search and download public stock media (Pexels / Pixabay / Openverse) for b-roll.");
12126
- registerStockSearch(stock, getTransport2);
12127
- registerStockDownload(stock);
12047
+ registerStockSearch(stock, deps);
12048
+ registerStockDownload(stock, deps);
12128
12049
  }
12129
12050
 
12130
12051
  // ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
@@ -13993,7 +13914,7 @@ function buildProgram() {
13993
13914
  registerPollCommand(program2, getTransport2);
13994
13915
  registerKnowledgeCommands(program2, getTransport2);
13995
13916
  registerAssetCommands(program2, getTransport2);
13996
- registerStockCommands(program2, getTransport2);
13917
+ registerStockCommands(program2, actionDeps);
13997
13918
  return program2;
13998
13919
  }
13999
13920
  var invokedAsBin = isDirectExecution(import.meta.url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actionway/cli-dev",
3
- "version": "0.0.0-dev.32821683196.320940b928ff",
3
+ "version": "0.0.0-dev.32930928283.846129ead8ae",
4
4
  "description": "Actionway development CLI for dev.actionway.ai",
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/contracts": "0.1.0",
23
- "@actionway/cli-core": "0.1.0"
22
+ "@actionway/cli-core": "0.1.0",
23
+ "@actionway/contracts": "0.1.0"
24
24
  },
25
25
  "engines": {
26
26
  "node": ">=20"
@@ -36,9 +36,9 @@
36
36
  },
37
37
  "actionway": {
38
38
  "channel": "development",
39
- "source_sha": "320940b928ff5d1dd7f858e5b4f5200ed2449c9f",
40
- "run_id": 32821683196,
41
- "run_url": "https://github.com/PawLogic/actionway/actions/runs/32821683196",
39
+ "source_sha": "846129ead8ae1663efa69c2cb9ae0ad7d0df68aa",
40
+ "run_id": 32930928283,
41
+ "run_url": "https://github.com/PawLogic/actionway/actions/runs/32930928283",
42
42
  "gateway_url": "https://dev.actionway.ai"
43
43
  }
44
44
  }