@fulldivevr/workcord-cli 2.17.0 → 3.0.0
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 +2 -17
- package/dist/auth.js +8 -0
- package/dist/cli.js +2 -0
- package/dist/commands/machine.js +212 -0
- package/dist/config.js +53 -1
- package/dist/generated/commands/browser-assistance.js +65 -0
- package/dist/generated/commands/call-recordings.js +13 -0
- package/dist/generated/commands/client-config.js +18 -0
- package/dist/generated/commands/dashboard-actions.js +33 -0
- package/dist/generated/commands/internal.js +25 -0
- package/dist/generated/commands/local-folders.js +157 -0
- package/dist/generated/commands/machine-agents.js +134 -0
- package/dist/generated/commands/messages.js +35 -1
- package/dist/generated/commands/room-agents.js +6 -0
- package/dist/generated/commands/room-call.js +14 -0
- package/dist/generated/commands/rooms.js +6 -0
- package/dist/generated/commands/users.js +24 -0
- package/dist/generated/index.js +10 -0
- package/dist/machine/adapters/claude.js +183 -0
- package/dist/machine/adapters/codex.js +166 -0
- package/dist/machine/agents.js +22 -0
- package/dist/machine/chunks.js +57 -0
- package/dist/machine/handler.js +90 -0
- package/dist/machine/lock.js +36 -0
- package/dist/machine/pair.js +67 -0
- package/dist/machine/policy.js +24 -0
- package/dist/machine/relay.js +234 -0
- package/dist/machine/rotate.js +36 -0
- package/dist/machine/service.js +112 -0
- package/dist/machine/sessions.js +143 -0
- package/dist/machine/threads.js +68 -0
- package/package.json +4 -3
- package/dist/commands/hermes.js +0 -649
package/README.md
CHANGED
|
@@ -541,21 +541,7 @@ part of any automated gate.
|
|
|
541
541
|
|
|
542
542
|
## Release
|
|
543
543
|
|
|
544
|
-
|
|
545
|
-
It regenerates commands, tests, builds, and packs the CLI before deployment.
|
|
546
|
-
After all deployments succeed, it publishes that archive to npmjs.org: `main`
|
|
547
|
-
updates `latest`, and `dev` updates `dev`. Manual backend deployments do not
|
|
548
|
-
publish. App workflows increment only the Flutter build number.
|
|
549
|
-
|
|
550
|
-
Configure npm trusted publishing for `fulldiveVR/wizeup-rooms-api`, workflow
|
|
551
|
-
`deploy-wize-rooms-api.yml`, with permission to publish and manage dist-tags for
|
|
552
|
-
`@fulldivevr/workcord-cli`. The API repository's `TOKEN_FOR_SUB` secret must also
|
|
553
|
-
have contents read/write access to `fulldiveVR/wizeup-rooms` so that release CI
|
|
554
|
-
can synchronize `pubspec.yaml`. Merge the app workflow changes before enabling
|
|
555
|
-
the backend pipeline. An existing npm version must match the verified archive;
|
|
556
|
-
release CI fails on a conflicting archive or a version that would lower a tag.
|
|
557
|
-
|
|
558
|
-
For a manual recovery publish:
|
|
544
|
+
Publishing is a manual maintainer action — there is no auto-publish CI.
|
|
559
545
|
|
|
560
546
|
1. `npm run regen` — refresh the spec and generated commands; commit the diff.
|
|
561
547
|
2. `npm run typecheck`
|
|
@@ -564,8 +550,7 @@ For a manual recovery publish:
|
|
|
564
550
|
`README.md`, `LICENSE`, `package.json`. No sources, no `openapi.json`, no
|
|
565
551
|
`.npmrc`.
|
|
566
552
|
5. Smoke: `node dist/cli.js --help` and `node dist/cli.js --version`.
|
|
567
|
-
6.
|
|
568
|
-
`npm publish --access public --registry=https://registry.npmjs.org --@fulldivevr:registry=https://registry.npmjs.org`.
|
|
553
|
+
6. Bump `version` in `package.json`, then `npm publish`.
|
|
569
554
|
|
|
570
555
|
`prepack` re-runs `typecheck` + `test` + `build`, so steps 2–3 also gate the publish.
|
|
571
556
|
|
package/dist/auth.js
CHANGED
|
@@ -28,6 +28,14 @@ export function resolveAuth(asUserId, env = process.env, config = {}) {
|
|
|
28
28
|
}
|
|
29
29
|
throw new Error("No credentials. Run `workcord auth login --email <address> --save`, or set WORKCORD_TOKEN. For privileged impersonation, set WORKCORD_JWT_SECRET and pass --as <userId>.");
|
|
30
30
|
}
|
|
31
|
+
export function resolveMachineCredential(env = process.env, file) {
|
|
32
|
+
const envKey = env.WORKCORD_MACHINE_KEY?.trim();
|
|
33
|
+
if (envKey)
|
|
34
|
+
return { key: envKey, machineId: undefined, baseUrl: file?.baseUrl || undefined, source: "env" };
|
|
35
|
+
if (file?.key)
|
|
36
|
+
return { key: file.key, machineId: file.machineId, baseUrl: file.baseUrl || undefined, source: "file" };
|
|
37
|
+
throw new Error("No machine key. Run `workcord machine pair` (or `workcord machine enroll`) first, or set WORKCORD_MACHINE_KEY.");
|
|
38
|
+
}
|
|
31
39
|
function envFlag(value) {
|
|
32
40
|
const v = value?.trim().toLowerCase();
|
|
33
41
|
return v === "1" || v === "true" || v === "yes";
|
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,7 @@ import { registerHub } from "./commands/hub.js";
|
|
|
16
16
|
import { registerAgent } from "./commands/agent.js";
|
|
17
17
|
import { registerAgentSkills } from "./commands/agent-skills.js";
|
|
18
18
|
import { registerReflections } from "./commands/reflections.js";
|
|
19
|
+
import { registerMachine } from "./commands/machine.js";
|
|
19
20
|
import { registerAll as registerGenerated } from "./generated/index.js";
|
|
20
21
|
const program = new Command();
|
|
21
22
|
const require = createRequire(import.meta.url);
|
|
@@ -43,6 +44,7 @@ registerReflections(program);
|
|
|
43
44
|
registerChallenges(program); // adds regenerate-cards (not in the OpenAPI spec)
|
|
44
45
|
registerHealth(program);
|
|
45
46
|
registerHub(program);
|
|
47
|
+
registerMachine(program);
|
|
46
48
|
registerGenerated(program);
|
|
47
49
|
program.parseAsync().catch((err) => {
|
|
48
50
|
const out = { error: err.message ?? String(err) };
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { realpath } from "node:fs/promises";
|
|
3
|
+
import { homedir, hostname } from "node:os";
|
|
4
|
+
import { dirname } from "node:path";
|
|
5
|
+
import { actingUserId, resolveMachineCredential } from "../auth.js";
|
|
6
|
+
import { call, getBaseUrl } from "../client.js";
|
|
7
|
+
import { deleteMachineFile, getMachineLockPath, getMachinePath, getMachineThreadsPath, readMachineFile, readOrCreateInstallationId, saveMachineFile, } from "../config.js";
|
|
8
|
+
import { normalizeBaseUrl } from "../http.js";
|
|
9
|
+
import { runClaude } from "../machine/adapters/claude.js";
|
|
10
|
+
import { runCodex } from "../machine/adapters/codex.js";
|
|
11
|
+
import { ADAPTER_NAMES, detectAdapters } from "../machine/agents.js";
|
|
12
|
+
import { handleTask, TaskContexts } from "../machine/handler.js";
|
|
13
|
+
import { pairComputer } from "../machine/pair.js";
|
|
14
|
+
import { nextRotationDelay, rotateMachineKey, ROTATE_EVERY_MS } from "../machine/rotate.js";
|
|
15
|
+
import { installService, serviceArgs, servicePaths, uninstallService } from "../machine/service.js";
|
|
16
|
+
import { acquireMachineLock } from "../machine/lock.js";
|
|
17
|
+
import { resolveRoots } from "../machine/policy.js";
|
|
18
|
+
import { ConversationThreads } from "../machine/threads.js";
|
|
19
|
+
import { MachineRelayClient } from "../machine/relay.js";
|
|
20
|
+
import { getOrCreateGroup } from "./_group.js";
|
|
21
|
+
const require = createRequire(import.meta.url);
|
|
22
|
+
const { version } = require("../../package.json");
|
|
23
|
+
export function relayUrl(baseUrl) {
|
|
24
|
+
const url = new URL("/api/v1/machine-agents/ws", normalizeBaseUrl(baseUrl));
|
|
25
|
+
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
26
|
+
return url.toString();
|
|
27
|
+
}
|
|
28
|
+
export async function probeMachine(baseUrl, key, installationId) {
|
|
29
|
+
const response = await fetch(new URL("/api/v1/machine-agents/self", normalizeBaseUrl(baseUrl)), {
|
|
30
|
+
headers: { authorization: `Bearer ${key}`, "x-workcord-installation-id": installationId },
|
|
31
|
+
signal: AbortSignal.timeout(15_000),
|
|
32
|
+
});
|
|
33
|
+
if (response.status === 401)
|
|
34
|
+
return "unauthorized";
|
|
35
|
+
return response.status === 409 ? "in_use" : "retry";
|
|
36
|
+
}
|
|
37
|
+
export function registerMachine(program) {
|
|
38
|
+
const group = getOrCreateGroup(program, "machine", "Use this computer as a private agent of your Shadow");
|
|
39
|
+
group
|
|
40
|
+
.command("enroll")
|
|
41
|
+
.description("Register this computer with WorkCord and save its key locally.")
|
|
42
|
+
.option("--name <name>", "name shown to you and your Shadow", hostname())
|
|
43
|
+
.action(async (opts) => {
|
|
44
|
+
const enrolled = (await call({
|
|
45
|
+
method: "POST",
|
|
46
|
+
path: "/api/v1/machine-agents",
|
|
47
|
+
body: { name: opts.name, platform: `${process.platform}-${process.arch}`, cliVersion: version },
|
|
48
|
+
asUserId: actingUserId(program),
|
|
49
|
+
}));
|
|
50
|
+
await saveMachineFile({
|
|
51
|
+
machineId: enrolled.machine.id,
|
|
52
|
+
key: enrolled.machineKey,
|
|
53
|
+
baseUrl: await getBaseUrl(),
|
|
54
|
+
name: enrolled.machine.name,
|
|
55
|
+
});
|
|
56
|
+
process.stdout.write(JSON.stringify({ machine: enrolled.machine, savedTo: getMachinePath() }) + "\n");
|
|
57
|
+
});
|
|
58
|
+
group
|
|
59
|
+
.command("pair")
|
|
60
|
+
.description("Pair this computer by confirming a code in the WorkCord app; no login needed here.")
|
|
61
|
+
.option("--name <name>", "name shown to you and your Shadow", hostname())
|
|
62
|
+
.action(async (opts) => {
|
|
63
|
+
const file = await pairComputer({
|
|
64
|
+
baseUrl: await getBaseUrl(),
|
|
65
|
+
name: opts.name,
|
|
66
|
+
installationId: await readOrCreateInstallationId(),
|
|
67
|
+
cliVersion: version,
|
|
68
|
+
path: getMachinePath(),
|
|
69
|
+
});
|
|
70
|
+
process.stderr.write("Paired. Start it with `workcord machine start --root <dir>`, or keep it running with `workcord machine install-service --root <dir>`.\n");
|
|
71
|
+
process.stdout.write(JSON.stringify({ machineId: file.machineId, name: file.name, savedTo: getMachinePath() }) + "\n");
|
|
72
|
+
});
|
|
73
|
+
group
|
|
74
|
+
.command("start")
|
|
75
|
+
.description("Connect this computer and run your tasks on it until stopped (foreground). Tasks run with full access, without approvals.")
|
|
76
|
+
.option("--root <dir>", "directory a task may work in (repeatable); without one, only session search runs", collect, [])
|
|
77
|
+
.option("--adapter <name>", "coding agent that runs tasks: auto, claude or codex", "auto")
|
|
78
|
+
.action(async (opts) => {
|
|
79
|
+
const credential = resolveMachineCredential(process.env, await readMachineFile());
|
|
80
|
+
const roots = await resolveRoots(opts.root);
|
|
81
|
+
const installed = await detectAdapters();
|
|
82
|
+
const adapters = pickAdapters(installed, opts.adapter);
|
|
83
|
+
const baseUrl = credential.baseUrl || (await getBaseUrl());
|
|
84
|
+
const installationId = await readOrCreateInstallationId();
|
|
85
|
+
const release = await acquireMachineLock(getMachineLockPath());
|
|
86
|
+
const contexts = new TaskContexts();
|
|
87
|
+
const threads = new ConversationThreads(getMachineThreadsPath());
|
|
88
|
+
const client = new MachineRelayClient({
|
|
89
|
+
url: relayUrl(baseUrl),
|
|
90
|
+
key: credential.key,
|
|
91
|
+
installationId,
|
|
92
|
+
cliVersion: version,
|
|
93
|
+
adapters: Object.keys(adapters),
|
|
94
|
+
handle: (rpc, signal, onEvent) => handleTask(rpc, {
|
|
95
|
+
roots, adapters, adapter: Object.keys(adapters)[0], contexts, threads, signal, onEvent,
|
|
96
|
+
}),
|
|
97
|
+
probe: () => probeMachine(baseUrl, credential.key, installationId),
|
|
98
|
+
});
|
|
99
|
+
const rotation = credential.source === "file" ? scheduleRotation(client) : undefined;
|
|
100
|
+
process.stderr.write(`machine: full access, agents: ${Object.keys(adapters).join(", ") || "none"}, roots: ${roots.length ? roots.join(", ") : "none (session search only)"}\n`);
|
|
101
|
+
process.once("SIGINT", () => client.stop());
|
|
102
|
+
process.once("SIGTERM", () => client.stop());
|
|
103
|
+
const outcome = await client.start().finally(() => {
|
|
104
|
+
if (rotation)
|
|
105
|
+
clearTimeout(rotation.timer);
|
|
106
|
+
return release();
|
|
107
|
+
});
|
|
108
|
+
if (!outcome.ok)
|
|
109
|
+
process.exitCode = 1;
|
|
110
|
+
});
|
|
111
|
+
group
|
|
112
|
+
.command("install-service")
|
|
113
|
+
.description("Keep `machine start` running in the background (launchd on macOS, systemd on Linux).")
|
|
114
|
+
.option("--root <dir>", "directory a task may work in (repeatable)", collect, [])
|
|
115
|
+
.option("--adapter <name>", "coding agent that runs tasks: auto, claude or codex", "auto")
|
|
116
|
+
.action(async (opts) => {
|
|
117
|
+
await readMachineFile().then((file) => resolveMachineCredential({}, file));
|
|
118
|
+
const roots = await resolveRoots(opts.root);
|
|
119
|
+
const installed = await detectAdapters();
|
|
120
|
+
pickAdapters(installed, opts.adapter);
|
|
121
|
+
const paths = servicePaths();
|
|
122
|
+
const pathDirs = [...new Set([dirname(process.execPath), ...Object.values(installed).map((path) => dirname(path)), "/usr/bin", "/bin"])];
|
|
123
|
+
const installedService = await installService({
|
|
124
|
+
node: process.execPath,
|
|
125
|
+
cli: await realpath(process.argv[1]),
|
|
126
|
+
args: serviceArgs({ roots, adapter: opts.adapter }),
|
|
127
|
+
pathDirs,
|
|
128
|
+
logPath: paths.log,
|
|
129
|
+
home: homedir(),
|
|
130
|
+
});
|
|
131
|
+
process.stdout.write(JSON.stringify({ ...installedService, log: paths.log }) + "\n");
|
|
132
|
+
});
|
|
133
|
+
group
|
|
134
|
+
.command("uninstall-service")
|
|
135
|
+
.description("Stop and remove the background service.")
|
|
136
|
+
.action(async () => {
|
|
137
|
+
process.stdout.write(JSON.stringify(await uninstallService()) + "\n");
|
|
138
|
+
});
|
|
139
|
+
group
|
|
140
|
+
.command("status")
|
|
141
|
+
.description("List your computers and whether each one is connected.")
|
|
142
|
+
.action(async () => {
|
|
143
|
+
const local = await readMachineFile();
|
|
144
|
+
const { machines } = (await call({ path: "/api/v1/machine-agents", asUserId: actingUserId(program) }));
|
|
145
|
+
process.stdout.write(JSON.stringify({
|
|
146
|
+
thisMachine: local?.machineId ?? null,
|
|
147
|
+
machines: machines.map((machine) => ({ ...machine, thisMachine: machine.id === local?.machineId })),
|
|
148
|
+
}) + "\n");
|
|
149
|
+
});
|
|
150
|
+
group
|
|
151
|
+
.command("revoke")
|
|
152
|
+
.description("Disconnect a computer for good. Defaults to this one.")
|
|
153
|
+
.argument("[machineId]", "computer to revoke")
|
|
154
|
+
.action(async (machineId) => {
|
|
155
|
+
const local = await readMachineFile();
|
|
156
|
+
const target = machineId || local?.machineId;
|
|
157
|
+
if (!target)
|
|
158
|
+
throw new Error("No machine id given and this computer is not enrolled.");
|
|
159
|
+
await call({
|
|
160
|
+
method: "DELETE",
|
|
161
|
+
path: `/api/v1/machine-agents/${encodeURIComponent(target)}`,
|
|
162
|
+
asUserId: actingUserId(program),
|
|
163
|
+
});
|
|
164
|
+
if (local?.machineId === target)
|
|
165
|
+
await deleteMachineFile();
|
|
166
|
+
process.stdout.write(JSON.stringify({ revoked: target }) + "\n");
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function collect(value, previous) {
|
|
170
|
+
return [...previous, value];
|
|
171
|
+
}
|
|
172
|
+
const RUNNERS = { claude: runClaude, codex: runCodex };
|
|
173
|
+
export function pickAdapters(installed, choice) {
|
|
174
|
+
const names = choice === "auto" ? ADAPTER_NAMES.filter((name) => installed[name]) : [choice];
|
|
175
|
+
const picked = {};
|
|
176
|
+
for (const name of names) {
|
|
177
|
+
if (!RUNNERS[name])
|
|
178
|
+
throw new Error(`--adapter must be auto, claude or codex, not ${name}.`);
|
|
179
|
+
const binary = installed[name];
|
|
180
|
+
if (!binary)
|
|
181
|
+
throw new Error(`${name} is not installed on this computer (not on PATH).`);
|
|
182
|
+
picked[name] = (input) => RUNNERS[name]({ ...input, binary });
|
|
183
|
+
}
|
|
184
|
+
return picked;
|
|
185
|
+
}
|
|
186
|
+
function scheduleRotation(client) {
|
|
187
|
+
const handle = { timer: undefined };
|
|
188
|
+
const run = async () => {
|
|
189
|
+
try {
|
|
190
|
+
const file = await readMachineFile();
|
|
191
|
+
if (file) {
|
|
192
|
+
const next = await rotateMachineKey({ file, path: getMachinePath() });
|
|
193
|
+
client.setKey(next.key);
|
|
194
|
+
process.stderr.write("machine: key rotated\n");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
process.stderr.write(`machine: key rotation failed, retrying in an hour: ${error.message}\n`);
|
|
199
|
+
handle.timer = setTimeout(run, 60 * 60_000);
|
|
200
|
+
handle.timer.unref?.();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
handle.timer = setTimeout(run, ROTATE_EVERY_MS);
|
|
204
|
+
handle.timer.unref?.();
|
|
205
|
+
};
|
|
206
|
+
void readMachineFile().then((file) => {
|
|
207
|
+
handle.timer = setTimeout(run, file ? nextRotationDelay(file) : ROTATE_EVERY_MS);
|
|
208
|
+
handle.timer.unref?.();
|
|
209
|
+
});
|
|
210
|
+
return handle;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=machine.js.map
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
3
|
import { homedir } from "node:os";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
5
|
+
import { writeMachineFileAtomic } from "./machine/rotate.js";
|
|
4
6
|
export const DEFAULT_BASE_URL = "https://work-rooms-api.wizeup.app";
|
|
5
7
|
const configPath = join(homedir(), ".workcord", "config.json");
|
|
6
8
|
export async function readConfig() {
|
|
@@ -55,4 +57,54 @@ export async function saveConfig(update) {
|
|
|
55
57
|
export function getConfigPath() {
|
|
56
58
|
return configPath;
|
|
57
59
|
}
|
|
60
|
+
// A file of its own: saveConfig writes back only the fields readConfig knows, so a
|
|
61
|
+
// machine key kept in config.json would be erased by an older CLI's `auth login --save`.
|
|
62
|
+
const machinePath = join(homedir(), ".workcord", "machine.json");
|
|
63
|
+
export async function readMachineFile() {
|
|
64
|
+
try {
|
|
65
|
+
const value = JSON.parse(await readFile(machinePath, "utf8"));
|
|
66
|
+
if (typeof value?.key !== "string" || typeof value.machineId !== "string")
|
|
67
|
+
return undefined;
|
|
68
|
+
return {
|
|
69
|
+
machineId: value.machineId,
|
|
70
|
+
key: value.key,
|
|
71
|
+
baseUrl: typeof value.baseUrl === "string" ? value.baseUrl : "",
|
|
72
|
+
name: typeof value.name === "string" ? value.name : "",
|
|
73
|
+
...(typeof value.rotatedAt === "string" ? { rotatedAt: value.rotatedAt } : {}),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
if (err.code === "ENOENT")
|
|
78
|
+
return undefined;
|
|
79
|
+
throw new Error(`Could not read ${machinePath}: ${err.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export async function saveMachineFile(file) {
|
|
83
|
+
await mkdir(dirname(machinePath), { recursive: true, mode: 0o700 });
|
|
84
|
+
await chmod(dirname(machinePath), 0o700);
|
|
85
|
+
await writeMachineFileAtomic(machinePath, file);
|
|
86
|
+
}
|
|
87
|
+
export async function deleteMachineFile() {
|
|
88
|
+
await rm(machinePath, { force: true });
|
|
89
|
+
}
|
|
90
|
+
export function getMachinePath() {
|
|
91
|
+
return machinePath;
|
|
92
|
+
}
|
|
93
|
+
const machineLockPath = join(homedir(), ".workcord", "machine.pid");
|
|
94
|
+
const installationIdPath = join(homedir(), ".workcord", "installation_id");
|
|
95
|
+
export function getMachineLockPath() {
|
|
96
|
+
return machineLockPath;
|
|
97
|
+
}
|
|
98
|
+
export function getMachineThreadsPath() {
|
|
99
|
+
return join(homedir(), ".workcord", "machine-threads.json");
|
|
100
|
+
}
|
|
101
|
+
export async function readOrCreateInstallationId(path = installationIdPath) {
|
|
102
|
+
const existing = (await readFile(path, "utf8").catch(() => "")).trim();
|
|
103
|
+
if (existing)
|
|
104
|
+
return existing;
|
|
105
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
106
|
+
const id = randomUUID();
|
|
107
|
+
await writeFile(path, `${id}\n`, { mode: 0o600 });
|
|
108
|
+
return id;
|
|
109
|
+
}
|
|
58
110
|
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { call } from "../../client.js";
|
|
2
|
+
import { actingUserId } from "../../auth.js";
|
|
3
|
+
import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
|
|
4
|
+
export function register(program) {
|
|
5
|
+
const group = getOrCreateGroup(program, "browser-assistance", "BrowserAssistance operations");
|
|
6
|
+
if (!hasSubcommand(group, "status")) {
|
|
7
|
+
group
|
|
8
|
+
.command("status")
|
|
9
|
+
.description("GET /api/v1/rooms/{roomId}/messages/{messageId}/browser-assistance")
|
|
10
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
11
|
+
.requiredOption("--message-id <value>", "messageId (path param)")
|
|
12
|
+
.action(async (opts) => {
|
|
13
|
+
const as = actingUserId(program);
|
|
14
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/messages/${encodeURIComponent(opts.messageId)}/browser-assistance`;
|
|
15
|
+
const data = await call({ method: "GET", path, asUserId: as });
|
|
16
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
if (!hasSubcommand(group, "grant")) {
|
|
20
|
+
group
|
|
21
|
+
.command("grant")
|
|
22
|
+
.description("POST /api/v1/rooms/{roomId}/messages/{messageId}/browser-assistance/viewer-grants")
|
|
23
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
24
|
+
.requiredOption("--message-id <value>", "messageId (path param)")
|
|
25
|
+
.option("--body <json>", "request body as JSON (no schema available)")
|
|
26
|
+
.action(async (opts) => {
|
|
27
|
+
const as = actingUserId(program);
|
|
28
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/messages/${encodeURIComponent(opts.messageId)}/browser-assistance/viewer-grants`;
|
|
29
|
+
const body = opts.body ? JSON.parse(opts.body) : undefined;
|
|
30
|
+
const data = await call({ method: "POST", path, asUserId: as, body });
|
|
31
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (!hasSubcommand(group, "complete")) {
|
|
35
|
+
group
|
|
36
|
+
.command("complete")
|
|
37
|
+
.description("POST /api/v1/rooms/{roomId}/messages/{messageId}/browser-assistance/complete")
|
|
38
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
39
|
+
.requiredOption("--message-id <value>", "messageId (path param)")
|
|
40
|
+
.option("--body <json>", "request body as JSON (no schema available)")
|
|
41
|
+
.action(async (opts) => {
|
|
42
|
+
const as = actingUserId(program);
|
|
43
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/messages/${encodeURIComponent(opts.messageId)}/browser-assistance/complete`;
|
|
44
|
+
const body = opts.body ? JSON.parse(opts.body) : undefined;
|
|
45
|
+
const data = await call({ method: "POST", path, asUserId: as, body });
|
|
46
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (!hasSubcommand(group, "cancel")) {
|
|
50
|
+
group
|
|
51
|
+
.command("cancel")
|
|
52
|
+
.description("POST /api/v1/rooms/{roomId}/messages/{messageId}/browser-assistance/cancel")
|
|
53
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
54
|
+
.requiredOption("--message-id <value>", "messageId (path param)")
|
|
55
|
+
.option("--body <json>", "request body as JSON (no schema available)")
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
const as = actingUserId(program);
|
|
58
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/messages/${encodeURIComponent(opts.messageId)}/browser-assistance/cancel`;
|
|
59
|
+
const body = opts.body ? JSON.parse(opts.body) : undefined;
|
|
60
|
+
const data = await call({ method: "POST", path, asUserId: as, body });
|
|
61
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=browser-assistance.js.map
|
|
@@ -43,6 +43,19 @@ export function register(program) {
|
|
|
43
43
|
process.stdout.write(JSON.stringify(data) + "\n");
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
+
if (!hasSubcommand(group, "remove-voice-agent")) {
|
|
47
|
+
group
|
|
48
|
+
.command("remove-voice-agent")
|
|
49
|
+
.description("DELETE /api/v1/rooms/{roomId}/call/voice-agent/{agentId}")
|
|
50
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
51
|
+
.requiredOption("--agent-id <value>", "agentId (path param)")
|
|
52
|
+
.action(async (opts) => {
|
|
53
|
+
const as = actingUserId(program);
|
|
54
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/call/voice-agent/${encodeURIComponent(opts.agentId)}`;
|
|
55
|
+
const data = await call({ method: "DELETE", path, asUserId: as });
|
|
56
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
57
|
+
});
|
|
58
|
+
}
|
|
46
59
|
if (!hasSubcommand(group, "silence-voice-agent")) {
|
|
47
60
|
group
|
|
48
61
|
.command("silence-voice-agent")
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { call } from "../../client.js";
|
|
2
|
+
import { actingUserId } from "../../auth.js";
|
|
3
|
+
import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
|
|
4
|
+
export function register(program) {
|
|
5
|
+
const group = getOrCreateGroup(program, "client-config", "ClientConfig operations");
|
|
6
|
+
if (!hasSubcommand(group, "get")) {
|
|
7
|
+
group
|
|
8
|
+
.command("get")
|
|
9
|
+
.description("GET /api/v1/client-config")
|
|
10
|
+
.action(async (opts) => {
|
|
11
|
+
const as = actingUserId(program);
|
|
12
|
+
const path = `/api/v1/client-config`;
|
|
13
|
+
const data = await call({ method: "GET", path, asUserId: as });
|
|
14
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=client-config.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { call } from "../../client.js";
|
|
2
|
+
import { actingUserId } from "../../auth.js";
|
|
3
|
+
import { getOrCreateGroup, hasSubcommand } from "../_helpers.js";
|
|
4
|
+
export function register(program) {
|
|
5
|
+
const group = getOrCreateGroup(program, "dashboard-actions", "DashboardActions operations");
|
|
6
|
+
if (!hasSubcommand(group, "run")) {
|
|
7
|
+
group
|
|
8
|
+
.command("run")
|
|
9
|
+
.description("POST /api/v1/rooms/{roomId}/dashboard/actions/{handlerId}/requests")
|
|
10
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
11
|
+
.requiredOption("--handler-id <value>", "handlerId (path param)")
|
|
12
|
+
.option("--body <json>", "request body as JSON (no schema available)")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const as = actingUserId(program);
|
|
15
|
+
const path = `/api/v1/rooms/${encodeURIComponent(opts.roomId)}/dashboard/actions/${encodeURIComponent(opts.handlerId)}/requests`;
|
|
16
|
+
const body = opts.body ? JSON.parse(opts.body) : undefined;
|
|
17
|
+
const data = await call({ method: "POST", path, asUserId: as, body });
|
|
18
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
if (!hasSubcommand(group, "app-actions-script")) {
|
|
22
|
+
group
|
|
23
|
+
.command("app-actions-script")
|
|
24
|
+
.description("GET /api/v1/dashboard/app-actions.js")
|
|
25
|
+
.action(async (opts) => {
|
|
26
|
+
const as = actingUserId(program);
|
|
27
|
+
const path = `/api/v1/dashboard/app-actions.js`;
|
|
28
|
+
const data = await call({ method: "GET", path, asUserId: as });
|
|
29
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=dashboard-actions.js.map
|
|
@@ -84,6 +84,31 @@ export function register(program) {
|
|
|
84
84
|
process.stdout.write(JSON.stringify(data) + "\n");
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
|
+
if (!hasSubcommand(group, "list-auto-join-rooms")) {
|
|
88
|
+
group
|
|
89
|
+
.command("list-auto-join-rooms")
|
|
90
|
+
.description("GET /api/v1/internal/rooms/auto-join")
|
|
91
|
+
.action(async (opts) => {
|
|
92
|
+
const as = actingUserId(program);
|
|
93
|
+
const path = `/api/v1/internal/rooms/auto-join`;
|
|
94
|
+
const data = await call({ method: "GET", path, asUserId: as });
|
|
95
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (!hasSubcommand(group, "set-room-auto-join")) {
|
|
99
|
+
group
|
|
100
|
+
.command("set-room-auto-join")
|
|
101
|
+
.description("PUT /api/v1/internal/rooms/{roomId}/auto-join")
|
|
102
|
+
.requiredOption("--room-id <value>", "roomId (path param)")
|
|
103
|
+
.option("--body <json>", "request body as JSON (no schema available)")
|
|
104
|
+
.action(async (opts) => {
|
|
105
|
+
const as = actingUserId(program);
|
|
106
|
+
const path = `/api/v1/internal/rooms/${encodeURIComponent(opts.roomId)}/auto-join`;
|
|
107
|
+
const body = opts.body ? JSON.parse(opts.body) : undefined;
|
|
108
|
+
const data = await call({ method: "PUT", path, asUserId: as, body });
|
|
109
|
+
process.stdout.write(JSON.stringify(data) + "\n");
|
|
110
|
+
});
|
|
111
|
+
}
|
|
87
112
|
if (!hasSubcommand(group, "voice-dispatch")) {
|
|
88
113
|
group
|
|
89
114
|
.command("voice-dispatch")
|