@skrr-ai/cli 0.1.87 → 0.1.88
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/dist/commands/agents/chat.js +27 -1
- package/dist/commands/computer/index.d.ts +19 -0
- package/dist/commands/computer/index.js +37 -0
- package/dist/commands/labels/create.d.ts +1 -0
- package/dist/commands/labels/create.js +2 -0
- package/dist/commands/labels/restore.d.ts +1 -0
- package/dist/commands/labels/restore.js +6 -3
- package/dist/commands/labels/update.d.ts +1 -0
- package/dist/commands/labels/update.js +2 -0
- package/dist/commands/machines/computer-adoption.d.ts +15 -0
- package/dist/commands/machines/computer-adoption.js +33 -0
- package/dist/commands/machines/dedicated/archive.d.ts +26 -0
- package/dist/commands/machines/dedicated/archive.js +113 -0
- package/dist/commands/machines/dedicated/audit.d.ts +25 -0
- package/dist/commands/machines/dedicated/audit.js +113 -0
- package/dist/commands/machines/dedicated/computer.d.ts +23 -0
- package/dist/commands/machines/dedicated/computer.js +64 -0
- package/dist/commands/machines/dedicated/cp.d.ts +2 -0
- package/dist/commands/machines/dedicated/cp.js +74 -2
- package/dist/commands/machines/dedicated/git-status.d.ts +15 -0
- package/dist/commands/machines/dedicated/git-status.js +56 -0
- package/dist/commands/machines/dedicated/index.js +15 -1
- package/dist/commands/machines/dedicated/ls.d.ts +27 -0
- package/dist/commands/machines/dedicated/ls.js +100 -0
- package/dist/commands/machines/dedicated/mkdir.d.ts +18 -0
- package/dist/commands/machines/dedicated/mkdir.js +57 -0
- package/dist/commands/machines/dedicated/mv.d.ts +24 -0
- package/dist/commands/machines/dedicated/mv.js +83 -0
- package/dist/commands/machines/dedicated/rm.d.ts +26 -0
- package/dist/commands/machines/dedicated/rm.js +100 -0
- package/dist/commands/machines/dedicated/search.d.ts +24 -0
- package/dist/commands/machines/dedicated/search.js +78 -0
- package/dist/commands/machines/dedicated/stat.d.ts +22 -0
- package/dist/commands/machines/dedicated/stat.js +92 -0
- package/dist/commands/machines/hosted/index.js +1 -1
- package/dist/commands/machines/hosted/list.js +1 -1
- package/dist/commands/machines/hosted/start.js +1 -1
- package/dist/commands/machines/services/declare.d.ts +24 -0
- package/dist/commands/machines/services/declare.js +73 -0
- package/dist/commands/machines/services/index.d.ts +15 -0
- package/dist/commands/machines/services/index.js +31 -0
- package/dist/commands/machines/services/ls.d.ts +17 -0
- package/dist/commands/machines/services/ls.js +60 -0
- package/dist/commands/machines/services/withdraw.d.ts +19 -0
- package/dist/commands/machines/services/withdraw.js +47 -0
- package/dist/commands/machines/share.d.ts +29 -0
- package/dist/commands/machines/share.js +100 -0
- package/dist/commands/machines/shared.d.ts +19 -0
- package/dist/commands/machines/shared.js +62 -0
- package/dist/commands/machines/shares.d.ts +16 -0
- package/dist/commands/machines/shares.js +69 -0
- package/dist/commands/machines/unshare.d.ts +19 -0
- package/dist/commands/machines/unshare.js +61 -0
- package/dist/commands/tasks/labels/create.d.ts +1 -0
- package/dist/commands/tasks/labels/create.js +3 -0
- package/dist/commands/views/create.d.ts +1 -0
- package/dist/commands/views/create.js +5 -0
- package/dist/lib/agent-home-workspace.d.ts +7 -0
- package/dist/lib/agent-home-workspace.js +147 -0
- package/dist/lib/computer-adoption.d.ts +55 -0
- package/dist/lib/computer-adoption.js +67 -0
- package/dist/lib/computer-consent.d.ts +13 -0
- package/dist/lib/computer-consent.js +33 -0
- package/dist/lib/computer-files.d.ts +239 -0
- package/dist/lib/computer-files.js +707 -0
- package/dist/lib/dedicated-copy.d.ts +45 -9
- package/dist/lib/dedicated-copy.js +141 -44
- package/dist/lib/dedicated-machines.d.ts +49 -0
- package/dist/lib/dedicated-machines.js +97 -6
- package/dist/lib/label-scope.d.ts +12 -0
- package/dist/lib/label-scope.js +15 -1
- package/dist/lib/machine-audit.d.ts +34 -0
- package/dist/lib/machine-audit.js +50 -0
- package/dist/lib/machine-grants.d.ts +70 -0
- package/dist/lib/machine-grants.js +47 -0
- package/dist/lib/machine-services.d.ts +64 -0
- package/dist/lib/machine-services.js +60 -0
- package/dist/lib/task-view-render.d.ts +2 -0
- package/dist/lib/task-view-render.js +1 -1
- package/dist/lib/views/vocabulary.d.ts +1 -1
- package/dist/lib/views/vocabulary.js +2 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.d.ts +955 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/computerWire.js +1070 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonToolApproval.js +7 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.d.ts +955 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/computerWire.js +1051 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonToolApproval.js +7 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +11 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +22143 -20728
- package/dist/node_modules/@skrr-ai/data-provider/package.json +1 -1
- package/oclif.manifest.json +11550 -9963
- package/package.json +2 -2
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
|
+
const computer_files_1 = require("../../../lib/computer-files");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr machines dedicated rm` — delete one path on the machine.
|
|
8
|
+
*
|
|
9
|
+
* As `rm` does: a directory needs --recursive and is refused `not_empty`
|
|
10
|
+
* without it. `--tag` is the optimistic-concurrency fence — the tag `stat`
|
|
11
|
+
* prints; a file that changed since that read is refused `file_changed`, so a
|
|
12
|
+
* scripted delete never removes a version it never saw. For `--recursive` the
|
|
13
|
+
* tag must be the folder's CONTENTS tag (`stat --contents`): anything changed
|
|
14
|
+
* inside the folder since is refused. `--recursive` without `--tag` is unfenced.
|
|
15
|
+
*/
|
|
16
|
+
class DedicatedMachinesRm extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
17
|
+
static summary = 'Delete a file or folder on a Dedicated Runtime machine';
|
|
18
|
+
static description = 'Deletes one path inside repos/ or user-data/, as the workload user. A ' +
|
|
19
|
+
'folder needs --recursive and is refused without it. --tag takes the tag ' +
|
|
20
|
+
'`stat` prints and refuses the delete when the path changed since. With ' +
|
|
21
|
+
"--recursive, --tag must be the folder's contents tag from `stat --contents` " +
|
|
22
|
+
'(inode:size:mtimeNs:contents), and the delete is refused if anything inside ' +
|
|
23
|
+
'the folder changed since; --recursive without --tag deletes whatever the ' +
|
|
24
|
+
'folder holds at that moment (unfenced). There is no trash: a deleted path is gone.';
|
|
25
|
+
static examples = [
|
|
26
|
+
'<%= config.bin %> machines dedicated rm rtl_abc123 user-data/notes/draft.md',
|
|
27
|
+
'<%= config.bin %> machines dedicated rm rtl_abc123 repos/app/dist --recursive',
|
|
28
|
+
'<%= config.bin %> machines dedicated rm rtl_abc123 repos/app/lock --tag 12345:3182:1761234567890000000',
|
|
29
|
+
'<%= config.bin %> machines dedicated rm rtl_abc123 repos/app/dist --recursive --tag <tag from `stat --contents`>',
|
|
30
|
+
];
|
|
31
|
+
static args = {
|
|
32
|
+
lease: core_1.Args.string({
|
|
33
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
34
|
+
required: true,
|
|
35
|
+
ignoreStdin: true,
|
|
36
|
+
}),
|
|
37
|
+
path: core_1.Args.string({
|
|
38
|
+
description: 'Path to delete, relative to /workspace (inside repos/ or user-data/)',
|
|
39
|
+
required: true,
|
|
40
|
+
ignoreStdin: true,
|
|
41
|
+
}),
|
|
42
|
+
};
|
|
43
|
+
static flags = {
|
|
44
|
+
recursive: core_1.Flags.boolean({
|
|
45
|
+
char: 'r',
|
|
46
|
+
description: 'Delete a folder and everything in it',
|
|
47
|
+
}),
|
|
48
|
+
tag: core_1.Flags.string({
|
|
49
|
+
description: 'Refuse unless the path still has this tag — the <inode>:<size>:<mtimeNs> `stat` prints; with --recursive, the <inode>:<size>:<mtimeNs>:<contents> tag `stat --contents` prints',
|
|
50
|
+
}),
|
|
51
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
52
|
+
};
|
|
53
|
+
async run() {
|
|
54
|
+
this.requireAuth();
|
|
55
|
+
const { args, flags } = await this.parse(DedicatedMachinesRm);
|
|
56
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
57
|
+
let tag;
|
|
58
|
+
if (flags.tag !== undefined) {
|
|
59
|
+
try {
|
|
60
|
+
tag = (0, computer_files_1.parseComputerFileTag)(flags.tag);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
this.error(err.message, { exit: 2 });
|
|
64
|
+
}
|
|
65
|
+
// Said here rather than spent on a round trip the server would refuse
|
|
66
|
+
// (`contents_tag_required`): a folder's own tag covers only its direct
|
|
67
|
+
// entries, which is not what a recursive delete erases.
|
|
68
|
+
if (flags.recursive === true && tag?.contents === undefined) {
|
|
69
|
+
this.error(`--recursive --tag needs the folder's contents tag, which covers everything inside it. Read it with \`${this.config.bin} machines dedicated stat ${leaseId} ${args.path} --contents\` and pass that tag.`, { exit: 2 });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
let result;
|
|
73
|
+
try {
|
|
74
|
+
const scope = this.scopeFrom(flags);
|
|
75
|
+
const generation = await (0, computer_files_1.resolveDedicatedFileGeneration)(leaseId, scope);
|
|
76
|
+
result = await (0, computer_files_1.deleteComputerFile)(leaseId, {
|
|
77
|
+
path: args.path,
|
|
78
|
+
generation,
|
|
79
|
+
...(tag ? { tag } : {}),
|
|
80
|
+
recursive: flags.recursive === true,
|
|
81
|
+
}, scope);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
const failure = (0, computer_files_1.describeComputerFileFailure)(err, {
|
|
85
|
+
bin: this.config.bin,
|
|
86
|
+
leaseId,
|
|
87
|
+
takesTag: true,
|
|
88
|
+
});
|
|
89
|
+
if (failure)
|
|
90
|
+
this.failWithCliError({ ...failure, exit: 1 });
|
|
91
|
+
this.handleApiError(err);
|
|
92
|
+
}
|
|
93
|
+
if (flags.json) {
|
|
94
|
+
this.log(JSON.stringify({ ...result, deleted: true }, null, 2));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
this.log(`Deleted ${result.path}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.default = DedicatedMachinesRm;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines dedicated search` — find files by name, or text inside them,
|
|
4
|
+
* under one folder. Guest-only today; the answer states whether it is whole.
|
|
5
|
+
*/
|
|
6
|
+
export default class DedicatedMachinesSearch extends DedicatedLeaseCommand {
|
|
7
|
+
static summary: string;
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static args: {
|
|
11
|
+
lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
|
+
path: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
13
|
+
};
|
|
14
|
+
static flags: {
|
|
15
|
+
query: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
16
|
+
content: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
'no-ignore': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
'case-sensitive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
'budget-ms': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
5
|
+
const computer_files_1 = require("../../../lib/computer-files");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr machines dedicated search` — find files by name, or text inside them,
|
|
8
|
+
* under one folder. Guest-only today; the answer states whether it is whole.
|
|
9
|
+
*/
|
|
10
|
+
class DedicatedMachinesSearch extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
11
|
+
static summary = 'Search a folder on a Dedicated Runtime machine';
|
|
12
|
+
static description = 'Finds files by name, or with --content lines containing the text, under one folder. ' +
|
|
13
|
+
'.gitignore is honoured unless --no-ignore. The search is bounded: it stops at the result ' +
|
|
14
|
+
'limit or at a time bound, and says which — a truncated or "still searching" answer is ' +
|
|
15
|
+
'never printed as complete. Available on dedicated machines, not on a personal machine.';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> machines dedicated search rtl_abc123 repos/app --query package.json',
|
|
18
|
+
'<%= config.bin %> machines dedicated search rtl_abc123 repos/app --query TODO --content --limit 50',
|
|
19
|
+
'<%= config.bin %> machines dedicated search rtl_abc123 repos/app --query dist --no-ignore --json',
|
|
20
|
+
];
|
|
21
|
+
static args = {
|
|
22
|
+
lease: core_1.Args.string({
|
|
23
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
24
|
+
required: true,
|
|
25
|
+
ignoreStdin: true,
|
|
26
|
+
}),
|
|
27
|
+
path: core_1.Args.string({
|
|
28
|
+
description: 'Folder to search under, relative to /workspace (inside repos/ or user-data/)',
|
|
29
|
+
required: true,
|
|
30
|
+
ignoreStdin: true,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
static flags = {
|
|
34
|
+
query: core_1.Flags.string({
|
|
35
|
+
description: 'Text to look for (one line, at most 200 characters)',
|
|
36
|
+
required: true,
|
|
37
|
+
}),
|
|
38
|
+
content: core_1.Flags.boolean({ description: 'Search inside files instead of file names' }),
|
|
39
|
+
'no-ignore': core_1.Flags.boolean({ description: 'Also search what .gitignore excludes' }),
|
|
40
|
+
'case-sensitive': core_1.Flags.boolean({ description: 'Match case exactly' }),
|
|
41
|
+
limit: core_1.Flags.integer({ description: 'Most results to return (at most 1000)' }),
|
|
42
|
+
'budget-ms': core_1.Flags.integer({ description: 'Time bound in milliseconds (at most 20000)' }),
|
|
43
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
44
|
+
};
|
|
45
|
+
async run() {
|
|
46
|
+
this.requireAuth();
|
|
47
|
+
const { args, flags } = await this.parse(DedicatedMachinesSearch);
|
|
48
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
49
|
+
let result;
|
|
50
|
+
try {
|
|
51
|
+
const scope = this.scopeFrom(flags);
|
|
52
|
+
const generation = await (0, computer_files_1.resolveDedicatedFileGeneration)(leaseId, scope);
|
|
53
|
+
result = await (0, computer_files_1.searchComputerFiles)(leaseId, {
|
|
54
|
+
path: args.path,
|
|
55
|
+
generation,
|
|
56
|
+
query: flags.query,
|
|
57
|
+
content: flags.content,
|
|
58
|
+
...(flags['no-ignore'] ? { respectIgnore: false } : {}),
|
|
59
|
+
caseSensitive: flags['case-sensitive'],
|
|
60
|
+
...(flags.limit !== undefined ? { limit: flags.limit } : {}),
|
|
61
|
+
...(flags['budget-ms'] !== undefined ? { budgetMs: flags['budget-ms'] } : {}),
|
|
62
|
+
}, scope);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const failure = (0, computer_files_1.describeComputerFileFailure)(err, { bin: this.config.bin, leaseId });
|
|
66
|
+
if (failure)
|
|
67
|
+
this.failWithCliError({ ...failure, exit: 1 });
|
|
68
|
+
this.handleApiError(err);
|
|
69
|
+
}
|
|
70
|
+
if (flags.json) {
|
|
71
|
+
this.log(JSON.stringify(result, null, 2));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
for (const line of (0, computer_files_1.computerFileSearchLines)(result))
|
|
75
|
+
this.log(line);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.default = DedicatedMachinesSearch;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ComputerFileStatResult } from '@skrr-ai/data-provider';
|
|
2
|
+
import { DedicatedLeaseCommand } from '../../../lib/dedicated-lease-command';
|
|
3
|
+
/** The `stat` read-out, as lines. Pure so a spec can pin it. */
|
|
4
|
+
export declare function computerFileStatLines(result: ComputerFileStatResult): string[];
|
|
5
|
+
/**
|
|
6
|
+
* `skrr machines dedicated stat` — one path's facts, including the entity tag
|
|
7
|
+
* a `mv`/`rm`/`file_changed` retry presents.
|
|
8
|
+
*/
|
|
9
|
+
export default class DedicatedMachinesStat extends DedicatedLeaseCommand {
|
|
10
|
+
static summary: string;
|
|
11
|
+
static description: string;
|
|
12
|
+
static examples: string[];
|
|
13
|
+
static args: {
|
|
14
|
+
lease: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
path: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
16
|
+
};
|
|
17
|
+
static flags: {
|
|
18
|
+
contents: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.computerFileStatLines = computerFileStatLines;
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const dedicated_lease_command_1 = require("../../../lib/dedicated-lease-command");
|
|
6
|
+
const computer_files_1 = require("../../../lib/computer-files");
|
|
7
|
+
/** The `stat` read-out, as lines. Pure so a spec can pin it. */
|
|
8
|
+
function computerFileStatLines(result) {
|
|
9
|
+
const { entry } = result;
|
|
10
|
+
const lines = [entry.path];
|
|
11
|
+
const row = (label, value) => {
|
|
12
|
+
if (value === undefined || value === null || value === '')
|
|
13
|
+
return;
|
|
14
|
+
lines.push(` ${`${label} `.padEnd(12)}${value}`);
|
|
15
|
+
};
|
|
16
|
+
row('type', entry.type);
|
|
17
|
+
row('size', `${entry.size} bytes`);
|
|
18
|
+
row('modified', Number.isFinite(entry.mtimeMs) ? new Date(entry.mtimeMs).toISOString() : undefined);
|
|
19
|
+
row('mode', `${entry.mode.toString(8).padStart(4, '0')} (${(0, computer_files_1.computerFileModeString)(entry.type, entry.mode)})`);
|
|
20
|
+
row('link target', entry.linkTarget);
|
|
21
|
+
if (entry.withheld) {
|
|
22
|
+
row('withheld', `${entry.withheld.reason}${entry.withheld.rule ? ` (${entry.withheld.rule})` : ''}`);
|
|
23
|
+
}
|
|
24
|
+
// `--contents` on a folder: how much a fenced `rm -r --tag` would erase.
|
|
25
|
+
if (result.entries !== undefined) {
|
|
26
|
+
row('contains', `${result.entries} entr${result.entries === 1 ? 'y' : 'ies'}, at every depth`);
|
|
27
|
+
}
|
|
28
|
+
// The tag is what `--tag` on mv and rm takes back, spelled the same way — for
|
|
29
|
+
// a folder read with --contents, with its contents digest as a fourth part.
|
|
30
|
+
row('tag', result.tag ? (0, computer_files_1.computerFileTagString)(result.tag) : undefined);
|
|
31
|
+
return lines;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* `skrr machines dedicated stat` — one path's facts, including the entity tag
|
|
35
|
+
* a `mv`/`rm`/`file_changed` retry presents.
|
|
36
|
+
*/
|
|
37
|
+
class DedicatedMachinesStat extends dedicated_lease_command_1.DedicatedLeaseCommand {
|
|
38
|
+
static summary = 'Show one path on a Dedicated Runtime machine, with its tag';
|
|
39
|
+
static description = 'Type, size, mtime, mode and link target of one path on the machine, plus its entity tag, ' +
|
|
40
|
+
'the optimistic-concurrency token --tag on `mv` and `rm` (and --if-tag on `cp`) accepts. ' +
|
|
41
|
+
'With --contents, a folder is also walked: its tag gains a fourth part, a digest of everything ' +
|
|
42
|
+
'inside it, and the entry count is shown — the tag `rm --recursive --tag` needs, so a fenced ' +
|
|
43
|
+
'recursive delete can only erase what you were shown. A path the machine withholds is answered ' +
|
|
44
|
+
'as a refusal.';
|
|
45
|
+
static examples = [
|
|
46
|
+
'<%= config.bin %> machines dedicated stat rtl_abc123 repos/app/package.json',
|
|
47
|
+
'<%= config.bin %> machines dedicated stat rtl_abc123 repos/app --json',
|
|
48
|
+
'<%= config.bin %> machines dedicated stat rtl_abc123 repos/app/dist --contents',
|
|
49
|
+
];
|
|
50
|
+
static args = {
|
|
51
|
+
lease: core_1.Args.string({
|
|
52
|
+
description: dedicated_lease_command_1.DEDICATED_LEASE_ARG_DESCRIPTION,
|
|
53
|
+
required: true,
|
|
54
|
+
ignoreStdin: true,
|
|
55
|
+
}),
|
|
56
|
+
path: core_1.Args.string({
|
|
57
|
+
description: 'Path on the machine, relative to /workspace',
|
|
58
|
+
required: true,
|
|
59
|
+
ignoreStdin: true,
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
static flags = {
|
|
63
|
+
contents: core_1.Flags.boolean({
|
|
64
|
+
description: 'For a folder: walk it and show its contents tag and entry count (for `rm --recursive --tag`)',
|
|
65
|
+
}),
|
|
66
|
+
json: core_1.Flags.boolean({ description: 'Output the result as JSON' }),
|
|
67
|
+
};
|
|
68
|
+
async run() {
|
|
69
|
+
this.requireAuth();
|
|
70
|
+
const { args, flags } = await this.parse(DedicatedMachinesStat);
|
|
71
|
+
const leaseId = await this.resolveLeaseArg(args.lease);
|
|
72
|
+
let result;
|
|
73
|
+
try {
|
|
74
|
+
const scope = this.scopeFrom(flags);
|
|
75
|
+
const generation = await (0, computer_files_1.resolveDedicatedFileGeneration)(leaseId, scope);
|
|
76
|
+
result = await (0, computer_files_1.statComputerFile)(leaseId, { path: args.path, generation, ...(flags.contents ? { contents: true } : {}) }, scope);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
const failure = (0, computer_files_1.describeComputerFileFailure)(err, { bin: this.config.bin, leaseId });
|
|
80
|
+
if (failure)
|
|
81
|
+
this.failWithCliError({ ...failure, exit: 1 });
|
|
82
|
+
this.handleApiError(err);
|
|
83
|
+
}
|
|
84
|
+
if (flags.json) {
|
|
85
|
+
this.log(JSON.stringify(result, null, 2));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
for (const line of computerFileStatLines(result))
|
|
89
|
+
this.log(line);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.default = DedicatedMachinesStat;
|
|
@@ -14,7 +14,7 @@ class Machines extends core_1.Command {
|
|
|
14
14
|
'<%= config.bin %> machines hosted connect <machine-id>',
|
|
15
15
|
];
|
|
16
16
|
async run() {
|
|
17
|
-
this.log('
|
|
17
|
+
this.log('Skrr Hosted Machine commands:');
|
|
18
18
|
this.log(' skrr machines hosted start start a hosted machine');
|
|
19
19
|
this.log(' skrr machines hosted list list Hosted Machine sessions');
|
|
20
20
|
this.log(' skrr machines hosted status show machine status');
|
|
@@ -6,7 +6,7 @@ const api_fetch_1 = require("../../../lib/api-fetch");
|
|
|
6
6
|
const format_1 = require("../../../lib/format");
|
|
7
7
|
const hosted_machines_1 = require("../../../lib/hosted-machines");
|
|
8
8
|
class HostedMachinesList extends base_command_1.BaseCommand {
|
|
9
|
-
static description = 'List
|
|
9
|
+
static description = 'List Skrr Hosted Machine sessions';
|
|
10
10
|
static examples = [
|
|
11
11
|
'<%= config.bin %> machines hosted list',
|
|
12
12
|
'<%= config.bin %> machines hosted list --workspace <workspace-id>',
|
|
@@ -5,7 +5,7 @@ const node_crypto_1 = require("node:crypto");
|
|
|
5
5
|
const base_command_1 = require("../../../base-command");
|
|
6
6
|
const hosted_machines_1 = require("../../../lib/hosted-machines");
|
|
7
7
|
class HostedMachinesStart extends base_command_1.BaseCommand {
|
|
8
|
-
static description = 'Start a
|
|
8
|
+
static description = 'Start a Skrr Hosted Machine';
|
|
9
9
|
static examples = [
|
|
10
10
|
'<%= config.bin %> machines hosted start --name scratch --wait',
|
|
11
11
|
'<%= config.bin %> machines hosted start --repo acme/app --installation-id 123 --branch main --wait',
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines services declare` — name a web service running on a machine
|
|
4
|
+
* so its computer's Services app can open it (design §20.5; 9-17, OSK-13579).
|
|
5
|
+
* A service is a port on the machine's own loopback and an optional path —
|
|
6
|
+
* never a host or a URL. Declaring a name again replaces it. Needs the owner
|
|
7
|
+
* or an operate grant. Declaring starts nothing: the service must already be
|
|
8
|
+
* listening, or opening it shows the browser's own error page.
|
|
9
|
+
*/
|
|
10
|
+
export default class MachinesServicesDeclare extends BaseCommand {
|
|
11
|
+
static description: string;
|
|
12
|
+
static examples: string[];
|
|
13
|
+
static args: {
|
|
14
|
+
machine: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
static flags: {
|
|
17
|
+
name: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
18
|
+
port: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
|
+
path: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
20
|
+
protocol: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
22
|
+
};
|
|
23
|
+
run(): Promise<void>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../../base-command");
|
|
5
|
+
const machine_services_1 = require("../../../lib/machine-services");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr machines services declare` — name a web service running on a machine
|
|
8
|
+
* so its computer's Services app can open it (design §20.5; 9-17, OSK-13579).
|
|
9
|
+
* A service is a port on the machine's own loopback and an optional path —
|
|
10
|
+
* never a host or a URL. Declaring a name again replaces it. Needs the owner
|
|
11
|
+
* or an operate grant. Declaring starts nothing: the service must already be
|
|
12
|
+
* listening, or opening it shows the browser's own error page.
|
|
13
|
+
*/
|
|
14
|
+
class MachinesServicesDeclare extends base_command_1.BaseCommand {
|
|
15
|
+
static description = 'Declare a web service on a machine (a port on the machine, and a path) so its computer can open it';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> machines services declare lease:dr_abc123 --name web --port 5173',
|
|
18
|
+
'<%= config.bin %> machines services declare lease:dr_abc123 --name docs --port 8443 --path /docs/ --protocol https',
|
|
19
|
+
];
|
|
20
|
+
static args = {
|
|
21
|
+
machine: core_1.Args.string({
|
|
22
|
+
ignoreStdin: true,
|
|
23
|
+
description: 'Machine id, uuid, daemon id, name, or a unique prefix',
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
static flags = {
|
|
28
|
+
name: core_1.Flags.string({
|
|
29
|
+
description: 'Lower-case name, e.g. web, api, storybook (declaring it again replaces it)',
|
|
30
|
+
required: true,
|
|
31
|
+
}),
|
|
32
|
+
port: core_1.Flags.integer({
|
|
33
|
+
description: 'The port it listens on, on the machine (1-65535)',
|
|
34
|
+
required: true,
|
|
35
|
+
min: 1,
|
|
36
|
+
max: 65535,
|
|
37
|
+
}),
|
|
38
|
+
path: core_1.Flags.string({ description: 'Absolute path to open, e.g. /docs/ (no query string)' }),
|
|
39
|
+
protocol: core_1.Flags.string({
|
|
40
|
+
description: 'http (default) or https',
|
|
41
|
+
options: [...machine_services_1.DECLARED_SERVICE_PROTOCOLS],
|
|
42
|
+
}),
|
|
43
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
44
|
+
};
|
|
45
|
+
async run() {
|
|
46
|
+
this.requireAuth();
|
|
47
|
+
const { args, flags } = await this.parse(MachinesServicesDeclare);
|
|
48
|
+
let result;
|
|
49
|
+
try {
|
|
50
|
+
result = await (0, machine_services_1.declareMachineService)(await (0, machine_services_1.servicesMachineId)(args.machine), {
|
|
51
|
+
name: flags.name,
|
|
52
|
+
port: flags.port,
|
|
53
|
+
...(flags.path ? { path: flags.path } : {}),
|
|
54
|
+
...(flags.protocol
|
|
55
|
+
? { protocol: flags.protocol }
|
|
56
|
+
: {}),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
this.handleApiError(err);
|
|
61
|
+
}
|
|
62
|
+
if (flags.json) {
|
|
63
|
+
this.log(JSON.stringify(result, null, 2));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const service = result?.service;
|
|
67
|
+
if (!service) {
|
|
68
|
+
this.error('The machine did not say what it stored.', { exit: 1 });
|
|
69
|
+
}
|
|
70
|
+
this.log(`${result?.replaced ? 'Replaced' : 'Declared'} ${service.name} → ${(0, machine_services_1.declaredServiceAddress)(service)} on the machine. Open it from the computer's Services app.`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.default = MachinesServicesDeclare;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines services` — a machine's declared services (design §20.5;
|
|
4
|
+
* 9-17, OSK-13579): the web services an agent or a person started on it, named
|
|
5
|
+
* so the computer's Services app can open them in the computer's own browser.
|
|
6
|
+
*
|
|
7
|
+
* Not `skrr machines dedicated service`, which keeps a WORKLOAD running on a
|
|
8
|
+
* Dedicated Runtime. A declared service is an address — a port on the
|
|
9
|
+
* machine's loopback and a path — and declaring one starts nothing.
|
|
10
|
+
*/
|
|
11
|
+
export default class MachinesServices extends Command {
|
|
12
|
+
static description: string;
|
|
13
|
+
static examples: string[];
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
/**
|
|
5
|
+
* `skrr machines services` — a machine's declared services (design §20.5;
|
|
6
|
+
* 9-17, OSK-13579): the web services an agent or a person started on it, named
|
|
7
|
+
* so the computer's Services app can open them in the computer's own browser.
|
|
8
|
+
*
|
|
9
|
+
* Not `skrr machines dedicated service`, which keeps a WORKLOAD running on a
|
|
10
|
+
* Dedicated Runtime. A declared service is an address — a port on the
|
|
11
|
+
* machine's loopback and a path — and declaring one starts nothing.
|
|
12
|
+
*/
|
|
13
|
+
class MachinesServices extends core_1.Command {
|
|
14
|
+
static description = "Declared services — web services on a machine, named so its computer can open them in the computer's own browser";
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> machines services ls lease:dr_abc123',
|
|
17
|
+
'<%= config.bin %> machines services declare lease:dr_abc123 --name web --port 5173',
|
|
18
|
+
'<%= config.bin %> machines services withdraw lease:dr_abc123 web',
|
|
19
|
+
];
|
|
20
|
+
async run() {
|
|
21
|
+
const rows = [
|
|
22
|
+
['ls', 'list the services declared on a machine'],
|
|
23
|
+
['declare', 'name a port on the machine (and a path) so the computer can open it'],
|
|
24
|
+
['withdraw', 'remove a declared service'],
|
|
25
|
+
];
|
|
26
|
+
this.log('Declared services (skrr machines services <command>):');
|
|
27
|
+
for (const [name, what] of rows)
|
|
28
|
+
this.log(` ${name.padEnd(10)} ${what}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.default = MachinesServices;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines services ls` — the web services declared on a machine (design
|
|
4
|
+
* §20.5; 9-17, OSK-13579), as its daemon holds them now. The owner and anyone
|
|
5
|
+
* the machine is shared with may list them.
|
|
6
|
+
*/
|
|
7
|
+
export default class MachinesServicesLs extends BaseCommand {
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
static args: {
|
|
11
|
+
machine: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
12
|
+
};
|
|
13
|
+
static flags: {
|
|
14
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../../base-command");
|
|
5
|
+
const format_1 = require("../../../lib/format");
|
|
6
|
+
const machine_services_1 = require("../../../lib/machine-services");
|
|
7
|
+
/**
|
|
8
|
+
* `skrr machines services ls` — the web services declared on a machine (design
|
|
9
|
+
* §20.5; 9-17, OSK-13579), as its daemon holds them now. The owner and anyone
|
|
10
|
+
* the machine is shared with may list them.
|
|
11
|
+
*/
|
|
12
|
+
class MachinesServicesLs extends base_command_1.BaseCommand {
|
|
13
|
+
static description = 'List the web services declared on a machine — name, address on the machine, who declared it';
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> machines services ls lease:dr_abc123',
|
|
16
|
+
'<%= config.bin %> machines services ls my-laptop --json',
|
|
17
|
+
];
|
|
18
|
+
static args = {
|
|
19
|
+
machine: core_1.Args.string({
|
|
20
|
+
ignoreStdin: true,
|
|
21
|
+
description: 'Machine id, uuid, daemon id, name, or a unique prefix',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
static flags = {
|
|
26
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
this.requireAuth();
|
|
30
|
+
const { args, flags } = await this.parse(MachinesServicesLs);
|
|
31
|
+
let result;
|
|
32
|
+
try {
|
|
33
|
+
result = await (0, machine_services_1.listMachineServices)(await (0, machine_services_1.servicesMachineId)(args.machine));
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
this.handleApiError(err);
|
|
37
|
+
}
|
|
38
|
+
if (flags.json) {
|
|
39
|
+
this.log(JSON.stringify(result, null, 2));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const services = result?.services ?? [];
|
|
43
|
+
if (services.length === 0) {
|
|
44
|
+
this.log('No services are declared on this machine.');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
(0, format_1.renderTable)(services.map((service) => ({
|
|
48
|
+
name: (0, format_1.formatCell)(service.name),
|
|
49
|
+
address: (0, format_1.formatCell)((0, machine_services_1.declaredServiceAddress)(service)),
|
|
50
|
+
by: (0, format_1.formatCell)(service.declaredBy.label),
|
|
51
|
+
since: (0, format_1.localStamp)(service.declaredAt),
|
|
52
|
+
})), [
|
|
53
|
+
{ key: 'name', header: 'NAME', verbatim: true },
|
|
54
|
+
{ key: 'address', header: 'ADDRESS ON THE MACHINE', verbatim: true },
|
|
55
|
+
{ key: 'by', header: 'DECLARED BY' },
|
|
56
|
+
{ key: 'since', header: `SINCE (${(0, format_1.localZone)()})` },
|
|
57
|
+
], (line) => this.log(line));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.default = MachinesServicesLs;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseCommand } from '../../../base-command';
|
|
2
|
+
/**
|
|
3
|
+
* `skrr machines services withdraw` — remove a declared service from a
|
|
4
|
+
* machine's computer (design §20.5; 9-17, OSK-13579). Stops nothing on the
|
|
5
|
+
* machine; the service simply leaves the Services app. Needs the owner or an
|
|
6
|
+
* operate grant.
|
|
7
|
+
*/
|
|
8
|
+
export default class MachinesServicesWithdraw extends BaseCommand {
|
|
9
|
+
static description: string;
|
|
10
|
+
static examples: string[];
|
|
11
|
+
static args: {
|
|
12
|
+
machine: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
13
|
+
name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
14
|
+
};
|
|
15
|
+
static flags: {
|
|
16
|
+
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_command_1 = require("../../../base-command");
|
|
5
|
+
const machine_services_1 = require("../../../lib/machine-services");
|
|
6
|
+
/**
|
|
7
|
+
* `skrr machines services withdraw` — remove a declared service from a
|
|
8
|
+
* machine's computer (design §20.5; 9-17, OSK-13579). Stops nothing on the
|
|
9
|
+
* machine; the service simply leaves the Services app. Needs the owner or an
|
|
10
|
+
* operate grant.
|
|
11
|
+
*/
|
|
12
|
+
class MachinesServicesWithdraw extends base_command_1.BaseCommand {
|
|
13
|
+
static description = 'Withdraw a declared service from a machine (stops nothing)';
|
|
14
|
+
static examples = ['<%= config.bin %> machines services withdraw lease:dr_abc123 web'];
|
|
15
|
+
static args = {
|
|
16
|
+
machine: core_1.Args.string({
|
|
17
|
+
ignoreStdin: true,
|
|
18
|
+
description: 'Machine id, uuid, daemon id, name, or a unique prefix',
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
name: core_1.Args.string({
|
|
22
|
+
ignoreStdin: true,
|
|
23
|
+
description: 'The declared service’s name',
|
|
24
|
+
required: true,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
static flags = {
|
|
28
|
+
json: core_1.Flags.boolean({ description: 'Output as JSON' }),
|
|
29
|
+
};
|
|
30
|
+
async run() {
|
|
31
|
+
this.requireAuth();
|
|
32
|
+
const { args, flags } = await this.parse(MachinesServicesWithdraw);
|
|
33
|
+
let result;
|
|
34
|
+
try {
|
|
35
|
+
result = await (0, machine_services_1.withdrawMachineService)(await (0, machine_services_1.servicesMachineId)(args.machine), args.name);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
this.handleApiError(err);
|
|
39
|
+
}
|
|
40
|
+
if (flags.json) {
|
|
41
|
+
this.log(JSON.stringify(result, null, 2));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
this.log(`Withdrew ${result?.withdrawn?.name ?? args.name}.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.default = MachinesServicesWithdraw;
|