@tapi-dev/sdk 0.1.40 → 0.1.45
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 +164 -245
- package/dist/runner-dev.d.ts +1 -0
- package/dist/runner-dev.js +270 -0
- 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,9 @@ 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";
|
|
21
|
+
import { openRunnerDev } from "./runner-dev.js";
|
|
20
22
|
const DEFAULT_DOWNLOADS_BASE_URL = "https://d4xaf52nfwiok.cloudfront.net";
|
|
21
23
|
const DEFAULT_STUDIO_API_BASE_URL = "https://determined-motivation-production.up.railway.app";
|
|
22
24
|
const DEFAULT_STUDIO_AUTH_HTML_URL = "https://rsarlong-1f92fd.gitlab.io/auth.html";
|
|
@@ -166,6 +168,10 @@ async function authenticateSdkUser() {
|
|
|
166
168
|
}
|
|
167
169
|
export async function runCli(argv = process.argv.slice(2)) {
|
|
168
170
|
const [command, subcommand, ...rest] = argv;
|
|
171
|
+
if (command === "runner" && subcommand === "dev") {
|
|
172
|
+
await openRunnerDev(rest);
|
|
173
|
+
return 0;
|
|
174
|
+
}
|
|
169
175
|
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
170
176
|
printHelp();
|
|
171
177
|
return 0;
|
|
@@ -240,12 +246,6 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
240
246
|
return addTappService(rest.slice(1));
|
|
241
247
|
}
|
|
242
248
|
}
|
|
243
|
-
if (subcommand === "queue") {
|
|
244
|
-
const queueCommand = rest[0] || "";
|
|
245
|
-
if (queueCommand === "add") {
|
|
246
|
-
return addTappQueue(rest.slice(1));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
249
|
console.error(`Unknown Tapp command: ${[subcommand, ...rest].filter(Boolean).join(" ")}`);
|
|
250
250
|
printTappHelp();
|
|
251
251
|
return 1;
|
|
@@ -270,6 +270,9 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
270
270
|
if (subcommand === "setup") {
|
|
271
271
|
return runRunnerSetup(rest);
|
|
272
272
|
}
|
|
273
|
+
if (subcommand === "gui") {
|
|
274
|
+
return openRunnerGui(rest);
|
|
275
|
+
}
|
|
273
276
|
if (subcommand === "slot") {
|
|
274
277
|
const slotCommand = rest[0] || "";
|
|
275
278
|
if (slotCommand === "set") {
|
|
@@ -328,6 +331,9 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
328
331
|
printStudioHelp();
|
|
329
332
|
return 0;
|
|
330
333
|
}
|
|
334
|
+
if (subcommand === "dev") {
|
|
335
|
+
return openStudioDev(rest);
|
|
336
|
+
}
|
|
331
337
|
const options = parseStudioOptions(rest);
|
|
332
338
|
if (subcommand === "install") {
|
|
333
339
|
return installStudio(options);
|
|
@@ -344,8 +350,6 @@ export async function runCli(argv = process.argv.slice(2)) {
|
|
|
344
350
|
}
|
|
345
351
|
export function parseStudioOptions(args) {
|
|
346
352
|
const raw = {};
|
|
347
|
-
let workspaceSearchRoot;
|
|
348
|
-
let skipWorkspace = false;
|
|
349
353
|
let projectIdSource;
|
|
350
354
|
let tappSelectionMode = "auto";
|
|
351
355
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -382,16 +386,13 @@ export function parseStudioOptions(args) {
|
|
|
382
386
|
continue;
|
|
383
387
|
}
|
|
384
388
|
if (arg === "--workspace") {
|
|
385
|
-
|
|
386
|
-
continue;
|
|
389
|
+
throw new Error("--workspace is retired. Use `tapi studio <tapp>` or `--tapp <id>`.");
|
|
387
390
|
}
|
|
388
391
|
if (arg.startsWith("--workspace=")) {
|
|
389
|
-
|
|
390
|
-
continue;
|
|
392
|
+
throw new Error("--workspace is retired. Use `tapi studio <tapp>` or `--tapp <id>`.");
|
|
391
393
|
}
|
|
392
394
|
if (arg === "--no-workspace") {
|
|
393
|
-
|
|
394
|
-
continue;
|
|
395
|
+
throw new Error("--no-workspace is retired. Studio no longer reads local workspace configs.");
|
|
395
396
|
}
|
|
396
397
|
if (arg === "--tapp") {
|
|
397
398
|
raw.projectId = normalizeProjectValue(requireOptionValue(args, ++index, "--tapp"), "tapp");
|
|
@@ -482,13 +483,11 @@ export function parseStudioOptions(args) {
|
|
|
482
483
|
}
|
|
483
484
|
throw new Error(`Unknown option: ${arg}`);
|
|
484
485
|
}
|
|
485
|
-
const workspace = skipWorkspace ? undefined : loadWorkspace(workspaceSearchRoot ?? process.cwd());
|
|
486
486
|
const channel = raw.channel ?? parseChannel(envString("TAPI_STUDIO_CHANNEL") ?? DEFAULT_CHANNEL);
|
|
487
487
|
const apiBaseUrl = normalizeHttpUrl(raw.apiBaseUrl
|
|
488
488
|
?? envString("TAPI_STUDIO_API_BASE_URL")
|
|
489
489
|
?? envString("TAPI_BASE_URL")
|
|
490
490
|
?? envString("TAPI_STUDIO_SERVER_URL")
|
|
491
|
-
?? workspace?.apiBaseUrl
|
|
492
491
|
?? DEFAULT_STUDIO_API_BASE_URL, "Studio API base URL");
|
|
493
492
|
const downloadsBaseUrl = normalizeHttpUrl(envString("TAPI_DOWNLOADS_BASE_URL") ?? DEFAULT_DOWNLOADS_BASE_URL, "TAPI_DOWNLOADS_BASE_URL");
|
|
494
493
|
const explicitManifestUrl = raw.manifestUrlOverride ?? envString("TAPI_STUDIO_MANIFEST_URL");
|
|
@@ -496,11 +495,11 @@ export function parseStudioOptions(args) {
|
|
|
496
495
|
? normalizeHttpUrl(explicitManifestUrl, "Studio manifest URL")
|
|
497
496
|
: `${downloadsBaseUrl.replace(/\/+$/, "")}/studio/channels/${channel}/latest.json`;
|
|
498
497
|
const envProjectId = envString("TAPI_PROJECT_ID");
|
|
499
|
-
const projectId = raw.projectId ?? envProjectId
|
|
498
|
+
const projectId = raw.projectId ?? envProjectId;
|
|
500
499
|
if (!projectIdSource && projectId) {
|
|
501
|
-
projectIdSource = raw.projectId ? "option" :
|
|
500
|
+
projectIdSource = raw.projectId ? "option" : "env";
|
|
502
501
|
}
|
|
503
|
-
const projectSlug = raw.projectSlug ?? envString("TAPI_PROJECT_SLUG")
|
|
502
|
+
const projectSlug = raw.projectSlug ?? envString("TAPI_PROJECT_SLUG");
|
|
504
503
|
const envInstallToken = envString("TAPI_STUDIO_INSTALL_TOKEN");
|
|
505
504
|
const installToken = raw.installToken ?? envInstallToken;
|
|
506
505
|
return {
|
|
@@ -515,20 +514,17 @@ export function parseStudioOptions(args) {
|
|
|
515
514
|
exePath: raw.exePath ?? envString("TAPI_STUDIO_EXE"),
|
|
516
515
|
installToken,
|
|
517
516
|
installTokenSource: raw.installToken ? "option" : installToken ? "env" : undefined,
|
|
518
|
-
workspace,
|
|
519
|
-
workspaceRoot: workspace?.root,
|
|
520
517
|
projectId,
|
|
521
518
|
projectSlug,
|
|
522
519
|
projectIdSource,
|
|
523
|
-
workspaceMode: Boolean(projectId
|
|
520
|
+
workspaceMode: Boolean(projectId),
|
|
524
521
|
tappSelectionMode,
|
|
525
522
|
};
|
|
526
523
|
}
|
|
527
524
|
function parseServiceOptions(args) {
|
|
528
525
|
let operation = "";
|
|
529
|
-
|
|
530
|
-
let
|
|
531
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
526
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
527
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
532
528
|
for (let index = 0; index < args.length; index += 1) {
|
|
533
529
|
const arg = args[index];
|
|
534
530
|
if (!arg)
|
|
@@ -566,7 +562,7 @@ function parseServiceOptions(args) {
|
|
|
566
562
|
throw new Error("services describe requires a service run like schwab.place_order.");
|
|
567
563
|
}
|
|
568
564
|
if (!projectId) {
|
|
569
|
-
throw new Error("services describe requires --project
|
|
565
|
+
throw new Error("services describe requires --project or TAPI_PROJECT_ID.");
|
|
570
566
|
}
|
|
571
567
|
return {
|
|
572
568
|
operation,
|
|
@@ -596,10 +592,9 @@ async function describeServiceOperation(args) {
|
|
|
596
592
|
}
|
|
597
593
|
}
|
|
598
594
|
function parseApiWorkspaceOptions(args) {
|
|
599
|
-
|
|
600
|
-
let
|
|
601
|
-
let
|
|
602
|
-
let catalogPath = workspace?.config.services?.catalog || ".tapi/services/catalog.json";
|
|
595
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
596
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
597
|
+
let catalogPath = "tapi-services.catalog.json";
|
|
603
598
|
for (let index = 0; index < args.length; index += 1) {
|
|
604
599
|
const arg = args[index];
|
|
605
600
|
if (!arg)
|
|
@@ -635,22 +630,18 @@ function parseApiWorkspaceOptions(args) {
|
|
|
635
630
|
throw new Error(`Unknown services option: ${arg}`);
|
|
636
631
|
}
|
|
637
632
|
if (!projectId) {
|
|
638
|
-
throw new Error("services command requires --project
|
|
633
|
+
throw new Error("services command requires --project or TAPI_PROJECT_ID.");
|
|
639
634
|
}
|
|
640
|
-
const root = workspace?.root || process.cwd();
|
|
641
635
|
return {
|
|
642
636
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
643
637
|
projectId,
|
|
644
|
-
catalogPath: resolve(
|
|
638
|
+
catalogPath: resolve(process.cwd(), catalogPath),
|
|
645
639
|
};
|
|
646
640
|
}
|
|
647
641
|
async function syncServiceCatalog(args) {
|
|
648
642
|
try {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
await writeJsonFile(options.catalogPath, catalog);
|
|
652
|
-
console.log(`Synced Tapi service-run catalog: ${options.catalogPath}`);
|
|
653
|
-
return 0;
|
|
643
|
+
void args;
|
|
644
|
+
throw new Error("services sync is retired. Service-run contracts are server-backed; use `tapi services describe <service.call>`.");
|
|
654
645
|
}
|
|
655
646
|
catch (error) {
|
|
656
647
|
console.error(formatError(error));
|
|
@@ -658,8 +649,7 @@ async function syncServiceCatalog(args) {
|
|
|
658
649
|
}
|
|
659
650
|
}
|
|
660
651
|
function parseTappServiceAddOptions(args) {
|
|
661
|
-
|
|
662
|
-
let apiBaseUrl = envString("TAPI_BASE_URL") || workspace?.apiBaseUrl || DEFAULT_STUDIO_API_BASE_URL;
|
|
652
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
663
653
|
let tappId = "";
|
|
664
654
|
let serviceCall = "";
|
|
665
655
|
let serviceMapId = "";
|
|
@@ -740,9 +730,8 @@ function parseTappServiceAddOptions(args) {
|
|
|
740
730
|
};
|
|
741
731
|
}
|
|
742
732
|
function parseTappCreateOptions(args) {
|
|
743
|
-
|
|
744
|
-
let
|
|
745
|
-
let tappId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
733
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
734
|
+
let tappId = envString("TAPI_PROJECT_ID") || "";
|
|
746
735
|
let name = "";
|
|
747
736
|
for (let index = 0; index < args.length; index += 1) {
|
|
748
737
|
const arg = args[index];
|
|
@@ -862,9 +851,7 @@ async function postTappServiceAdd(options) {
|
|
|
862
851
|
return body ?? {};
|
|
863
852
|
}
|
|
864
853
|
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 || "";
|
|
854
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
868
855
|
let displayName = "";
|
|
869
856
|
let maxSlots = 8;
|
|
870
857
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -883,14 +870,6 @@ function parseQueueCreateOptions(args) {
|
|
|
883
870
|
apiBaseUrl = arg.slice("--server=".length);
|
|
884
871
|
continue;
|
|
885
872
|
}
|
|
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
873
|
if (arg === "--max-slots") {
|
|
895
874
|
maxSlots = parsePositiveInteger(requireOptionValue(args, ++index, "--max-slots"), "--max-slots");
|
|
896
875
|
continue;
|
|
@@ -910,61 +889,12 @@ function parseQueueCreateOptions(args) {
|
|
|
910
889
|
}
|
|
911
890
|
return {
|
|
912
891
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
913
|
-
projectId,
|
|
914
892
|
displayName,
|
|
915
893
|
maxSlots,
|
|
916
894
|
};
|
|
917
895
|
}
|
|
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
896
|
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 || "";
|
|
897
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
968
898
|
let runnerId = "";
|
|
969
899
|
let slotIndex = 0;
|
|
970
900
|
let queueId = "";
|
|
@@ -984,14 +914,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
984
914
|
apiBaseUrl = arg.slice("--server=".length);
|
|
985
915
|
continue;
|
|
986
916
|
}
|
|
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
917
|
if (arg.startsWith("--")) {
|
|
996
918
|
throw new Error(`Unknown runner slot set option: ${arg}`);
|
|
997
919
|
}
|
|
@@ -1009,9 +931,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
1009
931
|
}
|
|
1010
932
|
throw new Error(`Unexpected runner slot set argument: ${arg}`);
|
|
1011
933
|
}
|
|
1012
|
-
if (!projectId) {
|
|
1013
|
-
throw new Error("runner slot set requires --project or TAPI_PROJECT_ID.");
|
|
1014
|
-
}
|
|
1015
934
|
if (!runnerId) {
|
|
1016
935
|
throw new Error("runner slot set requires a runner id.");
|
|
1017
936
|
}
|
|
@@ -1023,7 +942,6 @@ function parseRunnerSlotSetOptions(args) {
|
|
|
1023
942
|
}
|
|
1024
943
|
return {
|
|
1025
944
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
1026
|
-
projectId,
|
|
1027
945
|
runnerId,
|
|
1028
946
|
slotIndex,
|
|
1029
947
|
queueId,
|
|
@@ -1041,18 +959,6 @@ async function createQueue(args) {
|
|
|
1041
959
|
return 1;
|
|
1042
960
|
}
|
|
1043
961
|
}
|
|
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
962
|
async function setRunnerSlot(args) {
|
|
1057
963
|
try {
|
|
1058
964
|
const options = await withSdkAuth(parseRunnerSlotSetOptions(args));
|
|
@@ -1066,7 +972,7 @@ async function setRunnerSlot(args) {
|
|
|
1066
972
|
}
|
|
1067
973
|
}
|
|
1068
974
|
async function postQueueCreate(options) {
|
|
1069
|
-
const headers = sdkJsonHeaders(options.authToken
|
|
975
|
+
const headers = sdkJsonHeaders(options.authToken);
|
|
1070
976
|
const response = await fetch(`${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/queues`, {
|
|
1071
977
|
method: "POST",
|
|
1072
978
|
headers,
|
|
@@ -1082,23 +988,10 @@ async function postQueueCreate(options) {
|
|
|
1082
988
|
}
|
|
1083
989
|
return body ?? {};
|
|
1084
990
|
}
|
|
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
991
|
async function putRunnerSlot(options) {
|
|
1099
992
|
const response = await fetch(`${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/runners/${encodeURIComponent(options.runnerId)}/slots/${encodeURIComponent(String(options.slotIndex))}`, {
|
|
1100
993
|
method: "PUT",
|
|
1101
|
-
headers: sdkJsonHeaders(options.authToken
|
|
994
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1102
995
|
body: JSON.stringify({ queueId: options.queueId }),
|
|
1103
996
|
});
|
|
1104
997
|
const body = await readJsonBody(response);
|
|
@@ -1109,9 +1002,7 @@ async function putRunnerSlot(options) {
|
|
|
1109
1002
|
return body ?? {};
|
|
1110
1003
|
}
|
|
1111
1004
|
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 || "";
|
|
1005
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1115
1006
|
let runnerId = envString("TAPI_RUNNER_ID") || "";
|
|
1116
1007
|
let port = Number(envString("TAPI_RUNNER_SETUP_PORT") || "17687");
|
|
1117
1008
|
let openBrowser = true;
|
|
@@ -1131,14 +1022,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1131
1022
|
apiBaseUrl = arg.slice("--server=".length);
|
|
1132
1023
|
continue;
|
|
1133
1024
|
}
|
|
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
1025
|
if (arg === "--runner-id") {
|
|
1143
1026
|
runnerId = requireOptionValue(args, ++index, "--runner-id").trim();
|
|
1144
1027
|
continue;
|
|
@@ -1168,9 +1051,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1168
1051
|
}
|
|
1169
1052
|
throw new Error(`Unexpected runner setup argument: ${arg}`);
|
|
1170
1053
|
}
|
|
1171
|
-
if (!projectId) {
|
|
1172
|
-
throw new Error("runner setup requires --project or TAPI_PROJECT_ID.");
|
|
1173
|
-
}
|
|
1174
1054
|
if (!runnerId) {
|
|
1175
1055
|
throw new Error("runner setup requires --runner-id or TAPI_RUNNER_ID.");
|
|
1176
1056
|
}
|
|
@@ -1179,7 +1059,6 @@ export function parseRunnerSetupOptions(args) {
|
|
|
1179
1059
|
}
|
|
1180
1060
|
return {
|
|
1181
1061
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
1182
|
-
projectId,
|
|
1183
1062
|
runnerId,
|
|
1184
1063
|
port,
|
|
1185
1064
|
openBrowser,
|
|
@@ -1203,6 +1082,78 @@ async function runRunnerSetup(args) {
|
|
|
1203
1082
|
return 1;
|
|
1204
1083
|
}
|
|
1205
1084
|
}
|
|
1085
|
+
async function openRunnerGui(args) {
|
|
1086
|
+
try {
|
|
1087
|
+
if (hasHelpFlag(args)) {
|
|
1088
|
+
printRunnerHelp();
|
|
1089
|
+
return 0;
|
|
1090
|
+
}
|
|
1091
|
+
if (args.some((arg) => arg && arg.startsWith("-"))) {
|
|
1092
|
+
throw new Error(`Unknown runner gui option: ${args.find((arg) => arg.startsWith("-"))}`);
|
|
1093
|
+
}
|
|
1094
|
+
const executable = findInstalledRunnerGui();
|
|
1095
|
+
if (!executable) {
|
|
1096
|
+
throw new Error("Tapi Runner GUI is not installed. Run `tapi service install --channel pilot`, then retry.");
|
|
1097
|
+
}
|
|
1098
|
+
const child = spawn(executable, [], {
|
|
1099
|
+
detached: true,
|
|
1100
|
+
stdio: "ignore",
|
|
1101
|
+
windowsHide: false,
|
|
1102
|
+
});
|
|
1103
|
+
child.unref();
|
|
1104
|
+
console.log(`Opened Tapi Runner: ${executable}`);
|
|
1105
|
+
return 0;
|
|
1106
|
+
}
|
|
1107
|
+
catch (error) {
|
|
1108
|
+
console.error(formatError(error));
|
|
1109
|
+
return 1;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
function findInstalledRunnerGui() {
|
|
1113
|
+
const explicit = envString("TAPI_RUNNER_GUI_PATH");
|
|
1114
|
+
if (explicit && existsSync(explicit)) {
|
|
1115
|
+
return explicit;
|
|
1116
|
+
}
|
|
1117
|
+
const candidates = [];
|
|
1118
|
+
const localCandidate = join(getDefaultTapiDataDir(), "Service", "releases");
|
|
1119
|
+
const programData = envString("ProgramData") || "C:\\ProgramData";
|
|
1120
|
+
const roots = [
|
|
1121
|
+
join(programData, "Tapi", "Service", "releases"),
|
|
1122
|
+
localCandidate,
|
|
1123
|
+
resolve(process.cwd(), "build", "v2-processes", "runtime"),
|
|
1124
|
+
];
|
|
1125
|
+
for (const root of roots) {
|
|
1126
|
+
if (!existsSync(root))
|
|
1127
|
+
continue;
|
|
1128
|
+
const direct = join(root, "tapi-runner-gui.exe");
|
|
1129
|
+
if (existsSync(direct)) {
|
|
1130
|
+
candidates.push(direct);
|
|
1131
|
+
}
|
|
1132
|
+
let entries = [];
|
|
1133
|
+
try {
|
|
1134
|
+
entries = readdirSync(root);
|
|
1135
|
+
}
|
|
1136
|
+
catch {
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
for (const entry of entries) {
|
|
1140
|
+
const nested = join(root, String(entry), "tapi-runner-gui.exe");
|
|
1141
|
+
if (existsSync(nested)) {
|
|
1142
|
+
candidates.push(nested);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
const unique = Array.from(new Set(candidates));
|
|
1147
|
+
unique.sort((left, right) => {
|
|
1148
|
+
try {
|
|
1149
|
+
return statSync(right).mtimeMs - statSync(left).mtimeMs;
|
|
1150
|
+
}
|
|
1151
|
+
catch {
|
|
1152
|
+
return 0;
|
|
1153
|
+
}
|
|
1154
|
+
});
|
|
1155
|
+
return unique[0] || "";
|
|
1156
|
+
}
|
|
1206
1157
|
export async function startRunnerSetupServer(options, fetchImpl = fetch) {
|
|
1207
1158
|
const server = createServer((request, response) => {
|
|
1208
1159
|
void handleRunnerSetupRequest(request, response, options, fetchImpl);
|
|
@@ -1225,9 +1176,9 @@ export async function executeRunnerSetupAction(options, action, fetchImpl = fetc
|
|
|
1225
1176
|
if (!queueId) {
|
|
1226
1177
|
queue = await sdkJsonRequest(fetchImpl, `${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/queues`, {
|
|
1227
1178
|
method: "POST",
|
|
1228
|
-
headers: sdkJsonHeaders(options.authToken
|
|
1179
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1229
1180
|
body: JSON.stringify({
|
|
1230
|
-
displayName: String(action.displayName || `${options.
|
|
1181
|
+
displayName: String(action.displayName || `${options.runnerId} queue`).trim(),
|
|
1231
1182
|
maxSlots,
|
|
1232
1183
|
}),
|
|
1233
1184
|
});
|
|
@@ -1236,24 +1187,18 @@ export async function executeRunnerSetupAction(options, action, fetchImpl = fetc
|
|
|
1236
1187
|
if (!queueId) {
|
|
1237
1188
|
throw new Error("Runner setup needs an existing queue id or a created queue response with queueId.");
|
|
1238
1189
|
}
|
|
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
1190
|
const slots = [];
|
|
1245
1191
|
for (let offset = 0; offset < slotCount; offset += 1) {
|
|
1246
1192
|
const slotIndex = slotStart + offset;
|
|
1247
1193
|
slots.push(await sdkJsonRequest(fetchImpl, `${options.apiBaseUrl.replace(/\/+$/, "")}/api/sdk/v1/runners/${encodeURIComponent(options.runnerId)}/slots/${encodeURIComponent(String(slotIndex))}`, {
|
|
1248
1194
|
method: "PUT",
|
|
1249
|
-
headers: sdkJsonHeaders(options.authToken
|
|
1195
|
+
headers: sdkJsonHeaders(options.authToken),
|
|
1250
1196
|
body: JSON.stringify({ queueId }),
|
|
1251
1197
|
}));
|
|
1252
1198
|
}
|
|
1253
1199
|
return {
|
|
1254
1200
|
queueId,
|
|
1255
1201
|
queue: queueId && !Object.keys(queue).length ? { queueId } : queue,
|
|
1256
|
-
attachment,
|
|
1257
1202
|
slots,
|
|
1258
1203
|
};
|
|
1259
1204
|
}
|
|
@@ -1267,7 +1212,6 @@ async function handleRunnerSetupRequest(request, response, options, fetchImpl) {
|
|
|
1267
1212
|
if (request.method === "GET" && url.pathname === "/api/status") {
|
|
1268
1213
|
sendJson(response, 200, {
|
|
1269
1214
|
apiBaseUrl: options.apiBaseUrl,
|
|
1270
|
-
projectId: options.projectId,
|
|
1271
1215
|
runnerId: options.runnerId,
|
|
1272
1216
|
});
|
|
1273
1217
|
return;
|
|
@@ -1285,7 +1229,7 @@ async function handleRunnerSetupRequest(request, response, options, fetchImpl) {
|
|
|
1285
1229
|
}
|
|
1286
1230
|
}
|
|
1287
1231
|
function runnerSetupHtml(options) {
|
|
1288
|
-
const displayName = `${options.
|
|
1232
|
+
const displayName = `${options.runnerId} queue`;
|
|
1289
1233
|
return `<!doctype html>
|
|
1290
1234
|
<html lang="en">
|
|
1291
1235
|
<head>
|
|
@@ -1339,7 +1283,6 @@ code { word-break: break-all; }
|
|
|
1339
1283
|
<h2>Target</h2>
|
|
1340
1284
|
<dl>
|
|
1341
1285
|
<dt>Server</dt><dd><code>${escapeHtml(options.apiBaseUrl)}</code></dd>
|
|
1342
|
-
<dt>Tapp</dt><dd><code>${escapeHtml(options.projectId)}</code></dd>
|
|
1343
1286
|
<dt>Runner</dt><dd><code>${escapeHtml(options.runnerId)}</code></dd>
|
|
1344
1287
|
</dl>
|
|
1345
1288
|
</aside>
|
|
@@ -1425,11 +1368,10 @@ function parseNonNegativeInteger(value, label) {
|
|
|
1425
1368
|
return parsed;
|
|
1426
1369
|
}
|
|
1427
1370
|
function parseTriggerSyncOptions(args) {
|
|
1428
|
-
|
|
1429
|
-
let
|
|
1430
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
1371
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1372
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
1431
1373
|
let configPath = "";
|
|
1432
|
-
const root =
|
|
1374
|
+
const root = process.cwd();
|
|
1433
1375
|
for (let index = 0; index < args.length; index += 1) {
|
|
1434
1376
|
const arg = args[index];
|
|
1435
1377
|
if (!arg)
|
|
@@ -1465,7 +1407,7 @@ function parseTriggerSyncOptions(args) {
|
|
|
1465
1407
|
throw new Error(`Unknown triggers option: ${arg}`);
|
|
1466
1408
|
}
|
|
1467
1409
|
if (!projectId) {
|
|
1468
|
-
throw new Error("triggers sync requires --project
|
|
1410
|
+
throw new Error("triggers sync requires --project or TAPI_PROJECT_ID.");
|
|
1469
1411
|
}
|
|
1470
1412
|
return {
|
|
1471
1413
|
apiBaseUrl: normalizeHttpUrl(apiBaseUrl, "Tapi API base URL"),
|
|
@@ -1500,9 +1442,8 @@ async function syncServiceTriggers(args) {
|
|
|
1500
1442
|
}
|
|
1501
1443
|
}
|
|
1502
1444
|
function parseSessionsOptions(args) {
|
|
1503
|
-
|
|
1504
|
-
let
|
|
1505
|
-
let projectId = envString("TAPI_PROJECT_ID") || workspace?.projectId || "";
|
|
1445
|
+
let apiBaseUrl = envString("TAPI_BASE_URL") || DEFAULT_STUDIO_API_BASE_URL;
|
|
1446
|
+
let projectId = envString("TAPI_PROJECT_ID") || "";
|
|
1506
1447
|
let site = "";
|
|
1507
1448
|
let sessionId = "";
|
|
1508
1449
|
let json = false;
|
|
@@ -1558,7 +1499,7 @@ function parseSessionsOptions(args) {
|
|
|
1558
1499
|
throw new Error(`Unexpected sessions argument: ${arg}`);
|
|
1559
1500
|
}
|
|
1560
1501
|
if (!projectId) {
|
|
1561
|
-
throw new Error("sessions command requires --project
|
|
1502
|
+
throw new Error("sessions command requires --project or TAPI_PROJECT_ID.");
|
|
1562
1503
|
}
|
|
1563
1504
|
return {
|
|
1564
1505
|
sessionId,
|
|
@@ -3093,7 +3034,6 @@ function normalizeTappList(body) {
|
|
|
3093
3034
|
tappId,
|
|
3094
3035
|
name: typeof item.name === "string" && item.name.trim() ? item.name.trim() : tappId,
|
|
3095
3036
|
serviceCount: normalizeNonnegativeInteger(item.serviceCount),
|
|
3096
|
-
queueCount: normalizeNonnegativeInteger(item.queueCount),
|
|
3097
3037
|
});
|
|
3098
3038
|
}
|
|
3099
3039
|
return tapps;
|
|
@@ -3114,7 +3054,6 @@ function preferredStudioTappId(options, lastSelection, tapps) {
|
|
|
3114
3054
|
function formatTappChoice(tapp) {
|
|
3115
3055
|
const details = [
|
|
3116
3056
|
`${tapp.serviceCount} service${tapp.serviceCount === 1 ? "" : "s"}`,
|
|
3117
|
-
`${tapp.queueCount} queue${tapp.queueCount === 1 ? "" : "s"}`,
|
|
3118
3057
|
].join(", ");
|
|
3119
3058
|
return tapp.name === tapp.tappId
|
|
3120
3059
|
? `${tapp.tappId} ${pc.dim(`(${details})`)}`
|
|
@@ -3317,8 +3256,6 @@ async function launchPortableStudioServer(exePath, options, manifest) {
|
|
|
3317
3256
|
apiBaseUrl: options.apiBaseUrl,
|
|
3318
3257
|
projectId: options.projectId,
|
|
3319
3258
|
tappId: options.projectId,
|
|
3320
|
-
workspaceRoot: options.workspaceRoot,
|
|
3321
|
-
workspaceConfig: options.workspace?.configPath,
|
|
3322
3259
|
manifestVersion: manifest.version,
|
|
3323
3260
|
updatedAt: new Date().toISOString(),
|
|
3324
3261
|
});
|
|
@@ -3486,7 +3423,6 @@ async function runDoctor(options) {
|
|
|
3486
3423
|
console.log(`Studio channel: ${options.channel}`);
|
|
3487
3424
|
console.log(`Studio manifest: ${options.manifestUrl}`);
|
|
3488
3425
|
console.log(`Studio cache: ${options.cacheDir}`);
|
|
3489
|
-
console.log(`Workspace: ${options.workspaceRoot ?? "not found"}`);
|
|
3490
3426
|
console.log(`Project: ${options.projectId ?? "not set"}`);
|
|
3491
3427
|
try {
|
|
3492
3428
|
const manifest = await withCliSpinner("Fetching latest Tapi Studio manifest", () => fetchStudioManifest(options.manifestUrl));
|
|
@@ -3507,12 +3443,6 @@ function buildStudioLaunchEnv(options) {
|
|
|
3507
3443
|
const env = { ...process.env };
|
|
3508
3444
|
env.TAPI_STUDIO_API_BASE_URL = options.apiBaseUrl;
|
|
3509
3445
|
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
3446
|
if (options.projectId) {
|
|
3517
3447
|
env.TAPI_PROJECT_ID = options.projectId;
|
|
3518
3448
|
}
|
|
@@ -3893,7 +3823,6 @@ export function studioInstanceRecordPathForOptions(options) {
|
|
|
3893
3823
|
.update(JSON.stringify({
|
|
3894
3824
|
apiBaseUrl: comparableHttpUrl(options.apiBaseUrl),
|
|
3895
3825
|
projectId: options.projectId ?? "",
|
|
3896
|
-
workspaceRoot: comparableFsPath(options.workspaceRoot ?? ""),
|
|
3897
3826
|
}))
|
|
3898
3827
|
.digest("hex")
|
|
3899
3828
|
.slice(0, 24);
|
|
@@ -3955,8 +3884,6 @@ async function readStudioInstanceRecord(options) {
|
|
|
3955
3884
|
apiBaseUrl: typeof parsed.apiBaseUrl === "string" ? parsed.apiBaseUrl : "",
|
|
3956
3885
|
projectId: typeof parsed.projectId === "string" ? parsed.projectId : undefined,
|
|
3957
3886
|
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
3887
|
manifestVersion: typeof parsed.manifestVersion === "string" ? parsed.manifestVersion : undefined,
|
|
3961
3888
|
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : "",
|
|
3962
3889
|
};
|
|
@@ -3977,11 +3904,6 @@ function studioInstanceIdentityMatches(identity, options) {
|
|
|
3977
3904
|
if (expectedProject && actualProject && actualProject !== expectedProject) {
|
|
3978
3905
|
return false;
|
|
3979
3906
|
}
|
|
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
3907
|
const expectedApiBaseUrl = comparableHttpUrl(options.apiBaseUrl);
|
|
3986
3908
|
const actualApiBaseUrl = comparableHttpUrl(typeof identity.apiBaseUrl === "string" ? identity.apiBaseUrl : "");
|
|
3987
3909
|
if (expectedApiBaseUrl && actualApiBaseUrl && actualApiBaseUrl !== expectedApiBaseUrl) {
|
|
@@ -3992,10 +3914,6 @@ function studioInstanceIdentityMatches(identity, options) {
|
|
|
3992
3914
|
function comparableHttpUrl(value) {
|
|
3993
3915
|
return String(value || "").trim().replace(/\/+$/, "").toLowerCase();
|
|
3994
3916
|
}
|
|
3995
|
-
function comparableFsPath(value) {
|
|
3996
|
-
const trimmed = String(value || "").trim();
|
|
3997
|
-
return trimmed ? resolve(trimmed).toLowerCase() : "";
|
|
3998
|
-
}
|
|
3999
3917
|
function getDefaultTapiDataDir() {
|
|
4000
3918
|
if (process.platform === "win32") {
|
|
4001
3919
|
const localAppData = process.env.LOCALAPPDATA
|
|
@@ -4506,7 +4424,9 @@ async function isTapiManagedReleaseDir(directory) {
|
|
|
4506
4424
|
return Array.isArray(entries) && entries.length === 0;
|
|
4507
4425
|
}
|
|
4508
4426
|
function looksLikeTapiServiceReleaseDir(directory) {
|
|
4509
|
-
|
|
4427
|
+
const hasServiceHost = existsSync(join(directory, "tapi-service-host.exe"))
|
|
4428
|
+
|| existsSync(join(directory, "tapi-service-host", "tapi-service-host.exe"));
|
|
4429
|
+
return (hasServiceHost
|
|
4510
4430
|
&& existsSync(join(directory, "install_tapi_service.ps1"))
|
|
4511
4431
|
&& (existsSync(join(directory, "tapi-service-worker.exe"))
|
|
4512
4432
|
|| existsSync(join(directory, "tapi-service-worker", "tapi-service-worker.exe"))));
|
|
@@ -4693,10 +4613,9 @@ function printHelp() {
|
|
|
4693
4613
|
|
|
4694
4614
|
Usage:
|
|
4695
4615
|
tapi login
|
|
4696
|
-
tapi init --project PROJECT
|
|
4697
|
-
tapi link --project PROJECT
|
|
4698
4616
|
tapi studio install [--channel pilot] [--api-base-url URL]
|
|
4699
4617
|
tapi studio
|
|
4618
|
+
tapi studio dev --tapp <tapp>
|
|
4700
4619
|
tapi studio --tapp <tapp>
|
|
4701
4620
|
tapi studio --select
|
|
4702
4621
|
tapi studio open
|
|
@@ -4704,20 +4623,20 @@ Usage:
|
|
|
4704
4623
|
tapi tapp create <tapp>
|
|
4705
4624
|
tapi queue create [display-name]
|
|
4706
4625
|
tapi tapp service add <tapp> <service.call> --service-map ID --entry ENTRY
|
|
4707
|
-
tapi
|
|
4708
|
-
tapi runner
|
|
4626
|
+
tapi runner gui
|
|
4627
|
+
tapi runner dev --tapp <tapp> [--capacity 4]
|
|
4628
|
+
tapi runner setup --runner-id RUNNER
|
|
4709
4629
|
tapi runner slot set <runner-id> <slot-index> <queue-id>
|
|
4710
4630
|
tapi services describe <servicemap.run>
|
|
4711
|
-
tapi
|
|
4712
|
-
tapi triggers sync
|
|
4631
|
+
tapi triggers sync
|
|
4713
4632
|
tapi sessions
|
|
4714
4633
|
tapi service status
|
|
4715
4634
|
tapi doctor
|
|
4716
4635
|
|
|
4717
4636
|
Commands:
|
|
4718
4637
|
login Sign in with Firebase credentials for SDK commands
|
|
4719
|
-
init
|
|
4720
|
-
link
|
|
4638
|
+
init Retired; use tapp create/login/studio instead
|
|
4639
|
+
link Retired; use explicit Tapp commands instead
|
|
4721
4640
|
studio install Download, verify, and run the Tapi Studio installer
|
|
4722
4641
|
studio Open Tapi Studio for a selected Tapp
|
|
4723
4642
|
studio open Open Tapi Studio for a selected Tapp
|
|
@@ -4726,12 +4645,13 @@ Commands:
|
|
|
4726
4645
|
queue create Create a queue for service-run routing
|
|
4727
4646
|
tapp service add
|
|
4728
4647
|
Add a ServiceMap-backed service call to a Tapp
|
|
4729
|
-
|
|
4730
|
-
runner
|
|
4648
|
+
runner gui Open the installed desktop Runner app
|
|
4649
|
+
runner dev Run a source Runner for a Tapp development session
|
|
4650
|
+
runner setup Open the legacy local browser queue/slot setup UI
|
|
4731
4651
|
runner slot set Assign a queue to a runner slot
|
|
4732
4652
|
services describe
|
|
4733
4653
|
Print a ServiceMap service-run input/output contract
|
|
4734
|
-
services sync
|
|
4654
|
+
services sync Retired; service-run contracts are server-backed
|
|
4735
4655
|
triggers sync Upsert service triggers from tapi.config
|
|
4736
4656
|
sessions List dev-mode API sessions and open takeover sessions
|
|
4737
4657
|
service Inspect or control the local Tapi Windows service
|
|
@@ -4753,7 +4673,6 @@ function printTappHelp() {
|
|
|
4753
4673
|
Usage:
|
|
4754
4674
|
tapi tapp create <tapp> [--name NAME] [--api-base-url URL]
|
|
4755
4675
|
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
4676
|
|
|
4758
4677
|
Options:
|
|
4759
4678
|
--api-base-url <url> Tapi API base URL
|
|
@@ -4769,12 +4688,11 @@ function printQueueHelp() {
|
|
|
4769
4688
|
console.log(`Tapi queue commands
|
|
4770
4689
|
|
|
4771
4690
|
Usage:
|
|
4772
|
-
tapi queue create [display-name] [--max-slots N] [--
|
|
4691
|
+
tapi queue create [display-name] [--max-slots N] [--api-base-url URL]
|
|
4773
4692
|
|
|
4774
4693
|
Options:
|
|
4775
4694
|
--api-base-url <url> Tapi API base URL
|
|
4776
4695
|
--server <url> Alias for --api-base-url
|
|
4777
|
-
--project <id> Optional project scope for the queue request
|
|
4778
4696
|
--max-slots <n> Maximum runner slots this queue may use
|
|
4779
4697
|
`);
|
|
4780
4698
|
}
|
|
@@ -4782,16 +4700,21 @@ function printRunnerHelp() {
|
|
|
4782
4700
|
console.log(`Tapi runner commands
|
|
4783
4701
|
|
|
4784
4702
|
Usage:
|
|
4785
|
-
tapi runner
|
|
4786
|
-
tapi runner
|
|
4703
|
+
tapi runner gui
|
|
4704
|
+
tapi runner dev --tapp <tapp> [--capacity COUNT] [--workspace PATH] [--no-watch]
|
|
4705
|
+
tapi runner setup --runner-id RUNNER [--port PORT] [--no-open] [--api-base-url URL]
|
|
4706
|
+
tapi runner slot set <runner-id> <slot-index> <queue-id> [--api-base-url URL]
|
|
4787
4707
|
|
|
4788
4708
|
Options:
|
|
4789
4709
|
--api-base-url <url> Tapi API base URL
|
|
4790
4710
|
--server <url> Alias for --api-base-url
|
|
4791
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID or .tapi/project.json
|
|
4792
4711
|
--runner-id <id> Runner id for setup; defaults to TAPI_RUNNER_ID
|
|
4793
4712
|
--port <n> Local setup UI port; defaults to 17687
|
|
4794
4713
|
--no-open Print the setup URL without opening a browser
|
|
4714
|
+
|
|
4715
|
+
Notes:
|
|
4716
|
+
The normal Windows path is the Tapi Runner desktop app. The setup command is
|
|
4717
|
+
kept for development and automation fallback.
|
|
4795
4718
|
`);
|
|
4796
4719
|
}
|
|
4797
4720
|
function printSessionsHelp() {
|
|
@@ -4805,7 +4728,7 @@ Usage:
|
|
|
4805
4728
|
Options:
|
|
4806
4729
|
--api-base-url <url> Tapi API base URL
|
|
4807
4730
|
--server <url> Alias for --api-base-url
|
|
4808
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4731
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4809
4732
|
--site <name> Limit sessions to one sitemap/site
|
|
4810
4733
|
--json Print raw grouped session JSON
|
|
4811
4734
|
--no-interactive Print the grouped list without the arrow-key picker
|
|
@@ -4816,13 +4739,12 @@ function printServicesHelp() {
|
|
|
4816
4739
|
|
|
4817
4740
|
Usage:
|
|
4818
4741
|
tapi services describe <servicemap.run> [--api-base-url URL] [--project PROJECT]
|
|
4819
|
-
tapi services sync
|
|
4742
|
+
tapi services sync
|
|
4820
4743
|
|
|
4821
4744
|
Options:
|
|
4822
4745
|
--api-base-url <url> Tapi API base URL
|
|
4823
4746
|
--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
|
|
4747
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4826
4748
|
`);
|
|
4827
4749
|
}
|
|
4828
4750
|
function printTriggersHelp() {
|
|
@@ -4832,10 +4754,10 @@ Usage:
|
|
|
4832
4754
|
tapi triggers sync [--config FILE] [--api-base-url URL] [--project PROJECT]
|
|
4833
4755
|
|
|
4834
4756
|
Options:
|
|
4835
|
-
--config <path> Trigger config path; defaults to tapi.config.ts/js/json in the
|
|
4757
|
+
--config <path> Trigger config path; defaults to tapi.config.ts/js/json in the current directory
|
|
4836
4758
|
--api-base-url <url> Tapi API base URL
|
|
4837
4759
|
--server <url> Alias for --api-base-url
|
|
4838
|
-
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4760
|
+
--project <id> Tapi project id; defaults to TAPI_PROJECT_ID
|
|
4839
4761
|
|
|
4840
4762
|
Config:
|
|
4841
4763
|
export default {
|
|
@@ -4854,8 +4776,9 @@ function printStudioHelp() {
|
|
|
4854
4776
|
console.log(`Tapi Studio commands
|
|
4855
4777
|
|
|
4856
4778
|
Usage:
|
|
4857
|
-
tapi studio [options]
|
|
4858
|
-
tapi studio
|
|
4779
|
+
tapi studio [options]
|
|
4780
|
+
tapi studio dev --tapp <tapp> [options]
|
|
4781
|
+
tapi studio install [options]
|
|
4859
4782
|
tapi studio open [options]
|
|
4860
4783
|
tapi studio doctor [options]
|
|
4861
4784
|
|
|
@@ -4866,9 +4789,7 @@ Options:
|
|
|
4866
4789
|
--tapp <id> Open this Tapp directly
|
|
4867
4790
|
--select Force the account Tapp picker
|
|
4868
4791
|
--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
|
|
4792
|
+
--no-select Skip the picker and use explicit/env Tapp context
|
|
4872
4793
|
--project <id> Alias for --tapp
|
|
4873
4794
|
--project-slug <slug> Optional display slug for the bound project
|
|
4874
4795
|
--install-token <tok> Preissued Studio install token (skips browser sign-in)
|
|
@@ -4881,18 +4802,16 @@ Options:
|
|
|
4881
4802
|
`);
|
|
4882
4803
|
}
|
|
4883
4804
|
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
|
|
4805
|
+
console.log(`Tapi workspace ${command} is retired
|
|
4806
|
+
|
|
4807
|
+
Usage:
|
|
4808
|
+
tapi tapp create <tapp>
|
|
4809
|
+
tapi login
|
|
4810
|
+
tapi studio <tapp>
|
|
4811
|
+
|
|
4812
|
+
Options:
|
|
4813
|
+
--api-base-url <url> Tapi API base URL
|
|
4814
|
+
--server <url> Alias for --api-base-url
|
|
4896
4815
|
`);
|
|
4897
4816
|
}
|
|
4898
4817
|
function printServiceHelp() {
|