biaws 0.1.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.
Files changed (76) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +229 -0
  3. package/bin/biaws.js +3 -0
  4. package/docs/command-taxonomy.md +36 -0
  5. package/docs/instance-lifecycle.md +82 -0
  6. package/docs/releasing.md +105 -0
  7. package/package.json +63 -0
  8. package/shared/skillPackage.js +100 -0
  9. package/src/apiClient.js +89 -0
  10. package/src/baseCommands.js +122 -0
  11. package/src/commands/agent/configure.js +3 -0
  12. package/src/commands/agent/doctor.js +3 -0
  13. package/src/commands/agent.js +400 -0
  14. package/src/commands/api.js +17 -0
  15. package/src/commands/applications/get.js +17 -0
  16. package/src/commands/applications/list.js +32 -0
  17. package/src/commands/applications.js +7 -0
  18. package/src/commands/configure/claude.js +25 -0
  19. package/src/commands/configure/codex.js +25 -0
  20. package/src/commands/configure/doctor.js +49 -0
  21. package/src/commands/configure/skills.js +74 -0
  22. package/src/commands/configure.js +19 -0
  23. package/src/commands/demands/complete-task.js +6 -0
  24. package/src/commands/demands/get.js +16 -0
  25. package/src/commands/demands/list.js +48 -0
  26. package/src/commands/demands/task-status.js +49 -0
  27. package/src/commands/demands/tasks.js +44 -0
  28. package/src/commands/demands.js +7 -0
  29. package/src/commands/instance/backup.js +74 -0
  30. package/src/commands/instance/list.js +39 -0
  31. package/src/commands/instance/remove.js +72 -0
  32. package/src/commands/instance/restore.js +96 -0
  33. package/src/commands/instance/setup.js +349 -0
  34. package/src/commands/instance/show.js +31 -0
  35. package/src/commands/instance/start.js +32 -0
  36. package/src/commands/instance/status.js +42 -0
  37. package/src/commands/instance/stop.js +30 -0
  38. package/src/commands/instance.js +18 -0
  39. package/src/commands/issues/get.js +16 -0
  40. package/src/commands/issues/list.js +51 -0
  41. package/src/commands/issues/transition.js +33 -0
  42. package/src/commands/issues.js +7 -0
  43. package/src/commands/monitoring/describe.js +13 -0
  44. package/src/commands/monitoring/signal.js +25 -0
  45. package/src/commands/monitoring/signals.js +17 -0
  46. package/src/commands/monitoring/validate.js +14 -0
  47. package/src/commands/monitoring.js +163 -0
  48. package/src/commands/skills/install-all.js +13 -0
  49. package/src/commands/skills/install.js +16 -0
  50. package/src/commands/skills/list.js +5 -0
  51. package/src/commands/skills/publish-all.js +14 -0
  52. package/src/commands/skills/publish.js +11 -0
  53. package/src/commands/skills/status.js +7 -0
  54. package/src/commands/skills/update.js +12 -0
  55. package/src/commands/skills.js +303 -0
  56. package/src/commands/workspaces/get.js +15 -0
  57. package/src/commands/workspaces/list.js +20 -0
  58. package/src/commands/workspaces.js +7 -0
  59. package/src/compatibilityCommands.js +107 -0
  60. package/src/configure/command.js +50 -0
  61. package/src/core/context.js +162 -0
  62. package/src/core/errors.js +25 -0
  63. package/src/core/processRunner.js +119 -0
  64. package/src/core/prompts.js +138 -0
  65. package/src/core/redaction.js +29 -0
  66. package/src/core/terminal.js +72 -0
  67. package/src/core/wizard.js +279 -0
  68. package/src/domain/readCommand.js +65 -0
  69. package/src/domain/readService.js +126 -0
  70. package/src/domain/writeCommand.js +91 -0
  71. package/src/domain/writeService.js +122 -0
  72. package/src/index.js +5 -0
  73. package/src/instance/command.js +37 -0
  74. package/src/instance/service.js +515 -0
  75. package/src/localSkills.js +143 -0
  76. package/src/skillPackage.js +4 -0
@@ -0,0 +1,163 @@
1
+ import { BaseCommand } from "../baseCommands.js";
2
+ import { showTopic } from "../compatibilityCommands.js";
3
+
4
+ function parseMetadata(value) {
5
+ if (!value) return {};
6
+ let metadata;
7
+ try {
8
+ metadata = JSON.parse(value);
9
+ } catch {
10
+ throw new Error("--metadata deve conter um objeto JSON válido.");
11
+ }
12
+ if (!metadata || Array.isArray(metadata) || typeof metadata !== "object") {
13
+ throw new Error("--metadata deve conter um objeto JSON.");
14
+ }
15
+ return metadata;
16
+ }
17
+
18
+ function parsePayload(value) {
19
+ if (!value) return undefined;
20
+ try {
21
+ return JSON.parse(value);
22
+ } catch {
23
+ throw new Error("--payload deve conter JSON válido.");
24
+ }
25
+ }
26
+
27
+ function printSignal(result) {
28
+ const state = result.created ? "registrado" : "já recebido";
29
+ console.log(
30
+ `Sinal ${state}: runtime ${result.signal.runtimeId} está ${result.signal.status} (${result.signal.source}).`,
31
+ );
32
+ }
33
+
34
+ function buildSignalPayload(options) {
35
+ if (!options.source) throw new Error("Informe --source.");
36
+ const templateId = options.template;
37
+ const templateVersion = options["template-version"];
38
+ if (Boolean(templateId) !== Boolean(templateVersion)) {
39
+ throw new Error("Informe --template e --template-version juntos.");
40
+ }
41
+ if (!templateId && !options.status) throw new Error("Informe --status.");
42
+ if (templateId && !options.payload) {
43
+ throw new Error("Informe --payload ao usar um template.");
44
+ }
45
+ return {
46
+ ...(options.status ? { status: options.status } : {}),
47
+ source: options.source,
48
+ ...(options["signal-id"] ? { signalId: options["signal-id"] } : {}),
49
+ ...(options["observed-at"] ? { observedAt: options["observed-at"] } : {}),
50
+ ...(options.message ? { message: options.message } : {}),
51
+ ...(options["metadata-profile"]
52
+ ? { metadataProfile: options["metadata-profile"] }
53
+ : {}),
54
+ ...(templateId
55
+ ? { templateRef: { id: templateId, version: templateVersion } }
56
+ : {}),
57
+ metadata: parseMetadata(options.metadata),
58
+ ...(options.payload ? { payload: parsePayload(options.payload) } : {}),
59
+ };
60
+ }
61
+
62
+ function requiredTemplate(options) {
63
+ const templateId = options.template;
64
+ const version = options["template-version"] || options.version;
65
+ if (!templateId) throw new Error("Informe --template.");
66
+ if (!version) throw new Error("Informe --template-version.");
67
+ return { templateId, version };
68
+ }
69
+
70
+ async function describeTemplate(api, _positional, options) {
71
+ const { templateId, version } = requiredTemplate(options);
72
+ const result = await api.monitoring.describeTemplate(templateId, version);
73
+ if (options.json) console.log(JSON.stringify(result, null, 2));
74
+ else {
75
+ const contract = result.contract;
76
+ console.log(
77
+ `${contract.name} v${contract.templateRef.version} (${contract.status})`,
78
+ );
79
+ console.log(`Entrada: ${contract.input.mediaType}`);
80
+ console.log(`Transformação: ${contract.transformation.language}`);
81
+ console.log(`Amostra: ${JSON.stringify(contract.input.sample)}`);
82
+ if (contract.output)
83
+ console.log(`Saída: ${JSON.stringify(contract.output)}`);
84
+ }
85
+ return result;
86
+ }
87
+
88
+ async function validateTemplate(api, _positional, options) {
89
+ const { templateId, version } = requiredTemplate(options);
90
+ if (!options.payload) throw new Error("Informe --payload.");
91
+ const result = await api.monitoring.validateTemplate(
92
+ templateId,
93
+ version,
94
+ parsePayload(options.payload),
95
+ );
96
+ if (options.json) console.log(JSON.stringify(result, null, 2));
97
+ else {
98
+ const validation = result.validation;
99
+ console.log(
100
+ `Payload válido: ${validation.result.status}${validation.result.message ? ` — ${validation.result.message}` : ""}`,
101
+ );
102
+ }
103
+ return result;
104
+ }
105
+
106
+ async function sendSignal(api, runtimeReference, options) {
107
+ const result = await api.monitoring.signal(
108
+ runtimeReference,
109
+ buildSignalPayload(options),
110
+ );
111
+ if (options.json) console.log(JSON.stringify(result, null, 2));
112
+ else printSignal(result);
113
+ return result;
114
+ }
115
+
116
+ function printSignals(result) {
117
+ if (!result.items.length) {
118
+ console.log("Nenhum sinal recebido.");
119
+ return;
120
+ }
121
+ for (const signal of result.items) {
122
+ console.log(
123
+ `${signal.observedAt} ${signal.status.padEnd(11)} ${signal.source}${signal.message ? ` ${signal.message}` : ""}`,
124
+ );
125
+ }
126
+ }
127
+
128
+ async function listSignals(api, runtimeReference, options) {
129
+ const result = await api.monitoring.listSignals(runtimeReference, options);
130
+ if (options.json) console.log(JSON.stringify(result, null, 2));
131
+ else printSignals(result);
132
+ return result;
133
+ }
134
+
135
+ const MONITORING_ACTIONS = {
136
+ describe: describeTemplate,
137
+ signal: sendSignal,
138
+ signals: listSignals,
139
+ validate: validateTemplate,
140
+ };
141
+
142
+ export async function runMonitoringCommand(api, action, positional, options) {
143
+ const handler = MONITORING_ACTIONS[action];
144
+ if (!handler)
145
+ throw new Error(
146
+ `Ação de monitoramento desconhecida: ${action || "(vazia)"}`,
147
+ );
148
+ if (["describe", "validate"].includes(action)) {
149
+ return handler(api, positional, options);
150
+ }
151
+ const runtimeReference = positional[0];
152
+ if (!runtimeReference)
153
+ throw new Error("Informe o UUID ou caminho do runtime.");
154
+ return handler(api, runtimeReference, options);
155
+ }
156
+
157
+ export default class Monitoring extends BaseCommand {
158
+ static description = "Envia e consulta sinais de monitoramento";
159
+
160
+ async run() {
161
+ await showTopic(this, "monitoring");
162
+ }
163
+ }
@@ -0,0 +1,13 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
3
+
4
+ export default createSkillsCommand("install-all", {
5
+ description: "instala todas as skills publicadas",
6
+ flags: {
7
+ target: Flags.string({ description: "diretório de instalação" }),
8
+ force: Flags.boolean({
9
+ char: "f",
10
+ description: "atualiza instalações existentes",
11
+ }),
12
+ },
13
+ });
@@ -0,0 +1,16 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
3
+
4
+ export default createSkillsCommand("install", {
5
+ description: "instala uma skill publicada",
6
+ args: { skill: Args.string({ description: "ID da skill", required: true }) },
7
+ flags: {
8
+ target: Flags.string({ description: "diretório de instalação" }),
9
+ version: Flags.string({ description: "versão da skill" }),
10
+ force: Flags.boolean({
11
+ char: "f",
12
+ description: "substitui a instalação existente",
13
+ }),
14
+ },
15
+ positional: (args) => [args.skill],
16
+ });
@@ -0,0 +1,5 @@
1
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
2
+
3
+ export default createSkillsCommand("list", {
4
+ description: "lista skills publicadas",
5
+ });
@@ -0,0 +1,14 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
3
+
4
+ export default createSkillsCommand("publish-all", {
5
+ description: "publica as skills contidas em um diretório",
6
+ flags: {
7
+ dir: Flags.string({ description: "diretório do catálogo" }),
8
+ "initial-version": Flags.string({
9
+ description: "versão inicial",
10
+ required: true,
11
+ }),
12
+ changelog: Flags.string({ description: "notas da versão" }),
13
+ },
14
+ });
@@ -0,0 +1,11 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
3
+
4
+ export default createSkillsCommand("publish", {
5
+ description: "publica uma versão de skill",
6
+ flags: {
7
+ dir: Flags.string({ description: "diretório da skill", required: true }),
8
+ version: Flags.string({ description: "versão semântica", required: true }),
9
+ changelog: Flags.string({ description: "notas da versão" }),
10
+ },
11
+ });
@@ -0,0 +1,7 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { createSkillsCommand } from "../../compatibilityCommands.js";
3
+
4
+ export default createSkillsCommand("status", {
5
+ description: "verifica integridade e atualização das skills instaladas",
6
+ flags: { target: Flags.string({ description: "diretório de instalação" }) },
7
+ });
@@ -0,0 +1,12 @@
1
+ import { Flags } from "@oclif/core";
2
+ import {
3
+ createSkillsCommand,
4
+ optionalSkillArgument,
5
+ } from "../../compatibilityCommands.js";
6
+
7
+ export default createSkillsCommand("update", {
8
+ description: "atualiza uma ou todas as skills instaladas",
9
+ args: { skill: optionalSkillArgument },
10
+ flags: { target: Flags.string({ description: "diretório de instalação" }) },
11
+ positional: (args) => (args.skill ? [args.skill] : []),
12
+ });
@@ -0,0 +1,303 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import { BaseCommand } from "../baseCommands.js";
5
+ import { showTopic } from "../compatibilityCommands.js";
6
+ import { buildSkillPayload } from "../skillPackage.js";
7
+ import {
8
+ checksumInstalledSkill,
9
+ installSkillPackage,
10
+ readLock,
11
+ } from "../localSkills.js";
12
+
13
+ function targetFrom(options) {
14
+ return path.resolve(options.target || ".agents/skills");
15
+ }
16
+
17
+ function printJson(value, options) {
18
+ if (!options.json) return false;
19
+ console.log(JSON.stringify(value, null, 2));
20
+ return true;
21
+ }
22
+
23
+ async function install(api, skillId, version, options) {
24
+ const metadata = await api.get(skillId, version);
25
+ if (!metadata.skill) throw new Error(`Skill não encontrada: ${skillId}`);
26
+ const skillPackage = await api.download(skillId, metadata.skill.version);
27
+ return installSkillPackage(skillPackage, targetFrom(options), {
28
+ force: options.force,
29
+ });
30
+ }
31
+
32
+ async function findSkillDirectories(rootDirectory) {
33
+ const root = path.resolve(rootDirectory);
34
+ const entries = await readdir(root, { withFileTypes: true });
35
+ const directories = [];
36
+ for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
37
+ if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
38
+ const directory = path.join(root, entry.name);
39
+ try {
40
+ const children = await readdir(directory);
41
+ if (children.includes("SKILL.md")) directories.push(directory);
42
+ } catch (error) {
43
+ if (error.code !== "ENOENT" && error.code !== "EACCES") throw error;
44
+ }
45
+ }
46
+ return directories;
47
+ }
48
+
49
+ async function listSkills(api, _positional, options) {
50
+ const result = await api.list();
51
+ if (printJson(result, options)) return;
52
+ if (!result.items.length) {
53
+ console.log("Nenhuma skill publicada.");
54
+ return;
55
+ }
56
+ for (const item of result.items) {
57
+ console.log(`${item.skillId}@${item.latestVersion} ${item.description}`);
58
+ }
59
+ }
60
+
61
+ async function publishSkill(api, _positional, options) {
62
+ if (!options.dir) throw new Error("Informe --dir <diretório-da-skill>");
63
+ if (!options.version) throw new Error("Informe --version <semver>");
64
+ const payload = await buildSkillPayload(options.dir, options);
65
+ const result = await api.publish(payload);
66
+ if (!printJson(result, options)) {
67
+ console.log(
68
+ `Publicada ${result.skill.skillId}@${result.skill.version} (${result.skill.packageSha256})`,
69
+ );
70
+ }
71
+ }
72
+
73
+ async function publishAllSkills(api, _positional, options) {
74
+ const rootDirectory = options.dir || ".agents/skills";
75
+ const version = options["initial-version"] || options.version;
76
+ if (!version) throw new Error("Informe --initial-version <semver>");
77
+ const [directories, catalog] = await Promise.all([
78
+ findSkillDirectories(rootDirectory),
79
+ api.list({ includeDeprecated: true }),
80
+ ]);
81
+ const publishedVersions = new Map(
82
+ catalog.items.map((item) => [
83
+ item.skillId,
84
+ new Set((item.versions || []).map((candidate) => candidate.version)),
85
+ ]),
86
+ );
87
+ const result = { published: [], skipped: [], failed: [] };
88
+
89
+ for (const directory of directories) {
90
+ try {
91
+ const payload = await buildSkillPayload(directory, {
92
+ ...options,
93
+ version,
94
+ });
95
+ if (publishedVersions.get(payload.skillId)?.has(version)) {
96
+ result.skipped.push({
97
+ skillId: payload.skillId,
98
+ version,
99
+ reason: "version-already-exists",
100
+ });
101
+ continue;
102
+ }
103
+ const response = await api.publish(payload);
104
+ result.published.push({
105
+ skillId: response.skill.skillId,
106
+ version: response.skill.version,
107
+ packageSha256: response.skill.packageSha256,
108
+ });
109
+ } catch (error) {
110
+ result.failed.push({
111
+ directory,
112
+ message: error.message,
113
+ });
114
+ }
115
+ }
116
+
117
+ if (printJson(result, options)) {
118
+ if (result.failed.length) process.exitCode = 1;
119
+ return;
120
+ }
121
+ for (const item of result.published)
122
+ console.log(`Publicada ${item.skillId}@${item.version}`);
123
+ for (const item of result.skipped)
124
+ console.log(
125
+ `Ignorada ${item.skillId}@${item.version}: versão já existente`,
126
+ );
127
+ for (const item of result.failed)
128
+ console.error(`Falha em ${item.directory}: ${item.message}`);
129
+ console.log(
130
+ `Resumo: ${result.published.length} publicada(s), ${result.skipped.length} ignorada(s), ${result.failed.length} falha(s).`,
131
+ );
132
+ if (result.failed.length) process.exitCode = 1;
133
+ }
134
+
135
+ async function installSkill(api, positional, options) {
136
+ const skillId = positional[0];
137
+ if (!skillId)
138
+ throw new Error("Informe a skill: biaws skills install <skill-id>");
139
+ const result = await install(api, skillId, options.version, options);
140
+ if (!printJson(result, options)) {
141
+ console.log(
142
+ `Instalada ${skillId}@${result.skill.version} em ${result.directory}`,
143
+ );
144
+ }
145
+ }
146
+
147
+ async function installCatalogSkill(api, item, lock, options, results) {
148
+ const localSkill = lock.skills[item.skillId];
149
+ if (localSkill && !options.force) {
150
+ results.skipped.push({
151
+ skillId: item.skillId,
152
+ version: localSkill.version,
153
+ reason: "already-installed",
154
+ });
155
+ return;
156
+ }
157
+
158
+ try {
159
+ const result = await install(api, item.skillId, item.latestVersion, {
160
+ ...options,
161
+ force: Boolean(localSkill),
162
+ });
163
+ results.installed.push({
164
+ skillId: item.skillId,
165
+ version: result.skill.version,
166
+ directory: result.directory,
167
+ });
168
+ } catch (error) {
169
+ results.failed.push({ skillId: item.skillId, message: error.message });
170
+ }
171
+ }
172
+
173
+ function printInstallAllResults(results) {
174
+ for (const item of results.installed)
175
+ console.log(
176
+ `Instalada ${item.skillId}@${item.version} em ${item.directory}`,
177
+ );
178
+ for (const item of results.skipped)
179
+ console.log(`Preservada ${item.skillId}@${item.version}`);
180
+ for (const item of results.failed)
181
+ console.error(`Falha em ${item.skillId}: ${item.message}`);
182
+ }
183
+
184
+ async function installAllSkills(api, _positional, options) {
185
+ const [catalog, lock] = await Promise.all([
186
+ api.list(),
187
+ readLock(targetFrom(options)),
188
+ ]);
189
+ const results = { installed: [], skipped: [], failed: [] };
190
+ for (const item of catalog.items) {
191
+ await installCatalogSkill(api, item, lock, options, results);
192
+ }
193
+ if (printJson(results, options)) {
194
+ if (results.failed.length) process.exitCode = 1;
195
+ return results;
196
+ }
197
+ if (!options.quiet) printInstallAllResults(results);
198
+ if (results.failed.length) process.exitCode = 1;
199
+ return results;
200
+ }
201
+
202
+ function skillStatus(local, installedChecksum, latestVersion) {
203
+ if (installedChecksum === null) return "missing";
204
+ if (installedChecksum !== local.packageSha256) return "modified";
205
+ if (!latestVersion) return "not-in-catalog";
206
+ return latestVersion === local.version ? "current" : "update-available";
207
+ }
208
+
209
+ async function getInstalledSkillsStatus(api, options) {
210
+ const lock = await readLock(targetFrom(options));
211
+ const catalog = await api.list();
212
+ const latestById = new Map(
213
+ catalog.items.map((item) => [item.skillId, item.latestVersion]),
214
+ );
215
+ const items = [];
216
+ for (const [skillId, local] of Object.entries(lock.skills)) {
217
+ const installedChecksum = await checksumInstalledSkill(
218
+ path.join(targetFrom(options), skillId),
219
+ );
220
+ const latestVersion = latestById.get(skillId) || null;
221
+ items.push({
222
+ skillId,
223
+ installedVersion: local.version,
224
+ latestVersion,
225
+ status: skillStatus(local, installedChecksum, latestVersion),
226
+ });
227
+ }
228
+ return items;
229
+ }
230
+
231
+ async function showSkillsStatus(api, _positional, options) {
232
+ const items = await getInstalledSkillsStatus(api, options);
233
+ if (printJson({ items }, options)) return;
234
+ if (!items.length) {
235
+ console.log("Nenhuma skill instalada pelo Bondia Workspaces CLI.");
236
+ return;
237
+ }
238
+ for (const item of items) {
239
+ const latest = item.latestVersion ? `; catálogo ${item.latestVersion}` : "";
240
+ console.log(
241
+ `${item.skillId}@${item.installedVersion}: ${item.status}${latest}`,
242
+ );
243
+ }
244
+ }
245
+
246
+ async function updateSkills(api, positional, options) {
247
+ const requestedSkillId = positional[0];
248
+ const lock = await readLock(targetFrom(options));
249
+ const catalog = await api.list();
250
+ if (requestedSkillId && !lock.skills[requestedSkillId]) {
251
+ throw new Error(
252
+ `Skill não instalada pelo Bondia Workspaces CLI: ${requestedSkillId}`,
253
+ );
254
+ }
255
+ const candidates = catalog.items.filter(
256
+ (item) =>
257
+ (!requestedSkillId || item.skillId === requestedSkillId) &&
258
+ lock.skills[item.skillId] &&
259
+ lock.skills[item.skillId].version !== item.latestVersion,
260
+ );
261
+ const results = [];
262
+ for (const item of candidates) {
263
+ results.push(
264
+ await install(api, item.skillId, item.latestVersion, {
265
+ ...options,
266
+ force: true,
267
+ }),
268
+ );
269
+ }
270
+ if (printJson({ items: results }, options)) return;
271
+ if (!results.length) console.log("Todas as skills estão atualizadas.");
272
+ for (const result of results) {
273
+ console.log(
274
+ `Atualizada ${path.basename(result.directory)} para ${result.skill.version}`,
275
+ );
276
+ }
277
+ }
278
+
279
+ const ACTION_HANDLERS = {
280
+ install: installSkill,
281
+ "install-all": installAllSkills,
282
+ list: listSkills,
283
+ publish: publishSkill,
284
+ "publish-all": publishAllSkills,
285
+ status: showSkillsStatus,
286
+ update: updateSkills,
287
+ };
288
+
289
+ export async function runSkillsCommand(api, action, positional, options) {
290
+ const handler = ACTION_HANDLERS[action];
291
+ if (!handler)
292
+ throw new Error(`Ação de skills desconhecida: ${action || "(ausente)"}`);
293
+ return handler(api, positional, options);
294
+ }
295
+
296
+ export default class Skills extends BaseCommand {
297
+ static description =
298
+ "Gerencia publicação, instalação e atualização de skills";
299
+
300
+ async run() {
301
+ await showTopic(this, "skills");
302
+ }
303
+ }
@@ -0,0 +1,15 @@
1
+ import { Args } from "@oclif/core";
2
+ import { connectionFlags, ReadCommand } from "../../domain/readCommand.js";
3
+ export default class WorkspaceGet extends ReadCommand {
4
+ static description = "Obtém um workspace por ID";
5
+ static args = { id: Args.string({ required: true }) };
6
+ static flags = connectionFlags;
7
+ async run() {
8
+ const { args, flags } = await this.parse(WorkspaceGet);
9
+ const result = await this.read(flags, (api) => api.workspace(args.id), {
10
+ resource: "workspace",
11
+ operation: "get",
12
+ });
13
+ this.emit(flags, result, (p) => JSON.stringify(p.workspace || p, null, 2));
14
+ }
15
+ }
@@ -0,0 +1,20 @@
1
+ import { connectionFlags, ReadCommand } from "../../domain/readCommand.js";
2
+ import { table } from "../../domain/readService.js";
3
+ export default class WorkspaceList extends ReadCommand {
4
+ static description = "Lista workspaces autorizados";
5
+ static flags = connectionFlags;
6
+ async run() {
7
+ const { flags } = await this.parse(WorkspaceList);
8
+ const result = await this.read(flags, (api) => api.workspaces(), {
9
+ resource: "workspaces",
10
+ operation: "list",
11
+ });
12
+ this.emit(flags, result, (p) =>
13
+ table(p.items || [], [
14
+ ["ID", (x) => x.id],
15
+ ["NOME", (x) => x.name],
16
+ ["STATUS", (x) => x.status],
17
+ ]),
18
+ );
19
+ }
20
+ }
@@ -0,0 +1,7 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class Workspaces extends Command {
3
+ static description = "Consulta workspaces autorizados pela API";
4
+ async run() {
5
+ await this.config.runCommand("help", ["workspaces"]);
6
+ }
7
+ }