biaws 0.2.2 → 0.3.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 +1 -0
- package/docs/command-taxonomy.md +2 -3
- package/package.json +1 -1
- package/src/commandFactories.js +12 -2
- package/src/commands/agent.js +52 -9
- package/src/commands/configure/claude.js +9 -3
- package/src/commands/configure/codex.js +9 -3
- package/src/configuration/commands.js +1 -1
- package/src/configure/command.js +48 -0
- package/src/core/context.js +9 -10
- package/src/instance/service.js +5 -5
package/README.md
CHANGED
|
@@ -122,6 +122,7 @@ biaws workspace api PATCH /recurso/ID --body '{"status":"Ativo"}'
|
|
|
122
122
|
```bash
|
|
123
123
|
biaws workspace agent configure codex
|
|
124
124
|
biaws workspace agent configure claude
|
|
125
|
+
biaws workspace agent configure codex --no-interactive --env-file /caminho/instancia.env --workspace workspace-id
|
|
125
126
|
biaws workspace agent doctor codex
|
|
126
127
|
biaws workspace skills list
|
|
127
128
|
biaws workspace skills install SKILL_ID
|
package/docs/command-taxonomy.md
CHANGED
|
@@ -61,9 +61,8 @@ flags > variáveis de ambiente > configuração da pasta > perfil global > defau
|
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
As variáveis canônicas são `BIAWS_API_URL`, `BIAWS_API_KEY` e
|
|
64
|
-
`BIAWS_WORKSPACE_ID`.
|
|
65
|
-
|
|
66
|
-
antigos do CLI.
|
|
64
|
+
`BIAWS_WORKSPACE_ID`. Variáveis com o prefixo temporário anterior não são
|
|
65
|
+
aceitas como aliases.
|
|
67
66
|
|
|
68
67
|
## Convenções
|
|
69
68
|
|
package/package.json
CHANGED
package/src/commandFactories.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AuthenticatedApiCommand, ProjectCommand } from "./baseCommands.js";
|
|
|
4
4
|
import {
|
|
5
5
|
configureContextFlags,
|
|
6
6
|
configureContextInput,
|
|
7
|
+
interactiveConfigureInput,
|
|
7
8
|
legacyAgentContext,
|
|
8
9
|
} from "./configure/command.js";
|
|
9
10
|
import { runAgentCommand } from "./commands/agent.js";
|
|
@@ -85,12 +86,21 @@ export function createAgentCommand(action) {
|
|
|
85
86
|
|
|
86
87
|
async run() {
|
|
87
88
|
const { args, flags } = await this.parse(this.constructor);
|
|
88
|
-
const
|
|
89
|
+
const input =
|
|
90
|
+
action === "configure"
|
|
91
|
+
? await interactiveConfigureInput(this, flags)
|
|
92
|
+
: configureContextInput(flags);
|
|
93
|
+
const context = await this.projectContext(input);
|
|
89
94
|
await runAgentCommand(
|
|
90
95
|
context.api,
|
|
91
96
|
action,
|
|
92
97
|
[args.client],
|
|
93
|
-
{
|
|
98
|
+
{
|
|
99
|
+
...flags,
|
|
100
|
+
interactive: input.interactive,
|
|
101
|
+
project: context.projectDirectory,
|
|
102
|
+
prompts: this.adapters.prompts,
|
|
103
|
+
},
|
|
94
104
|
legacyAgentContext(context),
|
|
95
105
|
);
|
|
96
106
|
}
|
package/src/commands/agent.js
CHANGED
|
@@ -4,13 +4,14 @@ import path from "node:path";
|
|
|
4
4
|
|
|
5
5
|
import { BaseCommand, TOOL_DIRECTORY } from "../baseCommands.js";
|
|
6
6
|
import { showTopic } from "../commandFactories.js";
|
|
7
|
+
import { CliError } from "../core/errors.js";
|
|
7
8
|
import { readLock } from "../localSkills.js";
|
|
8
9
|
import { runSkillsCommand } from "./skills.js";
|
|
9
10
|
|
|
10
11
|
const CODEX_BEGIN = "# BEGIN BIAWS MANAGED MCP";
|
|
11
12
|
const CODEX_END = "# END BIAWS MANAGED MCP";
|
|
12
13
|
export const MCP_PACKAGE_NAME = "biaws-mcp";
|
|
13
|
-
export const MCP_PACKAGE_VERSION = "0.
|
|
14
|
+
export const MCP_PACKAGE_VERSION = "0.2.0";
|
|
14
15
|
export const MCP_PACKAGE_SPEC = `${MCP_PACKAGE_NAME}@${MCP_PACKAGE_VERSION}`;
|
|
15
16
|
const MCP_COMMAND = "npx";
|
|
16
17
|
const MCP_ARGS = ["--yes", MCP_PACKAGE_SPEC];
|
|
@@ -75,7 +76,7 @@ async function writeCodexConfiguration(
|
|
|
75
76
|
[mcp_servers.biaws]
|
|
76
77
|
command = ${JSON.stringify(MCP_COMMAND)}
|
|
77
78
|
args = ${JSON.stringify(MCP_ARGS)}
|
|
78
|
-
env = {${envFile ? ` BIAWS_ENV_FILE = ${JSON.stringify(envFile)},` : ""}
|
|
79
|
+
env = {${envFile ? ` BIAWS_ENV_FILE = ${JSON.stringify(envFile)},` : ""} BIAWS_WORKSPACE_ID = ${JSON.stringify(workspaceId)} }
|
|
79
80
|
${CODEX_END}
|
|
80
81
|
`;
|
|
81
82
|
const output = current ? `${current}\n\n${managed}` : managed;
|
|
@@ -113,14 +114,19 @@ async function writeClaudeConfiguration(
|
|
|
113
114
|
args: MCP_ARGS,
|
|
114
115
|
env: {
|
|
115
116
|
...(envFile ? { BIAWS_ENV_FILE: envFile } : {}),
|
|
116
|
-
|
|
117
|
+
BIAWS_WORKSPACE_ID: workspaceId,
|
|
117
118
|
},
|
|
118
119
|
};
|
|
119
120
|
await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
120
121
|
return configPath;
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
async function resolveWorkspaceId(
|
|
124
|
+
async function resolveWorkspaceId(
|
|
125
|
+
api,
|
|
126
|
+
requestedWorkspaceId = "",
|
|
127
|
+
interactive = false,
|
|
128
|
+
prompts,
|
|
129
|
+
) {
|
|
124
130
|
let identity;
|
|
125
131
|
try {
|
|
126
132
|
identity = await api.identity();
|
|
@@ -132,7 +138,22 @@ async function resolveWorkspaceId(api, requestedWorkspaceId = "") {
|
|
|
132
138
|
}
|
|
133
139
|
throw error;
|
|
134
140
|
}
|
|
135
|
-
const
|
|
141
|
+
const workspaces = identity?.actor?.workspaces || [];
|
|
142
|
+
let workspaceId = requestedWorkspaceId || identity?.actor?.workspaceId;
|
|
143
|
+
if (interactive && workspaces.length > 0) {
|
|
144
|
+
workspaceId = await prompts.ask({
|
|
145
|
+
name: "workspaceId",
|
|
146
|
+
type: "select",
|
|
147
|
+
message: "Workspace do projeto",
|
|
148
|
+
choices: workspaces.map((workspace) => ({
|
|
149
|
+
name: workspace.name
|
|
150
|
+
? `${workspace.name} (${workspace.id})`
|
|
151
|
+
: workspace.id,
|
|
152
|
+
value: workspace.id,
|
|
153
|
+
})),
|
|
154
|
+
...(workspaceId ? { default: workspaceId } : {}),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
136
157
|
if (!workspaceId) {
|
|
137
158
|
if ((identity?.actor?.workspaces?.length || 0) > 1) {
|
|
138
159
|
throw new Error(
|
|
@@ -153,7 +174,29 @@ async function configure(api, client, options, context) {
|
|
|
153
174
|
);
|
|
154
175
|
}
|
|
155
176
|
const projectDirectory = path.resolve(options.project || process.cwd());
|
|
156
|
-
const { workspaceId } = await resolveWorkspaceId(
|
|
177
|
+
const { workspaceId } = await resolveWorkspaceId(
|
|
178
|
+
api,
|
|
179
|
+
context.workspaceId,
|
|
180
|
+
options.interactive,
|
|
181
|
+
options.prompts,
|
|
182
|
+
);
|
|
183
|
+
if (options.interactive) {
|
|
184
|
+
const confirmed = await options.prompts.ask({
|
|
185
|
+
name: "confirmConfiguration",
|
|
186
|
+
type: "confirm",
|
|
187
|
+
message: `Configurar ${client} em ${projectDirectory} para o workspace ${workspaceId}?`,
|
|
188
|
+
default: true,
|
|
189
|
+
});
|
|
190
|
+
if (!confirmed) {
|
|
191
|
+
throw new CliError(
|
|
192
|
+
"Configuração cancelada antes de qualquer alteração.",
|
|
193
|
+
{
|
|
194
|
+
code: "PROMPT_CANCELLED",
|
|
195
|
+
exitCode: 130,
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
157
200
|
const target = skillTarget(client, projectDirectory);
|
|
158
201
|
const configPath =
|
|
159
202
|
client === "codex"
|
|
@@ -213,7 +256,7 @@ async function mcpStatus(envFile, workspaceId) {
|
|
|
213
256
|
env: {
|
|
214
257
|
...process.env,
|
|
215
258
|
...(envFile ? { BIAWS_ENV_FILE: envFile } : {}),
|
|
216
|
-
|
|
259
|
+
BIAWS_WORKSPACE_ID: workspaceId,
|
|
217
260
|
},
|
|
218
261
|
});
|
|
219
262
|
let output = "";
|
|
@@ -302,7 +345,7 @@ function configurationStatus(client, contents, envFile, workspaceId) {
|
|
|
302
345
|
contents.includes(`command = ${JSON.stringify(MCP_COMMAND)}`) &&
|
|
303
346
|
contents.includes(`args = ${JSON.stringify(MCP_ARGS)}`) &&
|
|
304
347
|
(!envFile || contents.includes(JSON.stringify(envFile))) &&
|
|
305
|
-
contents.includes(`
|
|
348
|
+
contents.includes(`BIAWS_WORKSPACE_ID = ${JSON.stringify(workspaceId)}`);
|
|
306
349
|
return {
|
|
307
350
|
ok,
|
|
308
351
|
detail: ok
|
|
@@ -316,7 +359,7 @@ function configurationStatus(client, contents, envFile, workspaceId) {
|
|
|
316
359
|
server?.command === MCP_COMMAND &&
|
|
317
360
|
JSON.stringify(server.args || []) === JSON.stringify(MCP_ARGS) &&
|
|
318
361
|
(!envFile || server.env?.BIAWS_ENV_FILE === envFile) &&
|
|
319
|
-
server.env?.
|
|
362
|
+
server.env?.BIAWS_WORKSPACE_ID === workspaceId;
|
|
320
363
|
return {
|
|
321
364
|
ok,
|
|
322
365
|
detail: ok
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ProjectCommand } from "../../baseCommands.js";
|
|
2
2
|
import {
|
|
3
3
|
configureContextFlags,
|
|
4
|
-
|
|
4
|
+
interactiveConfigureInput,
|
|
5
5
|
legacyAgentContext,
|
|
6
6
|
} from "../../configure/command.js";
|
|
7
7
|
import { runAgentCommand } from "../agent.js";
|
|
@@ -13,12 +13,18 @@ export default class ConfigureClaude extends ProjectCommand {
|
|
|
13
13
|
|
|
14
14
|
async run() {
|
|
15
15
|
const { flags } = await this.parse(ConfigureClaude);
|
|
16
|
-
const
|
|
16
|
+
const input = await interactiveConfigureInput(this, flags);
|
|
17
|
+
const context = await this.projectContext(input);
|
|
17
18
|
await runAgentCommand(
|
|
18
19
|
context.api,
|
|
19
20
|
"configure",
|
|
20
21
|
["claude"],
|
|
21
|
-
{
|
|
22
|
+
{
|
|
23
|
+
...flags,
|
|
24
|
+
interactive: input.interactive,
|
|
25
|
+
project: context.projectDirectory,
|
|
26
|
+
prompts: this.adapters.prompts,
|
|
27
|
+
},
|
|
22
28
|
legacyAgentContext(context),
|
|
23
29
|
);
|
|
24
30
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ProjectCommand } from "../../baseCommands.js";
|
|
2
2
|
import {
|
|
3
3
|
configureContextFlags,
|
|
4
|
-
|
|
4
|
+
interactiveConfigureInput,
|
|
5
5
|
legacyAgentContext,
|
|
6
6
|
} from "../../configure/command.js";
|
|
7
7
|
import { runAgentCommand } from "../agent.js";
|
|
@@ -13,12 +13,18 @@ export default class ConfigureCodex extends ProjectCommand {
|
|
|
13
13
|
|
|
14
14
|
async run() {
|
|
15
15
|
const { flags } = await this.parse(ConfigureCodex);
|
|
16
|
-
const
|
|
16
|
+
const input = await interactiveConfigureInput(this, flags);
|
|
17
|
+
const context = await this.projectContext(input);
|
|
17
18
|
await runAgentCommand(
|
|
18
19
|
context.api,
|
|
19
20
|
"configure",
|
|
20
21
|
["codex"],
|
|
21
|
-
{
|
|
22
|
+
{
|
|
23
|
+
...flags,
|
|
24
|
+
interactive: input.interactive,
|
|
25
|
+
project: context.projectDirectory,
|
|
26
|
+
prompts: this.adapters.prompts,
|
|
27
|
+
},
|
|
22
28
|
legacyAgentContext(context),
|
|
23
29
|
);
|
|
24
30
|
}
|
|
@@ -52,7 +52,7 @@ function credentialsWithKey(configuration, name, apiKey) {
|
|
|
52
52
|
async function requiredApiKey(command) {
|
|
53
53
|
const fromEnvironment = String(
|
|
54
54
|
command.adapters.environment.BIAWS_API_KEY ||
|
|
55
|
-
command.adapters.environment.
|
|
55
|
+
command.adapters.environment.BIAWS_API_KEY ||
|
|
56
56
|
"",
|
|
57
57
|
).trim();
|
|
58
58
|
if (fromEnvironment) return fromEnvironment;
|
package/src/configure/command.js
CHANGED
|
@@ -2,6 +2,8 @@ import path from "node:path";
|
|
|
2
2
|
|
|
3
3
|
import { Args, Flags } from "@oclif/core";
|
|
4
4
|
|
|
5
|
+
import { CliError } from "../core/errors.js";
|
|
6
|
+
|
|
5
7
|
export const configureContextFlags = Object.freeze({
|
|
6
8
|
project: Flags.string({
|
|
7
9
|
char: "p",
|
|
@@ -16,6 +18,12 @@ export const configureContextFlags = Object.freeze({
|
|
|
16
18
|
"env-file": Flags.string({
|
|
17
19
|
description: "arquivo privado com URL e chave de API",
|
|
18
20
|
}),
|
|
21
|
+
interactive: Flags.boolean({
|
|
22
|
+
char: "i",
|
|
23
|
+
allowNo: true,
|
|
24
|
+
description:
|
|
25
|
+
"usa o modo assistente (padrão em terminais; use --no-interactive para desativar)",
|
|
26
|
+
}),
|
|
19
27
|
force: Flags.boolean({
|
|
20
28
|
char: "f",
|
|
21
29
|
description: "substitui somente a configuração BIAWS conflitante",
|
|
@@ -23,6 +31,46 @@ export const configureContextFlags = Object.freeze({
|
|
|
23
31
|
json: Flags.boolean({ description: "emite somente JSON em stdout" }),
|
|
24
32
|
});
|
|
25
33
|
|
|
34
|
+
export async function interactiveConfigureInput(command, flags) {
|
|
35
|
+
const interactive =
|
|
36
|
+
flags.interactive === true ||
|
|
37
|
+
(flags.interactive !== false && command.adapters.terminal.isInteractive);
|
|
38
|
+
if (!interactive) {
|
|
39
|
+
return { ...configureContextInput(flags), interactive: false };
|
|
40
|
+
}
|
|
41
|
+
if (!command.adapters.prompts.isInteractive) {
|
|
42
|
+
throw new CliError("O modo assistente exige um terminal interativo.", {
|
|
43
|
+
code: "INTERACTIVE_INPUT_UNAVAILABLE",
|
|
44
|
+
exitCode: 2,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const project = String(
|
|
48
|
+
await command.adapters.prompts.ask({
|
|
49
|
+
name: "project",
|
|
50
|
+
message: "Diretório do projeto",
|
|
51
|
+
default: flags.project || command.adapters.cwd(),
|
|
52
|
+
}),
|
|
53
|
+
).trim();
|
|
54
|
+
const envFile = String(
|
|
55
|
+
await command.adapters.prompts.ask({
|
|
56
|
+
name: "envFile",
|
|
57
|
+
message: "Arquivo privado da instância (BIAWS_ENV_FILE)",
|
|
58
|
+
default:
|
|
59
|
+
flags["env-file"] || command.adapters.environment.BIAWS_ENV_FILE || "",
|
|
60
|
+
}),
|
|
61
|
+
).trim();
|
|
62
|
+
if (!envFile) {
|
|
63
|
+
throw new CliError("Informe o arquivo privado da instância.", {
|
|
64
|
+
code: "ENV_FILE_REQUIRED",
|
|
65
|
+
exitCode: 2,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...configureContextInput({ ...flags, project, "env-file": envFile }),
|
|
70
|
+
interactive: true,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
26
74
|
export const clientArgument = Args.string({
|
|
27
75
|
description: "cliente a diagnosticar",
|
|
28
76
|
options: ["codex", "claude"],
|
package/src/core/context.js
CHANGED
|
@@ -126,32 +126,31 @@ export async function resolveCommandContext(options) {
|
|
|
126
126
|
const configuredApiUrl =
|
|
127
127
|
input.apiUrl ||
|
|
128
128
|
explicitFileEnv.BIAWS_API_URL ||
|
|
129
|
-
explicitFileEnv.
|
|
129
|
+
explicitFileEnv.BIAWS_API_URL ||
|
|
130
|
+
environment.BIAWS_API_URL ||
|
|
130
131
|
environment.BIAWS_API_URL ||
|
|
131
|
-
environment.
|
|
132
|
-
environment.ISSUE_API_BASE_URL ||
|
|
132
|
+
environment.BIAWS_API_BASE_URL ||
|
|
133
133
|
workspaceConfiguration.apiUrl ||
|
|
134
134
|
profile.config.apiUrl ||
|
|
135
|
-
effectiveEnv.
|
|
136
|
-
effectiveEnv.
|
|
135
|
+
effectiveEnv.BIAWS_API_URL ||
|
|
136
|
+
effectiveEnv.BIAWS_API_BASE_URL ||
|
|
137
137
|
DEFAULT_API_URL;
|
|
138
138
|
const configuredApiKey = String(
|
|
139
139
|
input.apiKey ||
|
|
140
140
|
explicitFileEnv.BIAWS_API_KEY ||
|
|
141
|
-
explicitFileEnv.
|
|
141
|
+
explicitFileEnv.BIAWS_API_KEY ||
|
|
142
|
+
environment.BIAWS_API_KEY ||
|
|
142
143
|
environment.BIAWS_API_KEY ||
|
|
143
|
-
environment.ISSUE_API_KEY ||
|
|
144
144
|
profile.credentials.apiKey ||
|
|
145
|
-
effectiveEnv.
|
|
145
|
+
effectiveEnv.BIAWS_API_KEY ||
|
|
146
146
|
"",
|
|
147
147
|
);
|
|
148
148
|
const configuredWorkspaceId = String(
|
|
149
149
|
input.workspaceId ||
|
|
150
150
|
input.workspace ||
|
|
151
151
|
environment.BIAWS_WORKSPACE_ID ||
|
|
152
|
-
environment.ISSUE_WORKSPACE_ID ||
|
|
153
152
|
workspaceConfiguration.workspaceId ||
|
|
154
|
-
effectiveEnv.
|
|
153
|
+
effectiveEnv.BIAWS_WORKSPACE_ID ||
|
|
155
154
|
"",
|
|
156
155
|
).trim();
|
|
157
156
|
|
package/src/instance/service.js
CHANGED
|
@@ -6,8 +6,8 @@ import { parseEnv } from "../core/context.js";
|
|
|
6
6
|
|
|
7
7
|
const PORT_FIELDS = Object.freeze({
|
|
8
8
|
mongoPort: "MONGO_PORT",
|
|
9
|
-
apiPort: "
|
|
10
|
-
uiPort: "
|
|
9
|
+
apiPort: "BIAWS_API_PORT",
|
|
10
|
+
uiPort: "BIAWS_UI_PORT",
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
const STORAGE_FIELDS = Object.freeze({
|
|
@@ -143,11 +143,11 @@ export async function listInstances(context, filesystem) {
|
|
|
143
143
|
directory,
|
|
144
144
|
envFile: path.join(directory, ".env"),
|
|
145
145
|
mongoPort: Number(env.MONGO_PORT || 27_017),
|
|
146
|
-
apiPort: Number(env.
|
|
147
|
-
uiPort: Number(env.
|
|
146
|
+
apiPort: Number(env.BIAWS_API_PORT || 3_100),
|
|
147
|
+
uiPort: Number(env.BIAWS_UI_PORT || 4_400),
|
|
148
148
|
publicUrl:
|
|
149
149
|
env.BIAWS_PUBLIC_URL ||
|
|
150
|
-
`http://localhost:${env.
|
|
150
|
+
`http://localhost:${env.BIAWS_UI_PORT || 4_400}`,
|
|
151
151
|
storage: Object.values(STORAGE_FIELDS).some((key) => env[key])
|
|
152
152
|
? "directories"
|
|
153
153
|
: "volumes",
|