@tapi-dev/sdk 0.1.40 → 0.1.44
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 +36 -41
- package/dist/cli.d.ts +1 -6
- package/dist/cli.js +156 -245
- package/dist/studio-dev.d.ts +1 -0
- package/dist/studio-dev.js +312 -0
- package/dist/workspace.d.ts +0 -2
- package/dist/workspace.js +7 -100
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { createServer } from "node:http";
|
|
4
4
|
import { createServer as createNetServer } from "node:net";
|
|
5
5
|
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
-
import { createReadStream, createWriteStream, existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
6
|
+
import { createReadStream, createWriteStream, existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
7
7
|
import { mkdir, readFile, readdir, rename, rm, stat, statfs, unlink, writeFile } from "node:fs/promises";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { basename, dirname, join, resolve } from "node:path";
|
|
@@ -16,7 +16,8 @@ import { select } from "@inquirer/prompts";
|
|
|
16
16
|
import { Presets, SingleBar } from "cli-progress";
|
|
17
17
|
import pc from "yoctocolors";
|
|
18
18
|
import { TapiClient } from "./index.js";
|
|
19
|
-
import {
|
|
19
|
+
import { normalizeProjectValue, writeWorkspaceConfig, } from "./workspace.js";
|
|
20
|
+
import { openStudioDev } from "./studio-dev.js";
|
|
20
21
|
const DEFAULT_DOWNLOADS_BASE_URL = "https://d4xaf52nfwiok.cloudfront.net";
|
|
21
22
|
const DEFAULT_STUDIO_API_BASE_URL = "https://determined-motivation-production.up.railway.app";
|
|
22
23
|
const DEFAULT_STUDIO_AUTH_HTML_URL = "https://rsarlong-1f92fd.gitlab.io/auth.html";
|
|
@@ -240,12 +241,6 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
240
241
|
return addTappService(rest.slice(1));
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
|
-
if (subcommand === "queue") {
|
|
244
|
-
const queueCommand = rest[0] || "";
|
|
245
|
-
if (queueCommand === "add") {
|
|
246
|
-
return addTappQueue(rest.slice(1));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
244
|
console.error(`Unknown Tapp command: ${[subcommand, ...rest].filter(Boolean).join(" ")}`);
|
|
250
245
|
printTappHelp();
|
|
251
246
|
return 1;
|
|
@@ -270,6 +265,9 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
270
265
|
if (subcommand === "setup") {
|
|
271
266
|
return runRunnerSetup(rest);
|
|
272
267
|
}
|
|
268
|
+
if (subcommand === "gui") {
|
|
269
|
+
return openRunnerGui(rest);
|
|
270
|
+
}
|
|
273
271
|
if (subcommand === "slot") {
|
|
274
272
|
const slotCommand = rest[0] || "";
|
|
275
273
|
if (slotCommand === "set") {
|
|
@@ -328,6 +326,9 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
328
326
|
printStudioHelp();
|
|
329
327
|
return 0;
|
|
330
328
|
}
|
|
329
|
+
if (subcommand === "dev") {
|
|
330
|
+
return openStudioDev(rest);
|
|
331
|
+
}
|
|
331
332
|
const options = parseStudioOptions(rest);
|
|
332
333
|
if (subcommand === "install") {
|
|
333
334
|
return installStudio(options);
|
|
@@ -344,8 +345,6 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
344
345
|
}
|
|
345
346
|
export function parseStudioOptions(args) {
|
|
346
347
|
const raw = {};
|
|
347
|
-
let workspaceSearchRoot;
|
|
348
|
-
let skipWorkspace = false;
|
|
349
348
|
let projectIdSource;
|
|
350
349
|
let tappSelectionMode = "auto";
|
|
351
350
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -382,16 +381,13 @@ export function parseStudioOptions(args) {
|
|
|
382
381
|
continue;
|
|
383
382
|
}
|
|
384
383
|
if (arg === "--workspace") {
|
|
385
|
-
|
|
386
|
-
continue;
|
|
384
|
+
throw new Error("--workspace is retired. Use `tapi studio <tapp>` or `--tapp <id>`.");
|
|
387
385
|
}
|
|
388
386
|
if (arg.startsWith("--workspace=")) {
|
|
389
|
-
|
|
390
|
-
continue;
|
|
387
|
+
throw new Error("--workspace is retired. Use `tapi studio <tapp>` or `--tapp <id>`.");
|
|
391
388
|
}
|
|
392
389
|
if (arg === "--no-workspace") {
|
|
393
|
-
|
|
394
|
-
continue;
|
|
390
|
+
throw new Error("--no-workspace is retired. Studio no longer reads local workspace configs.");
|
|
395
391
|
}
|
|
396
392
|
if (arg === "--tapp") {
|
|
397
393
|
raw.projectId = normalizeProjectValue(requireOptionValue(args, ++index, "--tapp"), "tapp");
|
|
@@ -482,13 +478,11 @@ export function parseStudioOptions(args) {
|
|
|
482
478
|
}
|
|
483
479
|
throw new Error(`Unknown option: ${arg}`);
|
|
484
480
|
}
|
|
485
|
-
const workspace = skipWorkspace ? undefined : loadWorkspace(workspaceSearchRoot ?? process.cwd());
|
|
486
481
|
const channel = raw.channel ?? parseChannel(envString("TAPI_STUDIO_CHANNEL") ?? DEFAULT_CHANNEL);
|
|
487
482
|
const apiBaseUrl = normalizeHttpUrl(raw.apiBaseUrl
|
|
488
483
|
?? envString("TAPI_STUDIO_API_BASE_URL")
|
|
489
484
|
?? envString("TAPI_BASE_URL")
|
|
490
485
|
?? envString("TAPI_STUDIO_SERVER_URL")
|
|
491
|
-
?? workspace?.apiBaseUrl
|
|
492
486
|
?? DEFAULT_STUDIO_API_BASE_URL, "Studio API base URL");
|
|
493
487
|
const downloadsBaseUrl = normalizeHttpUrl(envString("TAPI_DOWNLOADS_BASE_URL") ?? DEFAULT_DOWNLOADS_BASE_URL, "TAPI_DOWNLOADS_BASE_URL");
|
|
494
488
|
const explicitManifestUrl = raw.manifestUrlOverride ?? envString("TAPI_STUDIO_MANIFEST_URL");
|
|
@@ -496,11 +490,11 @@ export function parseStudioOptions(args) {
|
|
|
496
490
|
? normalizeHttpUrl(explicitManifestUrl, "Studio manifest URL")
|
|
497
491
|
: `${downloadsBaseUrl.replace(/\/+$/, "")}/studio/channels/${channel}/latest.json`;
|
|
498
492
|
const envProjectId = envString("TAPI_PROJECT_ID");
|
|
499
|
-
const projectId = raw.projectId ?? envProjectId
|
|
493
|
+
const projectId = raw.projectId ?? envProjectId;
|
|
500
494
|
if (!projectIdSource && projectId) {
|
|
501
|
-
projectIdSource = raw.projectId ? "option" :
|
|
495
|
+
projectIdSource = raw.projectId ? "option" : "env";
|
|
502
496
|
}
|
|
503
|
-
const projectSlug = raw.projectSlug ?? envString("TAPI_PROJECT_SLUG")
|
|
497
|
+
const projectSlug = raw.projectSlug ?? envString("TAPI_PROJECT_SLUG");
|
|
504
498
|
const envInstallToken = envString("TAPI_STUDIO_INSTALL_TOKEN");
|
|
505
499
|
const installToken = raw.installToken ?? envInstallToken;
|
|
506
500
|
return {
|
|
@@ -515,20 +509,17 @@ export function parseStudioOptions(args) {
|
|
|
515
509
|
exePath: raw.exePath ?? envString("TAPI_STUDIO_EXE"),
|
|
516
510
|
installToken,
|
|
517
511
|
installTokenSource: raw.installToken ? "option" : installToken ? "env" : undefined,
|
|
518
|
-
workspace,
|
|
519
|
-
workspaceRoot: workspace?.root,
|
|
520
512
|
projectId,
|
|
521
513
|
projectSlug,
|
|
522
514
|
projectIdSource,
|
|
523
|
-
workspaceMode: Boolean(projectId
|
|
515
|
+
workspaceMode: Boolean(projectId),
|
|
524
516
|
tappSelectionMode,
|
|
525
517
|
};
|
|
526
518
|
}
|
|
527
519
|
function parseServiceOptions(args) {
|
|
528
520
|
let operation = "";
|
|
529
|
-
|
|
530
|
-
let
|
|
531
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
521
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
522
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
532
523
|
for (let index = 0; index < args.length; index += 1) {
|
|
533
524
|
const arg = args[index];
|
|
534
525
|
if (!arg)
|
|
@@ -566,7 +557,7 @@ function parseServiceOptions(args) {
|
|
|
566
557
|
throw new Error("services describe requires a service run like schwab.place_order.");
|
|
567
558
|
}
|
|
568
559
|
if (!projectId) {
|
|
569
|
-
throw new Error("services describe requires --project
|
|
560
|
+
throw new Error("services describe requires --project or TAPI_PROJECT_ID.");
|
|
570
561
|
}
|
|
571
562
|
return {
|
|
572
563
|
operation,
|
|
@@ -596,10 +587,9 @@ async function describeServiceOperation(args) {
|
|
|
596
587
|
}
|
|
597
588
|
}
|
|
598
589
|
function parseApiWorkspaceOptions(args) {
|
|
599
|
-
|
|
600
|
-
let
|
|
601
|
-
let
|
|
602
|
-
let catalogPath = workspace?.config.services?.catalog || ".tapi/services/catalog.json";
|
|
590
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
591
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
592
|
+
let catalogPath = "tapi-services.catalog.json";
|
|
603
593
|
for (let index = 0; index < args.length; index += 1) {
|
|
604
594
|
const arg = args[index];
|
|
605
595
|
if (!arg)
|
|
@@ -635,22 +625,18 @@ function parseApiWorkspaceOptions(args) {
|
|
|
635
625
|
throw new Error(`Unknown services option: ${arg}`);
|
|
636
626
|
}
|
|
637
627
|
if (!projectId) {
|
|
638
|
-
throw new Error("services command requires --project
|
|
628
|
+
throw new Error("services command requires --project or TAPI_PROJECT_ID.");
|
|
639
629
|
}
|
|
640
|
-
const root = workspace?.root || process.cwd();
|
|
641
630
|
return {
|
|
642
631
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
643
632
|
projectId,
|
|
644
|
-
catalogPath: resolve(
|
|
633
|
+
catalogPath: resolve(process.cwd(), catalogPath),
|
|
645
634
|
};
|
|
646
635
|
}
|
|
647
636
|
async function syncServiceCatalog(args) {
|
|
648
637
|
try {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
await writeJsonFile(options.catalogPath, catalog);
|
|
652
|
-
console.log(`Synced Tapi service-run catalog: ${options.catalogPath}`);
|
|
653
|
-
return 0;
|
|
638
|
+
void args;
|
|
639
|
+
throw new Error("services sync is retired. Service-run contracts are server-backed; use `tapi services describe <service.call>`.");
|
|
654
640
|
}
|
|
655
641
|
catch (error) {
|
|
656
642
|
console.error(formatError(error));
|
|
@@ -658,8 +644,7 @@ async function syncServiceCatalog(args) {
|
|
|
658
644
|
}
|
|
659
645
|
}
|
|
660
646
|
function parseTappServiceAddOptions(args) {
|
|
661
|
-
|
|
662
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
647
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
663
648
|
let tappId = "";
|
|
664
649
|
let serviceCall = "";
|
|
665
650
|
let serviceMapId = "";
|
|
@@ -740,9 +725,8 @@ function parseTappServiceAddOptions(args) {
|
|
|
740
725
|
};
|
|
741
726
|
}
|
|
742
727
|
function parseTappCreateOptions(args) {
|
|
743
|
-
|
|
744
|
-
let
|
|
745
|
-
let tappId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
728
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
729
|
+
let tappId = envString("TAPI_PROJECT_ID") || "";
|
|
746
730
|
let name = "";
|
|
747
731
|
for (let index = 0; index < args.length; index += 1) {
|
|
748
732
|
const arg = args[index];
|
|
@@ -862,9 +846,7 @@ async function postTappServiceAdd(options) {
|
|
|
862
846
|
return body ?? {};
|
|
863
847
|
}
|
|
864
848
|
function parseQueueCreateOptions(args) {
|
|
865
|
-
|
|
866
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
867
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
849
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
868
850
|
let displayName = "";
|
|
869
851
|
let maxSlots = 8;
|
|
870
852
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -883,14 +865,6 @@ function parseQueueCreateOptions(args) {
|
|
|
883
865
|
apiBaseUrl = arg.slice("--server=".length);
|
|
884
866
|
continue;
|
|
885
867
|
}
|
|
886
|
-
if (arg === "--project") {
|
|
887
|
-
projectId = normalizeProjectValue(requireOptionValue(args, ++index, "--project"), "project");
|
|
888
|
-
continue;
|
|
889
|
-
}
|
|
890
|
-
if (arg.startsWith("--project=")) {
|
|
891
|
-
projectId = normalizeProjectValue(arg.slice("--project=".length), "project");
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
868
|
if (arg === "--max-slots") {
|
|
895
869
|
maxSlots = parsePositiveInteger(requireOptionValue(args, ++index, "--max-slots"), "--max-slots");
|
|
896
870
|
continue;
|
|
@@ -910,61 +884,12 @@ function parseQueueCreateOptions(args) {
|
|
|
910
884
|
}
|
|
911
885
|
return {
|
|
912
886
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
913
|
-
projectId,
|
|
914
887
|
displayName,
|
|
915
888
|
maxSlots,
|
|
916
889
|
};
|
|
917
890
|
}
|
|
918
|
-
function parseTappQueueAddOptions(args) {
|
|
919
|
-
const workspace = loadWorkspace();
|
|
920
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
921
|
-
let tappId = "";
|
|
922
|
-
let queueId = "";
|
|
923
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
924
|
-
const arg = args[index];
|
|
925
|
-
if (!arg)
|
|
926
|
-
continue;
|
|
927
|
-
if (arg === "--api-base-url" || arg === "--server") {
|
|
928
|
-
apiBaseUrl = requireOptionValue(args, ++index, arg);
|
|
929
|
-
continue;
|
|
930
|
-
}
|
|
931
|
-
if (arg.startsWith("--api-base-url=")) {
|
|
932
|
-
apiBaseUrl = arg.slice("--api-base-url=".length);
|
|
933
|
-
continue;
|
|
934
|
-
}
|
|
935
|
-
if (arg.startsWith("--server=")) {
|
|
936
|
-
apiBaseUrl = arg.slice("--server=".length);
|
|
937
|
-
continue;
|
|
938
|
-
}
|
|
939
|
-
if (arg.startsWith("--")) {
|
|
940
|
-
throw new Error(`Unknown tapp queue add option: ${arg}`);
|
|
941
|
-
}
|
|
942
|
-
if (!tappId) {
|
|
943
|
-
tappId = normalizeProjectValue(arg, "tapp");
|
|
944
|
-
continue;
|
|
945
|
-
}
|
|
946
|
-
if (!queueId) {
|
|
947
|
-
queueId = arg.trim();
|
|
948
|
-
continue;
|
|
949
|
-
}
|
|
950
|
-
throw new Error(`Unexpected tapp queue add argument: ${arg}`);
|
|
951
|
-
}
|
|
952
|
-
if (!tappId) {
|
|
953
|
-
throw new Error("tapp queue add requires a Tapp id.");
|
|
954
|
-
}
|
|
955
|
-
if (!queueId) {
|
|
956
|
-
throw new Error("tapp queue add requires a queue id.");
|
|
957
|
-
}
|
|
958
|
-
return {
|
|
959
|
-
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
960
|
-
tappId,
|
|
961
|
-
queueId,
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
891
|
function parseRunnerSlotSetOptions(args) {
|
|
965
|
-
|
|
966
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
967
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
892
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
968
893
|
let runnerId = "";
|
|
969
894
|
let slotIndex = 0;
|
|
970
895
|
let queueId = "";
|
|
@@ -984,14 +909,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
984
909
|
apiBaseUrl = arg.slice("--server=".length);
|
|
985
910
|
continue;
|
|
986
911
|
}
|
|
987
|
-
if (arg === "--project") {
|
|
988
|
-
projectId = normalizeProjectValue(requireOptionValue(args, ++index, "--project"), "project");
|
|
989
|
-
continue;
|
|
990
|
-
}
|
|
991
|
-
if (arg.startsWith("--project=")) {
|
|
992
|
-
projectId = normalizeProjectValue(arg.slice("--project=".length), "project");
|
|
993
|
-
continue;
|
|
994
|
-
}
|
|
995
912
|
if (arg.startsWith("--")) {
|
|
996
913
|
throw new Error(`Unknown runner slot set option: ${arg}`);
|
|
997
914
|
}
|
|
@@ -1009,9 +926,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
1009
926
|
}
|
|
1010
927
|
throw new Error(`Unexpected runner slot set argument: ${arg}`);
|
|
1011
928
|
}
|
|
1012
|
-
if (!projectId) {
|
|
1013
|
-
throw new Error("runner slot set requires --project or TAPI_PROJECT_ID.");
|
|
1014
|
-
}
|
|
1015
929
|
if (!runnerId) {
|
|
1016
930
|
throw new Error("runner slot set requires a runner id.");
|
|
1017
931
|
}
|
|
@@ -1023,7 +937,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
1023
937
|
}
|
|
1024
938
|
return {
|
|
1025
939
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
1026
|
-
projectId,
|
|
1027
940
|
runnerId,
|
|
1028
941
|
slotIndex,
|
|
1029
942
|
queueId,
|
|
@@ -1041,18 +954,6 @@ async function createQueue(args) {
|
|
|
1041
954
|
return 1;
|
|
1042
955
|
}
|
|
1043
956
|
}
|
|
1044
|
-
async function addTappQueue(args) {
|
|
1045
|
-
try {
|
|
1046
|
-
const options = await withSdkAuth(parseTappQueueAddOptions(args));
|
|
1047
|
-
const result = await withCliSpinner(`Attaching Tapi queue ${options.queueId} to ${options.tappId}`, () => postTappQueueAdd(options));
|
|
1048
|
-
console.log(JSON.stringify(result, null, 2));
|
|
1049
|
-
return 0;
|
|
1050
|
-
}
|
|
1051
|
-
catch (error) {
|
|
1052
|
-
console.error(formatError(error));
|
|
1053
|
-
return 1;
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
957
|
async function setRunnerSlot(args) {
|
|
1057
958
|
try {
|
|
1058
959
|
const options = await withSdkAuth(parseRunnerSlotSetOptions(args));
|
|
@@ -1066,7 +967,7 @@ async function setRunnerSlot(args) {
|
|
|
1066
967
|
}
|
|
1067
968
|
}
|
|
1068
969
|
async function postQueueCreate(options) {
|
|
1069
|
-
const headers = sdkJsonHeaders(options.authToken
|
|
970
|
+
const headers = sdkJsonHeaders(options.authToken);
|
|
1070
971
|
const response = await fetch(`${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/queues`, {
|
|
1071
972
|
method: "POST",
|
|
1072
973
|
headers,
|
|
@@ -1082,23 +983,10 @@ async function postQueueCreate(options) {
|
|
|
1082
983
|
}
|
|
1083
984
|
return body ?? {};
|
|
1084
985
|
}
|
|
1085
|
-
async function postTappQueueAdd(options) {
|
|
1086
|
-
const response = await fetch(`${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/tapps/${encodeURIComponent(options.tappId)}/queues`, {
|
|
1087
|
-
method: "POST",
|
|
1088
|
-
headers: sdkJsonHeaders(options.authToken, options.tappId),
|
|
1089
|
-
body: JSON.stringify({ queueId: options.queueId }),
|
|
1090
|
-
});
|
|
1091
|
-
const body = await readJsonBody(response);
|
|
1092
|
-
if (!response.ok) {
|
|
1093
|
-
const detail = body?.detail ?? body?.error ?? body ?? `HTTP ${response.status}`;
|
|
1094
|
-
throw new Error(typeof detail === "string" ? detail : JSON.stringify(detail));
|
|
1095
|
-
}
|
|
1096
|
-
return body ?? {};
|
|
1097
|
-
}
|
|
1098
986
|
async function putRunnerSlot(options) {
|
|
1099
987
|
const response = await fetch(`${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/runners/${encodeURIComponent(options.runnerId)}/slots/${encodeURIComponent(String(options.slotIndex))}`, {
|
|
1100
988
|
method: "PUT",
|
|
1101
|
-
headers: sdkJsonHeaders(options.authToken
|
|
989
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1102
990
|
body: JSON.stringify({ queueId: options.queueId }),
|
|
1103
991
|
});
|
|
1104
992
|
const body = await readJsonBody(response);
|
|
@@ -1109,9 +997,7 @@ async function putRunnerSlot(options) {
|
|
|
1109
997
|
return body ?? {};
|
|
1110
998
|
}
|
|
1111
999
|
export function parseRunnerSetupOptions(args) {
|
|
1112
|
-
|
|
1113
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
1114
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
1000
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1115
1001
|
let runnerId = envString("TAPI_RUNNER_ID") || "";
|
|
1116
1002
|
let port = Number(envString("TAPI_RUNNER_SETUP_PORT") || "17687");
|
|
1117
1003
|
let openBrowser = true;
|
|
@@ -1131,14 +1017,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1131
1017
|
apiBaseUrl = arg.slice("--server=".length);
|
|
1132
1018
|
continue;
|
|
1133
1019
|
}
|
|
1134
|
-
if (arg === "--project") {
|
|
1135
|
-
projectId = normalizeProjectValue(requireOptionValue(args, ++index, "--project"), "project");
|
|
1136
|
-
continue;
|
|
1137
|
-
}
|
|
1138
|
-
if (arg.startsWith("--project=")) {
|
|
1139
|
-
projectId = normalizeProjectValue(arg.slice("--project=".length), "project");
|
|
1140
|
-
continue;
|
|
1141
|
-
}
|
|
1142
1020
|
if (arg === "--runner-id") {
|
|
1143
1021
|
runnerId = requireOptionValue(args, ++index, "--runner-id").trim();
|
|
1144
1022
|
continue;
|
|
@@ -1168,9 +1046,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1168
1046
|
}
|
|
1169
1047
|
throw new Error(`Unexpected runner setup argument: ${arg}`);
|
|
1170
1048
|
}
|
|
1171
|
-
if (!projectId) {
|
|
1172
|
-
throw new Error("runner setup requires --project or TAPI_PROJECT_ID.");
|
|
1173
|
-
}
|
|
1174
1049
|
if (!runnerId) {
|
|
1175
1050
|
throw new Error("runner setup requires --runner-id or TAPI_RUNNER_ID.");
|
|
1176
1051
|
}
|
|
@@ -1179,7 +1054,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1179
1054
|
}
|
|
1180
1055
|
return {
|
|
1181
1056
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
1182
|
-
projectId,
|
|
1183
1057
|
runnerId,
|
|
1184
1058
|
port,
|
|
1185
1059
|
openBrowser,
|
|
@@ -1203,6 +1077,78 @@ async function runRunnerSetup(args) {
|
|
|
1203
1077
|
return 1;
|
|
1204
1078
|
}
|
|
1205
1079
|
}
|
|
1080
|
+
async function openRunnerGui(args) {
|
|
1081
|
+
try {
|
|
1082
|
+
if (hasHelpFlag(args)) {
|
|
1083
|
+
printRunnerHelp();
|
|
1084
|
+
return 0;
|
|
1085
|
+
}
|
|
1086
|
+
if (args.some((arg) => arg && arg.startsWith("-"))) {
|
|
1087
|
+
throw new Error(`Unknown runner gui option: ${args.find((arg) => arg.startsWith("-"))}`);
|
|
1088
|
+
}
|
|
1089
|
+
const executable = findInstalledRunnerGui();
|
|
1090
|
+
if (!executable) {
|
|
1091
|
+
throw new Error("Tapi Runner GUI is not installed. Run `tapi service install --channel pilot`, then retry.");
|
|
1092
|
+
}
|
|
1093
|
+
const child = spawn(executable, [], {
|
|
1094
|
+
detached: true,
|
|
1095
|
+
stdio: "ignore",
|
|
1096
|
+
windowsHide: false,
|
|
1097
|
+
});
|
|
1098
|
+
child.unref();
|
|
1099
|
+
console.log(`Opened Tapi Runner: ${executable}`);
|
|
1100
|
+
return 0;
|
|
1101
|
+
}
|
|
1102
|
+
catch (error) {
|
|
1103
|
+
console.error(formatError(error));
|
|
1104
|
+
return 1;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
function findInstalledRunnerGui() {
|
|
1108
|
+
const explicit = envString("TAPI_RUNNER_GUI_PATH");
|
|
1109
|
+
if (explicit && existsSync(explicit)) {
|
|
1110
|
+
return explicit;
|
|
1111
|
+
}
|
|
1112
|
+
const candidates = [];
|
|
1113
|
+
const localCandidate = join(getDefaultTapiDataDir(), "Service", "releases");
|
|
1114
|
+
const programData = envString("ProgramData") || "C:\\ProgramData";
|
|
1115
|
+
const roots = [
|
|
1116
|
+
join(programData, "Tapi", "Service", "releases"),
|
|
1117
|
+
localCandidate,
|
|
1118
|
+
resolve(process.cwd(), "build", "v2-processes", "runtime"),
|
|
1119
|
+
];
|
|
1120
|
+
for (const root of roots) {
|
|
1121
|
+
if (!existsSync(root))
|
|
1122
|
+
continue;
|
|
1123
|
+
const direct = join(root, "tapi-runner-gui.exe");
|
|
1124
|
+
if (existsSync(direct)) {
|
|
1125
|
+
candidates.push(direct);
|
|
1126
|
+
}
|
|
1127
|
+
let entries = [];
|
|
1128
|
+
try {
|
|
1129
|
+
entries = readdirSync(root);
|
|
1130
|
+
}
|
|
1131
|
+
catch {
|
|
1132
|
+
continue;
|
|
1133
|
+
}
|
|
1134
|
+
for (const entry of entries) {
|
|
1135
|
+
const nested = join(root, String(entry), "tapi-runner-gui.exe");
|
|
1136
|
+
if (existsSync(nested)) {
|
|
1137
|
+
candidates.push(nested);
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const unique = Array.from(new Set(candidates));
|
|
1142
|
+
unique.sort((left, right) => {
|
|
1143
|
+
try {
|
|
1144
|
+
return statSync(right).mtimeMs - statSync(left).mtimeMs;
|
|
1145
|
+
}
|
|
1146
|
+
catch {
|
|
1147
|
+
return 0;
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1150
|
+
return unique[0] || "";
|
|
1151
|
+
}
|
|
1206
1152
|
export async function startRunnerSetupServer(options, fetchImpl = fetch) {
|
|
1207
1153
|
const server = createServer((request, response) => {
|
|
1208
1154
|
void handleRunnerSetupRequest(request, response, options, fetchImpl);
|
|
@@ -1225,9 +1171,9 @@ export async function executeRunnerSetupAction(options, action, fetchImpl = fetc
|
|
|
1225
1171
|
if (!queueId) {
|
|
1226
1172
|
queue = await sdkJsonRequest(fetchImpl, `${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/queues`, {
|
|
1227
1173
|
method: "POST",
|
|
1228
|
-
headers: sdkJsonHeaders(options.authToken
|
|
1174
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1229
1175
|
body: JSON.stringify({
|
|
1230
|
-
displayName: String(action.displayName || `${options.
|
|
1176
|
+
displayName: String(action.displayName || `${options.runnerId} queue`).trim(),
|
|
1231
1177
|
maxSlots,
|
|
1232
1178
|
}),
|
|
1233
1179
|
});
|
|
@@ -1236,24 +1182,18 @@ export async function executeRunnerSetupAction(options, action, fetchImpl = fetc
|
|
|
1236
1182
|
if (!queueId) {
|
|
1237
1183
|
throw new Error("Runner setup needs an existing queue id or a created queue response with queueId.");
|
|
1238
1184
|
}
|
|
1239
|
-
const attachment = await sdkJsonRequest(fetchImpl, `${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/tapps/${encodeURIComponent(options.projectId)}/queues`, {
|
|
1240
|
-
method: "POST",
|
|
1241
|
-
headers: sdkJsonHeaders(options.authToken, options.projectId),
|
|
1242
|
-
body: JSON.stringify({ queueId }),
|
|
1243
|
-
});
|
|
1244
1185
|
const slots = [];
|
|
1245
1186
|
for (let offset = 0; offset < slotCount; offset += 1) {
|
|
1246
1187
|
const slotIndex = slotStart + offset;
|
|
1247
1188
|
slots.push(await sdkJsonRequest(fetchImpl, `${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/runners/${encodeURIComponent(options.runnerId)}/slots/${encodeURIComponent(String(slotIndex))}`, {
|
|
1248
1189
|
method: "PUT",
|
|
1249
|
-
headers: sdkJsonHeaders(options.authToken
|
|
1190
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1250
1191
|
body: JSON.stringify({ queueId }),
|
|
1251
1192
|
}));
|
|
1252
1193
|
}
|
|
1253
1194
|
return {
|
|
1254
1195
|
queueId,
|
|
1255
1196
|
queue: queueId && !Object.keys(queue).length ? { queueId } : queue,
|
|
1256
|
-
attachment,
|
|
1257
1197
|
slots,
|
|
1258
1198
|
};
|
|
1259
1199
|
}
|
|
@@ -1267,7 +1207,6 @@ async function handleRunnerSetupRequest(request, response, options, fetchImpl) {
|
|
|
1267
1207
|
if (request.method === "GET" && url.pathname === "/api/status") {
|
|
1268
1208
|
sendJson(response, 200, {
|
|
1269
1209
|
apiBaseUrl: options.apiBaseUrl,
|
|
1270
|
-
projectId: options.projectId,
|
|
1271
1210
|
runnerId: options.runnerId,
|
|
1272
1211
|
});
|
|
1273
1212
|
return;
|
|
@@ -1285,7 +1224,7 @@ async function handleRunnerSetupRequest(request, response, options, fetchImpl) {
|
|
|
1285
1224
|
}
|
|
1286
1225
|
}
|
|
1287
1226
|
function runnerSetupHtml(options) {
|
|
1288
|
-
const displayName = `${options.
|
|
1227
|
+
const displayName = `${options.runnerId} queue`;
|
|
1289
1228
|
return `<!doctype html>
|
|
1290
1229
|
<html lang="en">
|
|
1291
1230
|
<head>
|
|
@@ -1339,7 +1278,6 @@ code { word-break: break-all; }
|
|
|
1339
1278
|
<h2>Target</h2>
|
|
1340
1279
|
<dl>
|
|
1341
1280
|
<dt>Server</dt><dd><code>${escapeHtml(options.apiBaseUrl)}</code></dd>
|
|
1342
|
-
<dt>Tapp</dt><dd><code>${escapeHtml(options.projectId)}</code></dd>
|
|
1343
1281
|
<dt>Runner</dt><dd><code>${escapeHtml(options.runnerId)}</code></dd>
|
|
1344
1282
|
</dl>
|
|
1345
1283
|
</aside>
|
|
@@ -1425,11 +1363,10 @@ function parseNonNegativeInteger(value, label) {
|
|
|
1425
1363
|
return parsed;
|
|
1426
1364
|
}
|
|
1427
1365
|
function parseTriggerSyncOptions(args) {
|
|
1428
|
-
|
|
1429
|
-
let
|
|
1430
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
1366
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1367
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
1431
1368
|
let configPath = "";
|
|
1432
|
-
const root =
|
|
1369
|
+
const root = process.cwd();
|
|
1433
1370
|
for (let index = 0; index < args.length; index += 1) {
|
|
1434
1371
|
const arg = args[index];
|
|
1435
1372
|
if (!arg)
|
|
@@ -1465,7 +1402,7 @@ function parseTriggerSyncOptions(args) {
|
|
|
1465
1402
|
throw new Error(`Unknown triggers option: ${arg}`);
|
|
1466
1403
|
}
|
|
1467
1404
|
if (!projectId) {
|
|
1468
|
-
throw new Error("triggers sync requires --project
|
|
1405
|
+
throw new Error("triggers sync requires --project or TAPI_PROJECT_ID.");
|
|
1469
1406
|
}
|
|
1470
1407
|
return {
|
|
1471
1408
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
@@ -1500,9 +1437,8 @@ async function syncServiceTriggers(args) {
|
|
|
1500
1437
|
}
|
|
1501
1438
|
}
|
|
1502
1439
|
function parseSessionsOptions(args) {
|
|
1503
|
-
|
|
1504
|
-
let
|
|
1505
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
1440
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1441
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
1506
1442
|
let site = "";
|
|
1507
1443
|
let sessionId = "";
|
|
1508
1444
|
let json = false;
|
|
@@ -1558,7 +1494,7 @@ function parseSessionsOptions(args) {
|
|
|
1558
1494
|
throw new Error(`Unexpected sessions argument: ${arg}`);
|
|
1559
1495
|
}
|
|
1560
1496
|
if (!projectId) {
|
|
1561
|
-
throw new Error("sessions command requires --project
|
|
1497
|
+
throw new Error("sessions command requires --project or TAPI_PROJECT_ID.");
|
|
1562
1498
|
}
|
|
1563
1499
|
return {
|
|
1564
1500
|
sessionId,
|
|
@@ -3093,7 +3029,6 @@ function normalizeTappList(body) {
|
|
|
3093
3029
|
tappId,
|
|
3094
3030
|
name: typeof item.name === "string" && item.name.trim() ? item.name.trim() : tappId,
|
|
3095
3031
|
serviceCount: normalizeNonnegativeInteger(item.serviceCount),
|
|
3096
|
-
queueCount: normalizeNonnegativeInteger(item.queueCount),
|
|
3097
3032
|
});
|
|
3098
3033
|
}
|
|
3099
3034
|
return tapps;
|
|
@@ -3114,7 +3049,6 @@ function preferredStudioTappId(options, lastSelection, tapps) {
|
|
|
3114
3049
|
function formatTappChoice(tapp) {
|
|
3115
3050
|
const details = [
|
|
3116
3051
|
`${tapp.serviceCount} service${tapp.serviceCount === 1 ? "" : "s"}`,
|
|
3117
|
-
`${tapp.queueCount} queue${tapp.queueCount === 1 ? "" : "s"}`,
|
|
3118
3052
|
].join(", ");
|
|
3119
3053
|
return tapp.name === tapp.tappId
|
|
3120
3054
|
? `${tapp.tappId} ${pc.dim(`(${details})`)}`
|
|
@@ -3317,8 +3251,6 @@ async function launchPortableStudioServer(exePath, options, manifest) {
|
|
|
3317
3251
|
apiBaseUrl: options.apiBaseUrl,
|
|
3318
3252
|
projectId: options.projectId,
|
|
3319
3253
|
tappId: options.projectId,
|
|
3320
|
-
workspaceRoot: options.workspaceRoot,
|
|
3321
|
-
workspaceConfig: options.workspace?.configPath,
|
|
3322
3254
|
manifestVersion: manifest.version,
|
|
3323
3255
|
updatedAt: new Date().toISOString(),
|
|
3324
3256
|
});
|
|
@@ -3486,7 +3418,6 @@ async function runDoctor(options) {
|
|
|
3486
3418
|
console.log(`Studio channel: ${options.channel}`);
|
|
3487
3419
|
console.log(`Studio manifest: ${options.manifestUrl}`);
|
|
3488
3420
|
console.log(`Studio cache: ${options.cacheDir}`);
|
|
3489
|
-
console.log(`Workspace: ${options.workspaceRoot ?? "not found"}`);
|
|
3490
3421
|
console.log(`Project: ${options.projectId ?? "not set"}`);
|
|
3491
3422
|
try {
|
|
3492
3423
|
const manifest = await withCliSpinner("Fetching latest Tapi Studio manifest", () => fetchStudioManifest(options.manifestUrl));
|
|
@@ -3507,12 +3438,6 @@ function buildStudioLaunchEnv(options) {
|
|
|
3507
3438
|
const env = { ...process.env };
|
|
3508
3439
|
env.TAPI_STUDIO_API_BASE_URL = options.apiBaseUrl;
|
|
3509
3440
|
env.TAPI_BASE_URL = env.TAPI_BASE_URL || options.apiBaseUrl;
|
|
3510
|
-
if (options.workspaceRoot) {
|
|
3511
|
-
env.TAPI_WORKSPACE_ROOT = options.workspaceRoot;
|
|
3512
|
-
}
|
|
3513
|
-
if (options.workspace?.configPath) {
|
|
3514
|
-
env.TAPI_WORKSPACE_CONFIG = options.workspace.configPath;
|
|
3515
|
-
}
|
|
3516
3441
|
if (options.projectId) {
|
|
3517
3442
|
env.TAPI_PROJECT_ID = options.projectId;
|
|
3518
3443
|
}
|
|
@@ -3893,7 +3818,6 @@ export function studioInstanceRecordPathForOptions(options) {
|
|
|
3893
3818
|
.update(JSON.stringify({
|
|
3894
3819
|
apiBaseUrl: comparableHttpUrl(options.apiBaseUrl),
|
|
3895
3820
|
projectId: options.projectId ?? "",
|
|
3896
|
-
workspaceRoot: comparableFsPath(options.workspaceRoot ?? ""),
|
|
3897
3821
|
}))
|
|
3898
3822
|
.digest("hex")
|
|
3899
3823
|
.slice(0, 24);
|
|
@@ -3955,8 +3879,6 @@ async function readStudioInstanceRecord(options) {
|
|
|
3955
3879
|
apiBaseUrl: typeof parsed.apiBaseUrl === "string" ? parsed.apiBaseUrl : "",
|
|
3956
3880
|
projectId: typeof parsed.projectId === "string" ? parsed.projectId : undefined,
|
|
3957
3881
|
tappId: typeof parsed.tappId === "string" ? parsed.tappId : undefined,
|
|
3958
|
-
workspaceRoot: typeof parsed.workspaceRoot === "string" ? parsed.workspaceRoot : undefined,
|
|
3959
|
-
workspaceConfig: typeof parsed.workspaceConfig === "string" ? parsed.workspaceConfig : undefined,
|
|
3960
3882
|
manifestVersion: typeof parsed.manifestVersion === "string" ? parsed.manifestVersion : undefined,
|
|
3961
3883
|
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : "",
|
|
3962
3884
|
};
|
|
@@ -3977,11 +3899,6 @@ function studioInstanceIdentityMatches(identity, options) {
|
|
|
3977
3899
|
if (expectedProject && actualProject && actualProject !== expectedProject) {
|
|
3978
3900
|
return false;
|
|
3979
3901
|
}
|
|
3980
|
-
const expectedWorkspace = comparableFsPath(options.workspaceRoot ?? "");
|
|
3981
|
-
const actualWorkspace = comparableFsPath(typeof identity.workspaceRoot === "string" ? identity.workspaceRoot : "");
|
|
3982
|
-
if (expectedWorkspace && actualWorkspace && actualWorkspace !== expectedWorkspace) {
|
|
3983
|
-
return false;
|
|
3984
|
-
}
|
|
3985
3902
|
const expectedApiBaseUrl = comparableHttpUrl(options.apiBaseUrl);
|
|
3986
3903
|
const actualApiBaseUrl = comparableHttpUrl(typeof identity.apiBaseUrl === "string" ? identity.apiBaseUrl : "");
|
|
3987
3904
|
if (expectedApiBaseUrl && actualApiBaseUrl && actualApiBaseUrl !== expectedApiBaseUrl) {
|
|
@@ -3992,10 +3909,6 @@ function studioInstanceIdentityMatches(identity, options) {
|
|
|
3992
3909
|
function comparableHttpUrl(value) {
|
|
3993
3910
|
return String(value || "").trim().replace(/\/+$/, "").toLowerCase();
|
|
3994
3911
|
}
|
|
3995
|
-
function comparableFsPath(value) {
|
|
3996
|
-
const trimmed = String(value || "").trim();
|
|
3997
|
-
return trimmed ? resolve(trimmed).toLowerCase() : "";
|
|
3998
|
-
}
|
|
3999
3912
|
function getDefaultTapiDataDir() {
|
|
4000
3913
|
if (process.platform === "win32") {
|
|
4001
3914
|
const localAppData = process.env.LOCALAPPDATA
|
|
@@ -4506,7 +4419,9 @@ async function isTapiManagedReleaseDir(directory) {
|
|
|
4506
4419
|
return Array.isArray(entries) && entries.length === 0;
|
|
4507
4420
|
}
|
|
4508
4421
|
function looksLikeTapiServiceReleaseDir(directory) {
|
|
4509
|
-
|
|
4422
|
+
const hasServiceHost = existsSync(join(directory, "tapi-service-host.exe"))
|
|
4423
|
+
|| existsSync(join(directory, "tapi-service-host", "tapi-service-host.exe"));
|
|
4424
|
+
return (hasServiceHost
|
|
4510
4425
|
&& existsSync(join(directory, "install_tapi_service.ps1"))
|
|
4511
4426
|
&& (existsSync(join(directory, "tapi-service-worker.exe"))
|
|
4512
4427
|
|| existsSync(join(directory, "tapi-service-worker", "tapi-service-worker.exe"))));
|
|
@@ -4693,10 +4608,9 @@ function printHelp() {
|
|
|
4693
4608
|
|
|
4694
4609
|
Usage:
|
|
4695
4610
|
tapi login
|
|
4696
|
-
tapi init --project PROJECT
|
|
4697
|
-
tapi link --project PROJECT
|
|
4698
4611
|
tapi studio install [--channel pilot] [--api-base-url URL]
|
|
4699
4612
|
tapi studio
|
|
4613
|
+
tapi studio dev --tapp <tapp>
|
|
4700
4614
|
tapi studio --tapp <tapp>
|
|
4701
4615
|
tapi studio --select
|
|
4702
4616
|
tapi studio open
|
|
@@ -4704,20 +4618,19 @@ Usage:
|
|
|
4704
4618
|
tapi tapp create <tapp>
|
|
4705
4619
|
tapi queue create [display-name]
|
|
4706
4620
|
tapi tapp service add <tapp> <service.call> --service-map ID --entry ENTRY
|
|
4707
|
-
tapi
|
|
4708
|
-
tapi runner setup --runner-id RUNNER
|
|
4621
|
+
tapi runner gui
|
|
4622
|
+
tapi runner setup --runner-id RUNNER
|
|
4709
4623
|
tapi runner slot set <runner-id> <slot-index> <queue-id>
|
|
4710
4624
|
tapi services describe <servicemap.run>
|
|
4711
|
-
tapi
|
|
4712
|
-
tapi triggers sync
|
|
4625
|
+
tapi triggers sync
|
|
4713
4626
|
tapi sessions
|
|
4714
4627
|
tapi service status
|
|
4715
4628
|
tapi doctor
|
|
4716
4629
|
|
|
4717
4630
|
Commands:
|
|
4718
4631
|
login Sign in with Firebase credentials for SDK commands
|
|
4719
|
-
init
|
|
4720
|
-
link
|
|
4632
|
+
init Retired; use tapp create/login/studio instead
|
|
4633
|
+
link Retired; use explicit Tapp commands instead
|
|
4721
4634
|
studio install Download, verify, and run the Tapi Studio installer
|
|
4722
4635
|
studio Open Tapi Studio for a selected Tapp
|
|
4723
4636
|
studio open Open Tapi Studio for a selected Tapp
|
|
@@ -4726,12 +4639,12 @@ Commands:
|
|
|
4726
4639
|
queue create Create a queue for service-run routing
|
|
4727
4640
|
tapp service add
|
|
4728
4641
|
Add a ServiceMap-backed service call to a Tapp
|
|
4729
|
-
|
|
4730
|
-
runner setup Open the local
|
|
4642
|
+
runner gui Open the installed desktop Runner app
|
|
4643
|
+
runner setup Open the legacy local browser queue/slot setup UI
|
|
4731
4644
|
runner slot set Assign a queue to a runner slot
|
|
4732
4645
|
services describe
|
|
4733
4646
|
Print a ServiceMap service-run input/output contract
|
|
4734
|
-
services sync
|
|
4647
|
+
services sync Retired; service-run contracts are server-backed
|
|
4735
4648
|
triggers sync Upsert service triggers from tapi.config
|
|
4736
4649
|
sessions List dev-mode API sessions and open takeover sessions
|
|
4737
4650
|
service Inspect or control the local Tapi Windows service
|
|
@@ -4753,7 +4666,6 @@ function printTappHelp() {
|
|
|
4753
4666
|
Usage:
|
|
4754
4667
|
tapi tapp create <tapp> [--name NAME] [--api-base-url URL]
|
|
4755
4668
|
tapi tapp service add <tapp> <service.call> --service-map ID --entry ENTRY [--api-base-url URL]
|
|
4756
|
-
tapi tapp queue add <tapp> <queue-id> [--api-base-url URL]
|
|
4757
4669
|
|
|
4758
4670
|
Options:
|
|
4759
4671
|
--api-base-url <url> Tapi API base URL
|
|
@@ -4769,12 +4681,11 @@ function printQueueHelp() {
|
|
|
4769
4681
|
console.log(`Tapi queue commands
|
|
4770
4682
|
|
|
4771
4683
|
Usage:
|
|
4772
|
-
tapi queue create [display-name] [--max-slots N] [--
|
|
4684
|
+
tapi queue create [display-name] [--max-slots N] [--api-base-url URL]
|
|
4773
4685
|
|
|
4774
4686
|
Options:
|
|
4775
4687
|
--api-base-url <url> Tapi API base URL
|
|
4776
4688
|
--server <url> Alias for --api-base-url
|
|
4777
|
-
--project <id> Optional project scope for the queue request
|
|
4778
4689
|
--max-slots <n> Maximum runner slots this queue may use
|
|
4779
4690
|
`);
|
|
4780
4691
|
}
|
|
@@ -4782,16 +4693,20 @@ function printRunnerHelp() {
|
|
|
4782
4693
|
console.log(`Tapi runner commands
|
|
4783
4694
|
|
|
4784
4695
|
Usage:
|
|
4785
|
-
tapi runner
|
|
4786
|
-
tapi runner
|
|
4696
|
+
tapi runner gui
|
|
4697
|
+
tapi runner setup --runner-id RUNNER [--port PORT] [--no-open] [--api-base-url URL]
|
|
4698
|
+
tapi runner slot set <runner-id> <slot-index> <queue-id> [--api-base-url URL]
|
|
4787
4699
|
|
|
4788
4700
|
Options:
|
|
4789
4701
|
--api-base-url <url> Tapi API base URL
|
|
4790
4702
|
--server <url> Alias for --api-base-url
|
|
4791
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID or .tapi/project.json
|
|
4792
4703
|
--runner-id <id> Runner id for setup; defaults to TAPI_RUNNER_ID
|
|
4793
4704
|
--port <n> Local setup UI port; defaults to 17687
|
|
4794
4705
|
--no-open Print the setup URL without opening a browser
|
|
4706
|
+
|
|
4707
|
+
Notes:
|
|
4708
|
+
The normal Windows path is the Tapi Runner desktop app. The setup command is
|
|
4709
|
+
kept for development and automation fallback.
|
|
4795
4710
|
`);
|
|
4796
4711
|
}
|
|
4797
4712
|
function printSessionsHelp() {
|
|
@@ -4805,7 +4720,7 @@ Usage:
|
|
|
4805
4720
|
Options:
|
|
4806
4721
|
--api-base-url <url> Tapi API base URL
|
|
4807
4722
|
--server <url> Alias for --api-base-url
|
|
4808
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4723
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4809
4724
|
--site <name> Limit sessions to one sitemap/site
|
|
4810
4725
|
--json Print raw grouped session JSON
|
|
4811
4726
|
--no-interactive Print the grouped list without the arrow-key picker
|
|
@@ -4816,13 +4731,12 @@ function printServicesHelp() {
|
|
|
4816
4731
|
|
|
4817
4732
|
Usage:
|
|
4818
4733
|
tapi services describe <servicemap.run> [--api-base-url URL] [--project PROJECT]
|
|
4819
|
-
tapi services sync
|
|
4734
|
+
tapi services sync
|
|
4820
4735
|
|
|
4821
4736
|
Options:
|
|
4822
4737
|
--api-base-url <url> Tapi API base URL
|
|
4823
4738
|
--server <url> Alias for --api-base-url
|
|
4824
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4825
|
-
--catalog <path> Catalog JSON output path
|
|
4739
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4826
4740
|
`);
|
|
4827
4741
|
}
|
|
4828
4742
|
function printTriggersHelp() {
|
|
@@ -4832,10 +4746,10 @@ Usage:
|
|
|
4832
4746
|
tapi triggers sync [--config FILE] [--api-base-url URL] [--project PROJECT]
|
|
4833
4747
|
|
|
4834
4748
|
Options:
|
|
4835
|
-
--config <path> Trigger config path; defaults to tapi.config.ts/js/json in the
|
|
4749
|
+
--config <path> Trigger config path; defaults to tapi.config.ts/js/json in the current directory
|
|
4836
4750
|
--api-base-url <url> Tapi API base URL
|
|
4837
4751
|
--server <url> Alias for --api-base-url
|
|
4838
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4752
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4839
4753
|
|
|
4840
4754
|
Config:
|
|
4841
4755
|
export default {
|
|
@@ -4854,8 +4768,9 @@ function printStudioHelp() {
|
|
|
4854
4768
|
console.log(`Tapi Studio commands
|
|
4855
4769
|
|
|
4856
4770
|
Usage:
|
|
4857
|
-
tapi studio [options]
|
|
4858
|
-
tapi studio
|
|
4771
|
+
tapi studio [options]
|
|
4772
|
+
tapi studio dev --tapp <tapp> [options]
|
|
4773
|
+
tapi studio install [options]
|
|
4859
4774
|
tapi studio open [options]
|
|
4860
4775
|
tapi studio doctor [options]
|
|
4861
4776
|
|
|
@@ -4866,9 +4781,7 @@ Options:
|
|
|
4866
4781
|
--tapp <id> Open this Tapp directly
|
|
4867
4782
|
--select Force the account Tapp picker
|
|
4868
4783
|
--last Reuse the last selected Tapp
|
|
4869
|
-
--no-select Skip the picker and use env
|
|
4870
|
-
--workspace <path> Search this directory for .tapi/project.json
|
|
4871
|
-
--no-workspace Do not load .tapi/project.json
|
|
4784
|
+
--no-select Skip the picker and use explicit/env Tapp context
|
|
4872
4785
|
--project <id> Alias for --tapp
|
|
4873
4786
|
--project-slug <slug> Optional display slug for the bound project
|
|
4874
4787
|
--install-token <tok> Preissued Studio install token (skips browser sign-in)
|
|
@@ -4881,18 +4794,16 @@ Options:
|
|
|
4881
4794
|
`);
|
|
4882
4795
|
}
|
|
4883
4796
|
function printWorkspaceHelp(command) {
|
|
4884
|
-
console.log(`Tapi workspace ${command}
|
|
4885
|
-
|
|
4886
|
-
Usage:
|
|
4887
|
-
tapi
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
--api-base-url <url> Tapi API base URL
|
|
4893
|
-
--server <url> Alias for --api-base-url
|
|
4894
|
-
--root <path> Directory where .tapi/project.json should be written
|
|
4895
|
-
--force Overwrite an existing workspace config
|
|
4797
|
+
console.log(`Tapi workspace ${command} is retired
|
|
4798
|
+
|
|
4799
|
+
Usage:
|
|
4800
|
+
tapi tapp create <tapp>
|
|
4801
|
+
tapi login
|
|
4802
|
+
tapi studio <tapp>
|
|
4803
|
+
|
|
4804
|
+
Options:
|
|
4805
|
+
--api-base-url <url> Tapi API base URL
|
|
4806
|
+
--server <url> Alias for --api-base-url
|
|
4896
4807
|
`);
|
|
4897
4808
|
}
|
|
4898
4809
|
function printServiceHelp() {
|