@cubis/foundry 0.3.13 → 0.3.14
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/Ai Agent Workflow/powers/postman/POWER.md +2 -2
- package/Ai Agent Workflow/powers/postman/SKILL.md +2 -2
- package/Ai Agent Workflow/skills/postman/POWER.md +3 -3
- package/Ai Agent Workflow/skills/postman/SKILL.md +2 -2
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/antigravity/agents/backend-specialist.md +1 -1
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/antigravity/workflows/backend.md +11 -1
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/codex/agents/backend-specialist.md +1 -1
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/codex/workflows/backend.md +5 -1
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/copilot/agents/backend-specialist.md +1 -1
- package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/copilot/workflows/backend.md +5 -1
- package/README.md +4 -0
- package/bin/cubis.js +303 -2
- package/package.json +1 -1
|
@@ -12,7 +12,7 @@ Before proceeding, validate that the user has completed the following steps befo
|
|
|
12
12
|
|
|
13
13
|
## Step 1
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
|
|
16
16
|
|
|
17
17
|
## Step 2
|
|
18
18
|
|
|
@@ -68,7 +68,7 @@ Create a hook that runs anytime the source code or configuration file has been c
|
|
|
68
68
|
|
|
69
69
|
Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
|
|
70
70
|
|
|
71
|
-
**Authentication**:
|
|
71
|
+
**Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
|
|
72
72
|
|
|
73
73
|
## Available MCP Servers
|
|
74
74
|
|
|
@@ -10,7 +10,7 @@ Before proceeding, validate that the user has completed the following steps befo
|
|
|
10
10
|
|
|
11
11
|
## Step 1
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
|
|
14
14
|
|
|
15
15
|
## Step 2
|
|
16
16
|
|
|
@@ -66,7 +66,7 @@ Create a hook that runs anytime the source code or configuration file has been c
|
|
|
66
66
|
|
|
67
67
|
Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
|
|
68
68
|
|
|
69
|
-
**Authentication**:
|
|
69
|
+
**Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
|
|
70
70
|
|
|
71
71
|
## Available MCP Servers
|
|
72
72
|
|
|
@@ -12,7 +12,7 @@ Before proceeding, validate that the user has completed the following steps befo
|
|
|
12
12
|
|
|
13
13
|
## Step 1
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
|
|
16
16
|
|
|
17
17
|
## Step 2
|
|
18
18
|
|
|
@@ -68,7 +68,7 @@ Create a hook that runs anytime the source code or configuration file has been c
|
|
|
68
68
|
|
|
69
69
|
Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
|
|
70
70
|
|
|
71
|
-
**Authentication**:
|
|
71
|
+
**Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
|
|
72
72
|
|
|
73
73
|
## Available MCP Servers
|
|
74
74
|
|
|
@@ -239,4 +239,4 @@ for (const collection of collections) {
|
|
|
239
239
|
|
|
240
240
|
**Full mode (112 tools):** Change URL to `https://mcp.postman.com/full`
|
|
241
241
|
|
|
242
|
-
**API Key Permissions:** Workspace management, collection read/write, environment read/write, collection runs
|
|
242
|
+
**API Key Permissions:** Workspace management, collection read/write, environment read/write, collection runs
|
|
@@ -10,7 +10,7 @@ Before proceeding, validate that the user has completed the following steps befo
|
|
|
10
10
|
|
|
11
11
|
## Step 1
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
|
|
14
14
|
|
|
15
15
|
## Step 2
|
|
16
16
|
|
|
@@ -66,7 +66,7 @@ Create a hook that runs anytime the source code or configuration file has been c
|
|
|
66
66
|
|
|
67
67
|
Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
|
|
68
68
|
|
|
69
|
-
**Authentication**:
|
|
69
|
+
**Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
|
|
70
70
|
|
|
71
71
|
## Available MCP Servers
|
|
72
72
|
|
|
@@ -3,7 +3,7 @@ name: backend-specialist
|
|
|
3
3
|
description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
|
|
4
4
|
tools: Read, Grep, Glob, Bash, Edit, Write
|
|
5
5
|
model: inherit
|
|
6
|
-
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
6
|
+
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Backend Development Architect
|
|
@@ -14,4 +14,14 @@ Use this workflow when backend architecture or implementation is primary.
|
|
|
14
14
|
1. Ask `@backend-specialist` for solution outline.
|
|
15
15
|
2. Validate API contracts, data model, and failure handling.
|
|
16
16
|
3. Implement backend changes with tests and observability.
|
|
17
|
-
4.
|
|
17
|
+
4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
|
|
18
|
+
5. Return summary including migration and rollout notes.
|
|
19
|
+
|
|
20
|
+
## Output Contract
|
|
21
|
+
- API/contract changes
|
|
22
|
+
- OpenAPI spec path
|
|
23
|
+
- Swagger UI route
|
|
24
|
+
- Stoplight route/component status
|
|
25
|
+
- Migration impact
|
|
26
|
+
- Reliability/security notes
|
|
27
|
+
- Verification evidence
|
|
@@ -3,7 +3,7 @@ name: backend-specialist
|
|
|
3
3
|
description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
|
|
4
4
|
tools: Read, Grep, Glob, Bash, Edit, Write
|
|
5
5
|
model: inherit
|
|
6
|
-
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
6
|
+
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Backend Development Architect
|
package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/codex/workflows/backend.md
CHANGED
|
@@ -16,10 +16,14 @@ Use this when backend architecture or service logic is primary.
|
|
|
16
16
|
1. Ask specialist(s) for design and risk assessment.
|
|
17
17
|
2. Validate contracts, data model, and failure handling.
|
|
18
18
|
3. Implement backend changes with observability.
|
|
19
|
-
4.
|
|
19
|
+
4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
|
|
20
|
+
5. Run targeted tests and summarize rollout notes.
|
|
20
21
|
|
|
21
22
|
## Output Contract
|
|
22
23
|
- API/contract changes
|
|
24
|
+
- OpenAPI spec path
|
|
25
|
+
- Swagger UI route
|
|
26
|
+
- Stoplight route/component status
|
|
23
27
|
- Migration impact
|
|
24
28
|
- Reliability/security notes
|
|
25
29
|
- Verification evidence
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: backend-specialist
|
|
3
3
|
description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
|
|
4
4
|
tools: Read, Grep, Glob, Bash, Edit, Write
|
|
5
|
-
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
5
|
+
skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Backend Development Architect
|
package/Ai Agent Workflow/workflows/agent-environment-setup/platforms/copilot/workflows/backend.md
CHANGED
|
@@ -16,10 +16,14 @@ Use this when backend architecture or service logic is primary.
|
|
|
16
16
|
1. Ask specialist(s) for design and risk assessment.
|
|
17
17
|
2. Validate contracts, data model, and failure handling.
|
|
18
18
|
3. Implement backend changes with observability.
|
|
19
|
-
4.
|
|
19
|
+
4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
|
|
20
|
+
5. Run targeted tests and summarize rollout notes.
|
|
20
21
|
|
|
21
22
|
## Output Contract
|
|
22
23
|
- API/contract changes
|
|
24
|
+
- OpenAPI spec path
|
|
25
|
+
- Swagger UI route
|
|
26
|
+
- Stoplight route/component status
|
|
23
27
|
- Migration impact
|
|
24
28
|
- Reliability/security notes
|
|
25
29
|
- Verification evidence
|
package/README.md
CHANGED
|
@@ -34,10 +34,13 @@ cbx workflows doctor codex
|
|
|
34
34
|
cbx workflows platforms
|
|
35
35
|
cbx workflows install --platform antigravity --dry-run
|
|
36
36
|
cbx workflows install --platform antigravity --terminal-integration --terminal-verifier codex
|
|
37
|
+
cbx workflows install --platform codex --postman
|
|
38
|
+
cbx workflows install --platform codex --postman --postman-workspace-id null
|
|
37
39
|
```
|
|
38
40
|
|
|
39
41
|
Install bootstrap behavior:
|
|
40
42
|
- `cbx workflows install` now also bootstraps `ENGINEERING_RULES.md` and `TECH.md` (creates when missing; keeps existing files unless explicitly regenerated).
|
|
43
|
+
- Optional `--postman` bootstrap creates `postman_setting.json` and installs/configures the Postman skill.
|
|
41
44
|
- Use `cbx rules init --platform <platform> --overwrite` to force-regenerate both files.
|
|
42
45
|
|
|
43
46
|
`rules` manages strict engineering policy and a generated codebase tech map:
|
|
@@ -112,6 +115,7 @@ Routing behavior:
|
|
|
112
115
|
- Antigravity/Copilot: workflow + agent markdown can be routed by platform conventions.
|
|
113
116
|
- Codex: use generated callable wrapper skills (`$workflow-*`, `$agent-*`).
|
|
114
117
|
- Example for backend intent in Codex: `$workflow-backend` or `$agent-backend-specialist`.
|
|
118
|
+
- Backend workflow policy: always include OpenAPI updates plus Swagger UI and Stoplight Elements status in output.
|
|
115
119
|
|
|
116
120
|
### Codex Runtime Mode
|
|
117
121
|
|
package/bin/cubis.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { confirm, select } from "@inquirer/prompts";
|
|
3
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import {
|
|
@@ -122,6 +122,12 @@ const CODEX_WORKFLOW_SKILL_PREFIX = "workflow-";
|
|
|
122
122
|
const CODEX_AGENT_SKILL_PREFIX = "agent-";
|
|
123
123
|
const TERMINAL_VERIFIER_PROVIDERS = ["codex", "gemini"];
|
|
124
124
|
const DEFAULT_TERMINAL_VERIFIER = "codex";
|
|
125
|
+
const POSTMAN_API_KEY_ENV_VAR = "POSTMAN_API_KEY";
|
|
126
|
+
const POSTMAN_MCP_URL = "https://mcp.postman.com/minimal";
|
|
127
|
+
const POSTMAN_SKILL_ID = "postman";
|
|
128
|
+
const POSTMAN_SETTINGS_FILENAME = "postman_setting.json";
|
|
129
|
+
const POSTMAN_API_KEY_MISSING_WARNING =
|
|
130
|
+
`Postman API key is not configured. Set ${POSTMAN_API_KEY_ENV_VAR} or update ${POSTMAN_SETTINGS_FILENAME}.`;
|
|
125
131
|
const TECH_SCAN_MAX_FILES = 5000;
|
|
126
132
|
const TECH_SCAN_IGNORED_DIRS = new Set([
|
|
127
133
|
".git",
|
|
@@ -231,6 +237,13 @@ function normalizeTerminalVerifier(value) {
|
|
|
231
237
|
return TERMINAL_VERIFIER_ALIASES[normalized] || null;
|
|
232
238
|
}
|
|
233
239
|
|
|
240
|
+
function normalizePostmanWorkspaceId(value) {
|
|
241
|
+
if (value === undefined || value === null) return null;
|
|
242
|
+
const normalized = String(value).trim();
|
|
243
|
+
if (!normalized || normalized.toLowerCase() === "null") return null;
|
|
244
|
+
return normalized;
|
|
245
|
+
}
|
|
246
|
+
|
|
234
247
|
function defaultState() {
|
|
235
248
|
return {
|
|
236
249
|
schemaVersion: 1,
|
|
@@ -1872,6 +1885,237 @@ async function writeGeneratedArtifact({ destination, content, dryRun = false })
|
|
|
1872
1885
|
return { action: exists ? "replaced" : "installed", path: destination };
|
|
1873
1886
|
}
|
|
1874
1887
|
|
|
1888
|
+
function resolvePostmanSettingsPath({ scope, cwd = process.cwd() }) {
|
|
1889
|
+
if (scope === "global") {
|
|
1890
|
+
return path.join(os.homedir(), ".cbx", POSTMAN_SETTINGS_FILENAME);
|
|
1891
|
+
}
|
|
1892
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
1893
|
+
return path.join(workspaceRoot, POSTMAN_SETTINGS_FILENAME);
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
function buildPostmanMcpConfig({ apiKey = null, mcpUrl = POSTMAN_MCP_URL }) {
|
|
1897
|
+
const authHeader = apiKey
|
|
1898
|
+
? `Bearer ${apiKey}`
|
|
1899
|
+
: `Bearer \${${POSTMAN_API_KEY_ENV_VAR}}`;
|
|
1900
|
+
return {
|
|
1901
|
+
mcpServers: {
|
|
1902
|
+
postman: {
|
|
1903
|
+
url: mcpUrl,
|
|
1904
|
+
headers: {
|
|
1905
|
+
Authorization: authHeader
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
},
|
|
1909
|
+
disabled: false
|
|
1910
|
+
};
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
function getPostmanApiKeySource({ apiKey, envApiKey }) {
|
|
1914
|
+
if (apiKey) return "inline";
|
|
1915
|
+
if (envApiKey) return "env";
|
|
1916
|
+
return "unset";
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
function normalizePostmanApiKey(value) {
|
|
1920
|
+
if (value === undefined || value === null) return null;
|
|
1921
|
+
const normalized = String(value).trim();
|
|
1922
|
+
return normalized || null;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
async function ensureGitIgnoreEntry({
|
|
1926
|
+
filePath,
|
|
1927
|
+
entry,
|
|
1928
|
+
dryRun = false
|
|
1929
|
+
}) {
|
|
1930
|
+
const exists = await pathExists(filePath);
|
|
1931
|
+
const original = exists ? await readFile(filePath, "utf8") : "";
|
|
1932
|
+
const lines = original.split(/\r?\n/).map((line) => line.trim());
|
|
1933
|
+
const alreadyPresent = lines.includes(entry);
|
|
1934
|
+
|
|
1935
|
+
if (alreadyPresent) {
|
|
1936
|
+
return { action: "unchanged", filePath };
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
if (dryRun) {
|
|
1940
|
+
return {
|
|
1941
|
+
action: exists ? "would-patch" : "would-create",
|
|
1942
|
+
filePath
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
const suffix = original.endsWith("\n") || original.length === 0 ? "" : "\n";
|
|
1947
|
+
const nextContent = `${original}${suffix}${entry}\n`;
|
|
1948
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
1949
|
+
await writeFile(filePath, nextContent, "utf8");
|
|
1950
|
+
return {
|
|
1951
|
+
action: exists ? "patched" : "created",
|
|
1952
|
+
filePath
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
async function resolvePostmanInstallSelection({
|
|
1957
|
+
scope,
|
|
1958
|
+
options,
|
|
1959
|
+
cwd = process.cwd()
|
|
1960
|
+
}) {
|
|
1961
|
+
const hasApiKeyOption = options.postmanApiKey !== undefined;
|
|
1962
|
+
const hasWorkspaceOption = options.postmanWorkspaceId !== undefined;
|
|
1963
|
+
const enabled = Boolean(options.postman) || hasApiKeyOption || hasWorkspaceOption;
|
|
1964
|
+
if (!enabled) return { enabled: false };
|
|
1965
|
+
|
|
1966
|
+
const explicitApiKey = hasApiKeyOption ? String(options.postmanApiKey || "").trim() : "";
|
|
1967
|
+
let apiKey = explicitApiKey || null;
|
|
1968
|
+
const envApiKey = String(process.env[POSTMAN_API_KEY_ENV_VAR] || "").trim();
|
|
1969
|
+
let defaultWorkspaceId = hasWorkspaceOption
|
|
1970
|
+
? normalizePostmanWorkspaceId(options.postmanWorkspaceId)
|
|
1971
|
+
: null;
|
|
1972
|
+
const warnings = [];
|
|
1973
|
+
|
|
1974
|
+
const canPrompt = !options.yes && process.stdin.isTTY;
|
|
1975
|
+
if (canPrompt && !hasApiKeyOption && !apiKey && !envApiKey) {
|
|
1976
|
+
const promptedApiKey = String(
|
|
1977
|
+
await input({
|
|
1978
|
+
message: `Postman API key (optional, leave blank to keep ${POSTMAN_API_KEY_ENV_VAR} env mode):`,
|
|
1979
|
+
default: ""
|
|
1980
|
+
})
|
|
1981
|
+
).trim();
|
|
1982
|
+
if (promptedApiKey) {
|
|
1983
|
+
apiKey = promptedApiKey;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
if (canPrompt && !hasWorkspaceOption) {
|
|
1988
|
+
const promptedWorkspaceId = await input({
|
|
1989
|
+
message: "Default Postman workspace ID (optional, leave blank for null):",
|
|
1990
|
+
default: ""
|
|
1991
|
+
});
|
|
1992
|
+
defaultWorkspaceId = normalizePostmanWorkspaceId(promptedWorkspaceId);
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
const apiKeySource = getPostmanApiKeySource({ apiKey, envApiKey });
|
|
1996
|
+
if (apiKeySource === "unset") {
|
|
1997
|
+
warnings.push(POSTMAN_API_KEY_MISSING_WARNING);
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
const settingsPath = resolvePostmanSettingsPath({ scope, cwd });
|
|
2001
|
+
const settings = {
|
|
2002
|
+
apiKey: apiKey || null,
|
|
2003
|
+
apiKeyEnvVar: POSTMAN_API_KEY_ENV_VAR,
|
|
2004
|
+
apiKeySource,
|
|
2005
|
+
defaultWorkspaceId: defaultWorkspaceId ?? null,
|
|
2006
|
+
mcpUrl: POSTMAN_MCP_URL,
|
|
2007
|
+
generatedBy: "cbx workflows install --postman",
|
|
2008
|
+
generatedAt: new Date().toISOString()
|
|
2009
|
+
};
|
|
2010
|
+
|
|
2011
|
+
return {
|
|
2012
|
+
enabled: true,
|
|
2013
|
+
apiKey,
|
|
2014
|
+
apiKeySource,
|
|
2015
|
+
defaultWorkspaceId: defaultWorkspaceId ?? null,
|
|
2016
|
+
warnings,
|
|
2017
|
+
settings,
|
|
2018
|
+
settingsPath
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2021
|
+
|
|
2022
|
+
async function configurePostmanInstallArtifacts({
|
|
2023
|
+
scope,
|
|
2024
|
+
profilePaths,
|
|
2025
|
+
postmanSelection,
|
|
2026
|
+
overwrite = false,
|
|
2027
|
+
dryRun = false,
|
|
2028
|
+
cwd = process.cwd()
|
|
2029
|
+
}) {
|
|
2030
|
+
if (!postmanSelection?.enabled) return null;
|
|
2031
|
+
|
|
2032
|
+
let warnings = postmanSelection.warnings.filter((warning) => warning !== POSTMAN_API_KEY_MISSING_WARNING);
|
|
2033
|
+
const settingsContent = `${JSON.stringify(postmanSelection.settings, null, 2)}\n`;
|
|
2034
|
+
const settingsResult = await writeTextFile({
|
|
2035
|
+
targetPath: postmanSelection.settingsPath,
|
|
2036
|
+
content: settingsContent,
|
|
2037
|
+
overwrite,
|
|
2038
|
+
dryRun
|
|
2039
|
+
});
|
|
2040
|
+
|
|
2041
|
+
let effectiveApiKey = normalizePostmanApiKey(postmanSelection.settings.apiKey);
|
|
2042
|
+
let effectiveDefaultWorkspaceId = postmanSelection.defaultWorkspaceId ?? null;
|
|
2043
|
+
let effectiveMcpUrl = postmanSelection.settings.mcpUrl || POSTMAN_MCP_URL;
|
|
2044
|
+
|
|
2045
|
+
if (settingsResult.action === "skipped" || settingsResult.action === "would-skip") {
|
|
2046
|
+
try {
|
|
2047
|
+
const existingSettingsRaw = await readFile(postmanSelection.settingsPath, "utf8");
|
|
2048
|
+
const existingSettings = JSON.parse(existingSettingsRaw);
|
|
2049
|
+
effectiveApiKey = normalizePostmanApiKey(existingSettings?.apiKey);
|
|
2050
|
+
effectiveDefaultWorkspaceId = normalizePostmanWorkspaceId(existingSettings?.defaultWorkspaceId);
|
|
2051
|
+
const existingMcpUrl = String(existingSettings?.mcpUrl || "").trim();
|
|
2052
|
+
if (existingMcpUrl) {
|
|
2053
|
+
effectiveMcpUrl = existingMcpUrl;
|
|
2054
|
+
}
|
|
2055
|
+
} catch {
|
|
2056
|
+
warnings.push(
|
|
2057
|
+
`Existing ${POSTMAN_SETTINGS_FILENAME} could not be parsed. Using install-time Postman values for MCP config.`
|
|
2058
|
+
);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
const envApiKey = normalizePostmanApiKey(process.env[POSTMAN_API_KEY_ENV_VAR]);
|
|
2063
|
+
const effectiveApiKeySource = getPostmanApiKeySource({
|
|
2064
|
+
apiKey: effectiveApiKey,
|
|
2065
|
+
envApiKey
|
|
2066
|
+
});
|
|
2067
|
+
if (effectiveApiKeySource === "unset") {
|
|
2068
|
+
warnings.push(POSTMAN_API_KEY_MISSING_WARNING);
|
|
2069
|
+
}
|
|
2070
|
+
|
|
2071
|
+
let gitIgnoreResult = null;
|
|
2072
|
+
if (scope === "project") {
|
|
2073
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
2074
|
+
const gitIgnorePath = path.join(workspaceRoot, ".gitignore");
|
|
2075
|
+
gitIgnoreResult = await ensureGitIgnoreEntry({
|
|
2076
|
+
filePath: gitIgnorePath,
|
|
2077
|
+
entry: POSTMAN_SETTINGS_FILENAME,
|
|
2078
|
+
dryRun
|
|
2079
|
+
});
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
const postmanSkillDir = path.join(profilePaths.skillsDir, POSTMAN_SKILL_ID);
|
|
2083
|
+
const postmanMcpPath = path.join(postmanSkillDir, "mcp.json");
|
|
2084
|
+
let mcpResult = null;
|
|
2085
|
+
const postmanSkillExists = await pathExists(postmanSkillDir);
|
|
2086
|
+
if (!dryRun && !postmanSkillExists) {
|
|
2087
|
+
mcpResult = {
|
|
2088
|
+
action: "missing-postman-skill",
|
|
2089
|
+
path: postmanMcpPath
|
|
2090
|
+
};
|
|
2091
|
+
} else {
|
|
2092
|
+
const mcpConfigContent = `${JSON.stringify(
|
|
2093
|
+
buildPostmanMcpConfig({
|
|
2094
|
+
apiKey: effectiveApiKey,
|
|
2095
|
+
mcpUrl: effectiveMcpUrl
|
|
2096
|
+
}),
|
|
2097
|
+
null,
|
|
2098
|
+
2
|
|
2099
|
+
)}\n`;
|
|
2100
|
+
mcpResult = await writeGeneratedArtifact({
|
|
2101
|
+
destination: postmanMcpPath,
|
|
2102
|
+
content: mcpConfigContent,
|
|
2103
|
+
dryRun
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
return {
|
|
2108
|
+
enabled: true,
|
|
2109
|
+
apiKeySource: effectiveApiKeySource,
|
|
2110
|
+
defaultWorkspaceId: effectiveDefaultWorkspaceId,
|
|
2111
|
+
warnings,
|
|
2112
|
+
settingsPath: postmanSelection.settingsPath,
|
|
2113
|
+
settingsResult,
|
|
2114
|
+
gitIgnoreResult,
|
|
2115
|
+
mcpResult
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
|
|
1875
2119
|
async function installAntigravityTerminalIntegrationArtifacts({
|
|
1876
2120
|
profilePaths,
|
|
1877
2121
|
provider,
|
|
@@ -2032,6 +2276,7 @@ async function installBundleArtifacts({
|
|
|
2032
2276
|
platform,
|
|
2033
2277
|
scope,
|
|
2034
2278
|
overwrite,
|
|
2279
|
+
extraSkillIds = [],
|
|
2035
2280
|
terminalVerifierSelection = null,
|
|
2036
2281
|
dryRun = false,
|
|
2037
2282
|
cwd = process.cwd()
|
|
@@ -2092,7 +2337,8 @@ async function installBundleArtifacts({
|
|
|
2092
2337
|
else installed.push(destination);
|
|
2093
2338
|
}
|
|
2094
2339
|
|
|
2095
|
-
const
|
|
2340
|
+
const manifestSkillIds = Array.isArray(platformSpec.skills) ? platformSpec.skills : [];
|
|
2341
|
+
const skillIds = unique([...manifestSkillIds, ...extraSkillIds.filter(Boolean)]);
|
|
2096
2342
|
for (const skillId of skillIds) {
|
|
2097
2343
|
const source = path.join(agentAssetsRoot(), "skills", skillId);
|
|
2098
2344
|
const destination = path.join(profilePaths.skillsDir, skillId);
|
|
@@ -2389,6 +2635,32 @@ function printInstallSummary({
|
|
|
2389
2635
|
}
|
|
2390
2636
|
}
|
|
2391
2637
|
|
|
2638
|
+
function printPostmanSetupSummary({ postmanSetup }) {
|
|
2639
|
+
if (!postmanSetup?.enabled) return;
|
|
2640
|
+
|
|
2641
|
+
console.log("\nPostman setup:");
|
|
2642
|
+
console.log(`- Settings file: ${postmanSetup.settingsResult.action} (${postmanSetup.settingsPath})`);
|
|
2643
|
+
console.log(`- API key source: ${postmanSetup.apiKeySource}`);
|
|
2644
|
+
console.log(
|
|
2645
|
+
`- Default workspace ID: ${postmanSetup.defaultWorkspaceId === null ? "null" : postmanSetup.defaultWorkspaceId}`
|
|
2646
|
+
);
|
|
2647
|
+
if (postmanSetup.gitIgnoreResult) {
|
|
2648
|
+
console.log(
|
|
2649
|
+
`- .gitignore (${postmanSetup.gitIgnoreResult.filePath}): ${postmanSetup.gitIgnoreResult.action}`
|
|
2650
|
+
);
|
|
2651
|
+
}
|
|
2652
|
+
if (postmanSetup.mcpResult) {
|
|
2653
|
+
console.log(`- Postman MCP config (${postmanSetup.mcpResult.path}): ${postmanSetup.mcpResult.action}`);
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
if (postmanSetup.warnings.length > 0) {
|
|
2657
|
+
console.log("- Warnings:");
|
|
2658
|
+
for (const warning of postmanSetup.warnings) {
|
|
2659
|
+
console.log(` - ${warning}`);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2392
2664
|
function printRemoveSummary({
|
|
2393
2665
|
platform,
|
|
2394
2666
|
scope,
|
|
@@ -2694,6 +2966,18 @@ function withInstallOptions(command) {
|
|
|
2694
2966
|
return withWorkflowBaseOptions(command)
|
|
2695
2967
|
.option("-b, --bundle <bundle>", "bundle id (default: agent-environment-setup)")
|
|
2696
2968
|
.option("--overwrite", "overwrite existing files")
|
|
2969
|
+
.option(
|
|
2970
|
+
"--postman",
|
|
2971
|
+
"optional: install Postman skill and generate postman_setting.json"
|
|
2972
|
+
)
|
|
2973
|
+
.option(
|
|
2974
|
+
"--postman-api-key <key>",
|
|
2975
|
+
"optional: set Postman API key inline for generated postman_setting.json and installed Postman MCP config"
|
|
2976
|
+
)
|
|
2977
|
+
.option(
|
|
2978
|
+
"--postman-workspace-id <id|null>",
|
|
2979
|
+
"optional: set default Postman workspace ID (use 'null' for no default)"
|
|
2980
|
+
)
|
|
2697
2981
|
.option(
|
|
2698
2982
|
"--terminal-integration",
|
|
2699
2983
|
"Antigravity only: enable terminal verification integration (prompts for verifier when interactive)"
|
|
@@ -2854,6 +3138,11 @@ async function runWorkflowInstall(options) {
|
|
|
2854
3138
|
platform,
|
|
2855
3139
|
options
|
|
2856
3140
|
});
|
|
3141
|
+
const postmanSelection = await resolvePostmanInstallSelection({
|
|
3142
|
+
scope,
|
|
3143
|
+
options,
|
|
3144
|
+
cwd: process.cwd()
|
|
3145
|
+
});
|
|
2857
3146
|
|
|
2858
3147
|
const installResult = await installBundleArtifacts({
|
|
2859
3148
|
bundleId,
|
|
@@ -2861,6 +3150,7 @@ async function runWorkflowInstall(options) {
|
|
|
2861
3150
|
platform,
|
|
2862
3151
|
scope,
|
|
2863
3152
|
overwrite: Boolean(options.overwrite),
|
|
3153
|
+
extraSkillIds: postmanSelection.enabled ? [POSTMAN_SKILL_ID] : [],
|
|
2864
3154
|
terminalVerifierSelection,
|
|
2865
3155
|
dryRun,
|
|
2866
3156
|
cwd: process.cwd()
|
|
@@ -2890,6 +3180,14 @@ async function runWorkflowInstall(options) {
|
|
|
2890
3180
|
skipTech: false,
|
|
2891
3181
|
cwd: process.cwd()
|
|
2892
3182
|
});
|
|
3183
|
+
const postmanSetupResult = await configurePostmanInstallArtifacts({
|
|
3184
|
+
scope,
|
|
3185
|
+
profilePaths: installResult.profilePaths,
|
|
3186
|
+
postmanSelection,
|
|
3187
|
+
overwrite: Boolean(options.overwrite),
|
|
3188
|
+
dryRun,
|
|
3189
|
+
cwd: process.cwd()
|
|
3190
|
+
});
|
|
2893
3191
|
|
|
2894
3192
|
const terminalVerificationRuleResult =
|
|
2895
3193
|
platform === "antigravity" && installResult.terminalIntegration
|
|
@@ -2930,6 +3228,9 @@ async function runWorkflowInstall(options) {
|
|
|
2930
3228
|
engineeringResults: engineeringArtifactsResult.engineeringResults,
|
|
2931
3229
|
techResult: engineeringArtifactsResult.techResult
|
|
2932
3230
|
});
|
|
3231
|
+
printPostmanSetupSummary({
|
|
3232
|
+
postmanSetup: postmanSetupResult
|
|
3233
|
+
});
|
|
2933
3234
|
if (dryRun) {
|
|
2934
3235
|
console.log("\nDry-run complete. Re-run without `--dry-run` to apply changes.");
|
|
2935
3236
|
} else {
|