@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.
- package/assets/skill/actionway/SKILL.md +1 -1
- package/assets/skill/actionway/references/capabilities/income-statement.md +1 -1
- package/assets/skill/actionway/references/capabilities/market-quote.md +1 -1
- package/assets/skill/actionway/references/capabilities/search-securities.md +1 -1
- package/assets/skill/actionway/references/capabilities/stock-download.md +1 -1
- package/dist/index.js +51 -130
- package/package.json +6 -6
|
@@ -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`) —
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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:"
|
|
11604
|
-
fail({ code: "E_SCHEMA", message: `--url must
|
|
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
|
-
|
|
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
|
|
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
|
-
"
|
|
12022
|
-
"
|
|
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 =
|
|
12087
|
-
const
|
|
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
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
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/
|
|
23
|
-
"@actionway/
|
|
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": "
|
|
40
|
-
"run_id":
|
|
41
|
-
"run_url": "https://github.com/PawLogic/actionway/actions/runs/
|
|
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
|
}
|