@uluops/setup 0.2.0 → 0.4.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 +56 -53
- package/assets/agents/anxiety-reader-agent.md +464 -0
- package/assets/commands/agents/anxiety-reader.md +160 -0
- package/assets/commands/agents/api-contract.md +1 -0
- package/assets/commands/agents/architect.md +1 -0
- package/assets/commands/agents/aristotle-analyst.md +1 -0
- package/assets/commands/agents/aristotle-explorer.md +1 -0
- package/assets/commands/agents/aristotle-forecaster.md +1 -0
- package/assets/commands/agents/aristotle-validator.md +1 -0
- package/assets/commands/agents/assumption-excavator.md +1 -0
- package/assets/commands/agents/audit.md +1 -0
- package/assets/commands/agents/{validate.md → code-validate.md} +6 -5
- package/assets/commands/agents/docs-validate.md +1 -0
- package/assets/commands/agents/frontend.md +1 -0
- package/assets/commands/agents/mcp-validate.md +1 -0
- package/assets/commands/agents/optimize.md +1 -0
- package/assets/commands/agents/pattern-analyzer.md +1 -0
- package/assets/commands/agents/prompt-quality.md +1 -0
- package/assets/commands/agents/prompt-validate.md +1 -0
- package/assets/commands/agents/public-interface.md +1 -0
- package/assets/commands/agents/release.md +1 -0
- package/assets/commands/agents/security.md +1 -0
- package/assets/commands/agents/test-review.md +1 -0
- package/assets/commands/agents/type-safety.md +1 -0
- package/assets/commands/agents/workflow-synthesis.md +1 -0
- package/assets/commands/pipelines/aristotle.md +143 -0
- package/assets/commands/pipelines/ship.md +188 -0
- package/assets/commands/workflows/prompt-audit.md +37 -747
- package/dist/cli.js +251 -207
- package/dist/harnesses/claude-code.d.ts +8 -0
- package/dist/harnesses/claude-code.js +72 -0
- package/dist/harnesses/codex.d.ts +15 -0
- package/dist/harnesses/codex.js +53 -0
- package/dist/harnesses/gemini-cli.d.ts +16 -0
- package/dist/harnesses/gemini-cli.js +54 -0
- package/dist/harnesses/index.d.ts +18 -0
- package/dist/harnesses/index.js +45 -0
- package/dist/harnesses/opencode.d.ts +14 -0
- package/dist/harnesses/opencode.js +130 -0
- package/dist/harnesses/types.d.ts +87 -0
- package/dist/harnesses/types.js +24 -0
- package/dist/lib/agent-transform.d.ts +12 -0
- package/dist/lib/agent-transform.js +129 -0
- package/dist/lib/asset-catalog.d.ts +9 -0
- package/dist/lib/asset-catalog.js +56 -0
- package/dist/lib/atomic-write.d.ts +11 -0
- package/dist/lib/atomic-write.js +28 -0
- package/dist/lib/config-merger.d.ts +7 -1
- package/dist/lib/config-merger.js +34 -5
- package/dist/lib/display.d.ts +14 -0
- package/dist/lib/display.js +66 -0
- package/dist/lib/file-ops.d.ts +6 -0
- package/dist/lib/file-ops.js +22 -1
- package/dist/lib/hash.d.ts +1 -0
- package/dist/lib/hash.js +1 -0
- package/dist/lib/health.d.ts +2 -0
- package/dist/lib/health.js +10 -0
- package/dist/lib/manifest.d.ts +22 -5
- package/dist/lib/manifest.js +148 -13
- package/dist/lib/paths.d.ts +15 -3
- package/dist/lib/paths.js +71 -13
- package/dist/lib/settings-merger.d.ts +9 -1
- package/dist/lib/settings-merger.js +45 -17
- package/dist/steps/agents.d.ts +5 -1
- package/dist/steps/agents.js +59 -9
- package/dist/steps/auth.js +26 -10
- package/dist/steps/commands.d.ts +6 -1
- package/dist/steps/commands.js +87 -9
- package/dist/steps/detect.d.ts +3 -0
- package/dist/steps/detect.js +7 -0
- package/dist/steps/mcp.d.ts +6 -2
- package/dist/steps/mcp.js +46 -21
- package/dist/steps/metrics.d.ts +14 -10
- package/dist/steps/metrics.js +59 -89
- package/dist/steps/shell.d.ts +2 -0
- package/dist/steps/shell.js +16 -9
- package/dist/steps/signup.d.ts +6 -3
- package/dist/steps/signup.js +26 -14
- package/dist/steps/verify.d.ts +2 -2
- package/dist/steps/verify.js +84 -117
- package/package.json +32 -7
- package/assets/commands/workflows/aristotle.md +0 -543
- package/assets/commands/workflows/ship.md +0 -721
- package/dist/test/auth.test.d.ts +0 -1
- package/dist/test/auth.test.js +0 -43
- package/dist/test/config-io.test.d.ts +0 -1
- package/dist/test/config-io.test.js +0 -56
- package/dist/test/config-merger.test.d.ts +0 -1
- package/dist/test/config-merger.test.js +0 -94
- package/dist/test/detect.test.d.ts +0 -1
- package/dist/test/detect.test.js +0 -25
- package/dist/test/file-ops.test.d.ts +0 -1
- package/dist/test/file-ops.test.js +0 -100
- package/dist/test/hash.test.d.ts +0 -1
- package/dist/test/hash.test.js +0 -14
- package/dist/test/manifest.test.d.ts +0 -1
- package/dist/test/manifest.test.js +0 -78
- package/dist/test/paths.test.d.ts +0 -1
- package/dist/test/paths.test.js +0 -30
- package/dist/test/settings-merger.test.d.ts +0 -1
- package/dist/test/settings-merger.test.js +0 -167
- package/dist/test/shell-profile.test.d.ts +0 -1
- package/dist/test/shell-profile.test.js +0 -40
- package/dist/test/shell.test.d.ts +0 -1
- package/dist/test/shell.test.js +0 -71
- package/dist/test/signup.test.d.ts +0 -1
- package/dist/test/signup.test.js +0 -83
package/dist/steps/verify.js
CHANGED
|
@@ -1,149 +1,126 @@
|
|
|
1
1
|
import { readdir, access } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { loadManifest } from "../lib/manifest.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const checks = [];
|
|
4
|
+
import { getHealthTimeout } from "../lib/health.js";
|
|
5
|
+
import { getProfile } from "../harnesses/index.js";
|
|
6
|
+
/** Verify a single harness entry, appending results to checks. Returns false if any check fails. */
|
|
7
|
+
async function verifyHarness(harnessName, hm, checks) {
|
|
9
8
|
let allOk = true;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
checks.push({
|
|
14
|
-
label: "Manifest found",
|
|
15
|
-
passed: false,
|
|
16
|
-
detail: "No manifest — run npx @uluops/setup first",
|
|
17
|
-
});
|
|
18
|
-
return { ok: false, checks };
|
|
19
|
-
}
|
|
20
|
-
checks.push({
|
|
21
|
-
label: `Manifest found (v${manifest.version}, installed ${manifest.installedAt.split("T")[0]})`,
|
|
22
|
-
passed: true,
|
|
23
|
-
});
|
|
24
|
-
// 2. MCP config
|
|
25
|
-
const config = await readConfig(manifest.mcpConfigPath);
|
|
26
|
-
const hasTracker = !!config.mcpServers?.["uluops-tracker"];
|
|
27
|
-
const hasRegistry = !!config.mcpServers?.["uluops-registry"];
|
|
28
|
-
if (hasTracker && hasRegistry) {
|
|
29
|
-
checks.push({
|
|
30
|
-
label: `MCP config present in ${manifest.mcpConfigPath} (2 servers)`,
|
|
31
|
-
passed: true,
|
|
32
|
-
});
|
|
9
|
+
let profile;
|
|
10
|
+
try {
|
|
11
|
+
profile = getProfile(harnessName);
|
|
33
12
|
}
|
|
34
|
-
|
|
35
|
-
checks.push({
|
|
36
|
-
|
|
37
|
-
passed: false,
|
|
38
|
-
detail: `Missing: ${[!hasTracker && "tracker", !hasRegistry && "registry"].filter(Boolean).join(", ")}`,
|
|
39
|
-
});
|
|
40
|
-
allOk = false;
|
|
13
|
+
catch {
|
|
14
|
+
checks.push({ label: `Harness: ${harnessName}`, passed: false, detail: "Unknown harness in manifest" });
|
|
15
|
+
return false;
|
|
41
16
|
}
|
|
42
|
-
//
|
|
43
|
-
const agentsDir = join(manifest.defsPath, "agents");
|
|
17
|
+
// MCP config
|
|
44
18
|
try {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
checks.push({
|
|
49
|
-
label: `${found}/${manifest.agents.length} agents in ${agentsDir}`,
|
|
50
|
-
passed: true,
|
|
51
|
-
});
|
|
19
|
+
const config = await profile.mcpConfig.read(hm.mcpConfigPath);
|
|
20
|
+
if (profile.mcpConfig.check(config)) {
|
|
21
|
+
checks.push({ label: `[${profile.displayName}] MCP config present in ${hm.mcpConfigPath} (2 servers)`, passed: true });
|
|
52
22
|
}
|
|
53
23
|
else {
|
|
54
|
-
checks.push({
|
|
55
|
-
label: `${found}/${manifest.agents.length} agents in ${agentsDir}`,
|
|
56
|
-
passed: false,
|
|
57
|
-
detail: `Missing ${manifest.agents.length - found} agent(s)`,
|
|
58
|
-
});
|
|
24
|
+
checks.push({ label: `[${profile.displayName}] MCP config`, passed: false, detail: "UluOps servers not found in config" });
|
|
59
25
|
allOk = false;
|
|
60
26
|
}
|
|
61
27
|
}
|
|
62
28
|
catch {
|
|
29
|
+
checks.push({ label: `[${profile.displayName}] MCP config`, passed: false, detail: `Cannot read ${hm.mcpConfigPath}` });
|
|
30
|
+
allOk = false;
|
|
31
|
+
}
|
|
32
|
+
// Agent files
|
|
33
|
+
const agentsDir = join(hm.defsPath, "agents");
|
|
34
|
+
try {
|
|
35
|
+
const agentFiles = await readdir(agentsDir);
|
|
36
|
+
const found = hm.agents.filter((a) => agentFiles.includes(a)).length;
|
|
63
37
|
checks.push({
|
|
64
|
-
label:
|
|
65
|
-
passed:
|
|
66
|
-
detail: `
|
|
38
|
+
label: `[${profile.displayName}] ${found}/${hm.agents.length} agents in ${agentsDir}`,
|
|
39
|
+
passed: found === hm.agents.length,
|
|
40
|
+
detail: found < hm.agents.length ? `Missing ${hm.agents.length - found} agent(s)` : undefined,
|
|
67
41
|
});
|
|
42
|
+
if (found < hm.agents.length)
|
|
43
|
+
allOk = false;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
checks.push({ label: `[${profile.displayName}] Agent files`, passed: false, detail: `Directory not found: ${agentsDir}` });
|
|
68
47
|
allOk = false;
|
|
69
48
|
}
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
// Command files
|
|
50
|
+
if (hm.commands.length > 0) {
|
|
51
|
+
const commandsDir = join(hm.defsPath, "commands");
|
|
73
52
|
let found = 0;
|
|
74
|
-
for (const cmd of
|
|
53
|
+
for (const cmd of hm.commands) {
|
|
75
54
|
try {
|
|
76
55
|
await access(join(commandsDir, cmd));
|
|
77
56
|
found++;
|
|
78
57
|
}
|
|
79
|
-
catch {
|
|
80
|
-
// Missing
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
if (found === manifest.commands.length) {
|
|
84
|
-
checks.push({
|
|
85
|
-
label: `${found}/${manifest.commands.length} commands in ${commandsDir}`,
|
|
86
|
-
passed: true,
|
|
87
|
-
});
|
|
58
|
+
catch { /* Missing */ }
|
|
88
59
|
}
|
|
89
|
-
else {
|
|
90
|
-
checks.push({
|
|
91
|
-
label: `${found}/${manifest.commands.length} commands in ${commandsDir}`,
|
|
92
|
-
passed: false,
|
|
93
|
-
detail: `Missing ${manifest.commands.length - found} command(s)`,
|
|
94
|
-
});
|
|
95
|
-
allOk = false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
60
|
checks.push({
|
|
100
|
-
label:
|
|
101
|
-
passed:
|
|
102
|
-
detail: `
|
|
61
|
+
label: `[${profile.displayName}] ${found}/${hm.commands.length} commands`,
|
|
62
|
+
passed: found === hm.commands.length,
|
|
63
|
+
detail: found < hm.commands.length ? `Missing ${hm.commands.length - found} command(s)` : undefined,
|
|
103
64
|
});
|
|
104
|
-
|
|
65
|
+
if (found < hm.commands.length)
|
|
66
|
+
allOk = false;
|
|
105
67
|
}
|
|
106
|
-
//
|
|
107
|
-
if (
|
|
108
|
-
const
|
|
109
|
-
const hookPresent = hasUluopsHook(settings);
|
|
110
|
-
const toolDir = getMetricsToolDir();
|
|
68
|
+
// Hooks
|
|
69
|
+
if (hm.hooksInstalled && profile.hooks && profile.paths.settingsPath) {
|
|
70
|
+
const hookPresent = await profile.hooks.check(profile.paths.settingsPath);
|
|
111
71
|
let hookFilePresent = false;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
72
|
+
if (profile.paths.toolsDir) {
|
|
73
|
+
try {
|
|
74
|
+
await access(join(profile.paths.toolsDir, "dist", "hook.js"));
|
|
75
|
+
hookFilePresent = true;
|
|
76
|
+
}
|
|
77
|
+
catch { /* Missing */ }
|
|
118
78
|
}
|
|
119
79
|
if (hookPresent && hookFilePresent) {
|
|
120
|
-
checks.push({
|
|
121
|
-
label: "Agent metrics hook configured and tool files present",
|
|
122
|
-
passed: true,
|
|
123
|
-
});
|
|
80
|
+
checks.push({ label: `[${profile.displayName}] Agent metrics hook configured`, passed: true });
|
|
124
81
|
}
|
|
125
82
|
else {
|
|
126
83
|
const missing = [
|
|
127
|
-
!hookPresent
|
|
128
|
-
!hookFilePresent
|
|
129
|
-
]
|
|
130
|
-
|
|
131
|
-
.join(", ");
|
|
132
|
-
checks.push({
|
|
133
|
-
label: "Agent metrics",
|
|
134
|
-
passed: false,
|
|
135
|
-
detail: missing,
|
|
136
|
-
});
|
|
84
|
+
...(!hookPresent ? ["hook not in settings"] : []),
|
|
85
|
+
...(!hookFilePresent ? ["hook.js not found"] : []),
|
|
86
|
+
].join(", ");
|
|
87
|
+
checks.push({ label: `[${profile.displayName}] Agent metrics`, passed: false, detail: missing });
|
|
137
88
|
allOk = false;
|
|
138
89
|
}
|
|
139
90
|
}
|
|
140
|
-
|
|
141
|
-
|
|
91
|
+
return allOk;
|
|
92
|
+
}
|
|
93
|
+
/** Run all verification checks against the current installation and return structured results. */
|
|
94
|
+
export async function verify() {
|
|
95
|
+
const checks = [];
|
|
96
|
+
let allOk = true;
|
|
97
|
+
// 1. Manifest
|
|
98
|
+
const manifest = await loadManifest();
|
|
99
|
+
if (!manifest) {
|
|
100
|
+
checks.push({
|
|
101
|
+
label: "Manifest found",
|
|
102
|
+
passed: false,
|
|
103
|
+
detail: "No manifest — run npx @uluops/setup first",
|
|
104
|
+
});
|
|
105
|
+
return { ok: false, checks };
|
|
106
|
+
}
|
|
107
|
+
checks.push({
|
|
108
|
+
label: `Manifest found (v${manifest.version}, installed ${manifest.installedAt.split("T")[0]})`,
|
|
109
|
+
passed: true,
|
|
110
|
+
});
|
|
111
|
+
// 2. Per-harness checks
|
|
112
|
+
for (const [harnessName, hm] of Object.entries(manifest.harnesses)) {
|
|
113
|
+
const ok = await verifyHarness(harnessName, hm, checks);
|
|
114
|
+
if (!ok)
|
|
115
|
+
allOk = false;
|
|
116
|
+
}
|
|
117
|
+
// 3. API connectivity (harness-agnostic)
|
|
118
|
+
const apiKey = process.env["ULUOPS_API_KEY"];
|
|
142
119
|
if (apiKey) {
|
|
143
120
|
try {
|
|
144
121
|
const res = await fetch("https://api.uluops.ai/api/v1/registry/users/me", {
|
|
145
122
|
headers: { Authorization: `Bearer ${apiKey}` },
|
|
146
|
-
signal: AbortSignal.timeout(
|
|
123
|
+
signal: AbortSignal.timeout(getHealthTimeout()),
|
|
147
124
|
});
|
|
148
125
|
if (res.ok) {
|
|
149
126
|
const data = (await res.json());
|
|
@@ -172,13 +149,3 @@ export async function verify() {
|
|
|
172
149
|
}
|
|
173
150
|
return { ok: allOk, checks };
|
|
174
151
|
}
|
|
175
|
-
function extractApiKey(config) {
|
|
176
|
-
const raw = config.mcpServers;
|
|
177
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
178
|
-
return process.env["ULUOPS_API_KEY"];
|
|
179
|
-
}
|
|
180
|
-
const servers = raw;
|
|
181
|
-
return (servers["uluops-registry"]?.env?.["ULUOPS_API_KEY"] ??
|
|
182
|
-
servers["uluops-tracker"]?.env?.["ULUOPS_TRACKER_API_KEY"] ??
|
|
183
|
-
process.env["ULUOPS_API_KEY"]);
|
|
184
|
-
}
|
package/package.json
CHANGED
|
@@ -1,22 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uluops/setup",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Zero-friction installer for UluOps
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Zero-friction installer for UluOps agentic harnesses",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Uluops/-uluops-setup.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://uluops.ai",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"uluops",
|
|
13
|
+
"mcp",
|
|
14
|
+
"agents",
|
|
15
|
+
"claude",
|
|
16
|
+
"opencode",
|
|
17
|
+
"agentic",
|
|
18
|
+
"harness",
|
|
19
|
+
"setup",
|
|
20
|
+
"installer"
|
|
21
|
+
],
|
|
5
22
|
"type": "module",
|
|
6
23
|
"bin": {
|
|
7
24
|
"uluops-setup": "./dist/cli.js"
|
|
8
25
|
},
|
|
26
|
+
"exports": {
|
|
27
|
+
"./cli": "./dist/cli.js"
|
|
28
|
+
},
|
|
9
29
|
"files": [
|
|
10
|
-
"dist",
|
|
30
|
+
"dist/cli.js",
|
|
31
|
+
"dist/cli.d.ts",
|
|
32
|
+
"dist/lib/**",
|
|
33
|
+
"dist/steps/**",
|
|
34
|
+
"dist/harnesses/**",
|
|
11
35
|
"assets"
|
|
12
36
|
],
|
|
13
37
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
38
|
+
"node": ">=20.0.0"
|
|
15
39
|
},
|
|
16
40
|
"scripts": {
|
|
17
|
-
"build": "tsc",
|
|
41
|
+
"build": "tsc -p tsconfig.build.json",
|
|
18
42
|
"dev": "tsx src/cli.ts",
|
|
19
|
-
"typecheck": "tsc --noEmit",
|
|
43
|
+
"typecheck": "tsc -p tsconfig.build.json --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
20
44
|
"test": "vitest run",
|
|
21
45
|
"test:watch": "vitest watch",
|
|
22
46
|
"prepublishOnly": "npm run build"
|
|
@@ -25,7 +49,8 @@
|
|
|
25
49
|
"@inquirer/prompts": "^7.0.0",
|
|
26
50
|
"@uluops/agent-metrics": "^0.2.0",
|
|
27
51
|
"chalk": "^5.0.0",
|
|
28
|
-
"commander": "^12.0.0"
|
|
52
|
+
"commander": "^12.0.0",
|
|
53
|
+
"jsonc-parser": "^3.3.1"
|
|
29
54
|
},
|
|
30
55
|
"devDependencies": {
|
|
31
56
|
"@types/node": "^22.0.0",
|